Configuration
Configure LogDeck to match your environment and security requirements.
Two ways to configure
LogDeck reads its configuration from environment variables and from a JSON config file that the Settings page writes. Environment variables win: anything pinned by the environment is shown in the UI but cannot be changed there, which is what you want when the deployment, not the admin, should have the final say.
Hosts, Coolify hosts, read-only mode, and authentication can come from either source. API tokens, alert rules, and log retention live only in the config file — set through the UI, the CLI, or (for retention) an environment override.
The data directory
Everything LogDeck persists lives in one directory — the directory of its config file, /data by default:
config.json— hosts, Coolify hosts, read-only mode, auth, API tokens, alert rules, and log-store settingslogs.db— the SQLite log storealerts-history.json— recently fired alerts
Mount it as a volume. Without one, all of the above is written inside the container and destroyed the next time you recreate it — you would lose your API tokens, your alert rules, and all stored log history.
volumes:
- logdeck-data:/dataSet CONFIG_PATH to move the config file (and with it the whole directory) somewhere else, for example CONFIG_PATH=/config/logdeck.json.
Environment Variables
DOCKER_HOSTSOptionalComma-separated list of Docker hosts to manage. Each entry uses name=host format and supports unix://, tcp://, and ssh:// URLs.
local=unix:///var/run/docker.sockDOCKER_HOSTS=local=unix:///var/run/docker.sockExamples:
# Local only
DOCKER_HOSTS=local=unix:///var/run/docker.sock
# Mix of local and remote TCP
DOCKER_HOSTS=local=unix:///var/run/docker.sock,staging=tcp://192.168.1.100:2375
# SSH connection (mount your SSH keys or forward agent)
DOCKER_HOSTS=local=unix:///var/run/docker.sock,prod=ssh://deploy@prod.example.comHost names appear in the UI and in the container list so you always know which Docker daemon you are interacting with. Hosts defined here cannot be edited or removed from the Settings page; hosts added in Settings are merged with them.
Podman is supported through its Docker-compatible API socket. When DOCKER_HOSTS is unset, LogDeck probes for a local socket in order: Docker, then rootless Podman ($XDG_RUNTIME_DIR/podman/podman.sock), then rootful Podman (/run/podman/podman.sock).
CONFIG_PATHOptionalPath to the JSON config file. Its directory also holds the log store and the alert history, so it should be on a mounted volume.
/data/config.jsonREADONLY_MODEOptionalSet to true to block every mutating operation. See Read-Only Mode below. Default: false.
PORTNot configurableThe server always listens on :8080 inside the container. Publish it on whichever host port you like (-p 8123:8080).
Persistence is on by default and needs no configuration. These variables override the logStore section of the config file. See Log History for the full picture.
LOG_STORE_ENABLEDOptionalfalse disables log persistence entirely: no database file, no History mode. Default: true.
LOG_STORE_PER_CONTAINER_MBOptionalRetention cap per container, in MB. Oldest lines are evicted first. Default: 50.
LOG_STORE_TOTAL_MBOptionalRetention cap for the whole store, in MB. Default: 1024.
LOG_STORE_ENABLED=true
LOG_STORE_PER_CONTAINER_MB=50
LOG_STORE_TOTAL_MB=1024TRUST_PROXY_HEADERSOptionalSet to true to trust X-Forwarded-For / X-Real-IP when identifying a client. LogDeck uses the client IP to rate limit the login endpoint. Enable this only behind a reverse proxy (Coolify, Traefik, Nginx); on a directly exposed server a client could spoof these headers to sidestep the rate limit.
CORS_ALLOWED_ORIGINSOptionalComma-separated origins allowed to call the API from a browser. Only needed when the frontend is served from a different origin than the backend, such as a local dev server. The shipped image serves both from the same origin.
http://localhost:5173,http://127.0.0.1:5173Authentication is completely optional
If these variables are not set, LogDeck runs without authentication — fine for local development or a trusted network. You can also enable it from the Settings page instead, with no environment variables at all; those credentials are stored in the config file. Setting them here pins auth so the UI cannot change it.
These three go together: set all of them, or none of them. Setting some but not all is a startup error.
JWT_SECRETRequired for authSecret key used to sign session tokens. Sessions last 7 days.
JWT_SECRET=your-super-secret-key-change-this-to-something-random-min-32-charsGenerate a random secret:
openssl rand -base64 32ADMIN_USERNAMERequired for authAdmin username for logging in.
ADMIN_USERNAME=adminADMIN_PASSWORDRequired for authA bcrypt hash of the admin password — never plain text. LogDeck validates the hash at startup and refuses to start if it is malformed.
Generate the hash:
htpasswd -bnBC 10 '' yourPassword | tr -d ':'
# ADMIN_PASSWORD=$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWyhtpasswd ships with apache2-utils on Debian/Ubuntu, httpd-tools on RHEL, and is preinstalled on macOS. In a compose file, escape the $ characters as $$, or keep the hash in an .env file.
ADMIN_PASSWORD_SALTLegacyOlder LogDeck deployments hashed the admin password as SHA256(password + salt). That combination — ADMIN_PASSWORD_SALT set, with ADMIN_PASSWORD holding the resulting hex digest — is still accepted, so existing setups keep working. Use bcrypt for new ones and leave this unset.
Only needed for Coolify-managed servers
If you deploy containers through Coolify, enabling this integration ensures that environment variable changes made in LogDeck are synced to Coolify and persist across redeployments. Without it, changes are lost when Coolify redeploys.
COOLIFY_CONFIGSRequired for CoolifyPer-host Coolify configuration. Each entry maps a Docker host name (from DOCKER_HOSTS) to a Coolify instance URL and API token. Generate API tokens from your Coolify dashboard under Settings → API Tokens.
# Format: hostName|apiURL|apiToken,hostName|apiURL|apiToken
# Single host
COOLIFY_CONFIGS=local|https://your-coolify-instance.com|your-api-token
# Multiple hosts with different Coolify instances
COOLIFY_CONFIGS=prod|https://coolify-prod.example.com|token-abc,staging|https://coolify-staging.example.com|token-xyzHow it works
- LogDeck detects Coolify-managed containers automatically via Docker labels
- When you update environment variables, changes are synced to the Coolify API
- Sync is best-effort: if the Coolify API is unreachable, the container update still succeeds
- Coolify-managed containers are marked with a badge in the container list
Password Hashing
When you configure authentication through the environment, ADMIN_PASSWORD must hold a bcrypt hash — never a plain-text password. LogDeck checks the hash at startup and exits with an error if it is not a valid bcrypt string.
If instead you enable authentication from the Settings page, you type the password into the form and LogDeck hashes and stores it in the config file for you. There is nothing to generate.
Generate a bcrypt hash
htpasswd -bnBC 10 '' yourPassword | tr -d ':'
# $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWyhtpasswd ships with apache2-utils on Debian/Ubuntu, httpd-tools on RHEL, and is preinstalled on macOS.
• A bcrypt hash contains $ characters. In a compose file, escape them as $$, or put the hash in an .env file instead.
• Treat the hash and the JWT secret like passwords — keep them out of version control.
• Use a different JWT_SECRET per deployment. Changing it invalidates every existing session.
• The legacy SHA256(password + salt) scheme is still accepted when ADMIN_PASSWORD_SALT is set, so older deployments keep working. Prefer bcrypt for new ones.
Complete Example
Here's a complete docker-compose.yml with all configuration options:
services:
logdeck:
image: amoabakelvin/logdeck:latest
container_name: logdeck
ports:
- "8123:8080"
volumes:
# Docker socket for container management
- /var/run/docker.sock:/var/run/docker.sock
# /proc for system stats
- /proc:/host/proc:ro
# Config file, stored logs, and alert history — do not skip this
- logdeck-data:/data
# SSH keys, if you use ssh:// hosts
# - ~/.ssh:/root/.ssh:ro
environment:
# Docker hosts (local + remote example)
DOCKER_HOSTS: "local=unix:///var/run/docker.sock,prod=ssh://deploy@prod.example.com"
# Authentication (optional - remove to run without auth,
# or enable it from the Settings page instead)
JWT_SECRET: "your-super-secret-key-min-32-characters-long"
ADMIN_USERNAME: "admin"
ADMIN_PASSWORD: "your-bcrypt-hash" # $$ escapes the $ in a compose file
# Log persistence (optional - on by default)
# LOG_STORE_PER_CONTAINER_MB: "50"
# LOG_STORE_TOTAL_MB: "1024"
# Read-only mode (optional)
# READONLY_MODE: "true"
# Behind a reverse proxy (optional)
# TRUST_PROXY_HEADERS: "true"
# Coolify integration (optional - host names must match DOCKER_HOSTS)
# COOLIFY_CONFIGS: "local|https://your-coolify-instance.com|your-api-token"
restart: unless-stopped
volumes:
logdeck-data:The server exposes GET /api/v1/healthz if you want to wire up an external health check. The runtime image is minimal and ships no curl or wget, so a compose healthcheck has to come from outside the container.
Read-Only Mode
Read-only mode prevents LogDeck from changing anything on your containers. It is useful in production, where you want to read logs but not touch what is running. When it is on, these are blocked for everyone, session or token:
- Starting, stopping, restarting, and removing containers
- Compose stack start, stop, and restart
- Environment variable and resource-limit edits
- The web terminal (opening a shell in a container)
Reading is unaffected: logs, history, stats, events, and container details all work as usual. LogDeck's own settings and alert rules also remain editable — read-only mode is about your containers, not about LogDeck's configuration.
Toggle it from the Settings page in the UI, or pin it with an environment variable:
READONLY_MODE=trueWhen READONLY_MODE is set, it takes precedence and the UI toggle is disabled — useful when the environment, not the admin, should have the final say.
API Tokens
API tokens give the LogDeck CLI and external tools their own credentials, so you never have to share your admin login. They are managed entirely in the UI — no environment variables involved:
- Create and revoke tokens under Settings → API Access
- Tokens are prefixed
ldk_and shown in full only once, at creation - Only a hash is stored; a lost token cannot be recovered, only revoked and replaced
- Requests authenticate with an
Authorization: Bearer <token>header
Scopes
Each token is created with one of two scopes.
admin — full access, equivalent to a logged-in admin session.
read — read-only. Give this one to CI jobs, dashboards, and AI agents that only need to look. A read token can:
- Read live logs, stored log history, container details, stats, and events
- List images, volumes, networks, and hosts
A read token cannot:
- Mutate anything — every request that is not a
GETis rejected with403, so no start/stop/restart/remove, no stack actions, no environment or resource edits, and no changes to settings or alert rules - Open the web terminal
- Read a container's environment variables (they carry secrets)
- Read the settings endpoint, which exposes host topology and the token inventory
- Read anything under
/alerts— rules, channels, and history are denied, because channel URLs and tokens (Slack/Discord webhooks, bot tokens) are secrets
Tokens only matter when authentication is enabled; on an open instance the API is reachable without them.
Docker Socket Permissions
LogDeck needs access to the Docker socket to interact with containers. Here are some important considerations:
Security Best Practices
- Run LogDeck only on trusted networks
- Enable authentication if exposing LogDeck to untrusted users
- If you only need log viewing (no container management), mount the socket as read-only (
:ro) - Use Docker's built-in authorization plugins for fine-grained access control
- Keep LogDeck behind a reverse proxy with TLS in production
Permission Issues
If you encounter permission errors accessing the Docker socket, ensure the user running LogDeck has appropriate permissions:
# Check socket permissions
ls -l /var/run/docker.sock
# If needed, add user to docker group (Linux)
sudo usermod -aG docker $USERReverse Proxy Setup
For production deployments, it's recommended to run LogDeck behind a reverse proxy like Nginx or Traefik with TLS enabled.
Nginx Example
server {
listen 443 ssl http2;
server_name logdeck.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8123;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Traefik Example (Docker Labels)
services:
logdeck:
image: amoabakelvin/logdeck:latest
container_name: logdeck
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /proc:/host/proc:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.logdeck.rule=Host(`logdeck.example.com`)"
- "traefik.http.routers.logdeck.entrypoints=websecure"
- "traefik.http.routers.logdeck.tls.certresolver=letsencrypt"
- "traefik.http.services.logdeck.loadbalancer.server.port=8080"
restart: unless-stopped