No description
Find a file
Pieter 797d5b4e36 fix: Clear Nextcloud log after initial maintenance repairs
During initial deployment, background jobs may fail temporarily
while the system is still initializing (e.g., theming migration
looking for directories that don't exist yet).

These errors are harmless and resolve on subsequent cron runs,
but they appear in the admin panel logs causing unnecessary
concern.

Solution: Clear the log file after running maintenance repairs
to remove any transient initialization errors.

Fixes admin panel showing "2 errors in the logs" after fresh
deployment.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-08 17:45:59 +01:00
.claude/agents feat: Complete Authentik SSO integration with automated OIDC setup 2026-01-08 16:56:19 +01:00
ansible fix: Clear Nextcloud log after initial maintenance repairs 2026-01-08 17:45:59 +01:00
docs feat: Complete Authentik SSO integration with automated OIDC setup 2026-01-08 16:56:19 +01:00
keys Complete SOPS secrets management setup (#5) 2025-12-27 14:23:36 +01:00
scripts feat: Complete Authentik SSO integration with automated OIDC setup 2026-01-08 16:56:19 +01:00
secrets chore: Add gitignore for secrets/clients to prevent plaintext files 2026-01-08 17:01:15 +01:00
tofu Deploy Zitadel identity provider with DNS automation (#3) (#8) 2026-01-05 16:40:37 +01:00
.gitignore Complete SOPS secrets management setup (#5) 2025-12-27 14:23:36 +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: Complete Authentik SSO integration with automated OIDC setup 2026-01-08 16:56:19 +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. Set environment variables
export HCLOUD_TOKEN="your-hetzner-api-token"
export SOPS_AGE_KEY_FILE="./keys/age-key.txt"

# 2. Deploy client (fully automated, ~10-15 minutes)
./scripts/deploy-client.sh <client_name>

This automatically:

  • Provisions VPS on Hetzner Cloud
  • Deploys Authentik (SSO/identity provider)
  • Deploys Nextcloud (file storage)
  • Configures OAuth2/OIDC integration
  • Sets up SSL certificates
  • Creates 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