Security
What DockBeacon can access, how it protects your servers, and how to run it safely in production. Applies to v0.7.0.
Security model
DockBeacon is a host admin tool. Treat access to it like SSH access to the server: operators can restart containers, run Compose actions, and edit .env files.
- Your data stays with you. Logs stream straight from Docker and PM2 to the browser. Nothing is stored, indexed, or sent to a cloud service.
- What it can reach: the Docker Engine (through the Docker socket), PM2 logs and controls when you grant access, files under
PROJECTS_DIRfor Compose stacks, and host usage from/proc. - What it cannot do: open a shell on the host, read arbitrary files, or reach other servers unless you install an agent there.
Sign-in and sessions
- Sign-in is always required. Passwords are stored as bcrypt hashes.
- Sessions are HMAC-signed cookies:
HttpOnly,SameSite=Lax, andSecurebehind HTTPS (COOKIE_SECURE=autohonoursX-Forwarded-Proto). They expire after 24 hours. - Repeated failed sign-ins are rate-limited.
- Optional single sign-on with any OIDC provider (Google, Microsoft Entra ID, Keycloak, Okta).
- On first start without
AUTH_PASS, a random temporary admin password is printed once tojournalctl -u docker-log-viewer. Change it after signing in; changing a password requires the current one. - Scripts can use
X-Auth-Token, a Bearer token, or HTTP Basic auth over HTTPS.
Roles
Every user has one role. Give most people viewer.
| Action | Viewer | Operator | Admin |
|---|---|---|---|
| Read Docker and PM2 logs, container stats, system status | ✓ | ✓ | ✓ |
| Switch between servers | ✓ | ✓ | ✓ |
| See active alerts, the timeline, and Diagnose | ✓ | ✓ | ✓ |
| Inspect containers | — | ✓ | ✓ |
| Start, stop, restart containers and PM2 apps | — | ✓ | ✓ |
Compose up / down / restart, edit .env, reveal masked secrets | — | ✓ | ✓ |
| Manage users and the shared server list | — | — | ✓ |
| Change alert rules and notification channels | — | — | ✓ |
| Read the audit log | — | — | ✓ |
Agents
- You sign in once on the control plane. Agents accept that session only when they share the same
AUTH_SECRET, so keep it secret and different per environment. - Agents require
CORS_ORIGINSset to the control plane URL and refuse cross-origin requests when it is missing (fail closed). - Keep agents on a private network. Only the control plane should reach an agent's port (
9447by default).
Network and HTTPS
- Lab and staging:
LISTEN_ADDR=0.0.0.0and openhttp://<host>:9447on a trusted network. - Production:
LISTEN_ADDR=127.0.0.1and put nginx, Caddy, or a load balancer in front for HTTPS. DockBeacon does not terminate TLS itself. - The proxy must pass WebSocket upgrades and
X-Forwarded-Proto. See the nginx example. - Firewall: allow 443 to the proxy, allow the control plane to reach agents on 9447, block 9447 from everywhere else.
Service hardening
The packaged systemd unit runs DockBeacon as the unprivileged docker-log-viewer user, never as root, with:
NoNewPrivileges=true: the process cannot gain privileges.ProtectSystem=fullandPrivateTmp=true: system directories are read-only and/tmpis private.ReadWritePathslimited to/var/lib/docker-log-viewerand/etc/docker-log-viewer.- The env file is readable only by root and the service group (
0640).
NoNewPrivileges for this service only. Hosts without PM2 keep the full setting. See PM2 access.Docker socket
The service joins the docker group to read logs and stats. Access to the Docker socket is powerful, close to root on that host, which is why roles and the audit log matter.
To shrink that surface, run docker-socket-proxy with only the endpoints you need and point DockBeacon at it with DOCKER_HOST.
PM2 access
PM2 support is off until you run sudo /usr/lib/docker-log-viewer/pm2-grant-access on a host that already runs PM2. It grants only:
- Read access (ACL) to the PM2 log directory.
- A sudo rule for
pm2 jlist(list apps) and a wrapper that can only start, stop, or restart an app already in the list. No arbitrary commands.
Browser protections
- Double-submit CSRF tokens (
dlv_csrfcookie +X-CSRF-Tokenheader) on every state-changing request made with a session cookie. - Cross-origin requests are allowed only from
CORS_ORIGINS, and WebSocket origins are checked against the same list. - Compose and
.envwrites are confined toPROJECTS_DIR.
Alerts and webhooks
- The control plane checks itself and every agent every 30 seconds. Agents only answer with container, PM2, and host states; they never send logs.
- Only admins can change alert rules and channels. Every change is written to the audit log.
- Webhook URLs are secrets (anyone with a Slack or Discord webhook URL can post to that channel). DockBeacon stores them in
alerts.jsonwith mode0600and never sends them back to the browser; Settings shows only the host and the last few characters. - Slack, Teams, and Discord URLs must use
https://. Plainhttp://is allowed only for your own generic webhook. - Messages contain the server and container or app name, the state, and a short reason such as an exit code. They never include log lines, env values, or labels.
- Diagnose is read-only and never returns env values or labels, so viewers can use it.
Secrets and data
- Values in
.envand container inspect whose names look like passwords, tokens, or keys are masked until an operator reveals them. - Users, the session signing secret, the shared server list, alert settings, alert history, the timeline's event log, and the audit log live in
/var/lib/docker-log-viewer/. Back it up and keep it private. - The timeline keeps container events for 14 days (
EVENTS_RETENTION_DAYS). Docker attaches every container label to its events, so only safe fields (name, image, Compose project, exit code) are stored. - Settings live in
/etc/docker-log-viewer/docker-log-viewer.env. Never pasteAUTH_SECRETor passwords into issues or chat.
Audit log
Privileged actions (container and PM2 control, Compose actions, env edits, secret reveals, user and server changes, alert setting changes, sign-ins) are written as JSON lines to /var/lib/docker-log-viewer/audit.log (AUDIT_LOG_PATH) and to the system journal. Admins can read the latest entries in Settings or via GET /api/audit.
Packages and updates
- Packages are built by CI from tagged releases and published with SHA256 checksums. The apt and yum repositories are currently unsigned, so verify checksums on sensitive hosts.
- Read the one-step installer before running it:
curl -fsSL https://dock-beacon.web.app/install.sh -o install.sh && less install.sh. - No telemetry. DockBeacon only makes outbound requests you can see: alerts go to the channels you add, and the update check runs every 6 hours: the server fetches
dock-beacon.web.app/latest.jsonwith the user agentDockBeacon/<version>. No usage data, hostnames, or logs are sent. Turn it off withUPDATE_CHECK=false. (This website, not the app, uses Google Analytics to count visits.)
Production checklist
- Bind to localhost
LISTEN_ADDR=127.0.0.1, HTTPS on a reverse proxy,COOKIE_SECURE=auto. - Change the first passwordOr configure OIDC and set
AUTH_LOCAL=falseto turn off password sign-in. - Least privilegeViewer for most people, operator only for on-call, admin for one or two owners.
- Strong, unique
AUTH_SECRETShared only between a control plane and its agents. - Firewall agentsOnly the control plane reaches port 9447.
- Back up
/var/lib/docker-log-viewer/and/etc/docker-log-viewer/. - Stay updatedThe header shows an Update badge when a new release is out. See Upgrade.
Report a vulnerability
Please report security issues privately, not in a public issue:
Report a vulnerability on GitHub (private security advisory).
Include the DockBeacon version, how to reproduce it, and the impact. You will get a reply within a few days, and fixes ship as a new release with a changelog note.