mirror of
https://github.com/tailscale/tailscale.git
synced 2025-07-31 16:23:44 +00:00
Add tailscale module.
This commit is contained in:
parent
b2a8340780
commit
e093c8c9a5
@ -123,9 +123,9 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
nixosModules = {
|
nixosModules = {
|
||||||
# tailscale = import ./nixos/tailscaled-module.nix;
|
tailscale = import ./nixos/tailscaled-module.nix self;
|
||||||
tsidp = import ./nixos/tsidp-module.nix self;
|
tsidp = import ./nixos/tsidp-module.nix self;
|
||||||
# default = self.nixosModules.tailscale;
|
default = self.nixosModules.tailscale;
|
||||||
};
|
};
|
||||||
|
|
||||||
devShells = eachSystem (pkgs: {
|
devShells = eachSystem (pkgs: {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{
|
self: {
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
@ -16,10 +16,200 @@ in {
|
|||||||
options.services.tailscale = {
|
options.services.tailscale = {
|
||||||
enable = mkEnabledOption "Enable Tailscale service";
|
enable = mkEnabledOption "Enable Tailscale service";
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = self.packages.${pkgs.system}.tailscale;
|
||||||
|
description = "The Tailscale package to use.";
|
||||||
|
};
|
||||||
|
|
||||||
port = mkOption {
|
port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 41641;
|
default = 41641;
|
||||||
description = "The port Tailscale listens on.";
|
description = "The port Tailscale listens on.";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "tailscale0";
|
||||||
|
description = "The network interface Tailscale uses.";
|
||||||
|
};
|
||||||
|
|
||||||
|
permitCertUid = mkOption {
|
||||||
|
type = types.nullOr types.nonEmptyStr;
|
||||||
|
default = null;
|
||||||
|
description = "Username or UID allowed to fetch tailnet TLS certificates";
|
||||||
|
};
|
||||||
|
|
||||||
|
disableTaildrop = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Disable Tailscale Taildrop feature.";
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Open the firewall for Tailscale traffic. Recommended true to allow for direct connections.";
|
||||||
|
};
|
||||||
|
|
||||||
|
useRoutingFeatures = mkOption {
|
||||||
|
type = types.enum [
|
||||||
|
"none"
|
||||||
|
"client"
|
||||||
|
"server"
|
||||||
|
"both"
|
||||||
|
];
|
||||||
|
default = "none";
|
||||||
|
example = "server";
|
||||||
|
description = ''
|
||||||
|
Enables settings required for Tailscale's routing features like subnet routers and exit nodes.
|
||||||
|
|
||||||
|
To use these these features, you will still need to call `sudo tailscale up` with the relevant flags like `--advertise-exit-node` and `--exit-node`.
|
||||||
|
|
||||||
|
When set to `client` or `both`, reverse path filtering will be set to loose instead of strict.
|
||||||
|
When set to `server` or `both`, IP forwarding will be enabled allowing proper packet forwarding for exit node or subnet router functionality.
|
||||||
|
|
||||||
|
See https://tailscale.com/kb/1019/subnets#enable-ip-forwarding for packet forwarding
|
||||||
|
See https://github.com/tailscale/tailscale/issues/3310 for reverse path filtering
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
authKeyFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
example = "/run/secrets/tailscale_key";
|
||||||
|
description = ''
|
||||||
|
Path to a file containing a Tailscale auth key. If set, this will be used to automatically authenticate the Tailscale client.
|
||||||
|
The file should contain a single line with the auth key.
|
||||||
|
This is useful for automated setups where you want to avoid manual authentication.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraUpFlags = mkOption {
|
||||||
|
description = ''
|
||||||
|
Extra flags to pass to {command}`tailscale up`. Only applied if `authKeyFile` is specified.";
|
||||||
|
'';
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = ["--ssh" "--accept-routes"];
|
||||||
|
};
|
||||||
|
|
||||||
|
extraSetFlags = mkOption {
|
||||||
|
description = "Extra flags to pass to {command}`tailscale set`.";
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = ["--advertise-exit-node" "--shields-up"];
|
||||||
|
};
|
||||||
|
|
||||||
|
extraDaemonFlags = mkOption {
|
||||||
|
description = "Extra flags to pass to {command}`tailscaled`.";
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = ["--no-logs-no-support" "-encrypt-state"];
|
||||||
|
};
|
||||||
|
|
||||||
|
RuntimeDirectory = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "tailscale";
|
||||||
|
description = "The runtime directory for Tailscale. This is where Tailscale will store its state.";
|
||||||
|
};
|
||||||
|
|
||||||
|
StateDirectory = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "tailscale";
|
||||||
|
description = "The state directory for Tailscale. This is where Tailscale will store its persistent state.";
|
||||||
|
};
|
||||||
|
|
||||||
|
CacheDirectory = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "tailscale";
|
||||||
|
description = "The cache directory for Tailscale. This is where Tailscale will store its cache.";
|
||||||
|
};
|
||||||
|
|
||||||
|
Cleanup = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether to clean up Tailscale state on post stop.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [cfg.package];
|
||||||
|
|
||||||
|
boot.kernel.sysctl = mkIf (cfg.useRoutingFeatures == "server" || cfg.useRoutingFeatures == "both") {
|
||||||
|
"net.ipv4.conf.all.forwarding" = mkOverride 97 true;
|
||||||
|
"net.ipv6.conf.all.forwarding" = mkOverride 97 true;
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedUDPPorts = mkIf cfg.openFirewall [cfg.port];
|
||||||
|
|
||||||
|
networking.firewall.checkReversePath = mkIf (
|
||||||
|
cfg.useRoutingFeatures == "client" || cfg.useRoutingFeatures == "both"
|
||||||
|
) "loose";
|
||||||
|
|
||||||
|
networking.dhcpcd.denyInterfaces = [cfg.interfaceName];
|
||||||
|
|
||||||
|
systemd.network.networks."50-tailscale" = mkIf config.networking.useNetworkd {
|
||||||
|
matchConfig = {
|
||||||
|
Name = cfg.interfaceName;
|
||||||
|
};
|
||||||
|
linkConfig = {
|
||||||
|
Unmanaged = true;
|
||||||
|
ActivationPolicy = "manual";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.packages = [cfg.package];
|
||||||
|
systemd.services.tailscaled = {
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
wants = ["network-pre.target"];
|
||||||
|
after = ["network-pre.target" "NetworkManager.service" "systemd-resolved.service"];
|
||||||
|
path =
|
||||||
|
[
|
||||||
|
(builtins.dirOf config.security.wrapperDir)
|
||||||
|
pkgs.iproute2
|
||||||
|
pkgs.procps
|
||||||
|
pkgs.getent
|
||||||
|
pkgs.shadow
|
||||||
|
]
|
||||||
|
++ lib.optional config.networking.resolvconf.enable config.networking.resolvconf.package;
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Environment =
|
||||||
|
[
|
||||||
|
"PORT=${toString cfg.port}"
|
||||||
|
''"FLAGS=--tun ${lib.escapeShellArg cfg.interfaceName} ${lib.concatStringsSep " " cfg.extraDaemonFlags}" ${lib.optionalString (cfg.authKeyFile != null) " --auth-key file:${cfg.authKeyFile}"}''
|
||||||
|
]
|
||||||
|
++ (lib.optionals (cfg.permitCertUid != null) [
|
||||||
|
"TS_PERMIT_CERT_UID=${cfg.permitCertUid}"
|
||||||
|
])
|
||||||
|
++ (lib.optionals (cfg.disableTaildrop) [
|
||||||
|
"TS_DISABLE_TAILDROP=true"
|
||||||
|
]);
|
||||||
|
|
||||||
|
Restart = "on-failure";
|
||||||
|
StateDirectory = cfg.StateDirectory;
|
||||||
|
StateDirectoryMode = "0700";
|
||||||
|
RuntimeDirectory = cfg.RuntimeDirectory;
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
CacheDirectory = cfg.CacheDirectory;
|
||||||
|
CacheDirectoryMode = "0750";
|
||||||
|
Type = "notify";
|
||||||
|
};
|
||||||
|
|
||||||
|
stopIfChanged = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.tailscaled-set = mkIf (cfg.extraSetFlags != []) {
|
||||||
|
after = ["tailscaled.service"];
|
||||||
|
wants = ["tailscaled.service"];
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
${lib.getExe cfg.package} set ${escapeShellArgs cfg.extraSetFlags}
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user