GitHub - highpost/tailscale-macos-container: Using Tailscale with Apple's containerization stack on macOS

3 min read Original article ↗

This repository demonstrates how to use Apple's macOS containerization stack to provision an Alpine Linux instance, and then add it to your tailnet.

Apple's macOS containerization stack uses the Virtualization framework to spin up a minimal Linux host VM for each container instance. Since neither the macOS host kernel nor the specialized Linux guest VM kernel includes a native WireGuard kernel module, the container must run Tailscale in userspace networking mode instead of attaching to a standard kernel TUN device.

The container example in this repo starts tailscaled with --tun=userspace-networking, authenticates the node using a Tailscale auth key and then enables Tailscale SSH. Once the container joins your tailnet, you can use Tailscale MagicDNS for naming and then connect to the container over Tailscale SSH without exposing any ports on the host or configuring a separate SSH server inside the container.

This example also demonstrates a macOS-specific method of securely storing your Tailscale auth key in Apple Keychain.

Modify access controls

Create a tag

Access controls > Tags

  • Tag name: myservers
  • Tag owners: your-email@example.com

Modify the Tailscale SSH access controls

Go to Access controls > Tailscale SSH and ensure your policy permits access to the tagged servers and specified users:

{
  "action": "accept",
  "src": ["autogroup:admin"],
  "dst": ["tag:myservers"],
  "users": ["player1", "player2"]
}
  • Add your new tag ("myservers") to the Destination (dst) array.
  • Add the Linux usernames defined in your cloud-config ("player1", "player2") to the Destination users (users) array.
  • Change "action" from "check" to "accept" for seamless SSH access.

Create a Tailscale auth key

  1. Generate an auth key via the Tailscale Admin Keys panel with these configurations:
  • Reusable: Enabled
  • Pre-authorized: Enabled
  • Tags: Choose the newly created tag: tag:myservers
  1. Store the newly created auth key in Keychain:
./store-ts-key-keychain.sh

(Note: This creates an entry named tailscale-auth-key-alpine-ts-server in your Keychain).

Build the image

Run the container

Connect to the container

Once run.sh finishes authenticating the machine, you can connect directly over your tailnet using Tailscale SSH or jump straight into the machine locally via OrbStack:

  • MagicDNS name: ssh player1@alpine-ts-server
  • built-in local SSH proxy: ssh player1@alpine-ts-server@orb
  • CLI: orb -m alpine-ts-server

Files

Containerfile and tini-start.sh should work on other OCI‑compatible container platforms. However, those platforms typically provide a kernel TUN device, so this userspace networking technique is mainly a macOS‑specific workaround rather than a general best practice.

Additional helper scripts provide macOS‑specific integration with Apple's container CLI:

  • build.sh: Builds the container image.
  • run.sh: Launches a container instance and retrieves the Tailscale auth key from Apple Keychain. It also demonstrates how to mount a local folder into a container using the --volume command-line option.
  • cleanup.sh: Removes the container from your tailnet, removes the container instance and deletes the container image.
  • store-ts-key-keychain.sh: Copies the Tailscale auth key from the system clipboard to Apple Keychain for later use by run.sh.