From ecbeb07ba2c5834e5f3c7413b4ed42eaa739f50f Mon Sep 17 00:00:00 2001 From: Joakim Date: Mon, 15 Dec 2025 16:33:33 +0100 Subject: [PATCH] Migrate sigvild-gallery to production environment - Add multi-environment architecture (homelab + production) - Create production environment (mini-vps) for client projects - Create homelab playbook for arch-vps services - Create production playbook for mini-vps services - Move sigvild-gallery from homelab to production - Restructure variables: group_vars/production + host_vars/arch-vps - Add backup-sigvild.yml playbook with auto-restore functionality - Fix restore logic to check for data before creating directories - Add manual variable loading workaround for Ansible 2.20 - Update all documentation for multi-environment setup - Add ADR-007 documenting multi-environment architecture decision --- README.md | 74 ++++++--- deploy-socket-updates.yml | 68 -------- docs/architecture-decisions.md | 117 +++++++++++++ docs/deployment-guide.md | 58 +++++-- docs/sigvild-gallery-deployment.md | 157 ++++++++++++------ group_vars/production/main.yml | 52 ++++++ host_vars/arch-vps/main.yml | 18 -- host_vars/mini-vps/main.yml | 0 inventory/hosts.yml | 20 ++- now-what.md | 25 +++ playbooks/backup-sigvild.yml | 24 +++ playbooks/homelab.yml | 64 +++++++ playbooks/production.yml | 29 ++++ roles/caddy/tasks/main.yml | 2 +- roles/sigvild-gallery/defaults/main.yml | 4 +- .../sigvild-gallery/tasks/deploy_backend.yml | 6 +- roles/sigvild-gallery/tasks/main.yml | 3 +- site.yml | 45 +++-- 18 files changed, 553 insertions(+), 213 deletions(-) delete mode 100644 deploy-socket-updates.yml create mode 100644 group_vars/production/main.yml create mode 100644 host_vars/mini-vps/main.yml create mode 100644 now-what.md create mode 100644 playbooks/backup-sigvild.yml create mode 100644 playbooks/homelab.yml create mode 100644 playbooks/production.yml diff --git a/README.md b/README.md index a6e8766..d44db3b 100644 --- a/README.md +++ b/README.md @@ -32,43 +32,64 @@ Rick-infra implements a security-first infrastructure stack featuring: └─────────────────────────────────────────────────────────────┘ ``` +## Infrastructure Environments + +Rick-infra manages **two separate environments**: + +### 🏠 Homelab (arch-vps) +Personal services and experimentation at **jnss.me**: +- PostgreSQL, Valkey, Podman infrastructure +- Authentik SSO (auth.jnss.me) +- Nextcloud (cloud.jnss.me) +- Gitea (git.jnss.me) + +### 🚀 Production (mini-vps) +Client projects requiring high uptime: +- Sigvild Gallery (sigvild.no, api.sigvild.no) +- Minimal infrastructure footprint + ## Quick Start ### Prerequisites - **VPS**: Fresh Arch Linux VPS with root access -- **DNS**: Domain pointed to VPS IP address +- **DNS**: Domains pointed to VPS IP addresses - **SSH**: Key-based authentication configured -### Deploy Complete Stack +### Deploy Infrastructure ```bash # 1. Clone repository git clone https://github.com/your-username/rick-infra.git cd rick-infra -# 2. Configure inventory -cp inventory/hosts.yml.example inventory/hosts.yml -# Edit inventory/hosts.yml with your VPS details +# 2. Configure inventory (already set up) +# inventory/hosts.yml defines homelab and production groups # 3. Set up vault variables -ansible-vault create host_vars/arch-vps/vault.yml -# Add required secrets (see deployment guide) +ansible-vault edit group_vars/production/vault.yml # Production secrets +ansible-vault edit host_vars/arch-vps/vault.yml # Homelab secrets -# 4. Deploy complete infrastructure -ansible-playbook -i inventory/hosts.yml site.yml --ask-vault-pass +# 4. Deploy to specific environment +ansible-playbook playbooks/homelab.yml # Deploy homelab +ansible-playbook playbooks/production.yml # Deploy production +ansible-playbook site.yml # Deploy both ``` -**Total deployment time**: 8-14 minutes for complete stack +**Deployment times**: +- Homelab (full stack): 8-14 minutes +- Production (minimal): 3-5 minutes ### Verify Deployment ```bash -# Check services +# Check homelab services curl -I https://auth.jnss.me/ # Authentik SSO -curl -I https://git.jnss.me/ # Gitea (if enabled) +curl -I https://cloud.jnss.me/ # Nextcloud +ansible homelab -a "systemctl status postgresql valkey caddy" -# Check infrastructure -ansible arch-vps -m command -a "systemctl status postgresql valkey caddy" +# Check production services +curl -I https://sigvild.no/ # Sigvild Gallery +ansible production -a "systemctl status sigvild-gallery caddy" ``` ## Key Features @@ -116,21 +137,32 @@ ansible arch-vps -m command -a "systemctl status postgresql valkey caddy" ## Core Services -### Infrastructure Services (Native systemd) +### Homelab Services (arch-vps) + +**Infrastructure (Native systemd)**: - **PostgreSQL** - High-performance database with Unix socket support - **Valkey** - Redis-compatible cache with Unix socket support - **Caddy** - Automatic HTTPS reverse proxy with Cloudflare DNS - **Podman** - Rootless container runtime with systemd integration -### Authentication Services +**Authentication**: - **Authentik** - Modern SSO server with OAuth2/OIDC/SAML support -- **Forward Auth** - Transparent service protection via Caddy integration -- **Multi-Factor Authentication** - TOTP, WebAuthn, SMS support +- **Forward Auth** - Transparent service protection via Caddy -### Application Services (Containerized) +**Applications (Containerized)**: +- **Nextcloud** - Personal cloud storage and file sync - **Gitea** - Self-hosted Git service with SSO integration -- **Gallery** - Media gallery with authentication -- **Custom Services** - Template for additional service integration + +### Production Services (mini-vps) + +**Infrastructure**: +- **Caddy** - Automatic HTTPS reverse proxy with Cloudflare DNS + +**Applications**: +- **Sigvild Gallery** - Wedding photo gallery with PocketBase API + - Frontend: SvelteKit static site + - Backend: Go + SQLite (PocketBase) + - Domains: sigvild.no, api.sigvild.no ## Architecture Benefits diff --git a/deploy-socket-updates.yml b/deploy-socket-updates.yml deleted file mode 100644 index bd84fe4..0000000 --- a/deploy-socket-updates.yml +++ /dev/null @@ -1,68 +0,0 @@ ---- -# Deploy Unix Socket Updates for PostgreSQL, Valkey, Authentik, and Gitea -# This playbook updates services to use Unix sockets for inter-process communication - -- name: Deploy Unix socket configuration updates - hosts: arch-vps - become: yes - - tasks: - - name: Display deployment plan - debug: - msg: | - 🔧 Unix Socket Migration Plan - ============================= - - 📦 Services to Update: - 1. PostgreSQL - Switch to socket-only (no TCP) - 2. Valkey - Add Unix socket support - 3. Authentik - Use sockets for DB/cache - 4. Gitea - Use sockets for DB/cache - - 🔒 Security Benefits: - - Zero network exposure for databases - - Better performance (25-30% faster) - - Simplified security model - - - name: Update PostgreSQL to socket-only - include_role: - name: postgresql - tags: [postgresql] - - - name: Update Valkey with Unix socket - include_role: - name: valkey - tags: [valkey] - - - name: Update Authentik for Unix sockets - include_role: - name: authentik - tags: [authentik] - - - name: Update Gitea for Unix sockets - include_role: - name: gitea - tags: [gitea] - - - name: Verify socket files exist - stat: - path: "{{ item }}" - loop: - - /run/postgresql/.s.PGSQL.5432 - - /run/valkey/valkey.sock - register: socket_checks - - - name: Display results - debug: - msg: | - ✅ Deployment Complete! - - Socket Status: - {% for check in socket_checks.results %} - - {{ check.item }}: {{ "EXISTS" if check.stat.exists else "MISSING" }} - {% endfor %} - - Next Steps: - 1. Check service logs: journalctl -u authentik-pod - 2. Test Authentik: curl http://arch-vps:9000/if/flow/initial-setup/ - 3. Test Gitea: curl http://arch-vps:3000/ \ No newline at end of file diff --git a/docs/architecture-decisions.md b/docs/architecture-decisions.md index 39591de..68e1ec5 100644 --- a/docs/architecture-decisions.md +++ b/docs/architecture-decisions.md @@ -1127,3 +1127,120 @@ curl -I http://127.0.0.1:9000/ 3. **Hardcoded GIDs** - Rejected for portability; facts provide dynamic resolution 4. **Directory permissions (777)** - Rejected for security; group-based access more restrictive. This is then later changed again to 777, due to Nextcloud switching from root to www-data, breaking group-based permissions. --- + +--- +## ADR-007: Multi-Environment Infrastructure Architecture + +**Date**: December 2025 +**Status**: Accepted +**Context**: Separation of homelab services from production client projects + +### Decision + +Rick-infra will manage two separate environments with different purposes and uptime requirements: + +1. **Homelab Environment** (arch-vps) + - Purpose: Personal services and experimentation + - Infrastructure: Full stack (PostgreSQL, Valkey, Podman, Caddy) + - Services: Authentik, Nextcloud, Gitea + - Uptime requirement: Best effort + +2. **Production Environment** (mini-vps) + - Purpose: Client projects requiring high uptime + - Infrastructure: Minimal (Caddy only) + - Services: Sigvild Gallery + - Uptime requirement: High availability + +### Rationale + +**Separation of Concerns**: +- Personal experiments don't affect client services +- Client services isolated from homelab maintenance +- Clear distinction between environments in code + +**Infrastructure Optimization**: +- Production runs minimal services (no PostgreSQL/Valkey overhead) +- Homelab can be rebooted/upgraded without affecting clients +- Cost optimization: smaller VPS for production + +**Operational Flexibility**: +- Different backup strategies per environment +- Different monitoring/alerting levels +- Independent deployment schedules + +### Implementation + +**Variable Organization**: +``` +rick-infra/ +├── group_vars/ +│ └── production/ # Production environment config +│ ├── main.yml +│ └── vault.yml +├── host_vars/ +│ └── arch-vps/ # Homelab host config +│ ├── main.yml +│ └── vault.yml +└── playbooks/ + ├── homelab.yml # Homelab deployment + ├── production.yml # Production deployment + └── site.yml # Orchestrates both +``` + +**Playbook Structure**: +- `site.yml` imports both homelab.yml and production.yml +- Each playbook manually loads variables (Ansible 2.20 workaround) +- Services deploy only to their designated environment + +**Inventory Groups**: +```yaml +homelab: + hosts: + arch-vps: + ansible_host: 69.62.119.31 + +production: + hosts: + mini-vps: + ansible_host: 72.62.91.251 +``` + +### Migration Example + +**Sigvild Gallery Migration** (December 2025): +- **From**: arch-vps (homelab) +- **To**: mini-vps (production) +- **Reason**: Client project requiring higher uptime +- **Process**: + 1. Created backup on arch-vps + 2. Deployed to mini-vps with automatic restore + 3. Updated DNS (5 min downtime) + 4. Removed from arch-vps configuration + +### Consequences + +**Positive**: +- Clear separation of personal vs. client services +- Reduced blast radius for experiments +- Optimized resource usage per environment +- Independent scaling and management + +**Negative**: +- Increased complexity in playbook organization +- Need to manage multiple VPS instances +- Ansible 2.20 variable loading requires workarounds +- Duplicate infrastructure code (Caddy on both) + +**Neutral**: +- Services can be migrated between environments with minimal friction +- Backup/restore procedures work across environments +- Group_vars vs. host_vars hybrid approach + +### Future Considerations + +- Consider grouping multiple client projects on production VPS +- Evaluate if homelab needs full infrastructure stack +- Monitor for opportunities to share infrastructure between environments +- Document migration procedures for moving services between environments + +--- diff --git a/docs/deployment-guide.md b/docs/deployment-guide.md index 43dc0a4..e02f24e 100644 --- a/docs/deployment-guide.md +++ b/docs/deployment-guide.md @@ -43,21 +43,45 @@ The rick-infra deployment system provides: └─────────────────────────────────────────────────────────────┘ ``` +## Infrastructure Overview + +Rick-infra now manages **two separate environments**: + +### Homelab (arch-vps) +Personal services and experimentation platform at **jnss.me**: +- PostgreSQL, Valkey, Podman infrastructure +- Caddy reverse proxy with auto-HTTPS +- Nextcloud (cloud.jnss.me) +- Authentik SSO (auth.jnss.me) +- Gitea (git.jnss.me) + +### Production (mini-vps) +Client projects requiring high uptime: +- Caddy reverse proxy with auto-HTTPS +- Sigvild Gallery (sigvild.no, api.sigvild.no) + ## Available Deployments -### 1. `site.yml` - Complete Infrastructure Stack -Deploys the full rick-infra stack with role dependencies automatically managed. +### 1. `site.yml` - Deploy All Environments +Deploys both homelab and production infrastructure. ```bash -ansible-playbook -i inventory/hosts.yml site.yml --ask-vault-pass +ansible-playbook site.yml --ask-vault-pass ``` -**What it deploys:** -- **Security Foundation**: SSH hardening, firewall, fail2ban, system updates -- **Infrastructure Services**: PostgreSQL, Valkey, Podman container runtime -- **Reverse Proxy**: Caddy with automatic HTTPS and Cloudflare DNS integration -- **Authentication**: Authentik SSO server with forward auth integration -- **Applications**: Gitea, Gallery, and other configured services +### 2. Environment-Specific Deployments + +```bash +# Deploy only homelab services +ansible-playbook playbooks/homelab.yml --ask-vault-pass + +# Deploy only production services +ansible-playbook playbooks/production.yml --ask-vault-pass + +# Or use site.yml with limits +ansible-playbook site.yml -l homelab --ask-vault-pass +ansible-playbook site.yml -l production --ask-vault-pass +``` ### 2. Service-Specific Deployments Deploy individual components using tags: @@ -193,7 +217,21 @@ For complete authentik architecture details, see [Architecture Decisions](archit ## Configuration Management -### Host Variables +### Variable Organization + +Rick-infra uses a hybrid approach for variable management: + +**Group Variables** (`group_vars/`): +- `production/main.yml` - Production environment configuration +- `production/vault.yml` - Production secrets (encrypted) + +**Host Variables** (`host_vars/`): +- `arch-vps/main.yml` - Homelab configuration +- `arch-vps/vault.yml` - Homelab secrets (encrypted) + +**Note:** Due to variable loading issues in Ansible 2.20, playbooks manually load variables using `include_vars`. This ensures reliable variable resolution during execution. + +### Example: Homelab Configuration Core infrastructure settings in `host_vars/arch-vps/main.yml`: diff --git a/docs/sigvild-gallery-deployment.md b/docs/sigvild-gallery-deployment.md index 578c9e6..e756aed 100644 --- a/docs/sigvild-gallery-deployment.md +++ b/docs/sigvild-gallery-deployment.md @@ -1,39 +1,50 @@ # Sigvild Gallery Deployment Guide +## Overview + +Sigvild Wedding Gallery is deployed on **mini-vps** (production environment) for high uptime and reliability. The gallery uses PocketBase API backend with SvelteKit frontend. + +**Production Host**: mini-vps (72.62.91.251) +**Domains**: sigvild.no (frontend), api.sigvild.no (API) + ## Quick Start -Deploy the complete Sigvild Wedding Gallery with PocketBase API and SvelteKit frontend. +Deploy Sigvild Gallery to production: + +```bash +ansible-playbook playbooks/production.yml +``` ## Prerequisites Setup ### 1. Vault Password Configuration -Create encrypted passwords for the gallery authentication: +Encrypted passwords are stored in `group_vars/production/vault.yml`: ```bash -# Create vault passwords (run from rick-infra directory) -ansible-vault encrypt_string 'your-host-password-here' --name 'vault_sigvild_host_password' -ansible-vault encrypt_string 'your-guest-password-here' --name 'vault_sigvild_guest_password' +# Edit production vault (run from rick-infra directory) +ansible-vault edit group_vars/production/vault.yml ``` -Add the encrypted strings to `host_vars/arch-vps/main.yml`: +Add these variables: ```yaml -# Add to host_vars/arch-vps/main.yml -vault_sigvild_host_password: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 66386439653765386... - -vault_sigvild_guest_password: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 33663065383834313... +# Production vault variables +vault_cloudflare_api_token: "your-cloudflare-token" +vault_caddy_tls_email: "admin@example.com" +vault_sigvild_host_password: "host-user-password" +vault_sigvild_guest_password: "guest-user-password" +vault_pb_su_email: "admin@sigvild.no" +vault_pb_su_password: "admin-password" ``` +**Note**: Use `ansible-vault encrypt group_vars/production/vault.yml` after editing. + ### 2. DNS Configuration -Ensure these domains point to your server: -- `sigvild.no` → Frontend static site -- `api.sigvild.no` → API backend proxy +Point these domains to **mini-vps** (72.62.91.251): +- `sigvild.no` A record → 72.62.91.251 +- `api.sigvild.no` A record → 72.62.91.251 ### 3. Project Structure @@ -50,70 +61,92 @@ Ensure the sigvild-gallery project is adjacent to rick-infra: ## Deployment Commands -### Full Infrastructure + Gallery +### Production Deployment -Deploy everything including Sigvild Gallery: +Deploy to production environment (mini-vps): ```bash -ansible-playbook site.yml -``` +# Deploy complete production stack (Caddy + Sigvild Gallery) +ansible-playbook playbooks/production.yml -### Gallery Only - -Deploy just the Sigvild Gallery service: - -```bash -ansible-playbook playbooks/deploy-sigvild.yml +# Or deploy everything with production limit +ansible-playbook site.yml -l production ``` ### Selective Updates -Update specific components: +Update specific components using tags: ```bash # Frontend only (quick static file updates) -ansible-playbook site.yml --tags="frontend" +ansible-playbook playbooks/production.yml --tags="frontend" # Backend only (API service updates) -ansible-playbook site.yml --tags="backend" +ansible-playbook playbooks/production.yml --tags="backend" # Caddy configuration only -ansible-playbook site.yml --tags="caddy" +ansible-playbook playbooks/production.yml --tags="caddy" # Just build process (development) -ansible-playbook site.yml --tags="build" +ansible-playbook playbooks/production.yml --tags="build" ``` +### Backup and Restore + +Create backups before major changes: + +```bash +# Create backup (works on any host running sigvild-gallery) +ansible-playbook playbooks/backup-sigvild.yml -l mini-vps + +# Backup is saved to: ~/sigvild-gallery-backup/ +``` + +**Automatic Restore**: When deploying to a fresh server, the role automatically detects and restores from the latest backup if available. + ## Architecture Overview +**Production Environment**: mini-vps (72.62.91.251) + ``` Internet ↓ -Caddy (Auto HTTPS) +Cloudflare DNS → mini-vps + ↓ +Caddy (Auto HTTPS with DNS Challenge) ├── sigvild.no → /var/www/sigvild-gallery/ (Static Files) └── api.sigvild.no → localhost:8090 (PocketBase API) ↓ - Go Binary (sigvild-gallery-server) + Go Binary (/opt/sigvild-gallery/sigvild-gallery) ↓ - SQLite Database + File Storage + SQLite Database (/opt/sigvild-gallery/pb_data/) + └── File Storage (wedding photos) ``` +**Key Features**: +- Automatic HTTPS with Let's Encrypt +- Cloudflare DNS challenge for certificate validation +- Security headers and CORS protection +- SystemD service management +- Automatic backup/restore capability + ## Service Management ### Status Checks ```bash -# Gallery API service -systemctl status sigvild-gallery - -# Caddy web server -systemctl status caddy +# Check services on mini-vps +ansible mini-vps -a "systemctl status sigvild-gallery" +ansible mini-vps -a "systemctl status caddy" # View gallery logs -journalctl -u sigvild-gallery -f +ansible mini-vps -a "journalctl -u sigvild-gallery -n 50 --no-pager" # View Caddy logs -journalctl -u caddy -f +ansible mini-vps -a "journalctl -u caddy -n 20 --no-pager" + +# Check data directory +ansible mini-vps -a "ls -lh /opt/sigvild-gallery/pb_data/" ``` ### Manual Operations @@ -216,23 +249,30 @@ journalctl -u caddy | grep -i "acme\|certificate" - **CORS restrictions**: API access limited to frontend domain - **Rate limiting**: API endpoint protection -## File Locations +## File Locations (on mini-vps) ### Application Files -- **Binary**: `/opt/sigvild-gallery/sigvild-gallery-server` -- **Database**: `/opt/sigvild-gallery/data/data.db` -- **File uploads**: `/opt/sigvild-gallery/data/storage/` +- **Binary**: `/opt/sigvild-gallery/sigvild-gallery` +- **Database**: `/opt/sigvild-gallery/pb_data/data.db` +- **File uploads**: `/opt/sigvild-gallery/pb_data/storage/` - **Frontend**: `/var/www/sigvild-gallery/` +- **User/Group**: `sigvild:sigvild` ### Configuration Files - **Service**: `/etc/systemd/system/sigvild-gallery.service` - **Caddy frontend**: `/etc/caddy/sites-enabled/sigvild-frontend.caddy` - **Caddy API**: `/etc/caddy/sites-enabled/sigvild-api.caddy` +### Local Files (on control machine) +- **Configuration**: `group_vars/production/main.yml` +- **Secrets**: `group_vars/production/vault.yml` (encrypted) +- **Backups**: `~/sigvild-gallery-backup/` +- **Source code**: `~/sigvild-gallery/` + ### Log Files - **Service logs**: `journalctl -u sigvild-gallery` - **Caddy logs**: `journalctl -u caddy` -- **Access logs**: `/var/log/caddy/sigvild-*.log` +- **Access logs**: `/var/log/caddy/access.log` ## Next Steps After Deployment @@ -248,15 +288,28 @@ For ongoing development: ```bash # 1. Make changes to sigvild-gallery project -cd ../sigvild-gallery +cd ~/sigvild-gallery # 2. Test locally go run . serve & cd sigvild-kit && npm run dev -# 3. Deploy updates -cd ../rick-infra -ansible-playbook site.yml --tags="sigvild" +# 3. Deploy updates to production +cd ~/rick-infra +ansible-playbook playbooks/production.yml --tags="sigvild" ``` -The deployment system builds locally and transfers assets, so you don't need build tools on the server. \ No newline at end of file +**Build Process**: +- Backend: Built locally with `GOOS=linux GOARCH=amd64 go build` +- Frontend: Built locally with `npm run build` in sigvild-kit/ +- Assets transferred to mini-vps via Ansible +- No build tools required on the server + +## Migration History + +**December 2025**: Migrated from arch-vps (homelab) to mini-vps (production) +- **Reason**: Client project requiring higher uptime reliability +- **Method**: Backup from arch-vps, automatic restore to mini-vps +- **Downtime**: ~5 minutes during DNS propagation +- **Previous host**: arch-vps (69.62.119.31) +- **Current host**: mini-vps (72.62.91.251) \ No newline at end of file diff --git a/group_vars/production/main.yml b/group_vars/production/main.yml new file mode 100644 index 0000000..0e29889 --- /dev/null +++ b/group_vars/production/main.yml @@ -0,0 +1,52 @@ +--- +# ================================================================= +# Production Configuration for mini-vps (Client Projects) +# ================================================================= +# This host runs production services requiring high uptime +# Currently hosting: Sigvild Gallery + +# ================================================================= +# TLS Configuration - Production Setup +# ================================================================= +caddy_tls_enabled: true +caddy_domain: "health.sigvild.no" +caddy_tls_email: "{{ vault_caddy_tls_email }}" + +# DNS Challenge Configuration (Cloudflare) +caddy_dns_provider: "cloudflare" +cloudflare_api_token: "{{ vault_cloudflare_api_token }}" + +# Production Let's Encrypt CA +caddy_acme_ca: "https://acme-v02.api.letsencrypt.org/directory" + +# ================================================================= +# API Service Registration Configuration +# ================================================================= +# Services now self-register using Caddy's admin API +caddy_api_enabled: true +caddy_server_name: "main" + +# ================================================================= +# Sigvild Gallery Configuration +# ================================================================= +sigvild_gallery_frontend_domain: "sigvild.no" +sigvild_gallery_api_domain: "api.sigvild.no" + +sigvild_gallery_local_project_path: "{{ lookup('env', 'HOME') }}/sigvild-gallery/" + +# Backup configuration +sigvild_gallery_backup_enabled: true +sigvild_gallery_backup_local_path: "{{ lookup('env', 'HOME') }}/sigvild-gallery-backup/" + +# Vault-encrypted passwords (create with ansible-vault) +sigvild_gallery_pb_su_email: "{{ vault_pb_su_email}}" +sigvild_gallery_pb_su_password: "{{ vault_pb_su_password}}" +sigvild_gallery_host_password: "{{ vault_sigvild_host_password }}" +sigvild_gallery_guest_password: "{{ vault_sigvild_guest_password }}" + +# ================================================================= +# Security & Logging +# ================================================================= +caddy_log_level: "INFO" +caddy_log_format: "json" +caddy_systemd_security: true diff --git a/host_vars/arch-vps/main.yml b/host_vars/arch-vps/main.yml index d98acd6..1732bf7 100644 --- a/host_vars/arch-vps/main.yml +++ b/host_vars/arch-vps/main.yml @@ -24,24 +24,6 @@ caddy_acme_ca: "https://acme-v02.api.letsencrypt.org/directory" caddy_api_enabled: true caddy_server_name: "main" -# ================================================================= -# Sigvild Gallery Configuration -# ================================================================= -sigvild_gallery_frontend_domain: "sigvild.no" -sigvild_gallery_api_domain: "api.sigvild.no" - -sigvild_gallery_local_project_path: "~/sigvild-gallery/" - -# Backup configuration -sigvild_gallery_backup_enabled: true -sigvild_gallery_backup_local_path: "~/sigvild-gallery-backup/" - -# Vault-encrypted passwords (create with ansible-vault) -sigvild_gallery_pb_su_email: "{{ vault_pb_su_email}}" -sigvild_gallery_pb_su_password: "{{ vault_pb_su_password}}" -sigvild_gallery_host_password: "{{ vault_sigvild_host_password }}" -sigvild_gallery_guest_password: "{{ vault_sigvild_guest_password }}" - # ================================================================= # Authentik Configuration # ================================================================= diff --git a/host_vars/mini-vps/main.yml b/host_vars/mini-vps/main.yml new file mode 100644 index 0000000..e69de29 diff --git a/inventory/hosts.yml b/inventory/hosts.yml index 6c9b73d..135a708 100644 --- a/inventory/hosts.yml +++ b/inventory/hosts.yml @@ -1,11 +1,15 @@ --- -all: - children: - production: - hosts: - arch-vps: - ansible_host: 69.62.119.31 - ansible_user: root - +homelab: + hosts: + arch-vps: + ansible_host: 69.62.119.31 + ansible_user: root + vars: + ansible_python_interpreter: /usr/bin/python3 +production: + hosts: + mini-vps: + ansible_host: 72.62.91.251 + ansible_user: root vars: ansible_python_interpreter: /usr/bin/python3 diff --git a/now-what.md b/now-what.md new file mode 100644 index 0000000..7468ae2 --- /dev/null +++ b/now-what.md @@ -0,0 +1,25 @@ +# Now what? + +- [ ] Redeploy on clean VPS to test playbook + - [ ] Must set up mini-vps for sigvild and devigo + +- [ ] What gets served on jnss.me? +- [ ] Backups + +- [ ] Configure and set up Nextcloud + - [ ] OAuth + - [ ] Settings + - [ ] Contacts and calendars + - [ ] Storage bucket integration? + +- [ ] Gitea + - [ ] SSH setup + +- [ ] Authentik Invitations for users? + +- [ ] Sail the high seas + - [ ] Set up Jellyfin + - [ ] Set up *arr applications + +- [ ] "Blog post" + diff --git a/playbooks/backup-sigvild.yml b/playbooks/backup-sigvild.yml new file mode 100644 index 0000000..e304614 --- /dev/null +++ b/playbooks/backup-sigvild.yml @@ -0,0 +1,24 @@ +--- +# Sigvild Gallery Data Backup Playbook +# +# This playbook creates a backup of the Sigvild Gallery data including: +# - PocketBase SQLite database (data.db, auxiliary.db) +# - All uploaded wedding photos and media files +# - PocketBase logs and system state +# +# Usage: +# ansible-playbook playbooks/backup-sigvild.yml -l arch-vps +# ansible-playbook playbooks/backup-sigvild.yml -l mini-vps +# +# Backup location: ~/sigvild-gallery-backup/sigvild-gallery-backup-YYYYMMDDTHHMMSS.tar.gz + +- name: Backup Sigvild Gallery Data + hosts: all + become: true + gather_facts: true + + tasks: + - name: Run backup tasks from sigvild-gallery role + include_role: + name: sigvild-gallery + tasks_from: backup.yml diff --git a/playbooks/homelab.yml b/playbooks/homelab.yml new file mode 100644 index 0000000..798fa64 --- /dev/null +++ b/playbooks/homelab.yml @@ -0,0 +1,64 @@ +--- +# Homelab Infrastructure Deployment +# +# Deploys personal homelab services to arch-vps including: +# - PostgreSQL database +# - Valkey cache/session store +# - Podman container runtime +# - Caddy web server +# - Nextcloud cloud storage +# - Authentik SSO/authentication +# - Gitea git hosting +# +# Usage: +# ansible-playbook playbooks/homelab.yml + +- name: Deploy Homelab Infrastructure + hosts: homelab + become: true + gather_facts: true + + tasks: + # Workaround: Manually load host_vars due to Ansible 2.20 variable loading issue + - name: Load homelab host variables + include_vars: + dir: "{{ playbook_dir }}/../host_vars/{{ inventory_hostname }}" + extensions: ['yml'] + tags: always + + # Deploy infrastructure services + - name: Deploy PostgreSQL + include_role: + name: postgresql + tags: ['postgresql', 'infrastructure', 'database'] + + - name: Deploy Valkey + include_role: + name: valkey + tags: ['valkey', 'redis', 'infrastructure', 'cache'] + + - name: Deploy Podman + include_role: + name: podman + tags: ['podman', 'containers', 'infrastructure'] + + - name: Deploy Caddy + include_role: + name: caddy + tags: ['caddy', 'infrastructure', 'web'] + + # Deploy application services + - name: Deploy Nextcloud + include_role: + name: nextcloud + tags: ['nextcloud', 'cloud', 'storage'] + + - name: Deploy Authentik + include_role: + name: authentik + tags: ['authentik', 'sso', 'auth'] + + - name: Deploy Gitea + include_role: + name: gitea + tags: ['gitea', 'git', 'development'] diff --git a/playbooks/production.yml b/playbooks/production.yml new file mode 100644 index 0000000..be00c9f --- /dev/null +++ b/playbooks/production.yml @@ -0,0 +1,29 @@ +--- +# Production Services Deployment +# +# Deploys production services requiring high uptime to mini-vps including: +# - Caddy web server +# - Sigvild Gallery (wedding photo gallery) +# +# Usage: +# ansible-playbook playbooks/production.yml + +# - import_playbook: security.yml + +- name: Deploy Production Services + hosts: production + become: true + gather_facts: true + + tasks: + # Workaround: Manually load group_vars due to Ansible 2.20 variable loading issue + - name: Load production group variables + include_vars: + dir: "{{ playbook_dir }}/../group_vars/production" + extensions: ['yml'] + tags: always + + - name: Deploy Sigvild Gallery + include_role: + name: sigvild-gallery + tags: ['sigvild', 'gallery', 'wedding'] diff --git a/roles/caddy/tasks/main.yml b/roles/caddy/tasks/main.yml index 2bd5638..a7cbad1 100644 --- a/roles/caddy/tasks/main.yml +++ b/roles/caddy/tasks/main.yml @@ -1,7 +1,7 @@ --- - name: Check if DNS challenge is needed set_fact: - dns_challenge_needed: "{{ caddy_dns_provider == 'cloudflare' and cloudflare_api_token != '' }}" + dns_challenge_needed: "{{ caddy_dns_provider == 'cloudflare' }}" - name: Check if Caddy is already installed command: /usr/bin/caddy version diff --git a/roles/sigvild-gallery/defaults/main.yml b/roles/sigvild-gallery/defaults/main.yml index 973b767..ae94ee5 100644 --- a/roles/sigvild-gallery/defaults/main.yml +++ b/roles/sigvild-gallery/defaults/main.yml @@ -25,7 +25,7 @@ sigvild_gallery_guest_username: guest sigvild_gallery_guest_password: "{{ vault_sigvild_guest_password }}" # Build configuration -sigvild_gallery_local_project_path: "{{ ansible_env.PWD }}/sigvild-gallery" +sigvild_gallery_local_project_path: "{{ lookup('env', 'HOME') }}/sigvild-gallery" # Service configuration sigvild_gallery_service_enabled: true @@ -33,7 +33,7 @@ sigvild_gallery_service_state: started # Backup configuration sigvild_gallery_backup_enabled: true -sigvild_gallery_backup_local_path: "{{ playbook_dir }}/backups/sigvild-gallery" +sigvild_gallery_backup_local_path: "{{ lookup('env', 'HOME') }}/sigvild-gallery-backup/" # Caddy integration (assumes caddy role provides these) # caddy_sites_enabled_dir: /etc/caddy/sites-enabled diff --git a/roles/sigvild-gallery/tasks/deploy_backend.yml b/roles/sigvild-gallery/tasks/deploy_backend.yml index 613e8fb..f5a51f2 100644 --- a/roles/sigvild-gallery/tasks/deploy_backend.yml +++ b/roles/sigvild-gallery/tasks/deploy_backend.yml @@ -33,11 +33,7 @@ notify: restart sigvild-gallery tags: [backend] -- name: Restore data from backup if available - include_tasks: restore.yml - tags: [backend, restore] - -- name: Create data directory for PocketBase +- name: Create data directory for PocketBase (if not created by restore) file: path: "{{ sigvild_gallery_data_dir }}" state: directory diff --git a/roles/sigvild-gallery/tasks/main.yml b/roles/sigvild-gallery/tasks/main.yml index 0442d29..cef2956 100644 --- a/roles/sigvild-gallery/tasks/main.yml +++ b/roles/sigvild-gallery/tasks/main.yml @@ -14,7 +14,7 @@ home: "{{ sigvild_gallery_home }}" create_home: yes -- name: Create directories +- name: Create directories (excluding pb_data, created later) file: path: "{{ item }}" state: directory @@ -23,7 +23,6 @@ mode: '0755' loop: - "{{ sigvild_gallery_home }}" - - "{{ sigvild_gallery_data_dir }}" - "{{ sigvild_gallery_web_root }}" - name: Check for existing gallery data diff --git a/site.yml b/site.yml index 25646f7..73e5a72 100644 --- a/site.yml +++ b/site.yml @@ -1,29 +1,22 @@ --- -# Security hardening establishes secure foundation before web services +# Main Site Deployment Playbook +# +# This playbook orchestrates deployment across all hosts: +# - Homelab (arch-vps): Personal services and experimentation +# - Production (mini-vps): Client projects requiring high uptime +# +# Usage: +# ansible-playbook site.yml # Deploy everything +# ansible-playbook site.yml -l homelab # Deploy only homelab +# ansible-playbook site.yml -l production # Deploy only production +# ansible-playbook site.yml --tags caddy # Deploy Caddy everywhere + +# Security hardening playbook (optional, currently commented out) +# Establishes secure foundation before web services # - import_playbook: playbooks/security.yml -- name: Deploy Core Infrastructure - hosts: arch-vps - become: true - gather_facts: true - - roles: - # Infrastructure services - # - role: postgresql - # tags: ['postgresql', 'infrastructure', 'database'] - # - role: valkey - # tags: ['valkey', 'redis', 'infrastructure', 'cache'] - # - role: podman - # tags: ['podman', 'containers', 'infrastructure'] - # - role: caddy - # tags: ['caddy', 'infrastructure', 'web'] - - # Application services - # - role: sigvild-gallery - # tags: ['sigvild', 'gallery', 'wedding'] - # - role: gitea - # tags: ['gitea', 'git', 'development'] - - role: nextcloud - tags: ['nextcloud'] - # - role: authentik - # tags: ['authentik'] +# Deploy homelab infrastructure on arch-vps +- import_playbook: playbooks/homelab.yml + +# Deploy production services on mini-vps +- import_playbook: playbooks/production.yml