LinuxServer socket-proxy gates container logs behind ALLOW_LOGS. Document
those extras on top of every profile that includes log viewing, keep
archive/changes/export/top disabled, and point Editor and Global Logs
troubleshooting at the self-hosting section.
Adds a "Docker socket proxy" section to self-hosting that maps Sencho
features to the Docker Engine API groups a proxy must allow. Three
profiles (monitoring / minimum management / full) with literal flag
values, a feature-to-API reference table, a keep-disabled list, and the
self-update caveat: helpers always mount the host Unix socket, so a
TCP-only proxy does not carry update traffic.
Also adds a production-hardening checklist item pointing at the section,
cross-links from the feature pages whose behavior depends on mutating
Docker access (mesh, file explorer, resources, remote updates, stack
management, scheduled operations), and a pointer from Compose Doctor's
proxy findings to the sizing guidance.
Closes#1796
Updates the backend listen port, Vite dev proxy target, Docker EXPOSE,
compose port mapping, .env.example default, GitHub Actions smoke-test
default, healthcheck URLs, and every doc/example reference. Test fixtures
that include example URLs were updated for consistency, though their
assertions are port-agnostic.
The rate-limit value of 3000 in middleware/rateLimiters.ts and the
3000 entry in WEB_UI_PORTS (which detects user containers like Grafana)
are intentionally untouched.
Every filesystem operation against user compose folders (save, create,
deploy, update, rollback, template install, fleet snapshot restore)
previously failed with EACCES whenever a stack container had chowned
its own bind mount to another UID, which is extremely common with
linuxserver/* images and anything that runs as root by default.
Running Sencho as root eliminates the entire class of permission bugs
at the source and matches the default posture of Portainer, Dockge,
Komodo, and Yacht. Mounting /var/run/docker.sock is already equivalent
to root-on-host, so the previous non-root hardening provided essentially
no additional isolation while breaking real features.
Changes:
- docker-entrypoint.sh: default path stays root, no GID dance, no
privilege drop. Opt-out via SENCHO_USER=sencho restores the legacy
behavior bit-for-bit (chown data dir, match Docker socket GID,
su-exec to the user). Fails fast if SENCHO_USER names a nonexistent
account. Kubernetes / OpenShift forced-non-root compat preserved via
the existing id -u = 0 guard.
- FileSystemService: delete forceDeleteViaDocker (the ~40-line helper
that shelled out to an alpine container to work around EACCES during
deleteStack) and simplify deleteStack to a single fsPromises.rm call.
Tests updated accordingly.
- Dockerfile: keep the sencho user+group pre-created so the opt-out
path works out of the box; comments updated to document the new
default.
- Docs: new "Container user" section in configuration.mdx documenting
the root default and the SENCHO_USER opt-out; troubleshooting and
self-hosting updated to match.
* fix(api): add tiered rate limiting to prevent polling lockouts
Replace the single global rate limiter (100 req/min/IP) with a tiered
system that separates high-frequency polling endpoints from standard
API traffic:
- Polling tier (300/min): /stats, /system/stats, /stacks/statuses,
/metrics/historical, /health, /meta, /auth/status, /auth/sso/providers,
/license. Exempt from the global limiter but governed by their own
safety net to prevent resource exhaustion.
- Standard tier (200/min): All other endpoints, raised from 100.
- Webhook tier (500/min): POST /webhooks/:id/trigger, dedicated limiter
for CI/CD platforms sharing datacenter IPs.
- Auth tier: Unchanged (5-10 attempts / 15 min).
Enterprise adaptations:
- Authenticated requests keyed by user session (JWT sub/username) instead
of IP, preventing shared NAT/VPN environments from pooling budgets.
- Internal node-to-node traffic (node_proxy tokens) bypasses all rate
limiters entirely.
Includes comprehensive stress tests (21 cases) validating tier
separation, node proxy bypass, and per-user keying.
* chore(deps): bump axios to 1.15.0 to fix SSRF vulnerability
Addresses GHSA-3p68-rc4w-qgx5 (NO_PROXY hostname normalization bypass).
* docs: remove security-sensitive implementation details from public documentation
Generalize or remove internal architecture details that could aid targeted
attacks — CVE tables, database schema, rate limit thresholds, proxy internals,
encryption algorithm names, and WebSocket middleware bypass info.
* test(metrics): fix flaky minute-bucket aggregation test
Floor baseTime to the start of the current minute so baseTime + 5000
never crosses a minute boundary and produces 2 buckets instead of 1.