Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions infrastructure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Infrastructure Services

Core infrastructure components for automa self-hosted platform.

## Quick Start

### 1. Create Networks

```bash
docker network create automa-proxy
docker network create automa-monitoring
```

### 2. Setup Environment

```bash
# Copy global env file
cp ../.env.example ../.env

# Edit with your values
vim ../.env
```

Required variables:
```bash
DOMAIN=example.com
GRAFANA_ADMIN_PASSWORD=changeme
TZ=Asia/Shanghai
```

### 3. Start Infrastructure

```bash
# Start all at once
cd caddy && docker compose up -d && cd ..
cd monitoring && docker compose up -d && cd ..
cd watchtower && docker compose up -d && cd ..
cd duplicati && docker compose up -d && cd ..
cd fail2ban && docker compose up -d && cd ..

# Or use Makefile
make infra-up
```

### 4. Verify

```bash
docker ps
docker network ls | grep automa
```

## Services

### Caddy (Reverse Proxy)
- **Port**: 80, 443
- **Web**: N/A (proxy only)
- **Config**: `caddy/Caddyfile`
- Auto HTTPS via Let's Encrypt

### Grafana (Monitoring Dashboard)
- **Port**: 3000 (internal)
- **Web**: https://grafana.example.com
- **User**: admin
- **Pass**: (from .env)

Import dashboards:
- 11074 - Node Exporter
- 193 - Docker
- 12486 - Loki Logs

### Prometheus (Metrics)
- **Port**: 9090 (localhost only)
- **Web**: http://localhost:9090
- **Config**: `monitoring/prometheus.yml`

### Loki (Logs)
- **Port**: 3100 (internal)
- No direct web UI (use Grafana)

### Duplicati (Remote Backup)
- **Port**: 8200 (localhost only)
- **Web**: http://localhost:8200
- Setup backup jobs via web UI

### Watchtower (Auto Update)
- No ports exposed
- Runs daily at midnight
- Only updates containers with label:
```yaml
labels:
- "com.centurylinklabs.watchtower.enable=true"
```

### Fail2ban (Security)
- No ports exposed
- Monitors logs and bans IPs
- Config: `fail2ban/data/jail.d/`

## Network Architecture

```
Internet
Caddy (80/443)
├─→ automa-proxy ─→ Nextcloud, Grafana
└─→ automa-monitoring ─→ Prometheus, Loki, etc.
```

## Updating Services

### Manual Update
```bash
cd monitoring
docker compose pull
docker compose up -d
```

### Auto Update (via Watchtower)
- Runs daily automatically
- Only updates labeled containers
- To disable for a service, set label to `false`

## Troubleshooting

### Check logs
```bash
docker logs automa-caddy
docker logs automa-prometheus
```

### Restart service
```bash
cd monitoring
docker compose restart grafana
```

### Reset service
```bash
cd monitoring
docker compose down
docker compose up -d
```

### Test Caddy config
```bash
docker exec -it automa-caddy caddy validate --config /etc/caddy/Caddyfile
```

## Resource Usage

Typical usage per service:

| Service | CPU | RAM | Disk |
|---------|-----|-----|------|
| Caddy | 0.1 | 50M | 50M |
| Prometheus | 0.5 | 500M | 10G |
| Grafana | 0.1 | 200M | 500M |
| Loki | 0.2 | 300M | 5G |
| Promtail | 0.02 | 50M | 10M |
| cAdvisor | 0.1 | 100M | 10M |
| Watchtower | 0.01 | 30M | 10M |
| Duplicati | 0.05 | 100M | 100M |
| Fail2ban | 0.02 | 50M | 100M |
| **Total** | **~1.2** | **~1.4G** | **~16G** |

## Security Notes

- Grafana and Duplicati only accessible via localhost
- Add firewall rules to restrict access
- Change default passwords
- Enable 2FA where supported
- Review logs regularly
39 changes: 39 additions & 0 deletions infrastructure/caddy/Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Global options
{
# ACME email for Let's Encrypt
email admin@{$DOMAIN}

# Disable admin API in production
admin off
}

# Nextcloud
cloud.{$DOMAIN} {
reverse_proxy nextcloud:80 {
header_up X-Forwarded-Proto {scheme}
header_up X-Real-IP {remote_host}
}

encode gzip

# Security headers
header Strict-Transport-Security "max-age=31536000;"
header X-Content-Type-Options "nosniff"
header X-Frame-Options "SAMEORIGIN"
}

# Grafana (monitoring dashboard)
grafana.{$DOMAIN} {
reverse_proxy grafana:3000
encode gzip
}

# Health check endpoint (no SSL)
http://health.{$DOMAIN} {
respond "OK" 200
}

# Default catch-all
{$DOMAIN} {
respond "Automa Services" 404
}
42 changes: 42 additions & 0 deletions infrastructure/caddy/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
services:
caddy:
image: caddy:2-alpine
container_name: automa-caddy
restart: unless-stopped

ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3

volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config

environment:
- DOMAIN=${DOMAIN:-example.com}

networks:
- automa-proxy

labels:
- "com.automa.service=caddy"
- "com.centurylinklabs.watchtower.enable=true"

healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:2019/config/"]
interval: 30s
timeout: 10s
retries: 3

volumes:
caddy_data:
name: automa_caddy_data
caddy_config:
name: automa_caddy_config

networks:
automa-proxy:
name: automa-proxy
external: true
33 changes: 33 additions & 0 deletions infrastructure/duplicati/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
services:
duplicati:
image: lscr.io/linuxserver/duplicati:latest
container_name: automa-duplicati
restart: unless-stopped

environment:
- PUID=1000
- PGID=1000
- TZ=${TZ:-Asia/Shanghai}

volumes:
- duplicati_config:/config
- ../../backups:/source:ro # Read-only access to local backups

ports:
- "127.0.0.1:8200:8200" # Only accessible locally

labels:
- "com.automa.service=duplicati"
- "com.centurylinklabs.watchtower.enable=true"

volumes:
duplicati_config:
name: automa_duplicati_config

# Setup:
# 1. Open http://localhost:8200
# 2. Add backup job
# 3. Source: /source (local backups)
# 4. Destination: S3/SFTP/WebDAV/etc
# 5. Schedule: Daily at 3 AM
# 6. Retention: Keep 30 days
26 changes: 26 additions & 0 deletions infrastructure/fail2ban/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
services:
fail2ban:
image: crazymax/fail2ban:latest
container_name: automa-fail2ban
restart: unless-stopped

network_mode: host

cap_add:
- NET_ADMIN
- NET_RAW

environment:
- TZ=${TZ:-Asia/Shanghai}
- F2B_LOG_LEVEL=INFO

volumes:
- fail2ban_data:/data
- /var/log:/var/log:ro

labels:
- "com.automa.service=fail2ban"

volumes:
fail2ban_data:
name: automa_fail2ban_data
Loading