web + internal/opt/stack/twenty/websecure, Let's Encrypt DNS-01 Hetzner| Container | Image | Purpose |
|---|---|---|
twenty-server |
twentycrm/twenty:latest | App + API |
twenty-worker |
twentycrm/twenty:latest | Background jobs |
twenty-db |
postgres:16-alpine | Database |
twenty-redis |
redis:7-alpine | Queue |
secure-headers only, no authentik-forwardauth (Twenty handles its own auth)twenty-server-data volume requires 1000:1000 ownership before first boot — otherwise signup fails with EACCESTag: service=twenty
/root/backup.sh backup twenty
restic snapshots --tag service=twenty
Additional daily pg_dump at 3:30 AM (cron):
30 3 * * * docker exec twenty-db pg_dump -U twenty twenty > /opt/stack/twenty/backups/twenty_$(date +\%Y\%m\%d).sql && find /opt/stack/twenty/backups -name "*.sql" -mtime +7 -delete
Local retention: 7 days. Older snapshots available in Restic on pCloud.
cd /opt/stack/twenty && docker compose stop twenty-server twenty-worker
docker exec -i twenty-db psql -U twenty twenty < /opt/stack/twenty/backups/twenty_YYYYMMDD.sql
docker compose up -d
# Update
cd /opt/stack/twenty
docker compose pull && docker compose up -d
# Logs
docker compose logs -f twenty-server
docker compose logs -f twenty-worker
# Health
curl -I https://crm.enclari.com
# Fix EACCES (if volume is new)
docker compose down
docker volume rm twenty_twenty-server-data
docker volume create twenty_twenty-server-data
docker run --rm -v twenty_twenty-server-data:/app/files alpine chown -R 1000:1000 /app/files
docker compose up -d