commit 883f31932e8271ce2033ddc48b1f563e173c446e Author: Tiara Rodney Date: Sat Mar 14 05:38:45 2026 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eef233f --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/letsencrypt/ +/.pytest_cache/ +/.ssh/ +/.local/ +/.tox/ +/.vault-pass diff --git a/.ssh.vault b/.ssh.vault new file mode 100644 index 0000000..f0298e0 --- /dev/null +++ b/.ssh.vault @@ -0,0 +1,35 @@ +$ANSIBLE_VAULT;1.1;AES256 +39316330396162386166363162646363343365343430393266666638356139383832353833326132 +6531356666643331363735373863323037303562393437620a303135613738303166346234663137 +65303562666362383266323161323832666165323237313033303961363935313561343731363934 +3632666365663637640a666666616336343362356164366239373065656239656237373331303166 +34343539666565636462343064666163333132373236343065323735333562616434323333386438 +38393137306438656463333135316539663264353736636233663035623131623835636534633336 +63306666343238656233653232663663323837666437346565616137633638613439393861306636 +38646663356237623765626237653732336362393739373835363431393963663065633535366632 +33383031303434396334373834663662653735353030336563646236313532656464333863636263 +34656262646233646230646335376565666237366138303733326339656166636133333433346432 +30616139393936383261393763636563386138393237343738613933303562343837353236626665 +37323635343535353032663866666238646635346138646666646562386433303063333862393761 +39346234633962326231333032653732393435336434616664663961633062353739383937383866 +61343030383530353235346561346531633832613634616533306136653930326634393530383730 +35316438636333313930333235316361393863303961666165616130616639356632356330383139 +39346335396532636334636336346434613934376131643165333438373630653732643033376537 +32383066623565643964623535333262376236316564356666336532613337653333613338613865 +34616561613533333636306163303131323834653934666661653866666562363638616630376566 +30643330393031613836353936636661653164353531303163623666666563643837346462376436 +39653665656164303135343738373436383265613363366664373466333963333532353335323436 +38633163656532356435356334376164373864383031366332633131316162336161643034653664 +61356538356563356232653964623165373239323664616339383263333365333633616564383138 +63343435343630353461376662626365626565616366373937306637346635313462393834393430 +35343962316630663238376262396332336639643136626434626336346437373438393963623863 +31623237336530376364626634653663313837306165376165346363306166343739393866623537 +30633735646434633762303065306231346363306339316636373066373464383764636634323163 +31356431333339653266393138353061643261306135336563303462343261393261376139613364 +31373861333065646237376535366138353438336463333363623464303431333135353133363461 +61646262343734343362643432633837623234646633336639336566623038346561393863303636 +36393861636631333363646438376133616461303834653262616565303362396634626630646137 +37616631383264656333383035396262656162613162653039366139623634393030656137656563 +65613135333364636437376163303230323435353834636262656539363964626331343465373038 +64333735643234326665653036303465646561646362626662653966303966623130356433313034 +3661666134663430643830613463663761333162393766636263 diff --git a/.vault-pass-debug b/.vault-pass-debug new file mode 100644 index 0000000..2f21015 --- /dev/null +++ b/.vault-pass-debug @@ -0,0 +1 @@ +&0geF%B46!H30#fnuY4ad8yCAxpM&C*! diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..aa12d53 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,55 @@ +# Contributing + +## Code style + +- YAML files use 4-space indentation, formatted with `yamlfix`. +- Jinja2 templates use the file extension `.j2`. +- Role names use snake_case (e.g., `docker_registry`). +- Task names are human-readable sentences (e.g., "Ensure SSL private keys are readable by containers"). + +## Role structure + +Each role follows the standard Ansible layout: + +``` +roles// +├── defaults/main.yml # Default variables +├── tasks/ +│ ├── main.yml # Entry point +│ └── *.yml # Additional task files (deploy, restore, etc.) +├── templates/ # Jinja2 templates (.j2) +├── files/ # Static files +└── meta/main.yml # Role dependencies +``` + +## Adding a new service + +1. Create a new role in `ansible/roles//`. +2. Add it to the proxy or IDP play in `ansible/playbooks/setup.yml` with a + `tags: []` annotation. +3. If the role depends on docker or apache, those roles handle themselves + internally — just declare the dependency in `meta/main.yml`. +## Testing changes + +Always test locally before deploying to production: + +```bash +# Run against local VMs +pipenv run ansible-playbook -i ansible/inventories/debug/hosts.ini ansible/playbooks/setup.yml \ + --tags +``` + +## Committing + +- Keep commits focused: one logical change per commit. +- Use conventional-ish commit messages: + - `feat: add offline email notifications to prosody` + - `fix: correct registry vhost name collision` + - `chore: migrate collection roles to local roles/` + +## Vault changes + +When adding new secrets, add them to the vault file and document the variable +name (but not the value) somewhere discoverable — either in the role's +`defaults/main.yml` as a commented placeholder or in the playbook next to the +role invocation. diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..0e1dbc5 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,168 @@ +# Development + +## Prerequisites + +```bash +sudo apt install -y qemu-system-x86 libvirt-daemon-system libvirt-clients \ + genisoimage ovmf screen +sudo usermod -aG libvirt $(whoami) +sudo usermod -aG kvm $(whoami) +pipenv install --dev +pipenv run ansible-galaxy collection install -r ansible/requirements.yml +``` + +## Repository layout + +``` +servers/ +├── ansible/ +│ ├── inventories/ +│ │ ├── debug/ # Local VMs (vm-proxy, vm-idp) +│ │ └── prod/ # Production VPS hosts +│ ├── playbooks/ +│ │ ├── setup.yml # Main deployment playbook +│ │ ├── backup.yml # Backup playbook +│ │ └── restore.yml # Restore playbook +│ ├── roles/ # All roles (formerly a separate collection) +│ └── requirements.yml # Ansible Galaxy dependencies +├── scripts/ +│ ├── provision.sh # One-time: create VMs + full playbook + snapshot +│ ├── deploy.sh # Iterate: restore + deploy a single service +│ ├── reset.sh # Restore VMs to a snapshot +│ ├── prod-deploy.sh # Deploy to production +│ └── vm/ # Low-level VM lifecycle (wrapping qemu-vm) +├── letsencrypt/ # TLS certificates (not committed) +├── Pipfile # Python dependencies +└── ansible.cfg # Ansible config (roles_path, vault) +``` + +## Development workflow + +The workflow is: develop and test locally against VMs, then deploy to +production once changes are idempotent and working. + +All scripts are meant to be run inside `pipenv shell` or via `pipenv run`. + +### 1. Provision (once) + +Creates VMs, runs the full ansible playbook, and snapshots the result as +`provisioned`. Prompts for sudo to set up the bridge network: + +```bash +pipenv run scripts/provision.sh +``` + +This gives you two VMs: +- **vm-proxy** at `10.10.0.2` (screen session `vm-proxy`) +- **vm-idp** at `10.10.0.3` (screen session `vm-idp`) + +Attach to a VM's serial console with `screen -r vm-proxy`. + +### 2. Iterate on a service + +Deploy a single service to the local VMs: + +```bash +# Deploy bugzilla on top of current VM state +pipenv run scripts/deploy.sh bugzilla + +# Skip dependencies you know haven't changed +pipenv run scripts/deploy.sh bugzilla --skip docker,apache + +# Restore to clean state first, then deploy +pipenv run scripts/deploy.sh prosody --restore + +# Restore to a specific snapshot first +pipenv run scripts/deploy.sh authentik --restore initialized +``` + +### 3. Reset + +Go back to a known state without deploying anything: + +```bash +# Reset to bare VMs (pre-ansible) +pipenv run scripts/reset.sh + +# Reset to fully provisioned state +pipenv run scripts/reset.sh provisioned +``` + +### 4. Custom snapshots + +Save and restore intermediate states during development: + +```bash +# Save current state +pipenv run scripts/vm/snapshot.sh after-bugzilla + +# Restore it later +pipenv run scripts/reset.sh after-bugzilla +``` + +### 5. Destroy and recreate + +Start completely from scratch: + +```bash +pipenv run scripts/vm/destroy.sh +pipenv run scripts/provision.sh +``` + +### 6. Deploy to production + +Once your changes work locally and are idempotent: + +```bash +# Full deployment +pipenv run scripts/prod-deploy.sh + +# Targeted deployment +pipenv run scripts/prod-deploy.sh prosody + +# Skip dependencies +pipenv run scripts/prod-deploy.sh bugzilla --skip docker,apache +``` + +## Low-level VM management + +The `scripts/vm/` directory contains building-block scripts for direct +VM control: + +| Script | Purpose | +|--------|---------| +| `vm/start.sh` | Start VMs in screen sessions | +| `vm/stop.sh` | Stop VMs gracefully | +| `vm/status.sh` | Show instances, volumes, screen sessions | +| `vm/snapshot.sh