ansible/CLAUDE.md
Phil 06a7889024 feat: migrate Hoarder to Karakeep bookmark manager
Complete migration from discontinued Hoarder to actively maintained Karakeep:

## Service Updates
- Update Docker image: ghcr.io/hoarder-app/hoarder → ghcr.io/karakeep-app/karakeep
- Update environment variables: HOARDER_VERSION → KARAKEEP_VERSION
- Upgrade Meilisearch: v1.6 → v1.13.3 for better search performance
- Update Glance labels and service references to Karakeep

## Data Preservation
- Maintain same domain: bookmarks.thesatelliteoflove.com
- Preserve volume structure: data and meilisearch volumes unchanged
- Keep directory structure: /opt/stacks/hoarder/ for continuity
- Maintain container naming for Caddyfile compatibility

## Meilisearch Migration
- Resolved database version incompatibility (v1.6.2 → v1.13.3)
- Backed up old database and created fresh v1.13.3 compatible database
- Manual reindex required via Admin Settings > Background Jobs

## Documentation Updates
- Update all service references from Hoarder to Karakeep
- Add both 'hoarder' and 'karakeep' tags for deployment flexibility
- Maintain backwards compatibility for existing automation

## Benefits
- Access to latest Karakeep features and security updates
- Continued development support (Hoarder discontinued)
- Improved search performance with Meilisearch v1.13.3
- Zero data loss during migration

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-06 14:15:36 -06:00

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, Karakeep, 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