- Bridge: Express API server with SQLite (projects, tasks, executions, outputs) - Dashboard: Next.js app rewired from WebSocket gateway to Tiger Bridge HTTP API - Tasks: Kanban board with drag-drop, project management with CRUD - Dispatch: Task dispatch to sandbox with file watcher for status updates - UI: Container health panel, workspace browser, logs viewer, output viewer Critical fixes: - Use execInSandbox instead of execOnHost for container operations - Watch symlink path instead of container-internal path - URL-encoded params for GET requests instead of body - PUT/DELETE support added to useBridgeRequest Sprints 1-5 complete. Ready for VPS deployment.
110 lines
5.4 KiB
Caddyfile
110 lines
5.4 KiB
Caddyfile
# ══════════════════════════════════════════════════════════════════════════════
|
|
# Caddyfile — Tiger Control Plane
|
|
# Deployed at: agent.manohargupta.com
|
|
#
|
|
# What Caddy does here:
|
|
# 1. Automatically obtains and renews TLS certificates via Let's Encrypt
|
|
# 2. Handles HTTPS → HTTP reverse proxy to the Next.js dashboard
|
|
# 3. Protects certain routes with basic auth (exec, restart, config write)
|
|
# 4. Sets security headers
|
|
#
|
|
# To deploy on your Hetzner VPS:
|
|
# 1. Install Caddy: apt install caddy
|
|
# 2. Copy this file: sudo cp Caddyfile /etc/caddy/Caddyfile
|
|
# 3. Set the basic auth password hash (see instructions below)
|
|
# 4. Reload: sudo systemctl reload caddy
|
|
#
|
|
# ── How to generate the basicauth password hash ──────────────────────────────
|
|
# Run this on your VPS:
|
|
# caddy hash-password --plaintext "your-password-here"
|
|
# Then paste the output as the hash below (the $2a$... string).
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
|
|
|
agent.manohargupta.com {
|
|
|
|
# ── TLS ──────────────────────────────────────────────────────────────────
|
|
# Caddy automatically fetches and renews TLS from Let's Encrypt.
|
|
# Your VPS must have ports 80 and 443 open for this to work.
|
|
tls {
|
|
# Optional: use a specific email for Let's Encrypt notifications
|
|
# email admin@manohargupta.com
|
|
}
|
|
|
|
# ── Security headers ─────────────────────────────────────────────────────
|
|
# These headers protect against common web attacks.
|
|
# X-Frame-Options prevents your dashboard from being embedded in iframes.
|
|
# X-Content-Type-Options stops browsers from guessing MIME types.
|
|
header {
|
|
X-Frame-Options "SAMEORIGIN"
|
|
X-Content-Type-Options "nosniff"
|
|
Referrer-Policy "strict-origin-when-cross-origin"
|
|
# Remove server info from responses
|
|
-Server
|
|
}
|
|
|
|
# ── Protected routes (require basic auth) ────────────────────────────────
|
|
# These are the "dangerous" endpoints — exec, restart, config writes.
|
|
# Basic auth adds a second layer of protection on top of the bridge token.
|
|
#
|
|
# Generate hash with: caddy hash-password --plaintext "YOUR_PASSWORD"
|
|
# Replace "CHANGE_ME_HASH" with the output.
|
|
|
|
@protected path /api/tiger/exec /api/tiger/restart /api/tiger/config
|
|
basicauth @protected {
|
|
# Username: tiger
|
|
# Hash: run `caddy hash-password --plaintext "your-password"` and paste here
|
|
tiger $2a$14$CHANGE_ME_HASH_GENERATED_BY_CADDY_HASH_PASSWORD_COMMAND
|
|
}
|
|
|
|
# ── Reverse proxy to Next.js dashboard ───────────────────────────────────
|
|
# The dashboard runs on port 3000 (localhost only).
|
|
# All requests go here by default.
|
|
reverse_proxy localhost:3000 {
|
|
# Forward the real client IP to Next.js so logs show the right IP
|
|
header_up X-Real-IP {remote_host}
|
|
header_up X-Forwarded-For {remote_host}
|
|
header_up X-Forwarded-Proto {scheme}
|
|
|
|
# Health check — Caddy verifies the backend is alive before routing
|
|
health_uri /api/tiger/status
|
|
health_interval 30s
|
|
health_timeout 10s
|
|
}
|
|
|
|
# ── Handle SSE (Server-Sent Events) correctly ────────────────────────────
|
|
# SSE is a streaming connection — we must disable buffering.
|
|
# Without this, Caddy buffers the stream and logs appear with a delay.
|
|
@sse path /api/tiger/logs
|
|
handle @sse {
|
|
reverse_proxy localhost:3000 {
|
|
header_up X-Real-IP {remote_host}
|
|
# Flush immediately — critical for streaming
|
|
flush_interval -1
|
|
}
|
|
}
|
|
|
|
# ── Logging ──────────────────────────────────────────────────────────────
|
|
log {
|
|
output file /var/log/caddy/agent.manohargupta.com.log {
|
|
roll_size 10MB
|
|
roll_keep 5
|
|
}
|
|
format json
|
|
}
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
|
# Tiger Bridge direct access — INTERNAL USE ONLY
|
|
# The bridge listens on localhost:3456 and is NOT publicly exposed.
|
|
# All bridge calls go through the Next.js dashboard routes.
|
|
#
|
|
# If you ever need to expose the bridge directly (debugging only),
|
|
# uncomment and use the block below. Remember to set a strong token!
|
|
# ══════════════════════════════════════════════════════════════════════════════
|
|
|
|
# bridge.agent.manohargupta.com {
|
|
# reverse_proxy localhost:3456
|
|
# tls {
|
|
# # email admin@manohargupta.com
|
|
# }
|
|
# }
|