about summary refs log tree commit diff
path: root/modules/tailscale-initrd.nix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/tailscale-initrd.nix')
-rw-r--r--modules/tailscale-initrd.nix99
1 files changed, 99 insertions, 0 deletions
diff --git a/modules/tailscale-initrd.nix b/modules/tailscale-initrd.nix
new file mode 100644
index 0000000..4b7610e
--- /dev/null
+++ b/modules/tailscale-initrd.nix
@@ -0,0 +1,99 @@
+# To set this up, first get tailscale working in an isolated linux shell:
+#  1. sudo systemctl stop tailscaled.service
+#  2. tailscaled -port 9993 -state tailscale-luks-setup.state -tun userspace-networking -socket ./tailscaled.sock
+#  3. tailscale -socket ./tailscaled.sock up -hostname HOSTNAME-luks
+#  4. tailscale -socket ./tailscaled.sock down
+#  5. ctrl-c out of tailscaled
+#  6 sudo systemctl start tailscaled.service
+#
+# Then add the .state file to your machine secrets and pass its path as tailscaleStatePath.
+
+{ config, lib, pkgs, ... }: {
+  options = {
+    modules.tailscale-initrd = with lib; {
+      enable = mkOption {
+        description = "Turn on unlock via tailscale";
+        default = false;
+      };
+
+      tailscaleStatePath = mkOption {
+        description = "Pre-initialized tailscale state file as a secret. Make sure to set it to not require re-authentication, otherwise the machine may not boot up after a few weeks.";
+      };
+    };
+  };
+
+  config =
+    let
+      cfg = config.modules.tailscale-initrd;
+      # TODO: This uses old-style non-nftables iptables; ideally, we wouldn't have to opt out of that.
+      # Enabling nftables compat means having to shuffle the list of
+      # modules down in availableKernelModules; that's a bunch of work
+      # (deploying to a linux machine & rebooting to see what doesn't
+      # work this time), so I'm a bit too lazy for that now.
+      iptables-static = (pkgs.iptables.override { nftablesCompat = false; }).overrideAttrs (old: {
+        dontDisableStatic = true;
+        configureFlags = (lib.remove "--enable-shared" old.configureFlags) ++ [
+          "--enable-static"
+          "--disable-shared"
+        ];
+      });
+    in
+    lib.mkIf cfg.enable {
+      boot.initrd = {
+        secrets = {
+          "/var/lib/tailscale/tailscaled.state" = cfg.tailscaleStatePath;
+          "/etc/ssl/certs/ca-certificates.crt" = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+          "/etc/ssl/certs/ca-bundle.crt" = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+        };
+        network = {
+          enable = true;
+          flushBeforeStage2 = true;
+          postCommands = ''
+            # Bring up tailscaled and dial in
+            echo 'nameserver 8.8.8.8' > /etc/resolv.conf
+            mkdir /dev/net
+            mknod /dev/net/tun c 10 200
+            .tailscaled-wrapped 2>/dev/null &
+            sleep 5
+            .tailscale-wrapped up
+            .tailscale-wrapped status
+
+            echo "echo 'Use cryptsetup-askpass to unlock!'" >> /root/.profile
+          '';
+        };
+        availableKernelModules = [
+          "ip6_tables"
+          "ip6table_filter"
+          "ip6table_nat"
+          "ip6table_raw"
+          "ip_tables"
+          "iptable_filter"
+          "iptable_nat"
+          "iptable_raw"
+          "nf_conntrack"
+          "nf_nat"
+          "tun"
+          "xt_comment"
+          "xt_conntrack"
+          "xt_mark"
+          "xt_MASQUERADE"
+          "xt_LOG"
+          "xt_tcpudp"
+        ];
+        extraUtilsCommands = ''
+          copy_bin_and_libs ${pkgs.tailscale}/bin/.tailscaled-wrapped
+          copy_bin_and_libs ${pkgs.tailscale}/bin/.tailscale-wrapped
+          copy_bin_and_libs ${pkgs.iproute}/bin/ip
+          copy_bin_and_libs ${iptables-static}/bin/iptables
+          copy_bin_and_libs ${iptables-static}/bin/xtables-legacy-multi
+
+          copy_bin_and_libs ${pkgs.strace}/bin/strace
+        '';
+        postMountCommands = ''
+          # tear down tailscale
+          pkill .tailscaled-wrapped
+          .tailscaled-wrapped --cleanup
+        '';
+      };
+    };
+}