SimpleLogin takes only https redirect addresses, each registered exactly, so the instance's SimpleLogin app registers one page on the register's web server, /simplelogin-callback, which sends the browser on to the app that began the sign-in: a 303 to the desktop's loopback (127.0.0.1, a port per app) or the phone's scheme, chosen by the marker the state begins with (`<app>-<platform>.<rest>`, the rest 1 to 512 characters of base64url), from a fixed table, so it sends nobody anywhere else. It forwards the code or SimpleLogin's error (`deny`) with the state and nothing else, refuses anything malformed, repeated or not a GET with a page that repeats nothing it was given, and keeps and logs nothing (no-store, no referrer). It is built ahead of the sign-in itself so development can sign in through learn.halkyon.eu's page, which the development app registers too. Android's assetlinks.json for Halkyon Learn signed with the release key is answered by the Caddyfile on learn.halkyon.eu alone: the one domain the project's builds name, and the server knows no app's key. A root test holds its fingerprint to tool/release/android-certificate.sha256. The app's intent filter comes with the sign-in; iOS's association waits for an Apple team ID. The profile page's language choice and look move to common/web_page.dart, shared by both pages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
68 lines
3 KiB
Caddyfile
68 lines
3 KiB
Caddyfile
# Caddy forwards to the API server, and profile pages (ADR 0011), the dictionaries
|
|
# devices download (ADR 0012) and SimpleLogin's forwarding page (ADR 0020) to the web
|
|
# server (8082), which serves nothing else. Never the calls between the instance's
|
|
# services (`/halkyon-base/…`, ADR 0016): they reach each other on its own network. Insights (8081) doesn't run in production;
|
|
# if it is ever re-enabled, reach it through an SSH tunnel, never through this file.
|
|
#
|
|
# {$DOMAIN} is `learn.halkyon.eu` on its server, where Caddy obtains and renews a
|
|
# Let's Encrypt certificate by itself, and `http://localhost` for the local rehearsal.
|
|
# {$ACCOUNT_SITE} is the account domain handles are on where it isn't {$DOMAIN}
|
|
# (`halkyon.eu`), whose profile pages this instance serves; empty for none.
|
|
{$DOMAIN} {$ACCOUNT_SITE} {
|
|
encode zstd gzip
|
|
|
|
# Profile pages, `/@handle`; asked for on the other host, they send the visitor to
|
|
# their own address.
|
|
@profile path /@*
|
|
handle @profile {
|
|
reverse_proxy server:8082
|
|
}
|
|
|
|
# The account domain serves profile pages alone. (An expression: a host matcher of
|
|
# an empty variable would match every host.)
|
|
@account expression `{host} == "{$ACCOUNT_SITE}"`
|
|
handle @account {
|
|
respond 404
|
|
}
|
|
|
|
# SimpleLogin's forwarding page (ADR 0020): where SimpleLogin sends a sign-in back,
|
|
# which sends it on to the app that began it, on the desktop or a phone.
|
|
@simplelogin path /simplelogin-callback
|
|
handle @simplelogin {
|
|
reverse_proxy server:8082
|
|
}
|
|
|
|
# Android's statement that Halkyon Learn, signed with the project's key
|
|
# (tool/release/android-certificate.sha256), opens learn.halkyon.eu's links
|
|
# itself (App Links, ADR 0020's D9), so SimpleLogin's way back reaches the app
|
|
# without the forwarding page. On learn.halkyon.eu alone, the one instance the
|
|
# project's builds name: another operator's domain is no link of the project's
|
|
# app. Written here rather than by the server, which knows no app's key.
|
|
@assetlinks {
|
|
host learn.halkyon.eu
|
|
path /.well-known/assetlinks.json
|
|
}
|
|
handle @assetlinks {
|
|
header Content-Type application/json
|
|
respond `[{"relation":["delegate_permission/common.handle_all_urls"],"target":{"namespace":"android_app","package_name":"app.halkyon.learn","sha256_cert_fingerprints":["27:E2:43:FC:BD:C8:26:FF:98:AB:7D:BB:10:43:6C:98:C3:BE:A2:4B:2A:01:5E:94:E4:CF:C7:D1:FC:2A:00:6C"]}}]` 200
|
|
}
|
|
|
|
# The dictionaries devices download to look Japanese up by themselves, named by
|
|
# their hashes; already compressed.
|
|
handle /device-dictionaries/* {
|
|
reverse_proxy server:8082
|
|
}
|
|
|
|
# Serverpod's streaming methods use WebSockets; reverse_proxy upgrades them as-is.
|
|
# Caddy puts the visitor's address last in X-Forwarded-For (what a visitor sends
|
|
# there it replaces), which the server's per-network limits count by, as
|
|
# TRUSTED_PROXIES names Caddy (compose.yaml); the server never reads the Forwarded
|
|
# header, which Caddy passes on as sent.
|
|
handle {
|
|
reverse_proxy server:8080
|
|
}
|
|
}
|
|
|
|
# The sites of the sidecars switched on (sidecars/README.md), which their compose files
|
|
# mount into sidecars/; none without.
|
|
import sidecars/*.caddy
|