I'm converting my Wobserver from using "plain old wireguard" and my laptops' Wireguard Configurations to using Tailscale for my private network. This setup is almost entirely lifted from Christine's post on setting up a Minecraft server on NixOS and Tailscale.
Why move to a proprietary VPN solution?
"Wireguard is a protocol not a product" – setting up iptables
, sysctl
and all this nonsense just to create a more-secure hub-and-spoke model
is fine, but COVID-19 wfh has changed the
nature of my network topology a fair bit, and I'll be moving more than a
few milliseconds away from Wobscale soon, so
having auto-discovered LAN routing will be really nice. I have tried
some options which kind of work here, but each ahve a fair bit of
tradeoffs and don't solve the auto-discovery.
☆ pivpn ☆ algo ☆ easy-wg-quick ☆
These are all decent enough, but each have different tradeoffs and non fit in to my systems philosophy and network topology. Tailscale solves this all.
Wireguard in a NixOS homogeneous environment could be alright because it would be managed programmatically alongside the rest of the host configuration, but dealing with generating configurations for mobile, windows, mac, etc, is a pain in the ass still. I'm not interested in building out shared-secret management, and Peering, and IP Address Management on top of a "protocol not a product", i guess.
Tailscale also gives me extensible social peering as well, as described in Christine's post, unlocking some convivial properties of the Arroyo Systems philosophy. It's not unrealistic to imagine using the social features of Tailscale to build out a private network of Arroyos, Arcologies and Wobservers.
Tailscale is built by people I generally trust and provide a really reasonable free tier, though I wouldn't mind a bit more server sharing. If they turn evil I'll have a bear of a time getting something as straightforward as MagicDNS working, but then so will a bunch of other folks and maybe we can build an open source version of this thing.
Tailscale on NixOS
This will eventually run on The Wobserver, but for now it only runs on the endpoint configuration.
Well here it is:
{ config, pkgs, lib, ... }:
{
tailscale-option>>
<<config = {
tailscale-pkg>>
<<tailscale-autoconnect>>
<<tailscale-firewall>>
<<};
}
Once you've deployed a configuration for the first time with Morph, check the machine list to see if the new machine is there.
Let's dig in to what's happening here.
Installing it
Tailscale is packaged in nixpkgs, and there is a NixOS module for it. Enable them both.
[ pkgs.tailscale ];
environment.systemPackages = true; services.tailscale.enable =
First-setup and Authentication
Initial setup is accomplished with an systemd one-shot
service that Christine wrote. I extend
it slightly by making an option which my various hosts can set the
first-connect auth-key to as services.tailscale.authKey
. Fetch a key from the tailscale
settings panel, generate an auth key
that isn't reusable, and set it in the host configuration like Virtuous Cassette.
with lib; {
options.services.tailscale = authKey = mkOption {
type = types.str;
description = "Set the tailscale auth key";
};
};
I love being able to set up systemd services with this script
option like tailscale-autoconnect
does. Very good stuff.
-autoconnect = {
systemd.services.tailscaledescription = "Automatic connection to Tailscale";
# make sure tailscale is running before trying to connect to tailscale
after = [ "network-pre.target" "tailscale.service" ];
wants = [ "network-pre.target" "tailscale.service" ];
wantedBy = [ "multi-user.target" ];
# set this service as a oneshot job
serviceConfig.Type = "oneshot";
# have the job run this shell script
script = with pkgs; ''
# wait for tailscaled to settle
sleep 2
# check if we are already authenticated to tailscale
status="$(${tailscale}/bin/tailscale status -json | ${jq}/bin/jq -r .BackendState)"
if [ $status = "Running" ]; then # if so, then do nothing
exit 0
fi
# otherwise authenticate with tailscale
${tailscale}/bin/tailscale up -authkey ${config.services.tailscale.authKey}
'';
};
Poking the Firewall
Tailscale needs a firewall port open – and it makes some amount of
sense to mark the tailscale0
interface as
trusted. Make sure to set ACLs in Tailscale!!
[ config.services.tailscale.port ];
networking.firewall.allowedUDPPorts = [ "tailscale0" ];
networking.firewall.trustedInterfaces = # warning: Strict reverse path filtering breaks Tailscale exit node
# use and some subnet routing setups. Consider setting
# `networking.firewall.checkReversePath` = 'loose'
"loose"; networking.firewall.checkReversePath =