# Caddyfile for Hermes Local Knowledge Infrastructure # Routes: file browsing + search UI + obsidian/hermes access # Usage: # HOME=/home/ubuntu caddy run --config /path/to/Caddyfile { # Disable admin API for security admin off } # Bind to localhost; Tailscale Funnel handles public HTTPS :8080 { # CORS headers for search UI frontend header { Access-Control-Allow-Origin "*" Access-Control-Allow-Methods "GET, POST, OPTIONS" Access-Control-Allow-Headers "Content-Type" } # ===== Directory listing routes ===== # Root: overview page or /output redirect root * /home/ubuntu/files/output file_server browse # /output — generated HTML reports (public) route /output/* { root * /home/ubuntu/files/output file_server browse } # /hermes — skills, memories, plans (via symlink) route /hermes/* { root * /home/ubuntu/files/hermes file_server browse } # /obsidian — synced Obsidian vault (read-only) route /obsidian/* { root * /home/ubuntu/files/obsidian file_server browse } # /projects — code projects (read-only) route /projects/* { root * /home/ubuntu/files/projects file_server browse } # /private — private files (auth recommended) route /private/* { root * /home/ubuntu/files/private file_server browse } # ===== Search UI ===== # /search — Semantic search web UI route /search/* { root * /home/ubuntu/search-ui file_server } # ===== API routes ===== # /api/search — Search API (proxied to Python backend) route /api/* { reverse_proxy localhost:8081 } # Markdown files render as HTML when accessed without .md extension @md file { path *.md } handle @md { file_server } } # ===== Global settings ===== # Handle errors handle_errors { @404 expression {http.error.status_code} == 404 respond "404 — Not Found" @500 expression {http.error.status_code} >= 500 respond "500 — Internal Server Error" }