Skip to content

Container User & Privilege Model

SentriKat's container runs the long-lived gunicorn process as a non-root user (sentrikat, the container's sentrikat UID (check with docker compose exec sentrikat id)). This page explains the lifecycle and what operators need to know about volume permissions.

Lifecycle

  1. Container starts as root. Required for update-ca-certificates and chown of runtime directories.
  2. Entrypoint installs custom CAs and validates secrets (SECRET_KEY, DB_PASSWORD in production mode).
  3. Privilege drop via gosu sentrikat: the entrypoint exec's gunicorn as the sentrikat user. From this point master and workers all run as the container's sentrikat UID (check with docker compose exec sentrikat id).
  4. Workers fork from master, inheriting the sentrikat UID.

This model prevents two classes of bugs:

  • A compromised gunicorn worker has no root privileges to escalate.
  • The "master is root, workers are sentrikat" mismatch (silently breaking log file writes) cannot occur.

Bind-mount permissions

Any host path mounted into the container must be writable by the container's sentrikat UID (check with docker compose exec sentrikat id):

Mount target Purpose Required ownership
/var/log/sentrikat Log files 999:999, mode 755
/app/data Uploads, encryption key, backups 999:999, mode 755
/data/... (with STORAGE_ROOT) Persistent data 999:999, mode 755
/app/custom-certs Custom CA certificates 0:0 read-only OK

Set ownership before starting the container:

sudo mkdir -p /opt/sentrikat/{logs,data,backups}
sudo chown -R 999:999 /opt/sentrikat
sudo chmod -R 755 /opt/sentrikat

Troubleshooting

Symptom: Permission denied writing logs

docker exec sentrikat ls -la /var/log/sentrikat/
# If files show `root:root`, the gosu privilege drop did not happen.

Recovery: chown in a shell, restart the container.

Symptom: container starts but exits immediately

docker logs sentrikat
# Look for "FATAL: SECRET_KEY must be set" or similar.
# Production mode requires SECRET_KEY and DB_PASSWORD changed
# from their default values.

Symptom: gosu: command not found

Indicates a base image without gosu. Should not happen with the official image — rebuild from a clean clone of the SentriKat repo.

See also

  • Dockerfile (look for RUN apt-get install ... gosu).
  • docker-entrypoint.sh (look for exec gosu sentrikat "$@").
  • Logging & Observability