infra/CLAUDE.md

193 lines
No EOL
5.7 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Overview
This is a multi-environment infrastructure-as-code repository managing:
- **Ansible**: Configuration management for servers across multiple environments (VNTX, home, app servers)
- **Terraform**: DNS infrastructure management across DNSimple, Porkbun, and PowerDNS
- **Home Lab**: Server configurations with Tailscale integration
## Common Commands
### Ansible Operations
```bash
# Run main playbook
cd ansible && ./run.sh
# Bootstrap new host
make bootstrap-init HOSTNAME=hostname ANSIBLE_HOST=ip_address
# Run specific playbook
ansible-playbook general.yml
# Run with specific tags
ansible-playbook -t caddy general.yml
# Gather facts from all hosts
make facts
```
### Terraform Operations
**IMPORTANT**: Use OpenTofu (tofu) instead of terraform for all operations.
```bash
cd terraform
tofu init
tofu plan
tofu apply
# Format terraform files before committing
tofu fmt
```
### Kubernetes Operations (K3s cluster at 204.110.191.2)
```bash
# Set kubeconfig
export KUBECONFIG=/Users/graham/dev/infra/home/ansible/kubeconfig
# Deploy APRS.me application
cd home/cluster/aprs
./deploy.sh
# Check deployment status
kubectl get pods -n aprs
kubectl get svc -n aprs
```
### Talos Operations
```bash
# Apply configuration to nodes (from cluster directory)
talosctl apply-config --talosconfig=./talosconfig -e 10.0.101.21 --nodes 10.0.101.21 --file controlplane.yaml --config-patch @node1.patch.yaml --config-patch @tailscale.patch.yaml
# Check node status
talosctl --talosconfig=./talosconfig -e 10.0.101.21 get nodes
# Bootstrap cluster (only needed once)
talosctl --talosconfig=./talosconfig -e 10.0.101.21 bootstrap
# Get kubeconfig
talosctl --talosconfig=./talosconfig -e 10.0.101.21 kubeconfig
```
## Architecture
### Directory Structure
- `ansible/` - Ansible playbooks and roles for server configuration
- `roles/` - Reusable roles (base, caddy, docker, resolvers, etc.)
- `group_vars/` - Group-specific variables
- `host_vars/` - Host-specific variables
- Main playbooks: `playbook.yml`, `general.yml`, `bootstrap.yml`
- `home/terraform/` - DNS infrastructure management
- Manages domains: w5isp.com, vntx.net/org, manero.org, mcintire.me, gridmap.org
- Providers: DNSimple, Porkbun, PowerDNS (reverse DNS)
- `home/` - Home lab configurations
- `cluster/` - Kubernetes application deployments
- `aprs/` - APRS.me deployment with PostgreSQL/PostGIS and Redis
- `wavelog/` - Wavelog amateur radio logging application
- `terraform/` - DNS infrastructure management
### Key Infrastructure Services
**Monitoring**: Icinga2 with MariaDB backend
**DNS**: Unbound resolvers, PowerDNS for reverse zones
**VPN**: Tailscale integration across environments
**Web Proxy**: Caddy for reverse proxy and SSL termination
### Security Notes
- Ansible user (UID 10001) with passwordless sudo
- SSH keys fetched from GitHub for authentication
- Tailscale requires `TAILSCALE_KEY` environment variable
- Terraform credentials should use environment variables (TF_VAR_*)
## Development Workflow
### Adding New Hosts
1. Add host to `ansible/hosts` inventory
2. Create host_vars file if needed
3. Run bootstrap: `make bootstrap-init HOSTNAME=x ANSIBLE_HOST=y`
4. Apply configuration: `ansible-playbook -l hostname general.yml`
### DNS Changes
1. Edit appropriate `home/terraform/dns_*.tf` file
2. Run `tofu fmt` to format
3. Review with `tofu plan`
4. Apply with `tofu apply`
## Testing
### Ansible
```bash
# Syntax check
ansible-playbook --syntax-check playbook.yml
# Dry run
ansible-playbook --check playbook.yml
# Test on specific host
ansible-playbook -l hostname playbook.yml
```
### Terraform
```bash
tofu validate
tofu plan
```
## Recent Infrastructure Updates
### K3s Cluster at 204.110.191.2
- **Purpose**: Home lab Kubernetes cluster
- **Node1 IPs**:
- Public: 204.110.191.2
- Tailscale: 100.102.235.20
- Internal: 10.0.101.21
- **API Access**: Currently only available on 10.0.101.21:6443 (not on Tailscale)
- **Context**: Use `kubectl config use-context homelab` to access
- **Storage**: Longhorn for persistent volumes
- **Applications**:
- **APRS.me**: Amateur radio APRS tracking application (https://aprs.me)
- PostgreSQL 17 with PostGIS (100GB Longhorn PVC)
- Redis for caching
- 2-replica StatefulSet for high availability
- Erlang clustering enabled
- LoadBalancer service assigned: 10.0.101.32
- **Note**: ghcr.io/aprsme/aprs.me:latest requires authentication
- Deploy with: `cd home/cluster/aprs && ./deploy.sh`
- **Wavelog**: Amateur radio logging application (https://log.w5isp.com)
- MariaDB 11 database (10GB storage)
- 20GB storage for configs, backups, uploads, QSL cards
- PHP application with custom limits (50MB uploads, 256MB memory)
- Deploy with: `cd home/cluster/wavelog && ./deploy.sh`
### New Server: w5isp.w5isp.com (204.110.191.200)
- **Purpose**: Single-node server running Debian 13
- **Features**:
- Web services with automatic SSL
- Single public IP handles all services
### DNS Configuration
- **Photos**: photos.w5isp.com → 204.110.191.212 (Caddy) → 100.107.11.77:2283
- **Mailcow**: mcintire.me mail records → mail.w5isp.com (sync.w5isp.com at 204.110.191.216)
- Full mail setup with MX, SPF, DKIM, DMARC records
- Autodiscover/Autoconfig for mail clients
- Backup MX: mail.nsnw.ca (priority 20)
- **Note**: sync.w5isp.com is the Mailcow server (not using Caddy proxy)
## Code Guidelines
### Communication Practices
- Do not ever reply with "you're right". Just fix the issue
- Never say you're right, just accept it and move on
### Notes for Claude
- As you learn new things, keep claude.md updated
## Clusters
- k3s cluster at 204.110.191.2