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

114 lines
5.3 KiB
Markdown

# 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
```bash
# 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
```bash
# 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:
```yaml
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