Security

What DockBeacon can access, how it protects your servers, and how to run it safely in production. Applies to v0.7.0.

Self-hosted, logs stay on your network Roles + audit log Runs as a non-root user No telemetry

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_DIR for 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, and Secure behind HTTPS (COOKIE_SECURE=auto honours X-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 to journalctl -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.

ActionViewerOperatorAdmin
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_ORIGINS set 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 (9447 by default).

Network and HTTPS

  • Lab and staging: LISTEN_ADDR=0.0.0.0 and open http://<host>:9447 on a trusted network.
  • Production: LISTEN_ADDR=127.0.0.1 and 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=full and PrivateTmp=true: system directories are read-only and /tmp is private.
  • ReadWritePaths limited to /var/lib/docker-log-viewer and /etc/docker-log-viewer.
  • The env file is readable only by root and the service group (0640).
PM2 exception. PM2 control needs a narrow sudo rule, so granting PM2 access adds a drop-in that relaxes 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_csrf cookie + X-CSRF-Token header) 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 .env writes are confined to PROJECTS_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.json with mode 0600 and 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://. Plain http:// 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 .env and 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 paste AUTH_SECRET or 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.json with the user agent DockBeacon/<version>. No usage data, hostnames, or logs are sent. Turn it off with UPDATE_CHECK=false. (This website, not the app, uses Google Analytics to count visits.)

Production checklist

  1. Bind to localhostLISTEN_ADDR=127.0.0.1, HTTPS on a reverse proxy, COOKIE_SECURE=auto.
  2. Change the first passwordOr configure OIDC and set AUTH_LOCAL=false to turn off password sign-in.
  3. Least privilegeViewer for most people, operator only for on-call, admin for one or two owners.
  4. Strong, unique AUTH_SECRETShared only between a control plane and its agents.
  5. Firewall agentsOnly the control plane reaches port 9447.
  6. Back up/var/lib/docker-log-viewer/ and /etc/docker-log-viewer/.
  7. 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.