docs: add comprehensive developer guide (mdBook)
Add a browsable mdBook developer guide under docs/dev-guide/ covering the full PiCloud v1.1.9 surface for developers building on the platform: - Guide: introduction, 10-minute quickstart, core concepts, writing scripts - Tutorials: 5 end-to-end example apps (URL shortener, webhook receiver, TODO API with auth, scheduled report, file-upload service) + feature matrix - SDK reference: kv/docs/files, pubsub/queue, http, email, users, secrets, invoke/retry/dead_letters, stdlib, ctx & events - HTTP API reference: every /api/v1 endpoint, auth, and capability - CLI reference: the `pic` client + the server admin recovery command - Config: every PICLOUD_* env var, capabilities & roles - Deployment: Docker Compose, bare binary, Caddy/TLS, production checklist - Operations: security, best practices, troubleshooting Every example was built and run against a live instance; SDK signatures, endpoint paths, and env vars were verified against source. Build the site with `mdbook serve docs/dev-guide`. A pointer is added to README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
71
docs/dev-guide/src/deploy/caddy-tls.md
Normal file
71
docs/dev-guide/src/deploy/caddy-tls.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Caddy & TLS
|
||||
|
||||
Caddy is the single entry point in front of PiCloud. The same topology serves dev and production — only
|
||||
the upstream targets and TLS settings change.
|
||||
|
||||
## Routing topology
|
||||
|
||||
Caddy routes by path prefix (from `caddy/Caddyfile`):
|
||||
|
||||
| Path | Goes to |
|
||||
|---|---|
|
||||
| `/healthz`, `/version` | picloud (liveness + version) |
|
||||
| `/api/v1/admin/*` | picloud (control plane) |
|
||||
| `/api/v1/execute/*` | picloud (execute-by-id) |
|
||||
| `/api/*` (anything else) | **404** — reserved for future API versions |
|
||||
| `/admin/*` | the dashboard SPA |
|
||||
| **everything else** | picloud's **user-route matcher** — your scripts' routes |
|
||||
|
||||
That final catch-all is what makes arbitrary user paths like `/hello` or `/r/abc123` work: Caddy
|
||||
forwards them to picloud, which matches them against the [route table](../guide/concepts.md#routes-and-domains)
|
||||
(or returns a JSON `404`). This is why your routes can't use the reserved prefixes `/api/`, `/admin/`,
|
||||
`/healthz`, `/version` — Caddy would never forward them to the matcher.
|
||||
|
||||
## Security headers & body limit
|
||||
|
||||
The Caddyfile adds defense-in-depth headers and a hard body cap:
|
||||
|
||||
- `X-Content-Type-Options: nosniff` and `Referrer-Policy: no-referrer` on **every** response.
|
||||
- A strict CSP, `X-Frame-Options: DENY`, `Cache-Control: no-store`, and a locked-down
|
||||
`Permissions-Policy` on the **dashboard** and **admin API**.
|
||||
- A **12 MB request-body ceiling** at the proxy (just above the orchestrator's 10 MiB user-route read).
|
||||
- **User-route responses get no CSP on purpose** — your scripts own their own response headers. The
|
||||
`?` (set-if-missing) operator means a script's own header wins over the default.
|
||||
|
||||
## Production: HTTPS with Let's Encrypt
|
||||
|
||||
Layer the production overlay, which swaps in `caddy/Caddyfile.prod` and exposes 80/443:
|
||||
|
||||
```sh
|
||||
export PICLOUD_DOMAIN="picloud.example.com"
|
||||
export PICLOUD_ADMIN_EMAIL="you@example.com"
|
||||
export POSTGRES_PASSWORD="$(head -c 24 /dev/urandom | base64)"
|
||||
export PICLOUD_SECRET_KEY="$(head -c 32 /dev/urandom | base64)"
|
||||
export PICLOUD_ADMIN_USERNAME="admin"
|
||||
export PICLOUD_ADMIN_PASSWORD="…"
|
||||
export PICLOUD_PUBLIC_BASE_URL="https://picloud.example.com"
|
||||
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
|
||||
```
|
||||
|
||||
Caddy obtains and renews a certificate for `PICLOUD_DOMAIN` automatically (HTTP/TLS-ALPN challenge — the
|
||||
host must be reachable on 80/443 from the internet). The prod overlay also:
|
||||
|
||||
- **removes the published Postgres port** (DB reachable only inside the compose network);
|
||||
- adds **HSTS** to every response (on top of the dev headers);
|
||||
- sets `restart: unless-stopped` on all services.
|
||||
|
||||
The prod Caddyfile reads `PICLOUD_DOMAIN` and `PICLOUD_ADMIN_EMAIL` from the environment, so set them
|
||||
before `up`.
|
||||
|
||||
## Custom domains for your apps
|
||||
|
||||
PiCloud's app [domains](../reference/rest-api/apps.md#domains) are matched by picloud *after* Caddy
|
||||
forwards the request — they're independent of Caddy's own host config. For multi-tenant setups
|
||||
(`{tenant}.example.com`), point a wildcard DNS record + Caddy cert at the box, then let each app claim
|
||||
its host pattern. The most-specific app claim wins; unclaimed hosts get a `404 no app claims host`.
|
||||
|
||||
## Adding a future API version
|
||||
|
||||
When `/api/v2/...` ships, add a `handle /api/v2/admin/* { … }` block before the catch-all `/api/*`
|
||||
404, mirroring the v1 block. The v1 routes stay live through the deprecation window.
|
||||
Reference in New Issue
Block a user