Tailnet-only (Serve, no Funnel) compose variants

Three more composes — compose.tailnet.yml, compose.tailnet.frontend.yml,
compose.tailnet.backend.yml — mirror the funnel set exactly but mount
serve.default/frontend/backend.tailnet.json, which drop AllowFunnel. The
sidecar still registers and serves HTTPS with a tailnet certificate, but
nothing is exposed publicly; Serve also needs no ACL change.

Project names carry a -tailnet suffix so both sets can coexist, and the
README explains that each set needs its own data directory (or host), plus
how to switch a host between funnel and tailnet by starting the other file
with the same .env.

Verified: all six composes validate with docker compose config, and the
six serve configs split cleanly into funnel (AllowFunnel present) and
tailnet-only (absent).
This commit is contained in:
2026-09-18 11:21:48 -05:00
parent ce016fb221
commit 30b1a1a4b0
8 changed files with 375 additions and 6 deletions
+32 -2
View File
@@ -5,7 +5,9 @@ sidecar. Nothing is published on the host's ports and no system nginx or
reverse proxy is involved: the sidecar shares the nginx service's network
namespace and Tailscale Serve/Funnel exposes it.
| Compose | Services | Funnel | Serve config |
## Funnel set (public HTTPS)
| Compose | Services | Entry point | Serve config |
| --- | --- | --- | --- |
| `compose.yml` (default) | mariadb, redis, backend, frontend, nginx, tailscale | `https://<host>.<tailnet>.ts.net` → nginx → backend + SPA | `serve.default.json` |
| `compose.frontend.yml` | frontend, nginx, tailscale | `https://<host>.<tailnet>.ts.net` → nginx → SPA only | `serve.frontend.json` |
@@ -15,15 +17,43 @@ Funnel can only expose ports **443**, **8443** and **10000**, so the separate
backend uses 8443. Change it in `serve.backend.json` (and `.env`) if you
prefer 10000.
## Tailnet-only set (no Funnel)
The same three stacks without `AllowFunnel` in the serve config: the sidecar
still registers the node and serves over HTTPS with a tailnet certificate,
but only devices on your tailnet can reach it — nothing is exposed to the
public internet.
| Compose | Serve config | Reachable at |
| --- | --- | --- |
| `compose.tailnet.yml` (both) | `serve.default.tailnet.json` | `https://<host>.<tailnet>.ts.net` |
| `compose.tailnet.frontend.yml` | `serve.frontend.tailnet.json` | `https://<host>.<tailnet>.ts.net` |
| `compose.tailnet.backend.yml` | `serve.backend.tailnet.json` | `https://<host>.<tailnet>.ts.net:8443` |
```bash
docker compose -f compose.tailnet.yml up -d
# or compose.tailnet.frontend.yml / compose.tailnet.backend.yml
```
Notes:
- Project names are `…-tailnet` so both sets can be installed side by side.
- Both sets use the same `deploy/data` directory (library, database, logs).
Run one set per data directory — two MariaDB instances on one data dir would
corrupt it. Giving the tailnet set its own `TS_HOSTNAME` (or running it on a
second host) is the way to run both.
- Switching a host from funnel to tailnet (or back) is just starting the other
compose file with the same `.env`.
## Usage
```bash
cd deploy
cp .env.example .env # fill in TS_AUTHKEY, SECRET_KEY, ALLOWED_HOSTS, ...
docker compose up -d # default: everything on one host
docker compose up -d # default: everything on one host, public funnel
# or
docker compose -f compose.frontend.yml up -d
docker compose -f compose.backend.yml up -d
# tailnet-only (no public funnel): compose.tailnet*.yml, see below
```
The images are pulled from the Gitea registry; append `--build` (or run the