These are the notes I made while trying to understand how I can serve a Podman container to my Tailnet. This is part of the research I’m doing around migrating from my old home Linux server to a new one.

Tailscale container

Start the Tailscale container:

mkdir "$HOME/ts-test2"
podman run -d --name ts-test2 \
  --cap-add=NET_ADMIN \
  --device=/dev/net/tun \
  -e TS_AUTHKEY=tskey-auth-XXXXX \
  -e TS_HOSTNAME=ts-test2 \
  -e TS_STATE_DIR=/var/lib/tailscale \
  -v $HOME/ts-test2:/var/lib/tailscale \
  docker.io/tailscale/tailscale:latest

See the container logs and the status of tailscale:

podman logs ts-test2
podman exec ts-test2 tailscale status

Nginx container

Start the Nginx container connected to the ts-test2 network:

podman run -d --name ts-test2-nginx \
  --network=container:ts-test2 \
  docker.io/nginx:latest

Watch the container logs:

podman logs -f ts-test2-nginx

In another terminal on the tailnet, load the Nginx landing page:

curl http://ts-test2/

If you aren’t using Tailscale Magic DNS, you can use the tailnet IP:

curl http://$(tailscale ip --4 ts-test2)

Serve Nginx (via https) over Tailscale

Manually run tailscale serve in the tailscale container:

podman exec ts-test2 tailscale serve --bg 80

Connecting to https://ts-test2.{tailname}.ts.net/ causes the TLS certificate to get issued. That’s been taking about 12s. If testing with curl, bump the timeout since the default is 10s. After the issuance you’ll see the Nginx landing page.

curl -v --connect-timeout 30 https://ts-test2.{tailname}.ts.net/

Replace {tailname} with the name of your tailnet.

Since the tailscale serve config is stored in the tailscale state file (tailscaled.state), it will be restored after reboots.

Helpful commands

To watch container logs:

podman logs -f ts-test2
podman logs -f ts-test2-nginx

To see tailscale status:

podman exec ts-test2 tailscale status
podman exec ts-test2 tailscale serve status