No description
Find a file
Pieter 9dda882f63 chore: Remove internal documentation from repository
Removed internal deployment logs, security notes, test reports, and docs
folder from git tracking. These files remain locally but are now ignored
by git as they contain internal/sensitive information not needed by
external contributors.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 20:12:40 +01:00
.claude/agents feat: Implement per-client SSH key isolation 2026-01-17 19:50:30 +01:00
ansible feat: Add DNS configuration and Docker improvements 2026-01-20 19:06:32 +01:00
clients feat: Implement client registry system (issue #12) 2026-01-17 20:24:53 +01:00
keys feat: Move Hetzner API token to SOPS encrypted secrets 2026-01-18 18:17:15 +01:00
scripts feat: Add DNS configuration and Docker improvements 2026-01-20 19:06:32 +01:00
secrets feat: Move Hetzner API token to SOPS encrypted secrets 2026-01-18 18:17:15 +01:00
tofu feat: Add private network architecture with NAT gateway 2026-01-20 19:06:19 +01:00
.gitignore chore: Ignore documentation and report markdown files 2026-01-20 20:10:37 +01:00
.sops.yaml Complete SOPS secrets management setup (#5) 2025-12-27 14:23:36 +01:00
README.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