# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a nginx reverse proxy running on Fly.io that uses Tailscale to route traffic to internal servers. It provides: - HTTPS termination and routing for multiple subdomains - Rate limiting and bot protection - Real-time traffic metrics via GoAccess - Access to internal Tailscale network services ## Architecture The solution uses a multi-stage Docker build: - **Stage 1 (builder)**: Builds any application code (currently minimal) - **Stage 2 (tailscale)**: Downloads and extracts Tailscale binaries - **Stage 3 (production)**: Final Alpine image with nginx, Tailscale, and GoAccess ### Memory Optimization Configured for 256MB Fly.io containers: - **Go GC settings**: `GOGC=10` and `GOMEMLIMIT=100MiB` for aggressive Tailscale memory management - **GoAccess**: Static HTML generation (60-second intervals) instead of real-time WebSocket - **Nginx**: Reduced connection timeouts and buffer sizes - **Package optimization**: Minimal Alpine packages only ### Key Components - **nginx.conf**: Main configuration with rate limiting zones, server blocks for each subdomain, and GoAccess metrics endpoint - **start.sh**: Container startup script that initializes Tailscale, starts GoAccess, and launches nginx - **goaccess.sh**: GoAccess dashboard setup with real-time WebSocket support - **.htpasswd**: Password protection for metrics dashboard ## Common Commands ### Deployment ```bash fly deploy # Deploy to Fly.io fly secrets set TAILSCALE_AUTHKEY= # Set/renew Tailscale auth (expires every 90 days) fly certs create # Add SSL certificate for new hostname ``` ### Local Development ```bash docker build -t reverse-proxy . # Build Docker image docker run -p 8080:8080 reverse-proxy # Run locally (requires TAILSCALE_AUTHKEY env var) ``` ### Tailscale Management - Create reusable auth keys at: https://login.tailscale.com/admin/settings/keys - Auth keys expire every 90 days and must be renewed ## Adding New Services 1. Add new server block in `nginx.conf`: ```nginx server { listen 0.0.0.0:8080; listen [::]:8080; server_name new-service.ralsina.me; location / { limit_req zone=global burst=20 nodelay; proxy_pass http://internal-host:port; proxy_set_header X-Forwarded-Host $http_host; } } ``` 2. Create SSL certificate: `flyctl certs create new-service.ralsina.me` ## Rate Limiting Configuration - **global**: 10r/s (all requests) - **post_requests**: 3r/s (POST/PUT/DELETE) - **api_services**: 5r/s (API endpoints) - **unknown_ua**: 2r/s (bots/crawlers) Rate limits are applied per zone and configured for low-traffic scenarios (< 12 users). ## Metrics Dashboard - Access: https://metrics.ralsina.me - Authentication: username `metrics`, password stored in `.htpasswd` - Static HTML generation (updates every 60 seconds for memory efficiency) - Logs location: `/var/log/nginx/access.log` - Note: Real-time WebSocket disabled to reduce memory usage on 256MB containers ## Important Notes - All server blocks must listen on `0.0.0.0:8080` for Fly.io compatibility - Use `[::]:8080` for IPv6 support - Container exposes port 8080 only (external 443→8080 handled by Fly.io) - Tailscale hostname is set to `reverseproxy` in the Tailscale network