2026-01-27 09:04:10 +01:00
# De Vrije Cloud: Post-Tyranny Tech Multi-Tenant Infrastructure
2025-12-24 12:12:17 +01:00
2026-01-27 09:04:10 +01:00
Infrastructure as Code for our "[Vrije Cloud ](https://www.vrije.cloud )" a scalable multi-tenant VPS platform running Nextcloud (file sync/share) on Hetzner Cloud.
2025-12-24 12:12:17 +01:00
## 🏗️ Architecture
- **Provisioning**: OpenTofu (open source Terraform fork)
- **Configuration**: Ansible with dynamic inventory
- **Secrets**: SOPS + Age encryption
- **Hosting**: Hetzner Cloud (EU-based, GDPR-compliant)
2026-01-08 16:56:19 +01:00
- **Identity**: Authentik (OAuth2/OIDC SSO, MIT license)
2025-12-24 12:12:17 +01:00
- **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
- [OpenTofu ](https://opentofu.org/ ) >= 1.6
- [Ansible ](https://docs.ansible.com/ ) >= 2.15
- [SOPS ](https://github.com/getsops/sops ) + [Age ](https://github.com/FiloSottile/age )
- [Hetzner Cloud account ](https://www.hetzner.com/cloud )
2026-01-08 16:56:19 +01:00
### Automated Deployment (Recommended)
**The fastest way to deploy a client:**
```bash
2026-01-18 18:17:15 +01:00
# 1. Ensure SOPS Age key is available (if not set)
2026-01-08 16:56:19 +01:00
export SOPS_AGE_KEY_FILE="./keys/age-key.txt"
2026-01-17 20:04:29 +01:00
# 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)
2026-01-18 18:17:15 +01:00
# The script automatically loads the Hetzner API token from SOPS
2026-01-17 20:04:29 +01:00
./scripts/deploy-client.sh newclient
2026-01-08 16:56:19 +01:00
```
2026-01-18 18:17:15 +01:00
**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` .
2026-01-17 20:04:29 +01:00
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
2026-01-08 16:56:19 +01:00
**Result**: Fully functional system, ready to use immediately!
### Management Scripts
```bash
# 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 ](scripts/README.md ) for detailed documentation.
### Manual Setup (Advanced)
< details >
< summary > Click to expand manual setup instructions< / summary >
2025-12-24 12:12:17 +01:00
1. **Clone repository** :
```bash
git clone < repo-url >
cd infrastructure
```
2. **Generate Age encryption key** :
```bash
age-keygen -o keys/age-key.txt
# Store securely in password manager!
```
3. **Configure OpenTofu variables** :
```bash
cp tofu/terraform.tfvars.example tofu/terraform.tfvars
# Edit with your Hetzner API token and configuration
```
2026-01-08 16:56:19 +01:00
4. **Create client secrets** :
```bash
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** :
2025-12-24 12:12:17 +01:00
```bash
cd tofu
tofu init
tofu apply
```
2026-01-08 16:56:19 +01:00
6. **Deploy applications** :
2025-12-24 12:12:17 +01:00
```bash
cd ../ansible
2026-01-08 16:56:19 +01:00
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 >
2025-12-24 12:12:17 +01:00
```
2026-01-08 16:56:19 +01:00
< / details >
2025-12-24 12:12:17 +01:00
## 🎯 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
2026-01-27 08:46:45 +01:00
MIT License - see [LICENSE ](LICENSE ) for details
2025-12-24 12:12:17 +01:00
## 🙋 Support
2026-01-27 09:04:10 +01:00
For issues or questions, please create am issue or contact us on [vrijecloud@postxsociety.org ](mailto:vrijecloud@postxsociety.org )