mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
docs: add Tailscale serve and funnel as a reverse-proxy option
This commit is contained in:
1 parent
5196aff766
commit
d10bc099c8
3 files changed
+113
No files matched your search
@@ -171,6 +171,7 @@ NEXT_PUBLIC_DASHBOARD_SNAPSHOT=false pnpm build
|
||||
| Next step | File |
|
||||
| ------------------------------------------------------------------- | ------------------------------------- |
|
||||
| TLS + reverse-proxy configuration | `docs/self-hosting/reverse-proxy.md` |
|
||||
| Tailnet-only HTTPS via `tailscale serve` (no reverse proxy) | `docs/self-hosting/tailscale.md` |
|
||||
| Push notifications — Web Push, Telegram, ntfy, webhook, email, APNs | `docs/self-hosting/notifications.md` |
|
||||
| Web/worker process split for horizontal scale | `docs/self-hosting/scaling.md` |
|
||||
| Off-host encrypted backups to S3/R2/B2 | `docs/ops/backup-restore.md` |
|
||||
|
||||
@@ -9,6 +9,11 @@ through unbuffered with a generous read timeout.
|
||||
This guide gives copy-paste blocks for five common fronts. Pick one;
|
||||
the env-var pairing is identical across them.
|
||||
|
||||
If the instance only needs to be reachable from your own devices, none
|
||||
of them is required: `tailscale serve` terminates trusted HTTPS on the
|
||||
tailnet with no extra container. See
|
||||
[`docs/self-hosting/tailscale.md`](tailscale.md).
|
||||
|
||||
## Pre-flight — env vars the proxy interacts with
|
||||
|
||||
| Variable | Required for | Notes |
|
||||
@@ -248,6 +253,11 @@ login works over HTTP. The trade-off is explicit: the session
|
||||
cookie crosses the wire unencrypted, so the network it traverses
|
||||
needs to be one you control.
|
||||
|
||||
For the Tailscale case specifically there is a better option than
|
||||
lifting the flag: `tailscale serve` gives the same surface real HTTPS
|
||||
with a tailnet-trusted certificate, and `SESSION_COOKIE_SECURE` stays
|
||||
unset. See [`docs/self-hosting/tailscale.md`](tailscale.md).
|
||||
|
||||
**Do not set this on a deployment that ever serves plain HTTP to the
|
||||
open internet.** Anyone with passive network access can capture the
|
||||
session cookie and impersonate the user. The right answer for any
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
# HealthLog over Tailscale
|
||||
|
||||
For a single Docker box that only you and your household need to reach,
|
||||
`tailscale serve` can stand in for the reverse proxy entirely. Tailscale
|
||||
terminates HTTPS with a certificate every device on your tailnet already
|
||||
trusts, there is no extra container to run and nothing to renew, and the
|
||||
free plan covers all of it. The trade is scope: the instance is reachable
|
||||
only from devices signed into your tailnet, which for a personal health
|
||||
record is usually the point.
|
||||
|
||||
Two modes exist, and the difference matters more here than for most apps:
|
||||
|
||||
- **`tailscale serve`** publishes HealthLog inside your tailnet only.
|
||||
Every device that should reach it runs the Tailscale client and signs
|
||||
into the same tailnet, including the iPhone if you use the iOS app.
|
||||
The instance is invisible from the public internet. This is the right
|
||||
default for a personal health record.
|
||||
- **`tailscale funnel`** publishes the same HTTPS endpoint to the public
|
||||
internet. No client is needed on the phone, but anyone on the internet
|
||||
can reach the sign-in page, so the instance becomes a public deployment
|
||||
and needs to be treated like one. Funnel is the deliberate opt-in, not
|
||||
the default.
|
||||
|
||||
## Set up `tailscale serve`
|
||||
|
||||
1. Install Tailscale on the Docker host and sign in. On macOS, the
|
||||
standalone app from tailscale.com is more full-featured than the App
|
||||
Store build; either works for this page.
|
||||
|
||||
2. With the compose stack running on `localhost:3000`, run:
|
||||
|
||||
```bash
|
||||
tailscale serve --bg localhost:3000
|
||||
```
|
||||
|
||||
3. If HTTPS certificates are not yet enabled for your tailnet, the CLI
|
||||
says so and prints the admin-console link that enables them. Follow
|
||||
that link once; it is a one-time, per-tailnet step.
|
||||
|
||||
4. The CLI prints the HTTPS URL it now serves, of the form
|
||||
`https://<machine>.<tailnet>.ts.net`. `--bg` persists the
|
||||
configuration across restarts, so this is a run-once command, not
|
||||
something to add to a boot script.
|
||||
|
||||
## Point HealthLog at the tailnet URL
|
||||
|
||||
Set the URL pair in `.env` to the exact HTTPS URL the CLI printed:
|
||||
|
||||
```env
|
||||
NEXT_PUBLIC_APP_URL="https://your-machine.your-tailnet.ts.net"
|
||||
APP_URL="https://your-machine.your-tailnet.ts.net"
|
||||
```
|
||||
|
||||
Both variables are on the bundled compose `environment:` whitelist, so
|
||||
values in `.env` reach the container. Restart to pick them up:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Cookies and TLS
|
||||
|
||||
`tailscale serve` terminates real HTTPS, so the session cookie's
|
||||
`Secure` flag works exactly as it does behind any TLS-terminating proxy.
|
||||
Leave `SESSION_COOKIE_SECURE` unset. The plain-HTTP escape hatch in the
|
||||
[reverse-proxy guide](reverse-proxy.md) exists for serving the raw
|
||||
`http://host:3000` surface across a trusted network without a TLS front;
|
||||
once `serve` fronts the app you do not need it.
|
||||
|
||||
`serve` is a single proxy hop in front of the app, which is the topology
|
||||
the default `TRUST_PROXY_HOPS=1` assumes. If the wide-event log shows a
|
||||
null client IP after the switch, or every caller lands in one shared
|
||||
rate-limit bucket, the "Verifying the proxy chain" section of the
|
||||
reverse-proxy guide shows how to read the mismatch warning and adjust.
|
||||
|
||||
## The iOS app and Apple Health
|
||||
|
||||
With `serve`, the iPhone reaches the instance the same way every other
|
||||
device does: install Tailscale from the App Store on the phone, sign
|
||||
into the same tailnet, then point the HealthLog iOS app at the
|
||||
`https://<machine>.<tailnet>.ts.net` URL. Apple Health sync works over
|
||||
this path; from the app's perspective the tailnet URL is an ordinary
|
||||
HTTPS origin with a trusted certificate.
|
||||
|
||||
## Public exposure with `tailscale funnel`
|
||||
|
||||
If the instance must be reachable without the Tailscale client, for
|
||||
example for someone outside your household's tailnet, `tailscale funnel`
|
||||
publishes the endpoint to the public internet. The command shape mirrors
|
||||
`serve`; follow the CLI's own output, which walks through any
|
||||
admin-console enablement funnel needs on your tailnet.
|
||||
|
||||
Before opening it, accept what it means: the sign-in page is now
|
||||
internet-facing. Close public registration once every household member
|
||||
has an account (the toggle lives in `/admin`, see
|
||||
[`getting-started.md`](getting-started.md)), and keep the image current
|
||||
via `pull_policy: always` as documented there. Everything the other
|
||||
guides say about publicly reachable hosts applies unchanged.
|
||||
|
||||
## Costs
|
||||
|
||||
The free Tailscale plan is enough for everything on this page.
|
||||
Reference in new issue
Block a user