feat: add comprehensive GitHub workflow and development tools
This commit is contained in:
198
deploy-synology/DEPLOYMENT_CHECKLIST.md
Normal file
198
deploy-synology/DEPLOYMENT_CHECKLIST.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# 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:
|
||||
```bash
|
||||
cd /volume1/docker/stiftung/deploy-synology
|
||||
```
|
||||
|
||||
2) Create `.env` from template and edit values:
|
||||
```bash
|
||||
cp env.template .env
|
||||
vi .env # or use Text Editor in DSM
|
||||
```
|
||||
|
||||
3) Required variables (example):
|
||||
```bash
|
||||
# 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):
|
||||
```bash
|
||||
cd /volume1/docker/stiftung/deploy-synology
|
||||
chmod +x *.sh
|
||||
```
|
||||
|
||||
2) Start services:
|
||||
```bash
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
3) Create a Django superuser:
|
||||
```bash
|
||||
sudo docker-compose exec web python manage.py createsuperuser
|
||||
```
|
||||
|
||||
4) Access the app:
|
||||
```
|
||||
http://<NAS_IP>:8081
|
||||
```
|
||||
|
||||
5) Health endpoint (for quick checks):
|
||||
```
|
||||
http://<NAS_IP>:8081/health/
|
||||
```
|
||||
|
||||
## 5) Clean Reset / Redeploy ✅
|
||||
|
||||
Use when you change envs, or need a clean DB:
|
||||
```bash
|
||||
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:
|
||||
```bash
|
||||
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 ✅
|
||||
|
||||
```bash
|
||||
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):
|
||||
```bash
|
||||
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):
|
||||
```bash
|
||||
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 ✅
|
||||
|
||||
```bash
|
||||
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:
|
||||
```bash
|
||||
sudo docker-compose up -d --build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Deployment Date: `________________`
|
||||
Deployed By: `________________`
|
||||
Notes: `________________`
|
||||
Reference in New Issue
Block a user