# 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:

```cron
0 3 * * * /opt/scripts/auto-deploy.sh >> /var/log/auto-deploy.log 2>&1
```

The auto-deploy script:
1. Pulls latest changes from GitLab
2. Builds Flutter web app
3. Rebuilds Go backend Docker image
4. Restarts services
5. Validates health checks

### 2. Manual Deployment (Immediate)

Trigger an immediate deployment:

```bash
# 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:

```bash
# Start webhook server (runs as systemd service)
systemctl start webhook-server

# Check webhook logs
journalctl -u webhook-server -f
```

## Service Management

### Starting All Services

```bash
# 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

```bash
cd /opt/flutter && docker-compose down
cd /opt/go && docker-compose down
cd /opt/traefik && docker-compose down
```

### Restarting Individual Services

```bash
# 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

```bash
# 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:**
```yaml
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:**
```yaml
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:**
```yaml
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:**
```yaml
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:**
```nginx
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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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:
```cron
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
```

### Backup Contents

1. **PostgreSQL database** (pg_dump)
2. **Nextcloud database** (mysqldump)
3. **Traefik certificates** (/opt/traefik/acme)
4. **Configuration files** (.env, docker-compose.yml)
5. **Nextcloud data volume**

### Backup Retention

- Keep backups for 30 days
- Stored in `/opt/backups/b0esche_cloud/`
- Compressed as `.tar.gz`

### Manual Backup

```bash
# Run backup now
/opt/scripts/backup.sh

# List backups
ls -lh /opt/backups/b0esche_cloud/
```

### Restore Procedure

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# Find latest backup
ls -lt /opt/backups/b0esche_cloud/ | head -5

# Restore (see Restore Procedure above)
```

#### Full System Recovery

1. Provision new server
2. Install Docker
3. Copy `/opt` from backup
4. Start services in order
5. Restore database from backup
6. 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

```sql
-- Check slow queries
SELECT * FROM pg_stat_activity WHERE state = 'active';

-- Analyze tables
ANALYZE;

-- Vacuum
VACUUM ANALYZE;
```

### Nginx

```nginx
# Add to nginx.conf for better performance
worker_connections 1024;
keepalive_timeout 65;
gzip_comp_level 6;
```

### Docker

```bash
# Limit container resources
docker update --memory="512m" --cpus="1" go-backend

# Clean up unused resources
docker system prune -f
```
