Skip to main content
Dockhand can be configured using environment variables. This guide covers all available configuration options.

Environment Variables

Core Settings

PORT
string
default:"3000"
Port number for the web server. The application listens on 0.0.0.0 by default.
environment:
  PORT: "8080"
HOST
string
default:"0.0.0.0"
Host address to bind the web server. Use 0.0.0.0 to accept connections from any interface.
environment:
  HOST: "127.0.0.1"  # Localhost only
DATA_DIR
string
default:"/app/data"
Directory for storing application data (database, stacks, cache). Should be mounted as a volume for data persistence.
environment:
  DATA_DIR: /app/data
volumes:
  - dockhand_data:/app/data
DOCKHAND_HOSTNAME
string
default:"auto-detected"
Override the detected Docker host hostname. Useful for licensing and multi-host setups.
environment:
  DOCKHAND_HOSTNAME: production-docker-01
If not set, Dockhand automatically detects the hostname from the Docker daemon.

Database Configuration

DATABASE_URL
string
default:"sqlite"
PostgreSQL connection string. If not set, Dockhand uses SQLite (stored in DATA_DIR/dockhand.db).
environment:
  DATABASE_URL: postgres://user:password@host:5432/database
Format: postgres://USERNAME:PASSWORD@HOST:PORT/DATABASE
Ensure the PostgreSQL database exists before starting Dockhand. Migrations run automatically.
DB_FAIL_ON_MIGRATION_ERROR
boolean
default:"true"
Stop application startup if database migrations fail. Set to false to continue despite migration errors (not recommended).
environment:
  DB_FAIL_ON_MIGRATION_ERROR: "false"
DB_VERBOSE_LOGGING
boolean
default:"false"
Enable verbose SQL query logging for debugging database issues.
environment:
  DB_VERBOSE_LOGGING: "true"
SKIP_MIGRATIONS
boolean
default:"false"
Skip database migrations entirely. Useful for read-only replicas or troubleshooting.
environment:
  SKIP_MIGRATIONS: "true"
Only use this if you know what you’re doing. Missing migrations will cause application errors.

Docker Connection

DOCKER_SOCKET
string
default:"/var/run/docker.sock"
Path to the Docker socket inside the container. Useful when Docker socket is mounted at a non-standard location.
environment:
  DOCKER_SOCKET: /custom/path/docker.sock
volumes:
  - /var/run/docker.sock:/custom/path/docker.sock
DOCKER_HOST
string
default:"unix:///var/run/docker.sock"
Docker daemon connection URL. Supports Unix socket, TCP, and SSH protocols.
# TCP connection
environment:
  DOCKER_HOST: tcp://192.168.1.100:2376

# Unix socket (default)
environment:
  DOCKER_HOST: unix:///var/run/docker.sock
When using TCP, configure TLS certificates via the web UI (Settings > Environments) for secure connections.
DOCKER_API_VERSION
string
default:"auto-negotiated"
Force a specific Docker API version. Normally auto-negotiated with the daemon.
environment:
  DOCKER_API_VERSION: "1.41"
HOST_DATA_DIR
string
default:"auto-detected"
Host path to the data directory. Used for translating container paths when creating stacks. Auto-detected by inspecting Dockhand’s own container.
environment:
  HOST_DATA_DIR: /opt/dockhand/data
volumes:
  - /opt/dockhand/data:/app/data
HOST_DOCKER_SOCKET
string
default:"auto-detected"
Host path to the Docker socket. Used for socket-proxy scenarios or non-standard socket locations.
environment:
  HOST_DOCKER_SOCKET: /var/run/docker.sock

Security & Authentication

ENCRYPTION_KEY
string
default:"auto-generated"
Base64-encoded 32-byte encryption key for encrypting sensitive data (passwords, tokens, certificates). Auto-generated if not provided.
environment:
  ENCRYPTION_KEY: "your-base64-encoded-32-byte-key-here"
Generate a key with: openssl rand -base64 32
Store this securely! Loss of the encryption key means loss of all encrypted credentials.
Force secure cookies (HTTPS-only). Auto-detected based on x-forwarded-proto header.
environment:
  COOKIE_SECURE: "true"  # Force secure cookies
  # or
  COOKIE_SECURE: "false" # Allow HTTP cookies
  • true: Always use Secure flag (requires HTTPS)
  • false: Never use Secure flag (allows HTTP)
  • Not set: Auto-detect based on x-forwarded-proto: https header
DISABLE_LOCAL_LOGIN
boolean
default:"false"
Disable username/password authentication and require SSO/OIDC login.
environment:
  DISABLE_LOCAL_LOGIN: "true"
