Files
stiftung-management-system/deploy-synology/DEPLOYMENT_CHECKLIST.md
2025-09-06 18:31:54 +02:00

6.2 KiB

Synology NAS Deployment Checklist (Detailed)

This document captures the exact steps and lessons learned to reliably deploy the Stiftung app on a Synology NAS.

1) Prerequisites

  • DSM 7.0+ with the Docker package installed (Package Center)
  • SSH enabled (Control Panel → Terminal & SNMP → Enable SSH)
  • At least 4GB RAM and 10GB free disk space
  • NAS local IP (e.g., 192.168.1.50) and open port 8081

2) Directory Layout on NAS

Create this structure on the NAS (e.g., under /volume1/docker/stiftung):

/volume1/docker/stiftung
  ├─ app/                  # Django app code (the entire project folder "app")
  ├─ deploy-synology/      # Deployment files (compose, scripts, env template)
  └─ data/                 # Persistent volumes created by compose
      ├─ db/
      ├─ backups/
      ├─ redis/
      ├─ uploads/
      └─ logs/

Important:

  • The deploy-synology/docker-compose.yml uses build.context: ../app. Ensure app/ sits next to deploy-synology/ in the same parent directory.
  • If you used File Station to upload ZIPs, make sure you actually extracted the real app contents (not an empty folder).

3) Environment Configuration

  1. Go to the deployment folder:
cd /volume1/docker/stiftung/deploy-synology
  1. Create .env from template and edit values:
cp env.template .env
vi .env   # or use Text Editor in DSM
  1. Required variables (example):
# Core
SECRET_KEY=change_me_to_a_long_random_string
DEBUG=False
ALLOWED_HOSTS=localhost,127.0.0.1,crnas,192.168.1.50
CSRF_TRUSTED_ORIGINS=http://crnas:8081,http://192.168.1.50:8081,http://localhost:8081

# Database
DB_PASSWORD=super_secure_db_password

# Paperless (optional)
PAPERLESS_URL=
PAPERLESS_TOKEN=

Notes:

  • The database service uses: POSTGRES_DB=stiftung, POSTGRES_USER=stiftung_user, POSTGRES_PASSWORD=${DB_PASSWORD}.
  • The app services also receive POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD. This alignment prevents auth failures.

4) First Deployment

  1. Make scripts executable (first time only):
cd /volume1/docker/stiftung/deploy-synology
chmod +x *.sh
  1. Start services:
./deploy.sh
  1. Create a Django superuser:
sudo docker-compose exec web python manage.py createsuperuser
  1. Access the app:
http://<NAS_IP>:8081
  1. Health endpoint (for quick checks):
http://<NAS_IP>:8081/health/

5) Clean Reset / Redeploy

Use when you change envs, or need a clean DB:

cd /volume1/docker/stiftung/deploy-synology
sudo docker-compose down -v
rm -rf ./data/db
mkdir -p ./data/db
POSTGRES_UID=$(sudo docker run --rm postgres:15-alpine id -u postgres)
POSTGRES_GID=$(sudo docker run --rm postgres:15-alpine id -g postgres)
sudo chown -R $POSTGRES_UID:$POSTGRES_GID ./data/db
sudo chmod 700 ./data/db
sudo docker-compose up -d --build
sudo docker-compose exec web python manage.py migrate

6) Backup & Restore (via UI)

  • Backups are written to ./data/backups (mounted as /app/backups inside containers).
  • Backup creation and restore are available in the app under Administration → Backup & Restore.
  • Restore requires uploading a backup created by this app (.tar.gz). The process runs in background; check the job status in the UI.

Recommended restore flow on NAS:

cd /volume1/docker/stiftung/deploy-synology
sudo docker-compose stop worker beat   # avoid writers during restore
# Start restore via UI → upload .tar.gz → Start
sudo docker-compose logs -f web | cat  # watch progress
# After completion:
sudo docker-compose exec web python manage.py migrate
sudo docker-compose restart web
sudo docker-compose start worker beat

7) Logs & Monitoring

cd /volume1/docker/stiftung/deploy-synology
sudo docker-compose ps
sudo docker-compose logs --tail=150 web | cat
sudo docker-compose logs -f web | cat

8) Known Pitfalls & Fixes

  • Build path error: ERROR: build path .../app does not exist

    • Ensure directory layout matches section 2 (compose uses ../app).
  • Image pull denied for gramps/gramps-web

    • GrampsWeb was removed from compose; use the provided compose without that service.
  • DB port already in use

    • The DB service exposes no host port. Access it internally via service name db.
  • Bind mount path does not exist (e.g., ./data/backups)

    • Ensure ../data/backups exists (compose will also create it). Use the provided layout.
  • FATAL: password authentication failed for user "stiftung_user"

    • The DB volume may have been initialized with an old password. Align credentials:
      • Quick fix (change DB user to match .env):
        sudo docker-compose exec db psql -U postgres -d postgres -c "ALTER USER stiftung_user WITH PASSWORD '...from .env DB_PASSWORD...'";
        sudo docker-compose restart web worker beat
        
      • Clean reinit (wipes data): use the Clean Reset steps above. Note path is ./data/db relative to compose.
  • SECRET_KEY empty → 500 ImproperlyConfigured

    • Ensure .env has a non-empty SECRET_KEY (and it propagates into the web container):
      sudo docker-compose exec web env | grep -E "DJANGO_SECRET_KEY|SECRET_KEY"
      
  • DisallowedHost for crnas

    • Add NAS hostname/IP to .env:
      ALLOWED_HOSTS=192.168.x.x,crnas,localhost,127.0.0.1
      CSRF_TRUSTED_ORIGINS=http://crnas:8081,http://192.168.x.x:8081,http://localhost:8081
      
  • Celery error: Unable to load celery application. Module 'core' has no attribute 'celery'

    • Fixed by adding core/celery.py and from .celery import app as celery_app in core/__init__.py (already included in the app).
  • Backup error: pg_dump not found

    • The app image installs postgresql-client (already included). Rebuild if you changed Dockerfile.
  • Restore 500 on upload

    • Fixed by ensuring the restore view imports BackupJob and uses the correct form field backup_file.

9) Updating the App

cd /volume1/docker/stiftung/deploy-synology
sudo docker-compose pull    # if using remote images
sudo docker-compose up -d --build web worker beat

If you changed environment values in .env, restart:

sudo docker-compose up -d --build

Deployment Date: ________________ Deployed By: ________________ Notes: ________________