tailscale

This commit is contained in:
2026-06-23 01:52:04 +09:00
parent 9166528301
commit 1309e3d02a
9 changed files with 160 additions and 35 deletions
-9
View File
@@ -1,5 +1,4 @@
name: NixOS build name: NixOS build
on: on:
pull_request: pull_request:
branches: branches:
@@ -17,14 +16,11 @@ on:
- ".sops.yaml" - ".sops.yaml"
- "secrets/**" - "secrets/**"
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: read contents: read
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
discover-hosts: discover-hosts:
name: Discover NixOS hosts name: Discover NixOS hosts
@@ -34,7 +30,6 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v31 uses: cachix/install-nix-action@v31
with: with:
@@ -42,7 +37,6 @@ jobs:
experimental-features = nix-command flakes experimental-features = nix-command flakes
accept-flake-config = true accept-flake-config = true
access-tokens = github.com=${{ github.token }} access-tokens = github.com=${{ github.token }}
- name: Evaluate NixOS hosts - name: Evaluate NixOS hosts
id: hosts id: hosts
run: | run: |
@@ -50,7 +44,6 @@ jobs:
hosts_json=$(nix eval --json '.#nixosConfigurations' --apply 'configs: builtins.attrNames configs') hosts_json=$(nix eval --json '.#nixosConfigurations' --apply 'configs: builtins.attrNames configs')
echo "hosts=${hosts_json}" >> "$GITHUB_OUTPUT" echo "hosts=${hosts_json}" >> "$GITHUB_OUTPUT"
echo "Discovered hosts: ${hosts_json}" echo "Discovered hosts: ${hosts_json}"
build-host: build-host:
name: Build ${{ matrix.host }} name: Build ${{ matrix.host }}
needs: discover-hosts needs: discover-hosts
@@ -63,7 +56,6 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v31 uses: cachix/install-nix-action@v31
with: with:
@@ -71,7 +63,6 @@ jobs:
experimental-features = nix-command flakes experimental-features = nix-command flakes
accept-flake-config = true accept-flake-config = true
access-tokens = github.com=${{ github.token }} access-tokens = github.com=${{ github.token }}
- name: Build NixOS system - name: Build NixOS system
run: | run: |
set -euo pipefail set -euo pipefail
-9
View File
@@ -1,5 +1,4 @@
name: NixOS eval name: NixOS eval
on: on:
pull_request: pull_request:
branches: branches:
@@ -17,14 +16,11 @@ on:
- ".sops.yaml" - ".sops.yaml"
- "secrets/**" - "secrets/**"
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: read contents: read
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
discover-hosts: discover-hosts:
name: Discover NixOS hosts name: Discover NixOS hosts
@@ -34,7 +30,6 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v31 uses: cachix/install-nix-action@v31
with: with:
@@ -42,7 +37,6 @@ jobs:
experimental-features = nix-command flakes experimental-features = nix-command flakes
accept-flake-config = true accept-flake-config = true
access-tokens = github.com=${{ github.token }} access-tokens = github.com=${{ github.token }}
- name: Evaluate NixOS hosts - name: Evaluate NixOS hosts
id: hosts id: hosts
run: | run: |
@@ -50,7 +44,6 @@ jobs:
hosts_json=$(nix eval --json '.#nixosConfigurations' --apply 'configs: builtins.attrNames configs') hosts_json=$(nix eval --json '.#nixosConfigurations' --apply 'configs: builtins.attrNames configs')
echo "hosts=${hosts_json}" >> "$GITHUB_OUTPUT" echo "hosts=${hosts_json}" >> "$GITHUB_OUTPUT"
echo "Discovered hosts: ${hosts_json}" echo "Discovered hosts: ${hosts_json}"
eval-host: eval-host:
name: Eval ${{ matrix.host }} name: Eval ${{ matrix.host }}
needs: discover-hosts needs: discover-hosts
@@ -63,7 +56,6 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v31 uses: cachix/install-nix-action@v31
with: with:
@@ -71,7 +63,6 @@ jobs:
experimental-features = nix-command flakes experimental-features = nix-command flakes
accept-flake-config = true accept-flake-config = true
access-tokens = github.com=${{ github.token }} access-tokens = github.com=${{ github.token }}
- name: Evaluate NixOS system derivation - name: Evaluate NixOS system derivation
run: | run: |
set -euo pipefail set -euo pipefail
+1
View File
@@ -69,6 +69,7 @@ in
"workloads/dev" "workloads/dev"
"workloads/personal" "workloads/personal"
"workloads/secure-storage" "workloads/secure-storage"
"workloads/tailscale/client"
]; ];
}; };
+90 -10
View File
@@ -1,38 +1,118 @@
{ lib, config, ... }: { lib, config, ... }:
let let
cfg = config.my.applications.tailscale; cfg = config.my.applications.tailscale;
hasAdvertiseRoutes = cfg.advertiseRoutes != [ ];
computedRoutingFeatures =
if cfg.routingFeatures != "auto" then
cfg.routingFeatures
else if hasAdvertiseRoutes && cfg.acceptRoutes then
"both"
else if hasAdvertiseRoutes then
"server"
else if cfg.acceptRoutes then
"client"
else
"none";
computedOpenFirewall = if cfg.openFirewall != null then cfg.openFirewall else hasAdvertiseRoutes;
computedSetFlags = [
"--accept-dns=${lib.boolToString cfg.acceptDns}"
"--accept-routes=${lib.boolToString cfg.acceptRoutes}"
]
++ lib.optionals hasAdvertiseRoutes [
"--advertise-routes=${lib.concatStringsSep "," cfg.advertiseRoutes}"
]
++ cfg.extraSetFlags;
in in
{ {
options.my.applications.tailscale = { options.my.applications.tailscale = {
enable = lib.mkEnableOption "Tailscale VPN"; enable = lib.mkEnableOption "Tailscale";
acceptDns = lib.mkOption { acceptDns = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = false; default = false;
description = "Accept DNS configuration from Tailscale"; description = "Accept DNS configuration from Tailscale.";
}; };
acceptRoutes = lib.mkOption { acceptRoutes = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = false;
description = "Accept subnet routes from Tailscale"; description = "Accept subnet routes advertised by other Tailscale nodes.";
};
advertiseRoutes = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "10.50.0.0/16" ];
description = "Subnet routes to advertise through this Tailscale node.";
};
routingFeatures = lib.mkOption {
type = lib.types.enum [
"auto"
"none"
"client"
"server"
"both"
];
default = "auto";
description = ''
Routing feature mode for Tailscale.
auto:
- advertiseRoutes only -> server
- acceptRoutes only -> client
- both -> both
- neither -> none
'';
};
openFirewall = lib.mkOption {
type = lib.types.nullOr lib.types.bool;
default = null;
description = ''
Whether to open the firewall for Tailscale's UDP port.
null means automatic:
- true when advertiseRoutes is non-empty
- false otherwise
'';
};
extraSetFlags = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Additional flags to pass to `tailscale set`.";
}; };
extraUpFlags = lib.mkOption { extraUpFlags = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
description = "Additional flags to pass to tailscale up"; description = ''
Additional flags to pass to `tailscale up`.
Note: on current NixOS this is only applied by the built-in
autoconnect service when services.tailscale.authKeyFile is set.
'';
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
services.tailscale = { services.tailscale = {
enable = true; enable = true;
extraUpFlags = [
"--accept-dns=${if cfg.acceptDns then "true" else "false"}" openFirewall = computedOpenFirewall;
] useRoutingFeatures = computedRoutingFeatures;
++ lib.optional cfg.acceptRoutes "--accept-routes"
++ cfg.extraUpFlags; # 常時反映したい設定は tailscale set に寄せる
extraSetFlags = computedSetFlags;
# authKeyFile を使う場合だけ効くものとして残す
inherit (cfg) extraUpFlags;
}; };
}; };
} }
+49 -5
View File
@@ -1,31 +1,75 @@
{ lib, config, ... }: { lib, config, ... }:
let let
cfg = config.my.features.network.tailscale; cfg = config.my.features.network.tailscale;
in in
{ {
options.my.features.network.tailscale = { options.my.features.network.tailscale = {
enable = lib.mkEnableOption "Tailscale VPN"; enable = lib.mkEnableOption "Tailscale VPN";
acceptDns = lib.mkOption { acceptDns = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = false; default = false;
description = "Accept DNS configuration from Tailscale"; description = "Accept DNS configuration from Tailscale.";
}; };
acceptRoutes = lib.mkOption { acceptRoutes = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = false;
description = "Accept subnet routes from Tailscale"; description = "Accept subnet routes from Tailscale.";
}; };
advertiseRoutes = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "10.50.0.0/16" ];
description = "Subnet routes to advertise through this machine.";
};
routingFeatures = lib.mkOption {
type = lib.types.enum [
"auto"
"none"
"client"
"server"
"both"
];
default = "auto";
description = "Override Tailscale routing features. Usually leave this as auto.";
};
openFirewall = lib.mkOption {
type = lib.types.nullOr lib.types.bool;
default = null;
description = "Override Tailscale firewall opening. Usually leave this as null.";
};
extraSetFlags = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Additional flags to pass to `tailscale set`.";
};
extraUpFlags = lib.mkOption { extraUpFlags = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
description = "Additional flags to pass to tailscale up"; description = "Additional flags to pass to `tailscale up`.";
}; };
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
my.applications.tailscale = { my.applications.tailscale = {
enable = true; enable = true;
inherit (cfg) acceptDns acceptRoutes extraUpFlags;
inherit (cfg)
acceptDns
acceptRoutes
advertiseRoutes
routingFeatures
openFirewall
extraSetFlags
extraUpFlags
;
}; };
}; };
} }
-1
View File
@@ -7,6 +7,5 @@
}; };
gui.camera.enable = true; gui.camera.enable = true;
identity.fingerprint.enable = true; identity.fingerprint.enable = true;
network.tailscale.enable = true;
}; };
} }
-1
View File
@@ -1,7 +1,6 @@
{ {
my.features = { my.features = {
cli.base.sshServer = true; cli.base.sshServer = true;
network.tailscale.enable = true;
services.container.enable = true; services.container.enable = true;
}; };
} }
+8
View File
@@ -0,0 +1,8 @@
{
my.features.network.tailscale = {
enable = true;
acceptDns = false;
acceptRoutes = true;
};
}
+12
View File
@@ -0,0 +1,12 @@
{
my.features.network.tailscale = {
enable = true;
acceptDns = false;
acceptRoutes = false;
advertiseRoutes = [
"10.50.0.0/16"
];
};
}