17 KiB
17 KiB
Network Architecture
Visual overview of how all services connect and communicate.
🌐 Network Flow Diagram
INTERNET
│
│ DNS A Records
│ (cloud.yourdomain.com → SERVER_IP)
↓
┌───────────────┐
│ Firewall (UFW)│
│ Ports: 80 │
│ 443 │
│ 41641 │
└───────┬───────┘
│
┌────────────────┼────────────────┐
│ │ │
Port 80/443 Port 41641 Port 22
│ │ │
↓ ↓ ↓
┌──────────────┐ ┌─────────────┐ ┌──────────┐
│ CADDY │ │ TAILSCALE │ │ SSH │
│ Reverse Proxy│ │ VPN │ │ Access │
└──────┬───────┘ └─────┬───────┘ └──────────┘
│ │
│ │
┌──────────┴────────┐ │
│ │ │
↓ ↓ ↓
┌─────────┐ ┌─────────────────┐
│ PUBLIC │ │ TAILSCALE-ONLY │
│SERVICES │ │ SERVICES │
└─────────┘ └─────────────────┘
🔐 Access Matrix
| Service | Public URL | Tailscale URL | Direct Access |
|---|---|---|---|
| Nextcloud | ✅ https://cloud.domain.com | ✅ Via Tailscale IP | ❌ No |
| OnlyOffice | ✅ https://office.domain.com | ✅ Via Tailscale IP | ❌ No |
| Excalidraw | ✅ https://draw.domain.com | ✅ Via Tailscale IP | ❌ No |
| Obsidian | ✅ https://notes.domain.com | ✅ Via Tailscale IP | ❌ No |
| Homarr | ❌ 403 Forbidden | ✅ https://home.domain.com | ❌ No |
| Dockhand | ❌ 403 Forbidden | ✅ https://manage.domain.com | ❌ No |
| Uptime Kuma | ❌ 403 Forbidden | ✅ https://uptime.domain.com | ❌ No |
| PostgreSQL | ❌ No | ❌ No | ✅ Docker network only |
| Redis | ❌ No | ❌ No | ✅ Docker network only |
| Caddy | ❌ No (serves others) | ❌ No | ✅ Docker network only |
| Watchtower | ❌ No | ❌ No | ✅ Docker network only |
🐳 Docker Network Topology
┌────────────────────────────────────────────────────────────────┐
│ nextcloud_network (bridge) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │PostgreSQL│ │ Redis │ │Nextcloud │ │OnlyOffice│ │
│ │ :5432 │ │ :6379 │ │ :80 │ │ :80 │ │
│ └──────────┘ └──────────┘ └────┬─────┘ └──────────┘ │
│ ↑ ↑ │ │
│ │ │ │ │
│ └──────────────┴─────────────┘ │
│ │ │
│ ┌──────────┐ ┌────┴─────┐ ┌──────────┐ ┌──────────┐ │
│ │Excalidraw│ │ Caddy │ │ Obsidian │ │ Homarr │ │
│ │ :80 │ │80→:80 │ │ :3000 │ │ :7575 │ │
│ └──────────┘ │443→:443 │ └──────────┘ └────┬─────┘ │
│ │ │ │ │
│ ┌──────────┐ │ │ ┌──────────┐ ↓ │
│ │ Dockhand │ │ │ │ Uptime │ /var/run/ │
│ │ :3000 │ │ │ │ Kuma │ docker.sock │
│ └──────────┘ └──────────┘ │ :3001 │ (read-only) │
│ └──────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Watchtower (monitors all) │ │
│ │ Accesses: /var/run/docker.sock │ │
│ └──────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
│ │
│ Exposed Ports │ Internal
│ │ Communication
↓ ↓
Host: 80, 443 Container-to-Container
(Caddy only) via Docker DNS
🔄 Request Flow Examples
Example 1: User Accesses Nextcloud
User Browser
│
│ HTTPS GET https://cloud.yourdomain.com
↓
Internet
│
↓
Firewall (Port 443)
│
↓
Caddy Container (:443)
│
│ Validates SSL certificate
│ Checks Caddyfile rules
│ Proxies to backend
↓
Nextcloud Container (:80)
│
│ Checks trusted domains
│ Queries PostgreSQL
│ Checks Redis cache
↓
PostgreSQL + Redis
│
│ Returns data
↓
Nextcloud → Caddy → User
Example 2: User Accesses Homarr (via Tailscale)
User Browser (on Tailscale)
│
│ HTTPS GET https://home.yourdomain.com
↓
Internet → DNS Resolution
│
↓
Firewall (Port 443)
│
↓
Caddy Container
│
│ Checks client IP: 100.64.x.x (Tailscale range)
│ ✅ Match! Proxy to backend
│
↓
Homarr Container (:7575)
│
│ Reads Docker socket
│ Shows container status
↓
Returns dashboard → Caddy → User
Example 3: User Accesses Homarr (NOT on Tailscale)
User Browser (public internet)
│
│ HTTPS GET https://home.yourdomain.com
↓
Internet → DNS Resolution
│
↓
Firewall (Port 443)
│
↓
Caddy Container
│
│ Checks client IP: NOT in 100.64.0.0/10
│ ❌ No match! Return 403 Forbidden
│
↓
403 Access Denied
Example 4: Nextcloud Connects to Database
Nextcloud Container
│
│ Docker DNS lookup: next-db
│ Resolves to: 172.20.0.x
↓
PostgreSQL Container (next-db:5432)
│
│ Internal Docker network
│ No external exposure
│
↓
Returns query results
📊 Data Flow Diagram
File Upload to Nextcloud
User → Caddy → Nextcloud → Storage Volume
│
├→ PostgreSQL (metadata)
└→ Redis (cache)
Document Editing with OnlyOffice
User → Caddy → Nextcloud → Caddy → OnlyOffice
│ │
↓ ↓
PostgreSQL Document
(metadata) Processing
│ │
↓ ↓
Nextcloud ←───────── OnlyOffice
│
↓
Storage Volume
Watchtower Auto-Update
Watchtower (cron: every 24h)
│
│ Check Docker Hub for new images
↓
New image available?
│
├─ NO → Sleep
│
├─ YES → Check container labels
│
├─ "enable=false" → Skip
├─ "enable=true" → Pull & Update
└─ "monitor-only=true" → Notify
🔐 Security Boundaries
┌─────────────────────────────────────────────────────────────┐
│ INTERNET (Untrusted) │
└────────────────────────┬────────────────────────────────────┘
│
┌────────▼────────┐
│ UFW Firewall │ ← Layer 1: Host Firewall
│ 22, 80, 443 │
└────────┬────────┘
│
┌────────▼────────┐
│ fail2ban │ ← Layer 2: Intrusion Detection
│ SSH Protection │
└────────┬────────┘
│
┌────────▼────────┐
│ Caddy (HTTPS) │ ← Layer 3: TLS Termination
│ SSL Validation │
└────────┬────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌───▼────┐ ┌────▼────┐ ┌─────▼─────┐
│ Public │ │Tailscale│ │ Docker │ ← Layer 4: Network
│Services│ │ Check │ │ Network │ Isolation
└────────┘ └─────────┘ └───────────┘
│
┌────▼────┐
│ Admin │ ← Layer 5: Admin Access
│ Services│ (Tailscale VPN only)
└─────────┘
🗄️ Data Persistence
Docker Volumes
Host Filesystem
│
├── /var/lib/docker/volumes/
│ ├── nextcloud_pg_data/ ← PostgreSQL database
│ ├── nextcloud_redis_data/ ← Redis cache
│ ├── nextcloud_nextcloud_data/ ← Nextcloud files
│ ├── nextcloud_nextcloud_apps/ ← Nextcloud apps
│ ├── nextcloud_onlyoffice_data/ ← OnlyOffice docs
│ ├── nextcloud_caddy_data/ ← SSL certificates
│ ├── nextcloud_caddy_config/ ← Caddy config
│ ├── nextcloud_dockhand_data/ ← Dockhand settings
│ └── nextcloud_uptime_kuma_data/ ← Uptime Kuma data
│
└── /opt/nextcloud-stack/
├── configs/
│ ├── caddy/Caddyfile
│ └── nextcloud/
├── data/
│ ├── homarr/
│ └── obsidian/
└── backups/
├── database/
└── volumes/
🔄 Update Mechanism
Watchtower Label-Based Control
# Auto-update allowed
labels:
- "com.centurylinklabs.watchtower.enable=true"
→ Caddy, Excalidraw, Obsidian, Homarr, Dockhand, Uptime Kuma
# Monitor only (notify, no update)
labels:
- "com.centurylinklabs.watchtower.monitor-only=true"
→ OnlyOffice
# Never auto-update (manual only)
labels:
- "com.centurylinklabs.watchtower.enable=false"
→ Nextcloud, PostgreSQL, Redis
📡 Monitoring Architecture
┌────────────────────────────────────────────────────────┐
│ Uptime Kuma │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ HTTP Monitors (every 60s) │ │
│ │ • https://cloud.yourdomain.com/status.php │ │
│ │ • https://office.yourdomain.com/health │ │
│ │ • https://draw.yourdomain.com │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ TCP Port Monitors │ │
│ │ • next-db:5432 (PostgreSQL) │ │
│ │ • next-redis:6379 (Redis) │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ SSL Certificate Monitor │ │
│ │ • Expiry check (30-day warning) │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Notifications │ │
│ │ • Email alerts │ │
│ │ • Slack/Discord webhooks (optional) │ │
│ └──────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘
🎯 Service Dependencies
Nextcloud
│
├─ requires → PostgreSQL (healthy)
├─ requires → Redis (healthy)
└─ requires → Caddy (for external access)
OnlyOffice
│
└─ requires → Caddy (for external access)
Homarr, Dockhand
│
├─ requires → Docker Socket (read-only)
└─ requires → Caddy (for Tailscale access)
Watchtower
│
└─ requires → Docker Socket (read-write)
All Services
│
└─ network → nextcloud_network
🌟 Architecture Benefits
High Availability Features
- Health checks: Containers auto-restart on failure
- Database connection pooling: Redis caching reduces DB load
- SSL auto-renewal: Caddy handles certificate lifecycle
Security Layers
- Network: UFW firewall + fail2ban
- Transport: TLS/SSL via Caddy
- Access: Tailscale VPN for admin interfaces
- Secrets: Ansible Vault encryption
- Isolation: Docker network segmentation
Scalability Points
- Database: Can migrate to external PostgreSQL
- Cache: Redis can be scaled/clustered
- Storage: Volumes can be moved to network storage
- Reverse Proxy: Caddy can be load-balanced
This architecture provides a secure, maintainable, and production-ready self-hosted cloud platform.