{"id":50420478,"url":"https://github.com/robotdad/frontdoor","last_synced_at":"2026-05-31T08:02:20.209Z","repository":{"id":346966825,"uuid":"1192189440","full_name":"robotdad/frontdoor","owner":"robotdad","description":"Local discovery portal for developer hosts","archived":false,"fork":false,"pushed_at":"2026-03-26T16:41:28.000Z","size":141,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T02:06:31.370Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robotdad.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-26T01:17:33.000Z","updated_at":"2026-03-26T16:41:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/robotdad/frontdoor","commit_stats":null,"previous_names":["robotdad/frontdoor"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/robotdad/frontdoor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotdad%2Ffrontdoor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotdad%2Ffrontdoor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotdad%2Ffrontdoor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotdad%2Ffrontdoor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robotdad","download_url":"https://codeload.github.com/robotdad/frontdoor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotdad%2Ffrontdoor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33723549,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-31T08:02:19.332Z","updated_at":"2026-05-31T08:02:20.200Z","avatar_url":"https://github.com/robotdad.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"assets/branding/icons/frontdoor-icon-128.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"assets/branding/icons/frontdoor-icon-128.png\"\u003e\n    \u003cimg alt=\"frontdoor\" src=\"assets/branding/icons/frontdoor-icon-128.png\" width=\"80\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n# frontdoor\n\n**frontdoor** is a developer-host dashboard and shared authentication gateway. It runs on your Linux machine and provides a single authenticated entry point that shows all your locally-running web apps in one place.\n\n## What frontdoor does\n\n- **Discovers services** from Caddy virtual host configs in `/etc/caddy/conf.d/` and TCP probing of known ports — no manual registration required for most apps.\n- **Shows status** with green/red dots: green means the upstream port is responding, red means it's down.\n- **Shared auth via domain cookie** — one login covers all apps on the host. frontdoor sets a `frontdoor_session` cookie on the root domain; apps that check this cookie get authentication for free.\n- **Authenticated identity forwarding** — Caddy's `forward_auth` validates every request through frontdoor, then injects the `X-Authenticated-User` header into the proxied request so downstream apps know who's calling without implementing their own auth.\n- **Detects unregistered processes** — TCP probe of the 8440+ port range surfaces processes that are listening but have no Caddy config yet, so nothing hides from the dashboard.\n\n## Install\n\n```bash\nsudo deploy/install.sh\n```\n\n### What the installer does\n\n1. **Installs to `/opt/frontdoor`** — copies the app, creates a virtualenv, installs Python dependencies.\n2. **Migrates filebrowser to `conf.d/`** — moves the filebrowser Caddy config into `/etc/caddy/conf.d/` and updates it to run on port 8447, freeing up the default port.\n3. **Takes over port 443** — configures Caddy to serve frontdoor on the host's Tailscale FQDN over HTTPS.\n4. **Short hostname redirect** — adds a redirect so `http://\u003cshort-hostname\u003e/` resolves to the HTTPS Tailscale address.\n5. **Creates `manifests/`** — initialises `/opt/frontdoor/manifests/` for per-app JSON metadata files that apps can drop in to customize their dashboard entry.\n\n## Using with Amplifier\n\nThe `frontdoor` bundle gives Amplifier the knowledge to inventory your host, provision new web apps, and wire them into the shared Caddy + Tailscale infrastructure — following the port allocation, auth, and service discovery conventions used across all frontdoor-managed hosts.\n\n### Prerequisites\n\n- [Amplifier](https://github.com/microsoft/amplifier) installed:\n  ```bash\n  uv tool install git+https://github.com/microsoft/amplifier\n  amplifier init   # configure your AI provider if you haven't yet\n  ```\n- Target host with **Caddy** installed. **Tailscale** is recommended for automatic cert provisioning and FQDN detection but is not required.\n\n### Install the Bundle\n\n```bash\namplifier bundle add git+https://github.com/robotdad/frontdoor@main\namplifier bundle use frontdoor --local   # activate for your current session\n```\n\n### Register the Skills\n\nThe skills ship in this repo's `skills/` directory and are discovered separately from the bundle. Register them once:\n\n```bash\n# In an Amplifier session:\nload_skill(source=\"git+https://github.com/robotdad/frontdoor\")\n```\n\nOnce registered, `host-infra-discovery` and `web-app-setup` are available automatically whenever Amplifier thinks they're relevant — or you can invoke them explicitly.\n\n### Typical Workflow\n\n**Step 1 — Inventory the host before touching it:**\n```\n\"Run host-infra-discovery on this host and give me the summary table\"\n```\n\n**Step 2 — Set up a new web app:**\n```\n\"Using that summary, help me set up a new app called myapp\"\n```\n\nAmplifier will load the relevant skill, run the shell commands to detect available ports and existing infrastructure, generate deployment files in your project's `deploy/` directory from the templates, and leave activation to you — run `deploy/install.sh` when you're ready to go live.\n\n### One-Shot (No Installation)\n\n```bash\namplifier run --bundle git+https://github.com/robotdad/frontdoor@main \\\n  \"What web apps are currently running on this host?\"\n```\n\n### Keep Up to Date\n\n```bash\namplifier bundle refresh frontdoor\n```\n\n## Downstream app integration\n\nApps behind frontdoor receive the authenticated username via the `X-Authenticated-User` request header, injected by Caddy's `forward_auth`. No app-level auth needed.\n\n**Reading the header:**\n```python\nuser = request.headers.get(\"X-Authenticated-User\", \"unknown\")\n```\n\n**Required Caddy snippet** (in `/etc/caddy/conf.d/\u003capp\u003e.caddy`):\n```caddy\nforward_auth localhost:8420 {\n    uri /api/auth/validate\n    copy_headers X-Authenticated-User\n}\n```\n\nFor the full integration guide (ports, manifests, sign-out, templates), see the `web-app-setup` skill.\n\n### Companion app: filebrowser\n\n[filebrowser](https://github.com/robotdad/filebrowser) is designed to work with frontdoor out of the box. When deployed together, filebrowser inherits frontdoor's SSO and its install script automatically configures the `forward_auth` integration.\n\n## Protocol support\n\nfrontdoor validates authentication for both HTTP and WebSocket protocols. Understanding the protocol handling is important when integrating apps that use persistent connections.\n\n### HTTP (works out of the box)\n\nStandard HTTP requests flow through Caddy's `forward_auth` transparently:\n\n```\nRequest → Caddy → forward_auth → frontdoor /api/auth/validate (HTTP)\n  → validates frontdoor_session cookie\n  → 200 + X-Authenticated-User header (success)\n  → 401 (failure, Caddy redirects to /login)\n```\n\n### WebSocket (requires explicit handler)\n\nCaddy's `forward_auth` sends WebSocket Upgrade requests to the validate endpoint. Without an explicit WebSocket handler, FastAPI's `StaticFiles` catch-all crashes on the non-HTTP ASGI scope. frontdoor handles this with a dedicated `@router.websocket(\"/api/auth/validate\")` endpoint:\n\n```\nWS Upgrade → Caddy → forward_auth → frontdoor /api/auth/validate (WebSocket)\n  → validate_ws() reads cookie from handshake headers (before accept)\n  → websocket.accept(headers=[x-authenticated-user: \u003cname\u003e]) + close()  (success)\n  → websocket.close(code=4001)  (failure, 401-equivalent)\n```\n\nKey details:\n- The session cookie is available on WebSocket handshake headers **before** accept -- no need to accept the connection first\n- Close code `4001` is the 401-equivalent for WebSocket; Caddy interprets close as auth failure\n- The `websockets` library (v16+) is pulled in transitively via `uvicorn[standard]`\n\n### Enabling additional protocols\n\nIf a new protocol doesn't work through `forward_auth`, the pattern is:\n\n1. **Check if `forward_auth` passes the protocol correctly.** If yes, no changes needed.\n2. **If the protocol needs a persistent connection** (like WebSocket), the downstream app may need to:\n   - Add a Caddy `handle` block to route protocol-specific paths before `forward_auth`\n   - Implement a cookie bridge to issue an app-level session cookie for protocol auth\n   - See [filebrowser's terminal WebSocket bypass](https://github.com/robotdad/filebrowser) for the working pattern\n3. **If the protocol is HTTP-based** (like SSE), it should work through `forward_auth` without changes.\n\nThe general Caddy bypass pattern:\n```caddy\n# Route protocol-specific paths BEFORE forward_auth\nhandle /api/\u003cprotocol-path\u003e* {\n    reverse_proxy localhost:\u003capp-port\u003e\n}\n\n# Everything else goes through auth\nhandle {\n    forward_auth localhost:8420 {\n        uri /api/auth/validate\n        copy_headers X-Authenticated-User\n    }\n    reverse_proxy localhost:\u003capp-port\u003e\n}\n```\n\nSee `docs/protocol-support.dot` for the full decision flowchart.\n\n## Architecture diagrams\n\nThe `docs/` directory contains DOT/Graphviz architecture diagrams. These are the source of truth for system design -- no rendered images are committed. View them with `dot -Tsvg \u003cfile\u003e.dot` or a live Graphviz preview extension.\n\n| Diagram | What it covers |\n|---------|---------------|\n| `docs/architecture.dot` | System overview: infrastructure, frontend, backend, discovery pipeline, auth core, downstream apps |\n| `docs/auth-flow.dot` | HTTP and WebSocket auth flows side by side, login flow, why WebSocket needs special handling |\n| `docs/protocol-support.dot` | Protocol traversal patterns, decision flowchart for enabling new protocols, Caddy config patterns |\n\nThese diagrams are particularly useful for AI agents working on this codebase -- they encode the system topology in a machine-parseable format that can be analyzed with graph tools.\n\n## Status commands\n\nCheck the frontdoor service:\n\n```bash\nsystemctl status frontdoor\n```\n\nFollow logs:\n\n```bash\njournalctl -u frontdoor -f\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobotdad%2Ffrontdoor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobotdad%2Ffrontdoor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobotdad%2Ffrontdoor/lists"}