[Unit] Description=Church Music Database Backend API (Flask/Gunicorn) Documentation=https://github.com/church-hop/music-database After=network.target postgresql.service Wants=postgresql.service [Service] Type=simple User=pts Group=pts WorkingDirectory=/media/pts/Website/Church_HOP_MusicData/backend Environment="PATH=/media/pts/Website/Church_HOP_MusicData/backend/venv/bin:/usr/local/bin:/usr/bin:/bin" EnvironmentFile=/media/pts/Website/Church_HOP_MusicData/backend/.env.systemd # Security: Run with minimal privileges NoNewPrivileges=true PrivateTmp=true ReadWritePaths=/media/pts/Website/Church_HOP_MusicData/backend/logs # Pre-start check: Kill any rogue processes on port 8080 ExecStartPre=/media/pts/Website/Church_HOP_MusicData/backend/pre-start-check.sh # Start command using gunicorn with inline configuration ExecStart=/media/pts/Website/Church_HOP_MusicData/backend/venv/bin/gunicorn \ --bind 127.0.0.1:8080 \ --workers 2 \ --worker-class sync \ --timeout 60 \ --keep-alive 5 \ --access-logfile /media/pts/Website/Church_HOP_MusicData/backend/logs/access.log \ --error-logfile /media/pts/Website/Church_HOP_MusicData/backend/logs/error.log \ --log-level info \ --name church_music_backend \ app:app # Reload gracefully ExecReload=/bin/kill -s HUP $MAINPID # Restart policy Restart=always RestartSec=10 StartLimitInterval=300 StartLimitBurst=5 # Resource limits (adjust based on your server capacity) MemoryMax=512M CPUQuota=50% # Logging StandardOutput=append:/media/pts/Website/Church_HOP_MusicData/backend/logs/service.log StandardError=append:/media/pts/Website/Church_HOP_MusicData/backend/logs/service-error.log SyslogIdentifier=church-music-backend # Timeout settings TimeoutStartSec=60 TimeoutStopSec=30 [Install] WantedBy=multi-user.target