Commit graph

4 commits

Author SHA1 Message Date
Pieter
79635eeece feat: Add private network architecture with NAT gateway
Enable deployment of client servers without public IPs using private
network (10.0.0.0/16) with NAT gateway via edge server.

## Infrastructure Changes:

### Terraform (tofu/):
- **network.tf**: Define private network and subnet (10.0.0.0/24)
  - NAT gateway route through edge server
  - Firewall rules for client servers

- **main.tf**: Support private-only servers
  - Optional public_ip_enabled flag per client
  - Dynamic network block for private IP assignment
  - User-data templates for public vs private servers

- **user-data-*.yml**: Cloud-init templates
  - Private servers: Configure default route via NAT gateway
  - Public servers: Standard configuration

- **dns.tf**: Update DNS to support edge routing
  - Client domains point to edge server IP
  - Wildcard DNS for subdomains

- **variables.tf**: Add private_ip and public_ip_enabled options

### Ansible:
- **deploy.yml**: Add diun and kuma roles to deployment

## Benefits:
- Cost savings: No public IP needed for each client
- Scalability: No public IP exhaustion limits
- Security: Clients not directly exposed to internet
- Centralized SSL: All TLS termination at edge

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-20 19:06:19 +01:00
Pieter
9eb6f2028a feat: Use Hetzner Volumes for Nextcloud data storage (issue #18)
Implement persistent block storage for Nextcloud user data, separating application and data layers:

OpenTofu Changes:
- tofu/volumes.tf: Create and attach Hetzner Volumes per client
  - Configurable size per client (default 100 GB for dev)
  - ext4 formatted, attached but not auto-mounted
- tofu/variables.tf: Add nextcloud_volume_size to client config
- tofu/terraform.tfvars: Set volume size for dev client (100 GB ~€5.40/mo)

Ansible Changes:
- ansible/roles/nextcloud/tasks/mount-volume.yml: New mount tasks
  - Detect volume device automatically
  - Format if needed, mount at /mnt/nextcloud-data
  - Add to fstab for persistence
  - Set correct permissions for www-data
- ansible/roles/nextcloud/tasks/main.yml: Include volume mounting
- ansible/roles/nextcloud/templates/docker-compose.nextcloud.yml.j2:
  - Use host mount /mnt/nextcloud-data/data instead of Docker volume
  - Keep app code in Docker volume (nextcloud-app)
  - User data now on Hetzner Volume

Scripts:
- scripts/resize-client-volume.sh: Online volume resizing
  - Resize via Hetzner API
  - Expand filesystem automatically
  - Show cost impact
  - Verify new size

Documentation:
- docs/storage-architecture.md: Complete storage guide
  - Architecture diagrams
  - Volume specifications
  - Sizing guidelines
  - Operations procedures
  - Performance considerations
  - Troubleshooting guide

- docs/volume-migration.md: Step-by-step migration
  - Safe migration from Docker volumes
  - Rollback procedures
  - Verification checklist
  - Timeline estimates

Benefits:
 Data independent from server instance
 Resize storage without rebuilding server
 Easy data migration between servers
 Better separation of concerns (app vs data)
 Simplified backup strategy
 Cost-optimized (pay for what you use)

Volume Pricing:
- 50 GB: ~€2.70/month
- 100 GB: ~€5.40/month
- 250 GB: ~€13.50/month
- Resizable online, no downtime

Note: Existing clients require manual migration
Follow docs/volume-migration.md for safe migration procedure

Closes #18

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-17 21:07:48 +01:00
Pieter
071ed083f7 feat: Implement per-client SSH key isolation
Resolves #14

Each client now gets a dedicated SSH key pair, ensuring that compromise
of one client server does not grant access to other client servers.

## Changes

### Infrastructure (OpenTofu)
- Replace shared `hcloud_ssh_key.default` with per-client `hcloud_ssh_key.client`
- Each client key read from `keys/ssh/<client_name>.pub`
- Server recreated with new key (dev server only, acceptable downtime)

### Key Management
- Created `keys/ssh/` directory for SSH keys
- Added `.gitignore` to protect private keys from git
- Generated ED25519 key pair for dev client
- Private key gitignored, public key committed

### Scripts
- **`scripts/generate-client-keys.sh`** - Generate SSH key pairs for clients
- Updated `scripts/deploy-client.sh` to check for client SSH key

### Documentation
- **`docs/ssh-key-management.md`** - Complete SSH key management guide
- **`keys/ssh/README.md`** - Quick reference for SSH keys directory

### Configuration
- Removed `ssh_public_key` variable from `variables.tf`
- Updated `terraform.tfvars` to remove shared SSH key reference
- Updated `terraform.tfvars.example` with new key generation instructions

## Security Improvements

 Client isolation: Each client has dedicated SSH key
 Granular rotation: Rotate keys per-client without affecting others
 Defense in depth: Minimize blast radius of key compromise
 Proper key storage: Private keys gitignored, backups documented

## Testing

-  Generated new SSH key for dev client
-  Applied OpenTofu changes (server recreated)
-  Tested SSH access: `ssh -i keys/ssh/dev root@78.47.191.38`
-  Verified key isolation: Old shared key removed from Hetzner

## Migration Notes

For existing clients:
1. Generate key: `./scripts/generate-client-keys.sh <client>`
2. Apply OpenTofu: `cd tofu && tofu apply` (will recreate server)
3. Deploy: `./scripts/deploy-client.sh <client>`

For new clients:
1. Generate key first
2. Deploy as normal

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-17 19:50:30 +01:00
Pieter
0135bd360a Implement OpenTofu infrastructure provisioning (#1)
Completed:
-  Hetzner Cloud provider configuration
-  VPS server provisioning with for_each pattern
-  Cloud firewall rules (SSH, HTTP, HTTPS)
-  SSH key management
-  Outputs for Ansible dynamic inventory
-  Variable structure and documentation
-  Test server successfully provisioned

Deferred:
- DNS configuration (commented out, waiting for domain)

Files added:
- tofu/versions.tf - Provider versions
- tofu/variables.tf - Input variable definitions
- tofu/main.tf - Core infrastructure resources
- tofu/dns.tf - DNS configuration (optional)
- tofu/outputs.tf - Outputs for Ansible integration
- tofu/terraform.tfvars.example - Configuration template
- tofu/README.md - Comprehensive setup guide

Closes #1

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-27 13:48:42 +01:00