This comprehensive update improves maintainability and removes unused services: ## Major Changes - Remove 5 unused services (beaver, grist, stirlingpdf, tasksmd, redlib) - Convert remaining static compose files to Jinja2 templates - Clean up Caddyfile removing orphaned proxy configurations - Align DNS records with active services ## Service Cleanup - Remove habits.thesatelliteoflove.com DNS record (beaver service) - Add missing DNS records for active services: - post.thesatelliteoflove.com (Postiz) - files.thesatelliteoflove.com (Pingvin Share) - bookmarks.thesatelliteoflove.com (Hoarder) ## Template Standardization - Convert caddy-compose.yml to template - Convert dockge-compose.yml to template - Convert hoarder-compose.yml to template - All services now use consistent template-driven approach ## Documentation Updates - Update CLAUDE.md with new service organization - Update README.md files with category-based deployment examples - Update todo.md with completed work summary - Service count updated to 22+ active services Infrastructure is now fully organized, cleaned up, and ready for future enhancements. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
5.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Overview
This is a personal infrastructure Ansible playbook that automates deployment and management of 22+ self-hosted Docker services across two domains (thesatelliteoflove.com
and nerder.land
). The setup uses Tailscale VPN for secure networking and Caddy for reverse proxy with automated HTTPS.
Important: Always review DEPLOYMENT_LEARNINGS.md
when working on this repository for lessons learned and troubleshooting guidance.
Common Commands
Initial Setup
# Install Ansible dependencies
ansible-galaxy install -r requirements.yml
# Bootstrap new server (creates user, installs Tailscale, security hardening)
ansible-playbook bootstrap.yml -i hosts.yml
# Deploy all Docker services
ansible-playbook site.yml -i hosts.yml
# Update DNS records in AWS Route53
ansible-playbook dns.yml -i hosts.yml
Service Management
# Deploy specific services using tags
ansible-playbook site.yml -i hosts.yml --tags caddy --vault-password-file vault_pass --extra-vars "@secrets.enc"
ansible-playbook site.yml -i hosts.yml --tags authentik,gitea --vault-password-file vault_pass --extra-vars "@secrets.enc"
ansible-playbook site.yml -i hosts.yml --tags docker --vault-password-file vault_pass --extra-vars "@secrets.enc" # all docker services
# Deploy services by category (new organized structure)
ansible-playbook site.yml -i hosts.yml --tags infrastructure --vault-password-file vault_pass --extra-vars "@secrets.enc"
ansible-playbook site.yml -i hosts.yml --tags media,productivity --vault-password-file vault_pass --extra-vars "@secrets.enc"
ansible-playbook site.yml -i hosts.yml --tags development,monitoring --vault-password-file vault_pass --extra-vars "@secrets.enc"
# Deploy only infrastructure components
ansible-playbook site.yml -i hosts.yml --tags common,cron --vault-password-file vault_pass --extra-vars "@secrets.enc"
Architecture
Host Configuration
- Bootstrap Host (
netcup
): 152.53.36.98 - Initial server setup target - Docker Host (
docker-01
): 100.70.169.99 - Main service deployment via Tailscale
Role Structure
- bootstrap: Initial server hardening, user creation, Tailscale VPN setup
- common: Basic system configuration, UFW firewall management
- docker: Comprehensive service deployment (22+ containerized applications, organized by category)
- cron: Scheduled task management (currently Warhammer RSS feed generation)
Docker Role Organization (Reorganized into Logical Categories)
The docker role is now organized into logical service groups under roles/docker/tasks/
:
- infrastructure/: Core platform components
- Caddy (reverse proxy), Authentik (SSO), Dockge (container management)
- development/: Development and collaboration tools
- Gitea, Code Server, Matrix (Conduit)
- media/: Content creation and consumption
- Audiobookshelf, Calibre, Ghost blog, Pinchflat, Pinry, Hoarder, Manyfold
- productivity/: Personal organization and document management
- Paperless-NGX, MMDL, Baikal (CalDAV/CardDAV), Syncthing, Heyform, Dawarich, Pingvin
- communication/: Social media and external communication
- GoToSocial (Fediverse), Postiz (social media management)
- monitoring/: System monitoring and alerts
- Changedetection, Glance dashboard, AppriseAPI
Data Structure
- All service data stored in
/opt/stacks/[service-name]/
on docker host - Docker Compose files generated from Jinja2 templates in
roles/docker/templates/
- Environment files templated for services requiring configuration
Key Implementation Details
Template-Driven Configuration
The docker role uses Jinja2 templates exclusively for all services. When modifying services:
- Update templates in
roles/docker/templates/[service]-compose.yml.j2
- Environment files use
.env.j2
templates where needed - Task files organized by category in
roles/docker/tasks/[category]/[service].yml
- All services now use templated configurations (no static compose files)
DNS Management
The dns.yml
playbook manages AWS Route53 records for both domains. All subdomains point to the netcup server (152.53.36.98), with Caddy handling internal routing to the docker host via Tailscale.
Security Architecture
- Tailscale provides secure networking between management and service hosts
- Services are network-isolated using Docker
- Caddy handles SSL termination with automatic Let's Encrypt certificates
- UFW firewall managed through Docker integration script
Service Dependencies
Many services depend on Authentik for SSO. When deploying new services, consider:
- Whether SSO integration is needed
- Caddy routing configuration for subdomain access
- Network connectivity requirements within Docker stack
- Hairpinning fixes for internal service-to-service communication
Hairpinning Resolution
Services inside Docker containers cannot reach external domains that resolve to the same server. Fix by adding extra_hosts
mappings:
extra_hosts:
- "auth.thesatelliteoflove.com:172.20.0.5"
- "cal.thesatelliteoflove.com:172.20.0.5"
Common domains requiring hairpinning fixes:
auth.thesatelliteoflove.com
(Authentik SSO)cal.thesatelliteoflove.com
(Baikal CalDAV)- Any service domain the container needs to communicate with