summaryrefslogtreecommitdiff
path: root/CLAUDE.md
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2025-10-04 16:25:00 -0700
committerElizabeth Hunt <me@liz.coffee>2025-10-04 16:25:25 -0700
commit0ba6199538478b22763cc4c768c775a9c20baac9 (patch)
treee5f97e9d382b6a869e74b0ec37670fc4cc04770c /CLAUDE.md
parenta59455fe4f0d06f85800117d7871496ff9fa916f (diff)
downloadinfra-0ba6199538478b22763cc4c768c775a9c20baac9.tar.gz
infra-0ba6199538478b22763cc4c768c775a9c20baac9.zip
Fix some stuff
Diffstat (limited to 'CLAUDE.md')
-rw-r--r--CLAUDE.md121
1 files changed, 121 insertions, 0 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..1213254
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,121 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Overview
+
+This is an Ansible-based infrastructure-as-code repository for managing the liz.coffee homelab infrastructure. It orchestrates deployment of services across a Docker Swarm cluster (3 nodes: swarm-one, swarm-two, swarm-three) and an outbound proxy server.
+
+## Architecture
+
+### Infrastructure Layout
+
+- **Swarm Cluster**: 3-node Docker Swarm cluster at 10.128.0.201-203
+ - Primary services deployed as Docker Swarm stacks
+ - Shared Ceph storage mounted across all nodes
+ - Keepalived for high availability
+ - Traefik as the ingress controller with automatic TLS via Let's Encrypt
+
+- **Outbound Proxy**: External-facing NGINX reverse proxy (outbound-two.liz.coffee)
+ - Routes external traffic to internal services via the swarm loadbalancer
+ - Uses docker-compose instead of swarm stacks
+
+### Service Deployment Patterns
+
+Services fall into two deployment models:
+
+1. **Docker Swarm Services** (most services): Use `tasks/manage-docker-swarm-service.yml`
+ - Deployed via `docker stack deploy`
+ - Templates rendered from `playbooks/roles/{service}/templates/`
+ - Health checks and rolling updates configured in docker-compose.yml
+ - Traefik labels for automatic routing and TLS
+
+2. **Docker Compose Services** (nginx_proxy, outbound): Use `tasks/manage-docker-compose-service.yml`
+ - Deployed via systemd service `docker-compose@{service}`
+ - Supports rollout using docker-rollout tool for zero-downtime deployments
+
+### Common Task Files
+
+- `tasks/manage-docker-swarm-service.yml`: Renders templates and deploys swarm stack
+- `tasks/manage-docker-compose-service.yml`: Renders templates, manages systemd service, performs rollouts
+- `tasks/copy-rendered-templates-recursive.yml`: Copies Jinja2 templates to destination
+
+## Key Commands
+
+### Vault Management
+
+Initialize or update vault secrets:
+```bash
+./ansible-vault-init.sh [secret_name]
+```
+
+To avoid password prompts, store vault password in `secrets.pwd`:
+```bash
+echo "your_password" > secrets.pwd
+```
+
+### Deployment
+
+Full deployment (all services in order):
+```bash
+ansible-playbook -e @secrets.enc --vault-password-file secrets.pwd deploy.yml
+```
+
+Deploy a specific playbook during development:
+```bash
+ansible-playbook -e @secrets.enc --vault-password-file secrets.pwd playbooks/{service}.yml
+```
+
+### Linting
+
+```bash
+yamllint --strict .
+ansible-lint
+```
+
+### Creating New Services
+
+Use the `create.py` script to scaffold a new service:
+```bash
+./create.py --service-name myservice --container-image myimage:latest --service-port 8080 [--external] [--internal]
+```
+
+This generates:
+- Ansible role in `playbooks/roles/{service}/`
+- Docker compose template with Traefik labels
+- Group vars in `group_vars/{service}.yml`
+- Inventory entry and playbook hook in `deploy.yml`
+- NGINX config (if `--external` specified)
+- DNS records (Cloudflare if `--external`, LabDNS if `--internal`)
+
+## File Organization
+
+- `inventory`: Ansible inventory defining host groups and connection details
+- `deploy.yml`: Master playbook importing all service playbooks in deployment order
+- `playbooks/`: Individual service playbooks
+- `playbooks/roles/`: Service-specific roles containing tasks and templates
+ - `{service}/tasks/main.yml`: Task entry point
+ - `{service}/templates/`: Jinja2 templates (docker-compose.yml, configs, etc.)
+- `group_vars/`: Variables per service/host group
+- `secrets.enc`: Ansible vault encrypted secrets
+- `ansible.cfg`: Ansible configuration (inventory path, SSH settings)
+
+## Variable Conventions
+
+Each service typically defines in `group_vars/{service}.yml`:
+- `{service}_domain`: FQDN for the service
+- `{service}_base`: Base directory path on swarm nodes (usually under `{{ swarm_base }}`)
+
+Common variables available across all playbooks:
+- `deployment_time`: Timestamp of deployment (forces container recreation)
+- `timezone`: System timezone
+- `homelab_build`: Boolean indicating local vs production deployment
+- `loadbalancer_ip`: Internal VIP for the swarm cluster
+
+## Important Notes
+
+- Most services use swarm-one (10.128.0.201) as the deployment target in inventory
+- Secrets are referenced as `{{ secret_name }}` from the vault
+- All swarm services should connect to the `proxy` external network for Traefik routing
+- Use `--resolve-image=always` in stack deploys to ensure latest images are pulled
+- The outbound role manages NGINX configs in `playbooks/roles/outbound/templates/proxy/nginx/conf.d/`