# The standard ScaleTail setup Every service in this repository starts from the same [template](../templates/service-template/). This page describes that shared setup once. The README of a service only lists what differs, under the heading "Deviations from the standard setup". ## Containers Each stack runs two containers that share one network namespace. | Compose service | Container name | Purpose | | --------------- | ----------------------- | -------------------------------------------------------------------- | | `tailscale` | `tailscale-` | Joins your Tailnet as a device named after `SERVICE` in `.env`. | | `application` | `app-` | Runs the service and uses the network of the `tailscale` container. | The application uses `network_mode: service:tailscale` and starts only after the `tailscale` container reports healthy. ## Tailnet access - **Web interface.** [Tailscale Serve](https://tailscale.com/kb/1312/serve) publishes the web interface at `https://..ts.net` and forwards it to the internal port of the application. `` is the value of `SERVICE`, and `.ts.net` is your [Tailnet DNS name](https://tailscale.com/kb/1217/tailnet-name), for example `tail1234.ts.net`. - **Requirements.** Your Tailnet needs [MagicDNS](https://tailscale.com/kb/1081/magicdns) and [HTTPS certificates](https://tailscale.com/kb/1153/enabling-https) enabled. The first request can take up to a minute, because Tailscale requests the certificate at that moment. - **Tailnet only.** Tailscale Funnel is disabled, so the service is not reachable from the public internet. - **Other ports.** Any other port the application listens on is reachable at the Tailscale IP address of the device, when your Tailnet policy allows it. - **No host ports.** The stack publishes no ports on the Docker host. To reach the service from your local network as well, uncomment the `ports` block of the `tailscale` service. ## Settings in `.env` | Variable | Purpose | | ------------- | -------------------------------------------------------------------------------------------- | | `SERVICE` | Name of the Tailnet device, the containers, and the data folder. | | `IMAGE_URL` | Image of the application. | | `SERVICEPORT` | Port used by the optional `ports` block. The port for Tailscale Serve is set in `compose.yaml`. | | `DNS_SERVER` | DNS server used by the optional `dns` block. | | `TS_AUTHKEY` | Your Tailscale auth key. Used only when the container is not logged in, for example at the first start or after you delete `./ts/state`. | | `TZ` | Time zone, passed to the application when its image supports it. | Some stacks need secrets that you choose. Compose stops with an error that starts with `required variable X is missing a value` until you set them. The service README lists them under "Before you start". ## Data All data stays in the service directory, next to `compose.yaml`. | Path | Content | | ------------------- | ----------------------------------------- | | `./config` | Holds `serve.json`, the Serve configuration. Compose writes it from the `configs` block in `compose.yaml` when it creates the container or starts a stopped one, so change `compose.yaml` instead and apply it with `docker compose up -d --force-recreate`. `docker compose restart` and a plain `docker compose up -d` keep the current file. | | `./ts/state` | Tailscale state, including the device key. | | `./-data/` | Data of the application. | Keep `./ts/state` when you recreate the stack. Without it, the device needs a valid auth key and joins your Tailnet as a new device. ## DNS The containers use Docker's DNS by default, so the application can reach other containers in the same stack by their Compose service name. It cannot resolve MagicDNS names of other Tailnet devices. - To reach another Tailnet device from the application, use its Tailscale IP address. - To use MagicDNS names instead, uncomment `TS_ACCEPT_DNS=true`. This replaces Docker's DNS, so Compose service names no longer resolve. Do not use it in a stack where the application depends on other containers by name. - If name resolution fails in general, uncomment the `dns` block to use the server from `DNS_SERVER`.