No description
Find a file
Pieter 13685eb454 feat: Add infrastructure roles for multi-tenant architecture
Add new Ansible roles and configuration for the edge proxy and
private network architecture:

## New Roles:
- **edge-traefik**: Edge reverse proxy that routes to private clients
  - Dynamic routing configuration for multiple clients
  - SSL termination at the edge
  - Routes traffic to private IPs (10.0.0.x)

- **nat-gateway**: NAT/gateway configuration for edge server
  - IP forwarding and masquerading
  - Allows private network clients to access internet
  - iptables rules for Docker integration

- **diun**: Docker Image Update Notifier
  - Monitors containers for available updates
  - Email notifications via Mailgun
  - Per-client configuration

- **kuma**: Uptime monitoring integration
  - Registers HTTP monitors for client services
  - Automated monitor creation via API
  - Checks Authentik, Nextcloud, Collabora endpoints

## New Playbooks:
- **setup-edge.yml**: Configure edge server with proxy and NAT

## Configuration:
- **host_vars**: Per-client Ansible configuration (valk, white)
  - SSH bastion configuration for private IPs
  - Client-specific secrets file references

This enables the scalable multi-tenant architecture where:
- Edge server has public IP and routes traffic
- Client servers use private IPs only (cost savings)
- All traffic flows through edge proxy with SSL termination

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 19:05:51 +01:00
.claude/agents feat: Implement per-client SSH key isolation 2026-01-17 19:50:30 +01:00
ansible feat: Add infrastructure roles for multi-tenant architecture 2026-01-20 19:05:51 +01:00
clients feat: Implement client registry system (issue #12) 2026-01-17 20:24:53 +01:00
docs fix: Remove SMTP password from documentation 2026-01-18 19:05:22 +01:00
keys feat: Move Hetzner API token to SOPS encrypted secrets 2026-01-18 18:17:15 +01:00
scripts feat: Configure status.vrije.cloud and auto-monitor integration 2026-01-18 18:55:33 +01:00
secrets feat: Move Hetzner API token to SOPS encrypted secrets 2026-01-18 18:17:15 +01:00
tofu feat: Configure status.vrije.cloud and auto-monitor integration 2026-01-18 18:55:33 +01:00
.gitignore 🚀 GREEN CLIENT DEPLOYMENT + CRITICAL SECURITY FIXES 2026-01-18 17:06:04 +01:00
.sops.yaml Complete SOPS secrets management setup (#5) 2025-12-27 14:23:36 +01:00
PROJECT_REFERENCE.md feat: Complete Authentik SSO integration with automated OIDC setup 2026-01-08 16:56:19 +01:00
README.md feat: Move Hetzner API token to SOPS encrypted secrets 2026-01-18 18:17:15 +01:00
SECURITY-NOTE-tokens.md feat: Move Hetzner API token to SOPS encrypted secrets 2026-01-18 18:17:15 +01:00
TEST-REPORT-blue-client.md feat: Move Hetzner API token to SOPS encrypted secrets 2026-01-18 18:17:15 +01:00

Post-X Society Multi-Tenant Infrastructure

Infrastructure as Code for a scalable multi-tenant VPS platform running Nextcloud (file sync/share) on Hetzner Cloud.

🏗️ Architecture

  • Provisioning: OpenTofu (open source Terraform fork)
  • Configuration: Ansible with dynamic inventory
  • Secrets: SOPS + Age encryption
  • Hosting: Hetzner Cloud (EU-based, GDPR-compliant)
  • Identity: Authentik (OAuth2/OIDC SSO, MIT license)
  • Storage: Nextcloud (German company, AGPL 3.0)

📁 Repository Structure

infrastructure/
├── .claude/agents/          # AI agent definitions for specialized tasks
├── docs/                    # Architecture decisions and runbooks
├── tofu/                    # OpenTofu configurations for Hetzner
├── ansible/                 # Ansible playbooks and roles
├── secrets/                 # SOPS-encrypted secrets (git-safe)
├── docker/                  # Docker Compose configurations
└── scripts/                 # Deployment and management scripts

🚀 Quick Start

Prerequisites

The fastest way to deploy a client:

# 1. Ensure SOPS Age key is available (if not set)
export SOPS_AGE_KEY_FILE="./keys/age-key.txt"

# 2. Add client to terraform.tfvars
# clients = {
#   newclient = {
#     server_type = "cx22"
#     location    = "fsn1"
#     subdomain   = "newclient"
#     apps        = ["authentik", "nextcloud"]
#   }
# }

# 3. Deploy client (fully automated, ~10-15 minutes)
# The script automatically loads the Hetzner API token from SOPS
./scripts/deploy-client.sh newclient

Note: The Hetzner API token is now stored encrypted in secrets/shared.sops.yaml and loaded automatically by all scripts. No need to manually set HCLOUD_TOKEN.

The script will automatically:

  • Generate unique SSH key pair (if missing)
  • Create secrets file from template (if missing, opens in editor)
  • Provision VPS on Hetzner Cloud
  • Deploy Authentik (SSO/identity provider)
  • Deploy Nextcloud (file storage)
  • Configure OAuth2/OIDC integration
  • Set up SSL certificates
  • Create admin accounts

Result: Fully functional system, ready to use immediately!

Management Scripts

# Deploy a fresh client
./scripts/deploy-client.sh <client_name>

# Rebuild existing client (destroy + redeploy)
./scripts/rebuild-client.sh <client_name>

# Destroy client infrastructure
./scripts/destroy-client.sh <client_name>

See scripts/README.md for detailed documentation.

Manual Setup (Advanced)

Click to expand manual setup instructions
  1. Clone repository:

    git clone <repo-url>
    cd infrastructure
    
  2. Generate Age encryption key:

    age-keygen -o keys/age-key.txt
    # Store securely in password manager!
    
  3. Configure OpenTofu variables:

    cp tofu/terraform.tfvars.example tofu/terraform.tfvars
    # Edit with your Hetzner API token and configuration
    
  4. Create client secrets:

    cp secrets/clients/test.sops.yaml secrets/clients/<client>.sops.yaml
    sops secrets/clients/<client>.sops.yaml
    # Update client_name, domains, regenerate all passwords
    
  5. Provision infrastructure:

    cd tofu
    tofu init
    tofu apply
    
  6. Deploy applications:

    cd ../ansible
    export HCLOUD_TOKEN="your-token"
    export SOPS_AGE_KEY_FILE="../keys/age-key.txt"
    
    ansible-playbook -i hcloud.yml playbooks/setup.yml --limit <client>
    ansible-playbook -i hcloud.yml playbooks/deploy.yml --limit <client>
    

🎯 Project Principles

  1. EU/GDPR-first: European vendors and data residency
  2. Truly open source: Avoid source-available or restrictive licenses
  3. Client isolation: Full separation between tenants
  4. Infrastructure as Code: All changes via version control
  5. Security by default: Encryption, hardening, least privilege

📖 Documentation

🤝 Contributing

This project uses specialized AI agents for development:

  • Architect: High-level design decisions
  • Infrastructure: OpenTofu + Ansible implementation
  • Authentik: Identity provider and SSO configuration
  • Nextcloud: File sync/share configuration

See individual agent files in .claude/agents/ for responsibilities.

🔒 Security

  • Secrets are encrypted with SOPS + Age before committing
  • Age private keys are NEVER stored in this repository
  • See .gitignore for protected files

📝 License

TBD

🙋 Support

For issues or questions, please create a GitHub issue with the appropriate label:

  • agent:architect - Architecture/design questions
  • agent:infrastructure - IaC implementation
  • agent:authentik - Identity provider/SSO
  • agent:nextcloud - File sync/share