Tailscale-Based Device Onboarding¶
The Modern Way: Use Tailscale to bootstrap new devices from any existing device on your private network.
🏗️ Architecture¶
The onboarding flow uses a temporary local web server to "serve" the encrypted bundles across the Tailnet.
Main Device (Source) New Device (Target)
-------------------- -------------------
1. Run ./serve-via-tailscale.sh
2. Python Server starts 3. Install Tailscale
3. Serves .age bundles <--- 4. Curl bundle
5. Decrypt & Run Setup
🚀 Step-by-Step Setup¶
1. On Existing Device (Source)¶
Start the bootstrap server on your primary machine:
This will print a specialized URL and curl command for you to use.
2. On New Device (Target)¶
Automatic Discovery (Recommended):
If you have coder-core or can copy one script:
Manual (No pre-existing files): If the device is completely fresh, manually run:
# 1. Install Tailscale & age
brew install tailscale age
sudo tailscale up
# 2. Pull and execute the bundle
# (Replace IP with the one shown on your source device)
curl http://100.x.y.z:8080/device-bootstrap.age | age -d | bash
✅ What is Automated?¶
Once the bash command runs, the following is performed automatically:
- SSH Setup: Installs private/public keys and configures
~/.ssh/config. - Infisical CLI: Installs the CLI and logs in using Machine Identity.
- Repository Setup: Either clones
coder-coreor restores it from the embedded backup. - Verification: Tests connections to
bruno,dev-vps, and Infisical.
🔒 Security Advantages¶
- No USB Required: Everything happens over the encrypted WireGuard tunnel.
- Private IP only: The bootstrap server binds ONLY to the Tailscale interface (
100.x.y.z). - Encrypted Payloads: Even if someone were on your Tailnet, they would still need the
agepassphrase to read the bundle.
❓ Troubleshooting¶
Cannot reach IP:
- Ensure both devices are connected to the same Tailnet.
- Check if a local firewall (like
ufwor macOS Firewall) is blocking port 8080.
"age: command not found":
- The script attempts to install
ageviabrew, but if you don't have Homebrew, you must install it manually first.