total 20 drwxr-xr-x 2 root root 4096 Sep 11 10:39 . drwxr-xr-x 10 root root 4096 Sep 11 11:57 .. -rw-r--r-- 1 root root 1055 Sep 11 10:39 bulkmailer-api.service.example -rw-r--r-- 1 root root 719 Sep 11 10:39 bulkmailer-worker.service.example -rw-r--r-- 1 root root 2361 Sep 11 10:38 nginx.conf.example ---contents--- == bulkmailer-api.service.example == # Example systemd unit for running the API WITHOUT Docker (bare-metal / VM). # Install to /etc/systemd/system/bulkmailer-api.service, then: # sudo systemctl daemon-reload # sudo systemctl enable --now bulkmailer-api # # Assumes: # - Code deployed to /opt/bulkmailer # - Python virtualenv at /opt/bulkmailer/venv (pip install -r requirements.txt) # - .env file present at /opt/bulkmailer/.env # - Postgres and Redis already running/reachable per DATABASE_URL/REDIS_URL [Unit] Description=Bulk Gmail Mailer API (gunicorn+uvicorn) After=network.target postgresql.service redis.service [Service] Type=simple User=bulkmailer Group=bulkmailer WorkingDirectory=/opt/bulkmailer EnvironmentFile=/opt/bulkmailer/.env ExecStart=/opt/bulkmailer/venv/bin/gunicorn app.main:app \ -k uvicorn.workers.UvicornWorker \ --bind 0.0.0.0:8000 \ --workers 2 \ --timeout 60 \ --access-logfile - \ --error-logfile - Restart=on-failure RestartSec=5 == bulkmailer-worker.service.example == # Example systemd unit for the Celery worker WITHOUT Docker (bare-metal / VM). # Install to /etc/systemd/system/bulkmailer-worker.service, then: # sudo systemctl daemon-reload # sudo systemctl enable --now bulkmailer-worker [Unit] Description=Bulk Gmail Mailer Celery worker (real Gmail sending) After=network.target postgresql.service redis.service [Service] Type=simple User=bulkmailer Group=bulkmailer WorkingDirectory=/opt/bulkmailer EnvironmentFile=/opt/bulkmailer/.env ExecStart=/opt/bulkmailer/venv/bin/celery -A app.worker.celery_app worker \ --loglevel=INFO -Q send,control Restart=on-failure RestartSec=5 NoNewPrivileges=true ProtectSystem=full PrivateTmp=true [Install] WantedBy=multi-user.target == nginx.conf.example == # Example reverse-proxy config terminating HTTPS in front of the `api` # container (docker-compose service on 127.0.0.1:8000). # # Install certbot (Let's Encrypt) or bring your own cert/key, then: # sudo cp nginx.conf.example /etc/nginx/sites-available/bulkmailer # sudo ln -s /etc/nginx/sites-available/bulkmailer /etc/nginx/sites-enabled/ # sudo nginx -t && sudo systemctl reload nginx # # Replace `your-domain.example.com` and the cert paths below. server { listen 80; server_name your-domain.example.com; # Redirect all HTTP to HTTPS location / { return 301 https://$host$request_uri; } # Let's Encrypt HTTP-01 challenge path (certbot webroot mode) location /.well-known/acme-challenge/ { root /var/www/certbot; } } server { listen 443 ssl http2; server_name your-domain.example.com; ssl_certificate /etc/letsencrypt/live/your-domain.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3;