12 KiB
12 KiB
b0esche.cloud Deployment Guide
This guide covers production deployment, server configuration, and operations.
Production Architecture
Server Overview
| Component | Domain | Port | Container |
|---|---|---|---|
| Flutter Web | www.b0esche.cloud | 80 | flutter-web |
| Go Backend | go.b0esche.cloud | 8080 | go-backend |
| PostgreSQL | internal | 5432 | go-postgres |
| Nextcloud | storage.b0esche.cloud | 80 | nextcloud |
| Collabora | of.b0esche.cloud | 9980 | collabora |
| Traefik | - | 80, 443 | traefik |
Server Directory Structure
/opt/
├── traefik/
│ ├── docker-compose.yml # Traefik + Nextcloud + Collabora
│ ├── traefik.yml # Static configuration
│ ├── .env # DNS credentials
│ └── acme/ # SSL certificates
├── go/
│ ├── docker-compose.yml # Go backend + PostgreSQL
│ ├── .env.production # Production environment
│ └── data/
│ └── postgres/
│ └── backend/
│ └── go_cloud/ # Backend source code
├── flutter/
│ ├── docker-compose.yml # Nginx for Flutter
│ ├── nginx.conf # Nginx configuration
│ └── web/ # Built Flutter files
├── scripts/
│ ├── auto-deploy.sh # Daily auto-deployment
│ ├── deploy-now.sh # Manual deployment trigger
│ ├── backup.sh # Backup script
│ ├── monitor.sh # Health monitoring
│ └── webhook-server.py # GitLab webhook receiver
└── auto-deploy/
└── b0esche_cloud_rollout/ # Deployment workspace
Deployment Methods
1. Automatic Deployment (Recommended)
Deployments run automatically at 3 AM daily via cron:
0 3 * * * /opt/scripts/auto-deploy.sh >> /var/log/auto-deploy.log 2>&1
The auto-deploy script:
- Pulls latest changes from GitLab
- Builds Flutter web app
- Rebuilds Go backend Docker image
- Restarts services
- Validates health checks
2. Manual Deployment (Immediate)
Trigger an immediate deployment:
# From local machine
ssh b0esche-cloud '/opt/scripts/deploy-now.sh'
# Or directly on server
/opt/scripts/deploy-now.sh
3. GitLab Webhook (On Push)
The webhook server listens for push events:
# Start webhook server (runs as systemd service)
systemctl start webhook-server
# Check webhook logs
journalctl -u webhook-server -f
Service Management
Starting All Services
# Start in order (dependencies first)
cd /opt/traefik && docker-compose up -d
cd /opt/go && docker-compose up -d
cd /opt/flutter && docker-compose up -d
Stopping All Services
cd /opt/flutter && docker-compose down
cd /opt/go && docker-compose down
cd /opt/traefik && docker-compose down
Restarting Individual Services
# Restart Go backend
cd /opt/go && docker-compose restart go-backend
# Restart Flutter frontend
cd /opt/flutter && docker-compose restart flutter-web
# Restart Traefik (caution: brief SSL interruption)
cd /opt/traefik && docker-compose restart traefik
Viewing Logs
# Follow Go backend logs
docker logs -f go-backend
# Follow Flutter/Nginx logs
docker logs -f flutter-web
# Follow Traefik logs
docker logs -f traefik
# All logs with timestamps
docker logs -f --timestamps go-backend
Configuration Files
Traefik Configuration
docker-compose.yml:
version: '3.8'
services:
traefik:
image: traefik:v2.10
container_name: traefik
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./acme:/etc/traefik/acme
networks:
- proxy
restart: unless-stopped
networks:
proxy:
external: true
traefik.yml:
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: admin@b0esche.cloud
storage: /etc/traefik/acme/acme.json
dnsChallenge:
provider: bunny
delayBeforeCheck: 30
providers:
docker:
exposedByDefault: false
Go Backend Configuration
docker-compose.yml:
version: '3.8'
services:
postgres:
image: postgres:15-alpine
container_name: go-postgres
environment:
POSTGRES_USER: go_backend
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: go_backend
volumes:
- ./data/postgres:/var/lib/postgresql/data
networks:
- backend
restart: unless-stopped
go-backend:
build:
context: ./data/postgres/backend/go_cloud
dockerfile: Dockerfile
container_name: go-backend
env_file: .env.production
labels:
- "traefik.enable=true"
- "traefik.http.routers.go.rule=Host(`go.b0esche.cloud`)"
- "traefik.http.routers.go.tls.certresolver=letsencrypt"
depends_on:
- postgres
networks:
- proxy
- backend
restart: unless-stopped
networks:
proxy:
external: true
backend:
driver: bridge
Flutter/Nginx Configuration
docker-compose.yml:
version: '3.8'
services:
flutter-web:
image: nginx:alpine
container_name: flutter-web
volumes:
- ./web:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.flutter.rule=Host(`www.b0esche.cloud`)"
- "traefik.http.routers.flutter.tls.certresolver=letsencrypt"
networks:
- proxy
restart: unless-stopped
networks:
proxy:
external: true
nginx.conf:
server {
listen 80;
server_name www.b0esche.cloud;
root /usr/share/nginx/html;
index index.html;
# Flutter web app routing
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript;
}
Database Operations
Running Migrations
# Enter backend container
docker exec -it go-backend sh
# Run migrations
./api migrate up
# Or from host
docker exec go-backend ./api migrate up
Database Backup
# Manual backup
docker exec go-postgres pg_dump -U go_backend -Fc go_backend > backup.sqlc
# Restore from backup
docker exec -i go-postgres pg_restore -U go_backend -d go_backend < backup.sqlc
Connecting to Database
# Via docker exec
docker exec -it go-postgres psql -U go_backend -d go_backend
# Common queries
\dt # List tables
\d users # Describe table
SELECT count(*) FROM users; # Count users
SSL Certificate Management
Certificate Status
# Check certificate expiry
docker exec traefik cat /etc/traefik/acme/acme.json | jq '.letsencrypt.Certificates[].certificate.NotAfter'
# Force certificate renewal
docker restart traefik
Manual Certificate Operations
# Backup certificates
cp -r /opt/traefik/acme /opt/traefik/acme.backup
# View certificate details
openssl s_client -connect www.b0esche.cloud:443 -servername www.b0esche.cloud </dev/null 2>/dev/null | openssl x509 -noout -dates
Monitoring
Health Checks
# Check all services
/opt/scripts/monitor.sh
# Manual health checks
curl -s https://go.b0esche.cloud/health
curl -s -o /dev/null -w "%{http_code}" https://www.b0esche.cloud
curl -s -o /dev/null -w "%{http_code}" https://storage.b0esche.cloud
Container Status
# All containers
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# Resource usage
docker stats --no-stream
# Container health
docker inspect --format='{{.State.Health.Status}}' go-backend
Disk Usage
# Docker disk usage
docker system df
# PostgreSQL data size
du -sh /opt/go/data/postgres
# Log sizes
du -sh /var/lib/docker/containers/*/
Backup Strategy
Automated Backups
Backups run daily via cron:
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
Backup Contents
- PostgreSQL database (pg_dump)
- Nextcloud database (mysqldump)
- Traefik certificates (/opt/traefik/acme)
- Configuration files (.env, docker-compose.yml)
- Nextcloud data volume
Backup Retention
- Keep backups for 30 days
- Stored in
/opt/backups/b0esche_cloud/ - Compressed as
.tar.gz
Manual Backup
# Run backup now
/opt/scripts/backup.sh
# List backups
ls -lh /opt/backups/b0esche_cloud/
Restore Procedure
# 1. Stop services
cd /opt/go && docker-compose down
cd /opt/flutter && docker-compose down
# 2. Extract backup
cd /opt/backups/b0esche_cloud
tar -xzf 20260113_020000.tar.gz
# 3. Restore database
docker exec -i go-postgres pg_restore -U go_backend -d go_backend < go_backend.sqlc
# 4. Restore configurations
cp .env.production /opt/go/
cp go-docker-compose.yml /opt/go/docker-compose.yml
# 5. Restart services
cd /opt/go && docker-compose up -d
cd /opt/flutter && docker-compose up -d
Troubleshooting
Common Issues
Service won't start
# Check logs for errors
docker logs go-backend --tail 50
# Check container status
docker inspect go-backend | jq '.[0].State'
# Check port conflicts
netstat -tlnp | grep -E '80|443|8080'
Database connection issues
# Test database connectivity
docker exec go-backend ping -c 3 postgres
# Check PostgreSQL logs
docker logs go-postgres --tail 50
# Verify credentials
docker exec go-postgres psql -U go_backend -c "SELECT 1"
SSL certificate errors
# Check certificate status
curl -vI https://www.b0esche.cloud 2>&1 | grep -A 5 "Server certificate"
# Force renewal
docker restart traefik
sleep 60
curl -vI https://www.b0esche.cloud
Out of disk space
# Check disk usage
df -h
# Clean Docker resources
docker system prune -a --volumes
# Clean old backups
find /opt/backups -mtime +30 -delete
# Clean old logs
truncate -s 0 /var/log/auto-deploy.log
Emergency Procedures
Rollback Deployment
# 1. Stop current services
cd /opt/go && docker-compose down
cd /opt/flutter && docker-compose down
# 2. Checkout previous version
cd /opt/auto-deploy/b0esche_cloud_rollout
git log --oneline -10 # Find last working commit
git checkout <commit-hash>
# 3. Redeploy
/opt/scripts/auto-deploy.sh
Database Recovery
# Find latest backup
ls -lt /opt/backups/b0esche_cloud/ | head -5
# Restore (see Restore Procedure above)
Full System Recovery
- Provision new server
- Install Docker
- Copy
/optfrom backup - Start services in order
- Restore database from backup
- Verify health checks
Security Checklist
- All services behind Traefik (no direct port exposure)
- SSL certificates valid and auto-renewing
- Database not accessible from internet
- Strong passwords in
.env.production - Regular backups verified
- Firewall configured (only 80, 443, 22 open)
- SSH key authentication only
- Auto-deploy logs monitored
Performance Tuning
PostgreSQL
-- Check slow queries
SELECT * FROM pg_stat_activity WHERE state = 'active';
-- Analyze tables
ANALYZE;
-- Vacuum
VACUUM ANALYZE;
Nginx
# Add to nginx.conf for better performance
worker_connections 1024;
keepalive_timeout 65;
gzip_comp_level 6;
Docker
# Limit container resources
docker update --memory="512m" --cpus="1" go-backend
# Clean up unused resources
docker system prune -f