Ensure you have a working OIDC provider configured before enabling this, or you’ll be locked out.

User & Permissions

PUID
integer
default:"1001"
User ID to run the application as. Useful for matching host user permissions.
environment:
  PUID: "1000"
The container automatically configures the dockhand user with this UID on startup.
PGID
integer
default:"1001"
Group ID to run the application as. Useful for matching host group permissions.
environment:
  PGID: "1000"

Performance & Timeouts

COMPOSE_TIMEOUT
integer
default:"900"
Timeout in seconds for Docker Compose operations (up, down, pull). Increase for slow networks or large images.
environment:
  COMPOSE_TIMEOUT: "1800"  # 30 minutes
SKIP_DF_COLLECTION
boolean
default:"false"
Skip disk usage collection (df command). Recommended for Synology NAS and other systems where df is slow.
environment:
  SKIP_DF_COLLECTION: "true"
Disabling this removes disk usage graphs from the dashboard but significantly improves performance on affected systems.
MEMORY_MONITOR
boolean
default:"false"
Enable memory usage tracking and RSS snapshots for debugging memory leaks. Enables the /api/debug/memory endpoint.
environment:
  MEMORY_MONITOR: "true"
This is a debugging feature and adds overhead. Only enable when troubleshooting memory issues.
SNAPSHOT_INTERVAL
integer
default:"60"
Interval in minutes for memory snapshots when MEMORY_MONITOR=true.
environment:
  MEMORY_MONITOR: "true"
  SNAPSHOT_INTERVAL: "30"  # Every 30 minutes
DISABLE_METRICS
boolean
default:"false"
Disable metrics collection subprocess. Metrics include container stats, system info, and resource usage.
environment:
  DISABLE_METRICS: "true"
DISABLE_EVENTS
boolean
default:"false"
Disable Docker event stream monitoring. Events drive real-time UI updates.
environment:
  DISABLE_EVENTS: "true"

Git Integration

GIT_REPOS_DIR
string
default:"$DATA_DIR/git-repos"
Directory for storing cloned Git repositories (for Git-based stacks).
environment:
  GIT_REPOS_DIR: /app/data/git-repos

Configuration Examples

Production Deployment with PostgreSQL

docker-compose.yaml
services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: dockhand
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: dockhand
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - dockhand

  dockhand:
    image: fnsys/dockhand:latest
    restart: unless-stopped
    ports:
      - 3000:3000
    environment:
      # Database
      DATABASE_URL: postgres://dockhand:${DB_PASSWORD}@postgres:5432/dockhand
      
      # Security
      ENCRYPTION_KEY: ${ENCRYPTION_KEY}
      COOKIE_SECURE: "true"
      
      # Performance
      COMPOSE_TIMEOUT: "1800"
      
      # Authentication
      DISABLE_LOCAL_LOGIN: "true"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - dockhand_data:/app/data
    depends_on:
      - postgres
    networks:
      - dockhand

volumes:
  postgres_data:
  dockhand_data:

networks:
  dockhand:

Remote Docker Host Management

docker-compose.yaml
services:
  dockhand:
    image: fnsys/dockhand:latest
    restart: unless-stopped
    ports:
      - 3000:3000
    environment:
      # Connect to remote Docker daemon
      DOCKER_HOST: tcp://remote-docker.example.com:2376
      
      # Custom hostname
      DOCKHAND_HOSTNAME: central-management
    volumes:
      # No Docker socket needed for remote
      - dockhand_data:/app/data

volumes:
  dockhand_data:
Configure TLS certificates for the remote Docker host via the web UI (Settings > Environments).

High-Performance Configuration

docker-compose.yaml
services:
  dockhand:
    image: fnsys/dockhand:latest
    restart: unless-stopped
    ports:
      - 3000:3000
    environment:
      # Disable slow operations
      SKIP_DF_COLLECTION: "true"
      
      # Increase timeouts for large operations
      COMPOSE_TIMEOUT: "3600"
      
      # Custom UID/GID
      PUID: "1000"
      PGID: "1000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - dockhand_data:/app/data
    deploy:
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 512M

volumes:
  dockhand_data:

Debugging Configuration

docker-compose.yaml
services:
  dockhand:
    image: fnsys/dockhand:latest
    restart: unless-stopped
    ports:
      - 3000:3000
    environment:
      # Enable debugging
      DB_VERBOSE_LOGGING: "true"
      MEMORY_MONITOR: "true"
      SNAPSHOT_INTERVAL: "15"
      
      # Lenient error handling
      DB_FAIL_ON_MIGRATION_ERROR: "false"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - dockhand_data:/app/data

