# Guilan ACE Deployment ## Local and deployment layout ```text parent-directory/ guilan-ace-backend/ guilan-ace-frontend/ guilan-ace-deployment/ backend/ Dockerfile frontend/ Dockerfile certs/ traefik/ docker-compose.yml grafana-datasources.yml nginx-static.conf prometheus.yml ``` ## Usage 1. Keep `guilan-ace-backend`, `guilan-ace-frontend`, and `guilan-ace-deployment` as sibling repositories in your local workspace. 2. Copy `.env.example` to `.env`. 3. On the deployment server, place the backend repo at `guilan-ace-deployment/backend/guilan-ace-backend`. 4. On the deployment server, place the frontend repo at `guilan-ace-deployment/frontend/guilan-ace-frontend`. 5. Create `backend/guilan-ace-backend/.env` from the backend repo sample. 6. Create `frontend/guilan-ace-frontend/.env` from the frontend repo sample. 7. Run `docker compose up -d --build`. ## Notes - Traefik terminates TLS and routes frontend, API, admin, static, media, Grafana, Prometheus, and Uptime Kuma. - The frontend is a Next.js standalone Node runtime behind Traefik on internal port `3000`. - Alertmanager has been removed from this stack. Prometheus scraping and Grafana provisioning remain intact. - Dockerfiles live only in this deployment repository, and compose is intentionally wired only for the nested production layout. ## Backups and restores The deployment repo owns backup automation in `scripts/`. Backups include: - PostgreSQL dump from the `db` service. - Django media files from the `django_media` Docker volume. - Deployment, backend, and frontend `.env` files when present. The scripts expect this production layout: ```text guilan-ace-deployment/ .env backend/guilan-ace-backend/.env frontend/guilan-ace-frontend/.env docker-compose.yml ``` Add these backup variables to `guilan-ace-deployment/.env`: ```env S3_BACKUP_BUCKET=c284984 S3_BACKUP_PREFIX=backup/guilan-ace S3_BACKUP_REGION=us-east-1 S3_BACKUP_ENDPOINT_URL=https://c284984.parspack.net S3_BACKUP_ACCESS_KEY_ID=replace-with-access-key S3_BACKUP_SECRET_ACCESS_KEY=replace-with-secret-key BACKUP_ENCRYPTION_PASSPHRASE=replace-with-long-random-passphrase BACKUP_LOCAL_KEEP_LATEST=3 BACKUP_REMOTE_KEEP_LATEST=10 ``` Install script dependencies on the server: ```bash sudo apt-get update sudo apt-get install -y docker-compose-plugin rclone openssl chmod +x ~/guilan-ace-deployment/scripts/*.sh ``` Create a manual local backup: ```bash cd ~/guilan-ace-deployment ./scripts/backup.sh ``` Create, encrypt, upload, and rotate an S3 backup: ```bash cd ~/guilan-ace-deployment ./scripts/backup-upload-s3.sh ``` Restore from a local backup archive: ```bash cd ~/guilan-ace-deployment ./scripts/restore.sh backups/guilan-ace-backup-YYYYMMDD-HHMMSS.tar.gz docker compose up -d --build ``` Restore the latest encrypted S3 backup: ```bash cd ~/guilan-ace-deployment ./scripts/restore-from-s3.sh latest docker compose up -d --build ``` Restore only selected parts by setting skip flags: ```bash RESTORE_SKIP_ENV=1 ./scripts/restore.sh backups/guilan-ace-backup-YYYYMMDD-HHMMSS.tar.gz RESTORE_SKIP_DB=1 RESTORE_SKIP_MEDIA=1 ./scripts/restore-from-s3.sh latest ``` Database restore recreates the configured database and is destructive unless `RESTORE_SKIP_DB=1` is set. Run encrypted S3 backups periodically with cron: ```bash crontab -e ``` Example: run every day at `03:30` server time and write logs to `backups/backup.log`: ```cron 30 3 * * * cd /home/ubuntu/guilan-ace-deployment && ./scripts/backup-upload-s3.sh >> /home/ubuntu/guilan-ace-deployment/backups/backup.log 2>&1 ``` Example: run every 6 hours: ```cron 0 */6 * * * cd /home/ubuntu/guilan-ace-deployment && ./scripts/backup-upload-s3.sh >> /home/ubuntu/guilan-ace-deployment/backups/backup.log 2>&1 ```