Source: https://dockhand.pro/ # Deploy Must have Docker installed: https://wiki.gabesville.com/books/docker/page/install-docker Run the docker command to install and run Dockhand: `sudo docker run -d -p 3000:3000 --name dockhand --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /srv/docker/dockhand/dockhand_data:/app/data fnsys/dockhand:latest` Go to http://IPADDRESS:3000 to access If firewall(UFW) is enabled you may need to allow port 3000 (test first before creating the rule) # Updating 1. CD to location you want the update script created 2. `sudo nano update-dockhand.sh` 3. Copypasta into file: ``` sudo docker stop dockhand sleep 10s sudo docker rm dockhand sudo docker image rm -f fnsys/dockhand:latest sleep 10s sudo docker run -d -p 3000:3000 --name dockhand --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /srv/docker/dockhand/dockhand_data:/app/data fnsys/dockhand:latest ``` 4. `sudo chmod u+x update-dockhand.sh` 5. to run: `bash update-dockhand.sh` # How variables and secrets are handled: This document summarizes how environment variables and secrets behave when using **Dockerhand** to deploy a stack from a `compose.yaml` and `.env` file. --- ## Mental Model Dockerhand has **two different injection mechanisms**: | Type | When injected | Usable in `${VAR}` | Available in container | |---------------------|--------------------------|--------------------|------------------------| | **Variables** | Before `docker compose` | ✅ Yes | ✅ Yes | | **Secrets** | At container runtime | ❌ No | ✅ Yes | **Key takeaway:** > Dockerhand secrets do **not** participate in Docker Compose variable interpolation. --- ## `.env` File Usage Use `.env` for: - Non-secret defaults - Local development - Structural configuration Example: ```env DB_USERNAME=postgres DB_HOSTNAME=database DB_PORT=5432 DB_DATABASE_NAME=immich IMMICH_VERSION=release UPLOAD_LOCATION=/mnt/media ⚠️ Do not rely on .env for secrets in production. ❌ What Does NOT Work (Common Pitfall) This fails when DB_PASSWORD is marked as a secret in Dockerhand: environment: DB_PASSWORD: ${DB_PASSWORD} Reason: Secrets are injected after Compose parsing ${DB_PASSWORD} resolves to empty ✅ Correct Pattern for Dockerhand Secrets Rule Never interpolate secrets with ${VAR}. Declare the variable name only. compose.yaml (Canonical Pattern) Application container (e.g. Immich) services: immich-server: env_file: - .env environment: DB_USERNAME: DB_PASSWORD: DB_HOSTNAME: DB_PORT: DB_DATABASE_NAME: Database container (Postgres) services: database: environment: POSTGRES_USER: POSTGRES_PASSWORD: Dockerhand Configuration Variables (non-secret) DB_USERNAME=postgres POSTGRES_USER=postgres Secrets DB_PASSWORD=******** POSTGRES_PASSWORD=******** ✔ Secrets are injected by name ✔ Containers receive them at runtime ✔ No ${VAR} expansion involved Why This Works Compose does not attempt interpolation Dockerhand injects secrets directly into container environments Applications read expected variables normally No accidental empty passwords No secret leakage via docker inspect Postgres-Specific Notes POSTGRES_PASSWORD is only used on initial DB creation Existing volumes require password changes via: ALTER USER postgres WITH PASSWORD 'newpassword'; Authentication failures can be misleading when the app receives an empty password Debugging Checklist If authentication fails: Confirm secret is not interpolated (${VAR}) Confirm variable name matches what the app expects Check inside container: env | grep PASSWORD Check Postgres logs for auth method (scram-sha-256) TL;DR .env = defaults & structure Dockerhand variables = safe overrides Dockerhand secrets = runtime injection only Never use ${VAR} for secrets Declare env var names and let Dockerhand fill them Final Rule to Remember If it’s marked as a secret in Dockerhand, Compose must never try to expand it.