Deployment Phase
Objective: Deploy the application to a production-ready server in this case (Hetzner) for now, with proper configuration, security, and monitoring in place.
1. Deployment Preparation
1.1 Tools
Tool | Purpose |
---|---|
Docker | Build and run application containers. |
Hetzner Console | Manage server infrastructure. |
Nginx | Reverse proxy for handling HTTP/HTTPS traffic. |
Certbot | Generate and renew SSL certificates. |
1.2 Checklist
- Confirm Hetzner credentials and IP address.
- Verify that the database credentials are available.
- Ensure Docker Hub account access.
- Check that the production
.env
file is ready with correct values.
2. Docker [Local]
2.1 Build the Docker Image
docker build -t app/app_backend:0.0.1 --build-arg REQUIREMENTS_FILE=prod.txt .
2.2 Test Docker
docker run -p 8000:80 app/app_backend:0.0.1
2.3 Login to Docker Hub
docker login -u app
2.4 Tag the Docker Image
docker tag app/app_backend:0.0.1 app/app_backend:0.0.1
2.5 Push the Docker Image
docker push app/app_backend:0.0.1
3. Database Setup
3.1 Connect to Hetzner Managed Database
Retrieve credentials from Hetzner and log in:
psql -d app_db -U app -h some_host.your-server.de
3.2 Verify Database
\dt
4. Server Preparation
4.1 Connect to the Server
ssh root@<ip>
4.2 Install Required Packages
apt update
apt install -y docker.io nginx certbot python3-certbot-nginx
systemctl enable --now docker
4.3 Pull Docker Image
docker pull app/app_backend:0.0.1
4.4 Set Up Environment Variables
Create /app/.env
with the following content:
DATABASE_NAME=app_db
DATABASE_USER=app
DATABASE_PASSWORD=<password>
DATABASE_HOST=some_host.your-server.de
DATABASE_PORT=5432
DJANGO_SECRET_KEY=<your_secret_key>
DEBUG=False
5. Docker Deployment [Server]
5.1 Run the Docker Container
docker run -d --name app_backend \
--env-file /app/.env \
-v /app/staticfiles:/app/staticfiles \
-p 8000:80 \
app/app_backend:0.0.1
5.2 Verify the Docker Container
docker ps
docker logs <container_id>
5.3 Check Database Migrations
psql -d app_db -U app -h some_host.your-server.de
python manage.py migrate
6. Static Files Setup [Server]
6.1 Collect Static Files
docker exec -it app_backend bash
python manage.py collectstatic --noinput
6.2 Verify Static Files
ls /app/staticfiles
7. Nginx Configuration
7.1 Configure Nginx
Update /etc/nginx/sites-available/default
:
server {
listen 80;
server_name api.app.no;
location /static/ {
alias /app/staticfiles/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
7.2 Test and Restart Nginx
nginx -t
systemctl restart nginx
7.3 Verify Static Files Access
curl http://api.app.no/static/admin/css/base.css
8. SSL Setup
8.1 Install Certbot
apt install certbot python3-certbot-nginx
8.2 Obtain SSL Certificate
certbot --nginx -d api.app.no
8.3 Test SSL Certificate
curl https://api.app.no
8.4 Enable Auto Renewal
certbot renew --dry-run
9. DNS Configuration
9.1 Add A Record
Type | Host | Value | TTL |
---|---|---|---|
A | @ | ip 192.0.0.1 | 1 Hour |
9.2 Add CNAME Record (Optional)
Type | Host | Value | TTL |
---|---|---|---|
CNAME | www | api.app.no | 1 Hour |
10. Verification and Testing
10.1 Verify Application
- Access the application via
https://api.app.no
. - Verify API endpoints.
- Confirm the database is populated correctly.
10.2 Test Static Files
curl https://api.app.no/static/admin/css/base.css
11. Rollback (If Required)
TODO separate document
11.1 Stop the Current Container
docker stop app_backend
docker rm app_backend
11.2 Deploy the Previous Version
docker pull app/app_backend:<previous_version>
docker run -d --name app_backend \
--env-file /app/.env \
-v /app/staticfiles:/app/staticfiles \
-p 8000:80 \
app/app_backend:<previous_version>
12. Post-Deployment Monitoring
12.1 Monitoring
Tool | Purpose |
---|---|
Prometheus | Real-time application and server monitoring. |
Grafana | Visualization of metrics from Prometheus. |
ELK Stack | Centralized log aggregation (Elasticsearch, Logstash, Kibana). |
12.2 Set Up Metrics and Alerts
- Track critical metrics:
- CPU and memory usage.
- API response times.
- Error rates (4xx/5xx HTTP status codes).
- Configure alerts for critical thresholds using Prometheus or another monitoring tool.
12.3 Monitor Logs
- Use ELK Stack or a similar solution to centralize logs:
apt install filebeat filebeat setup
13 Firewall Configuration
TODO, separate docs as well as cloudflare config and setup todo
- Restrict server access:
ufw allow OpenSSH ufw allow 'Nginx Full' ufw enable
13.3 Secure Environment Variables
- Move
.env
file out of the application directory. - Set permissions to restrict access:
chmod 600 /path/to/.env chown app_user:app_user /path/to/.env
14 CI/CD GitHub Actions
Step | Description |
---|---|
Build Docker image | Automate Docker builds on new code pushes. |
Push to Docker Hub | Automatically push the latest images to Docker Hub. |
Deploy to Hetzner | SSH into Hetzner and pull the new Docker image. |
15. Backup Strategy
15.1 Database Backup
Schedule automatic backups using pg_dump
:
pg_dump -U app -h some_host.your-server.de app_db > app_db_$(date +%F).sql
15.2 Docker Image Backup
Tag Docker images with a version before any changes:
docker tag app/app_backend:latest app/app_backend:backup-$(date +%F)
```
### 15.3 Environment File Backup
Encrypt sensitive backups using GPG:
```bash
gpg --encrypt --recipient "email@example.com" /path/to/.env
16. E2E Testing After Deployment
Test Type | Steps |
---|---|
API Tests | Verify all endpoints return expected responses. |
UI Tests | Check user flows in the frontend (if applicable). |
Load Tests | Simulate high traffic to test application limits. |
17. Regular Maintenance
Task | Frequency |
---|---|
Rotate API keys | Monthly |
Backup Verification | Weekly |
Security Updates | As Needed |
Log Review | Daily |
18. Rollback Plan
TODO separate document