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
- 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
- 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
- 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--volumecommand-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 byrun.sh.