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.ymlusesbuild.context: ../app. Ensureapp/sits next todeploy-synology/in the same parent directory. - If you used File Station to upload ZIPs, make sure you actually extracted the real
appcontents (not an empty folder).
3) Environment Configuration ✅
- Go to the deployment folder:
cd /volume1/docker/stiftung/deploy-synology
- Create
.envfrom template and edit values:
cp env.template .env
vi .env # or use Text Editor in DSM
- 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 ✅
- Make scripts executable (first time only):
cd /volume1/docker/stiftung/deploy-synology
chmod +x *.sh
- Start services:
./deploy.sh
- Create a Django superuser:
sudo docker-compose exec web python manage.py createsuperuser
- Access the app:
http://<NAS_IP>:8081
- 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/backupsinside 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).
- Ensure directory layout matches section 2 (compose uses
-
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.
- The DB service exposes no host port. Access it internally via service name
-
Bind mount path does not exist (e.g.,
./data/backups)- Ensure
../data/backupsexists (compose will also create it). Use the provided layout.
- Ensure
-
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/dbrelative to compose.
- Quick fix (change DB user to match .env):
- The DB volume may have been initialized with an old password. Align credentials:
-
SECRET_KEY empty → 500 ImproperlyConfigured
- Ensure
.envhas a non-emptySECRET_KEY(and it propagates into the web container):sudo docker-compose exec web env | grep -E "DJANGO_SECRET_KEY|SECRET_KEY"
- Ensure
-
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
- Add NAS hostname/IP to
-
Celery error:
Unable to load celery application. Module 'core' has no attribute 'celery'- Fixed by adding
core/celery.pyandfrom .celery import app as celery_appincore/__init__.py(already included in the app).
- Fixed by adding
-
Backup error:
pg_dumpnot found- The app image installs
postgresql-client(already included). Rebuild if you changed Dockerfile.
- The app image installs
-
Restore 500 on upload
- Fixed by ensuring the restore view imports
BackupJoband uses the correct form fieldbackup_file.
- Fixed by ensuring the restore view imports
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: ________________