Files
dotfiles_arch/ansible/ARCHITECTURE.md
2026-02-16 23:40:30 +01:00

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

  1. Network: UFW firewall + fail2ban
  2. Transport: TLS/SSL via Caddy
  3. Access: Tailscale VPN for admin interfaces
  4. Secrets: Ansible Vault encryption
  5. 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.