Files
linumiq_net-user 3b3f589d64 dev: document server-only pieces (authorizer + frps.toml)
Add dev/SERVER-ONLY.md (extended check-subdomain authorizer code + dev frps
notes) and dev/frps/frps.toml.example (sanitized template) so the gitignored,
server-only parts of the dev setup are reproducible from the repo.
2026-05-30 14:18:53 +02:00

2.6 KiB

Server-only dev pieces (NOT in git)

Two files required by the dev environment live only on the server because they sit under gitignored paths (Supabase volumes/ and the secret-bearing frps.toml), matching the production gitignore policy. They are documented here so the dev setup is fully reproducible from the repo.


1. Shared on-demand-TLS authorizer (prod check-subdomain edge function)

Path on server (gitignored, prod stack): /docker/supabase/volumes/functions/check-subdomain/index.ts

The shared Caddy uses a single global on_demand_tls { ask ... } endpoint, so this prod function authorizes dev hostnames too. It was extended additively — the prod allow-list logic is byte-for-byte unchanged. The added block, placed at the top of the request handler:

// Dev environment (served by the same shared Caddy).
const DEV_RESERVED = new Set<string>([
  "app-dev.linumiq.net",
  "api-dev.linumiq.net",
]);
const DEV_SUFFIX = ".dev.linumiq.net";
const DEV_AUTHORIZER = "http://supabase-dev-edge-functions:9000/check-subdomain";

// ...inside Deno.serve handler, before the prod reserved/label checks:

// Dev reserved hosts served by the shared Caddy.
if (DEV_RESERVED.has(domain)) {
  return new Response("ok: dev reserved", { status: 200 });
}

// Dev tunnel subdomains: delegate to the dev authorizer, which validates the
// label against the dev tunnels table. Fail closed if it is unreachable.
if (domain.endsWith(DEV_SUFFIX)) {
  try {
    const r = await fetch(
      `${DEV_AUTHORIZER}?domain=${encodeURIComponent(domain)}`,
    );
    const body = await r.text();
    return new Response(body, { status: r.status });
  } catch (_e) {
    return deny("dev authorizer unreachable");
  }
}

The dev authorizer it delegates to is the unmodified prod logic running in the dev stack (/docker/dev/supabase/volumes/functions/check-subdomain/index.ts, identical to prod's original, with TUNNEL_BASE_DOMAIN=dev.linumiq.net).

To reach the dev authorizer, the prod functions container is also attached to the dev_edge network (see caddy/supabase compose). After editing, restart: cd /docker/supabase && docker compose restart functions.


2. Dev frps config (/docker/dev/frps/frps.toml)

Gitignored because it carries the dev frps dashboard password. A sanitized template is tracked at frps/frps.toml.example; copy it and set the password.


3. Dev secrets

All dev secrets are generated fresh and independent of prod. They live in the gitignored */.env / .env.production files under /docker/dev/ and in /docker/dev/.dev-secrets.env. Never commit them.