# 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-.json` here (Proxy -> http://:) AND # mirror it to /config/share/serve-.json on valhalla (see bind note below) # 2. add a `ts-` service block below (copy ts-roms), join the svc network, # bind /config/share/serve-.json -> /config/serve.json # 3. add that network under `networks:` as external # 4. push, then admin console -> Machines -> -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