Skip to content

Server Context

This guide documents the server environment for agents working on this system. Understanding this context is essential before making changes.

ServiceContainerImagePurpose
traefiktraefiktraefik:latestReverse proxy, SSL termination
docsdocsdocs-starlightDocumentation site (Starlight)
n8nn8nn8nio/n8n:latestWorkflow automation
postgres-mainpostgres-mainpostgres:15-alpinePostgreSQL database
bucko-web-prodbucko-web-prodbucko-bucko-webStatic website (Astro)
admineradmineradminerDatabase admin UI
promtailpromtailgrafana/promtail:latestLog shipping
PathPurpose
/opt/docker/All Docker projects root
/opt/docker/bucko/Bucko website (Astro)
/opt/docker/docs/Documentation site (Starlight)
/opt/docker/n8n/n8n workflow automation
/opt/docker/postgres/PostgreSQL configuration
/opt/docker/traefik/Traefik reverse proxy
/home/samob/User home, backup storage
┌─────────────────┐
│ Traefik │
│ (reverse proxy)│
│ :80, :443 │
└────────┬────────┘
┌────────┴────────┐
│ proxy network │
│ (external) │
└────────┬────────┘
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ docs │ │ n8n │ │bucko-web │
│ :4322 │ │ :5678 │ │ :4321 │
└───────────┘ └─────┬─────┘ └───────────┘
┌───────────┐
│ postgres │
│ :5432 │
└───────────┘

All web services connect to the proxy Docker network. Traefik routes traffic based on Host headers.

DomainServiceContainer
bucko.smilepowered.orgBucko websitebucko-web-prod
n8n.smilepowered.orgn8n workflowsn8n
docs.smilepowered.orgDocumentationdocs
adm.smilepowered.orgTraefik dashboardtraefik
ServiceLocationNotes
PostgreSQL/opt/docker/postgres/compose.yamlPOSTGRES_PASSWORD
n8n database/opt/docker/n8n/compose.yamlDB_POSTGRESDB_PASSWORD
n8n encryption/opt/docker/n8n/compose.yamlN8N_ENCRYPTION_KEY - also in volume
Traefik/opt/docker/traefik/compose.yamlACME email for Let’s Encrypt

To expose a service through Traefik, add these labels to compose.yaml:

labels:
- "traefik.enable=true"
- "traefik.http.routers.<name>.rule=Host(`<domain>`)"
- "traefik.http.routers.<name>.entrypoints=websecure"
- "traefik.http.routers.<name>.tls.certresolver=letsencrypt"
- "traefik.http.services.<name>.loadbalancer.server.port=<internal_port>"
Terminal window
# List all running containers
docker ps
# View container logs
docker logs <container_name>
# Follow logs in real-time
docker logs -f <container_name>
# Restart a service
cd /opt/docker/<service> && docker compose restart
# Rebuild and restart
cd /opt/docker/<service> && docker compose build && docker compose up -d
Terminal window
# List databases
docker exec postgres-main psql -U postgres -c "\l"
# Backup a database
docker exec postgres-main pg_dump -U <user> <database> > backup.sql
# Restore a database
cat backup.sql | docker exec -i postgres-main psql -U <user> -d <database>
Terminal window
# Check Traefik logs for errors
docker logs traefik | grep -i error
# Verify container labels
docker inspect <container_name> --format '{{json .Config.Labels}}' | jq
# Check proxy network
docker network inspect proxy

For services that require building (docs, bucko):

Terminal window
cd /opt/docker/<service>
./build.sh # Build static files using Docker node:22-alpine
docker compose build # Build container image
docker compose up -d # Start container

Compare running container image IDs with local latest images:

Terminal window
# Get running container image ID
docker inspect <container_name> --format '{{.Image}}'
# Pull latest image
docker pull <image>:latest
# Compare with local images
docker images --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}\t{{.CreatedAt}}" | grep <image>
  1. Pull the latest image:

    Terminal window
    docker pull <image>:latest
  2. Recreate the container:

    Terminal window
    cd /opt/docker/<service>
    docker compose up -d
  3. Verify update:

    Terminal window
    docker inspect <container_name> --format '{{.Image}}'
    docker images --format "{{.ID}}" <image>:latest

Both IDs should match after update.

ContainerImageUpdate Command
traefiktraefik:latestcd /opt/docker/traefik && docker compose up -d
n8nn8nio/n8n:latestcd /opt/docker/n8n && docker compose up -d
postgres-mainpostgres:15-alpinecd /opt/docker/postgres && docker compose up -d
admineradminercd /opt/docker/adminer && docker compose up -d
promtailgrafana/promtail:latestcd /opt/docker/promtail && docker compose up -d
LocationContents
/home/samob/Local backup copies (persistent)
/opt/docker/docs/public/downloads/Downloadable backups via docs site
Terminal window
docker logs <container_name>

Check for port conflicts, missing volumes, or configuration errors.

  1. Verify container has correct labels
  2. Verify container is on proxy network
  3. Check Traefik logs: docker logs traefik
Terminal window
docker inspect <container_name> | grep -A 20 Labels
docker network inspect proxy
  1. Check postgres is running: docker ps | grep postgres
  2. Verify credentials in compose.yaml match
  3. Test connection: docker exec postgres-main psql -U postgres -c "\l"

Files created by Docker may be owned by root. Use Docker to modify:

Terminal window
docker run --rm -v /opt/docker/<service>:/app -w /app node:22-alpine sh -c "rm -rf node_modules"