No description
Find a file
Pieter 9b631232a8 Update README with user adjustments
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-27 09:04:10 +01:00
.claude/agents feat: Implement per-client SSH key isolation 2026-01-17 19:50:30 +01:00
ansible feat: Add brand recovery flow config and improve security 2026-01-26 09:17:08 +01:00
clients docs: Remove Zitadel references and update documentation 2026-01-20 20:19:04 +01:00
keys feat: Add Nextcloud maintenance automation and cleanup 2026-01-24 12:44:54 +01:00
scripts feat: Configure Diun with Docker Hub auth and watchRepo control 2026-01-24 13:16:25 +01:00
secrets feat: Add brand recovery flow config and improve security 2026-01-26 09:17:08 +01:00
tofu feat: Add Nextcloud maintenance automation and cleanup 2026-01-24 12:44:54 +01:00
.gitignore feat: Add brand recovery flow config and improve security 2026-01-26 09:17:08 +01:00
.sops.yaml Complete SOPS secrets management setup (#5) 2025-12-27 14:23:36 +01:00
LICENSE Add MIT License to project 2026-01-27 08:46:45 +01:00
README.md Update README with user adjustments 2026-01-27 09:04:10 +01:00

De Vrije Cloud: Post-Tyranny Tech Multi-Tenant Infrastructure

Infrastructure as Code for our "Vrije Cloud" 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

📝 License

MIT License - see LICENSE for details

🙋 Support

For issues or questions, please create am issue or contact us on vrijecloud@postxsociety.org