Files
homelabstack/stacks/share/docker-compose.yml
T
ginnoir bf68f5a3da fix(share): absolute host bind for serve config
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.
2026-06-06 23:06:30 -05:00

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