volumes:
  dockhand_data:

Session Management

Session timeout is configured via the web UI:
1

Navigate to Settings

Go to Settings > Authentication in the web interface.
2

Set Session Timeout

Configure Session Timeout in seconds:
  • Minimum: 1 second
  • Maximum: 2592000 seconds (30 days)
  • Default: 86400 seconds (24 hours)
3

Save Changes

Click Save. New sessions will use the updated timeout.
Sessions are stored in the database and survive container restarts.

TLS & HTTPS

Dockhand does not include a built-in TLS/HTTPS server. Use a reverse proxy for production deployments.

Nginx Reverse Proxy Example

nginx.conf
server {
    listen 443 ssl http2;
    server_name dockhand.example.com;

    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    location / {
        proxy_pass http://dockhand:3000;
        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;
        
        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
The X-Forwarded-Proto: https header enables automatic secure cookie mode.

Traefik Reverse Proxy Example

docker-compose.yaml
services:
  traefik:
    image: traefik:v2.10
    command:
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --providers.docker=true
      - [email protected]
      - --certificatesresolvers.letsencrypt.acme.storage=/acme.json
      - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - traefik_acme:/acme.json

  dockhand:
    image: fnsys/dockhand:latest
    labels:
      - traefik.enable=true
      - traefik.http.routers.dockhand.rule=Host(`dockhand.example.com`)
      - traefik.http.routers.dockhand.entrypoints=websecure
      - traefik.http.routers.dockhand.tls.certresolver=letsencrypt
      - traefik.http.services.dockhand.loadbalancer.server.port=3000
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - dockhand_data:/app/data

volumes:
  traefik_acme:
  dockhand_data:

Backup & Restore

SQLite Database

# Stop Dockhand
docker stop dockhand

# Backup data directory
docker run --rm \
  -v dockhand_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/dockhand-backup-$(date +%Y%m%d).tar.gz /data

# Start Dockhand
docker start dockhand

PostgreSQL Database

# Backup PostgreSQL database
docker exec dockhand-postgres pg_dump -U dockhand dockhand \
  > dockhand-backup-$(date +%Y%m%d).sql

# Backup data directory (stacks, configs)
docker run --rm \
  -v dockhand_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/dockhand-data-$(date +%Y%m%d).tar.gz /data

Troubleshooting

Symptoms: “Migration failed” errors on startupSolutions:
  1. Check database connectivity:
    docker logs dockhand | grep -i database
    
  2. Verify DATABASE_URL format:
    postgres://USERNAME:PASSWORD@HOST:PORT/DATABASE
    
  3. Skip migrations temporarily (for diagnosis only):
    environment:
      SKIP_MIGRATIONS: "true"
    
Symptom: Slow dashboard, high CPU usageSolution: Disable disk usage collection
environment:
  SKIP_DF_COLLECTION: "true"
The df command is extremely slow on Synology DSM and can freeze the UI.
Symptom: Container memory grows over timeSolution: Enable memory monitoring
environment:
  MEMORY_MONITOR: "true"
  SNAPSHOT_INTERVAL: "30"
Then access: http://localhost:3000/api/debug/memory
Symptom: Stack deployments fail with “timeout” errorsSolution: Increase timeout
environment:
  COMPOSE_TIMEOUT: "1800"  # 30 minutes
Useful for large images or slow networks.
Symptom: “Permission denied” or “Socket not accessible”Solutions:
  1. Add Docker socket group:
    docker run -d \
      --name dockhand \
      --group-add $(stat -c '%g' /var/run/docker.sock) \
      -v /var/run/docker.sock:/var/run/docker.sock \
      fnsys/dockhand:latest
    
  2. Verify socket is mounted:
    docker exec dockhand ls -la /var/run/docker.sock
    
  3. Check entrypoint logs:
    docker logs dockhand 2>&1 | head -20
    
Solution: Temporarily re-enable local login
docker stop dockhand
docker rm dockhand

# Start without DISABLE_LOCAL_LOGIN
docker run -d \
  --name dockhand \
  -p 3000:3000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v dockhand_data:/app/data \
  fnsys/dockhand:latest
Then configure OIDC provider before re-enabling.

Next Steps

Authentication

Configure OIDC/SSO and LDAP authentication

Stacks

Deploy and manage Docker Compose stacks

API Reference

Integrate Dockhand with automation tools

Deployment Guide

Production deployment best practices

Build docs developers (and LLMs) love