Skip to content

Commit 2a7a615

Browse files
committed
Apply the VPN to all hosts in the datacenter
After fiddling with Headscale a bit more I'm pretty sold. Now every host on the network is connected to the VPN. I've added a `project vpn setup` command to bootstrap new nodes, but I think the `tailscaled-autoconnect` service is better suited. Hopefully I can find a clean way to make that work without provisioning a key on every deployment (it only needs to happen once).
1 parent 0b224e8 commit 2a7a615

File tree

5 files changed

+58
-9
lines changed

5 files changed

+58
-9
lines changed

flake.nix

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
inherit (nixpkgs-unstable) lib;
3737
inherit (import ./lib flake-inputs) defineHost deviceProfiles makeImage;
3838

39+
domain = "selfhosted.city";
40+
datacenter = "nova";
41+
3942
# A subset of Hydra's standard architectures.
4043
standardSystems = [
4144
"x86_64-linux"
@@ -130,8 +133,7 @@
130133

131134
colmena = (lib.mapAttrs defineHost hosts) // rec {
132135
defaults.lab = {
133-
domain = "selfhosted.city";
134-
datacenter = "nova";
136+
inherit datacenter domain;
135137

136138
networks = {
137139
datacenter.ipv4 = {
@@ -260,6 +262,40 @@
260262
}
261263
];
262264
};
265+
266+
vpn = {
267+
about = "Manage the VPN.";
268+
subcommands.register = {
269+
about = "Register a node on the VPN.";
270+
args = [
271+
{
272+
id = "host";
273+
about = "Host to initialize.";
274+
required = true;
275+
}
276+
{
277+
id = "server_url";
278+
about = "URL of the VPN server.";
279+
short = "s";
280+
long = "server-url";
281+
default_value = "http://rpi4-003.host.${datacenter}.${domain}:8080";
282+
}
283+
];
284+
285+
# TODO: Use Colmena's deploy key commands instead and
286+
# defer the oneshot setup by the key service.
287+
run = pkgs.unstable.writers.writeNu "bootstrap-vpn-client.nu" ''
288+
use std/log
289+
290+
let server_host = $env.server_url | url parse | get host
291+
let response = ssh $server_host headscale preauthkey create --user dc-${datacenter} --output json | from json
292+
log info $"Auth key created id=($response.id)"
293+
294+
ssh $env.host tailscale up --login-server $env.server_url --auth-key $response.key
295+
log info "VPN client ready"
296+
'';
297+
};
298+
};
263299
};
264300
};
265301
})

hosts/rpi3-001.nix

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2+
lab.profiles = {
3+
vpn.client.enable = true;
4+
};
5+
26
home-manager.users.root.home.stateVersion = "23.11";
37
system.stateVersion = "23.05";
48
}

hosts/rpi3-002.nix

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
{
2-
# File server is temporarily disabled. 2/3 drives corrupted.
3-
# I'm a terrible sysadmin.
4-
lab.profiles.file-server.enable = false;
2+
lab.profiles = {
3+
vpn.client.enable = true;
4+
5+
# File server is temporarily disabled. 2/3 drives corrupted.
6+
# I'm a terrible sysadmin.
7+
file-server.enable = false;
8+
};
9+
510
networking.hostId = "e3cda066"; # Required by ZFS
611

712
home-manager.users.root.home.stateVersion = "23.11";

hosts/rpi4-001.nix

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ let
55
inherit (config.lab.services.gateway) wan;
66
in
77
{
8-
lab.profiles.router.enable = true;
8+
lab.profiles = {
9+
router.enable = true;
10+
vpn.client.enable = true;
11+
};
912

1013
# Assign sensible names to the network interfaces. Anything with vlans needs
1114
# a hardware-related filter to avoid conflicts with virtual devices.

platforms/nixos/modules/lab/profiles/vpn/server.nix

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,18 @@ in
1919
};
2020

2121
config = lib.mkIf cfg.enable {
22+
networking.firewall.allowedTCPPorts = [ port ];
23+
2224
services.headscale = {
2325
enable = true;
2426
settings = {
2527
server_url = "http://${config.networking.hostName}.host.${datacenter}.${domain}:${toString port}";
2628
listen_addr = "0.0.0.0:${toString port}";
27-
dns.base_domain = "vpn.${datacenter}.${domain}";
29+
dns.base_domain = "${datacenter}.vpn.${domain}";
30+
logtail.enabled = true;
2831

2932
# TODO: Define ACLs.
3033
};
3134
};
32-
33-
networking.firewall.allowedTCPPorts = [ port ];
3435
};
3536
}

0 commit comments

Comments
 (0)