Using Tailscale to access your SPIN Runtime

Tailscale is a VPN service that allows you to access your SPIN Runtime from anywhere. It’s particularly interesting because it doesn’t require you to expose your SPIN Runtime to the public internet.

Obtain Tailscale authentication key

  1. Ensure there is a tag tag:container in your Tailscale network under Access Controls.
    {
        "tagOwners": {
            "tag:container": ["autogroup:admin"],
        },
        // ...
    }
    
  2. Go to OAuth client settings and create a new client. Enable Write permissions for Devices -> Core and choose the tag:container tag. Then enable Write for All (there probably is a better way to do this).
  3. Copy the client secret. this is your <AUTH_KEY>.
Learn more in Tailscale’s documentation about Tailscale with Docker.

Set up using sidecar container

The following configuration will set up a sidecar container that will proxy HTTPS traffic to the SPIN Runtime. You’ll need to replace the following variables:
  • <AUTH_KEY>: Your Tailscale authentication key.
  • <HOSTNAME>: The hostname of your SPIN Runtime. This will be part of the URL you use to access your SPIN runtime.
  • <SPIN_TOKEN>: Your SPIN Runtime token. You receive this token when you add a new runtime in the SPIN UI.
compose.yml
---
version: "3.7"
services:
  tailscale-sidecar:
    image: tailscale/tailscale:latest
    hostname: <HOSTNAME>
    environment:
      - TS_AUTHKEY=<AUTH_KEY>?ephemeral=true
      - TS_EXTRA_ARGS=--advertise-tags=tag:container
      - TS_SERVE_CONFIG=/config/proxy-config.json
      - TS_STATE_DIR=/var/lib/tailscale
      - TS_USERSPACE=false
    volumes:
      - ${PWD}/tailscale-sidecar/state:/var/lib/tailscale
      - ${PWD}/proxy-config.json:/config/proxy-config.json
    devices:
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - net_admin
      - sys_module
    restart: unless-stopped
  spin-runtime:
    image: ghcr.io/siftd/spin-runtime:latest
    environment:
      - SPIN_TOKEN=<SPIN_TOKEN>
    volumes:
      - ${PWD}/runtime-data:/opt/spin/var
    depends_on:
      - tailscale-sidecar
    network_mode: service:tailscale-sidecar
    restart: unless-stopped
The following configuration file will instruct the tailscale sidecar to proxy HTTPS traffic to the SPIN Runtime. Put this file in the same directory as the compose.yml file, it will be mounted into the tailscale sidecar container.
proxy-config.json
{
    "TCP": {
        "443": {
            "HTTPS": true
        }
    },
    "Web": {
        "${TS_CERT_DOMAIN}:443": {
            "Handlers": {
                "/": {
                    "Proxy": "http://127.0.0.1:8888"
                }
            }
        }
    },
    "AllowFunnel": {
        "${TS_CERT_DOMAIN}:443": false
    }
}
Start the containers by running:
docker compose up -d
You should see a new machine pop up in your Tailscale dashboard. If you don’t, check the logs of your docker containers for potential errors:
docker compose logs -f

Accessing the runtime

You can now access your SPIN Runtime at:
https://<HOSTNAME>.<TAILNET_DOMAIN>.ts.net
You can obtain the fully qualified domain name (FQDN) of your runtime in the Tailscale dashboard by clicking on the machine and looking at the “Full domain” field.