Portainer's git-stack checkout does not materialize sibling repo files
at the relative bind path, so ./serve-roms.json mounted as an empty
auto-created directory and tailscale serve failed ('is a directory').
Switch to an absolute /config/share/serve-roms.json bind (matching every
other stack's /config convention); the file is mirrored on the host.
53 lines
2.3 KiB
YAML
53 lines
2.3 KiB
YAML
# share stack — Tailscale `serve` nodes that expose individual INTERNAL services
|
|
# to EXTERNAL tailnet users (a friend on his own tailnet) over each node's 100.x
|
|
# CGNAT identity. No public exposure, no LAN access, and immune to the friend's
|
|
# home-subnet addressing (a node IP can never collide with his 192.168.1.0/24).
|
|
#
|
|
# Each service to share = one userspace Tailscale container that `tailscale serve`s
|
|
# straight to that service's backend, so the container joins that service's PRIVATE
|
|
# network (roms, foundry, media, ...) — NOT edge/Caddy.
|
|
#
|
|
# Shared, set-once-for-all plumbing:
|
|
# - Auth: ONE reusable, NON-ephemeral, TAGGED (tag:share) auth key in stack.env
|
|
# authenticates EVERY node here. Tagged nodes never expire.
|
|
# - ACL : ONE rule { src: [friend@…], dst: ["tag:share:443"] } governs them all.
|
|
# - Admin (one-time): enable MagicDNS + HTTPS certificates; add
|
|
# "tagOwners": { "tag:share": ["autogroup:admin"] }.
|
|
#
|
|
# To share a NEW service:
|
|
# 1. add a `serve-<svc>.json` here (Proxy -> http://<container>:<port>) AND
|
|
# mirror it to /config/share/serve-<svc>.json on valhalla (see bind note below)
|
|
# 2. add a `ts-<svc>` service block below (copy ts-roms), join the svc network,
|
|
# bind /config/share/serve-<svc>.json -> /config/serve.json
|
|
# 3. add that network under `networks:` as external
|
|
# 4. push, then admin console -> Machines -> <svc>-share -> Share -> friend email
|
|
|
|
services:
|
|
ts-roms:
|
|
image: tailscale/tailscale:latest
|
|
container_name: ts-roms
|
|
hostname: roms-share
|
|
restart: unless-stopped
|
|
networks: [roms]
|
|
env_file:
|
|
- stack.env
|
|
environment:
|
|
- TS_HOSTNAME=roms-share
|
|
- TS_STATE_DIR=/var/lib/tailscale
|
|
- TS_USERSPACE=true
|
|
- TS_SERVE_CONFIG=/config/serve.json
|
|
- TS_EXTRA_ARGS=--advertise-tags=tag:share
|
|
volumes:
|
|
- /config/share/ts-roms:/var/lib/tailscale
|
|
# Absolute host bind: Portainer's git-stack checkout does NOT materialize
|
|
# sibling repo files at the relative bind path (Docker then auto-creates a
|
|
# DIRECTORY and serve fails with "is a directory"). The serve config is
|
|
# canonical in this repo (serve-roms.json) and mirrored to the host path
|
|
# below — update both when it changes (same model as Caddyfile).
|
|
- /config/share/serve-roms.json:/config/serve.json:ro
|
|
|
|
networks:
|
|
roms:
|
|
name: roms
|
|
external: true
|