deploy wireguard
This commit is contained in:
parent
a47d096503
commit
3f9cd6a0c1
6 changed files with 181 additions and 212 deletions
|
|
@ -6,12 +6,12 @@
|
||||||
./containers.nix
|
./containers.nix
|
||||||
./proxy.nix
|
./proxy.nix
|
||||||
../system-default.nix
|
../system-default.nix
|
||||||
../../../modules/vpn/tailscale.nix
|
|
||||||
../../../modules/podman.nix
|
../../../modules/podman.nix
|
||||||
../../../modules/traefik.nix
|
../../../modules/traefik.nix
|
||||||
../../../modules/borg/client.nix
|
../../../modules/borg/client.nix
|
||||||
../../../modules/media/server.nix
|
../../../modules/media/server.nix
|
||||||
../../../modules/file-server/samba.nix
|
../../../modules/file-server/samba.nix
|
||||||
|
../../../modules/vpn/client.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# GRUB bootloader with ZFS support
|
# GRUB bootloader with ZFS support
|
||||||
|
|
@ -132,9 +132,11 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.tailscale-custom = {
|
services.wireguard-client = {
|
||||||
exitNode = true;
|
enable = true;
|
||||||
subnetRoutes = [ "10.1.1.0/24" ];
|
address = "10.2.2.10/24";
|
||||||
|
serverPublicKey = "46QHjSzAas5g9Hll1SCEu9tbR5owCxXAy6wGOUoPwUM=";
|
||||||
|
serverEndpoint = "91.98.84.215:51820";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Media server services
|
# Media server services
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
loadBalancer = {
|
loadBalancer = {
|
||||||
serversTransport = "longTimeout";
|
serversTransport = "longTimeout";
|
||||||
servers = [{
|
servers = [{
|
||||||
url = "http://10.1.1.152:8080";
|
url = "http://10.2.2.10:8080";
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
music = {
|
music = {
|
||||||
loadBalancer = {
|
loadBalancer = {
|
||||||
servers = [{
|
servers = [{
|
||||||
url = "http://10.1.1.152:4533";
|
url = "http://10.2.2.10:4533";
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@
|
||||||
./containers.nix
|
./containers.nix
|
||||||
./proxy.nix
|
./proxy.nix
|
||||||
../system-default.nix
|
../system-default.nix
|
||||||
../../../modules/vpn/tailscale.nix
|
|
||||||
../../../modules/podman.nix
|
../../../modules/podman.nix
|
||||||
../../../modules/traefik.nix
|
../../../modules/traefik.nix
|
||||||
../../../modules/borg/client.nix
|
../../../modules/borg/client.nix
|
||||||
../../../modules/git/server.nix
|
../../../modules/git/server.nix
|
||||||
|
../../../modules/vpn/server.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# GRUB bootloader with UEFI support
|
# GRUB bootloader with UEFI support
|
||||||
|
|
@ -44,7 +44,6 @@
|
||||||
firewall = {
|
firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
allowedTCPPorts = [ 22 80 443 27017 ];
|
allowedTCPPorts = [ 22 80 443 27017 ];
|
||||||
trustedInterfaces = [ "tailscale0" ];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -71,7 +70,14 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.tailscale-custom.exitNode = true;
|
services.wireguard-server = {
|
||||||
|
enable = true;
|
||||||
|
address = "10.2.2.1/24";
|
||||||
|
peers = [{
|
||||||
|
publicKey = "MCuSF/aFZy7Jq3nI6VpU7jbfZOuEGuMjgpxRWazxtmY=";
|
||||||
|
allowedIPs = [ "10.2.2.10/32" ];
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
services.git-server-custom = {
|
services.git-server-custom = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
||||||
75
modules/vpn/client.nix
Normal file
75
modules/vpn/client.nix
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
# NOTE: Private key file at: `/etc/wireguard/private.key` with mode 600
|
||||||
|
# Auto-generated on first boot; get public key with: `sudo sh -c 'wg pubkey < /etc/wireguard/private.key'`
|
||||||
|
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.wireguard-client;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.services.wireguard-client = {
|
||||||
|
enable = mkEnableOption "WireGuard VPN client";
|
||||||
|
|
||||||
|
address = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "10.2.2.2/24";
|
||||||
|
};
|
||||||
|
|
||||||
|
serverPublicKey = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
|
||||||
|
serverEndpoint = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "vpn.example.com:51820";
|
||||||
|
};
|
||||||
|
|
||||||
|
allowedIPs = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ "10.2.2.0/24" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [ pkgs.wireguard-tools ];
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d /etc/wireguard 0700 root root - -"
|
||||||
|
"f /etc/wireguard/private.key 0600 root root - -"
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.services.wireguard-keygen = {
|
||||||
|
description = "Generate WireGuard private key";
|
||||||
|
before = [ "wg-quick-wg0.service" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
if [ ! -s /etc/wireguard/private.key ]; then
|
||||||
|
${pkgs.wireguard-tools}/bin/wg genkey > /etc/wireguard/private.key
|
||||||
|
chmod 600 /etc/wireguard/private.key
|
||||||
|
echo "Public key: $(${pkgs.wireguard-tools}/bin/wg pubkey < /etc/wireguard/private.key)"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.wg-quick.interfaces.wg0 = {
|
||||||
|
privateKeyFile = "/etc/wireguard/private.key";
|
||||||
|
address = [ cfg.address ];
|
||||||
|
|
||||||
|
peers = [{
|
||||||
|
publicKey = cfg.serverPublicKey;
|
||||||
|
allowedIPs = cfg.allowedIPs;
|
||||||
|
endpoint = cfg.serverEndpoint;
|
||||||
|
persistentKeepalive = 25;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.trustedInterfaces = [ "wg0" ];
|
||||||
|
};
|
||||||
|
}
|
||||||
89
modules/vpn/server.nix
Normal file
89
modules/vpn/server.nix
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
# NOTE: Private key file at: `/etc/wireguard/private.key` with mode 600
|
||||||
|
# Auto-generated on first boot; get public key with: `sudo sh -c 'wg pubkey < /etc/wireguard/private.key'`
|
||||||
|
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.wireguard-server;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.services.wireguard-server = {
|
||||||
|
enable = mkEnableOption "WireGuard VPN server";
|
||||||
|
|
||||||
|
address = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "10.2.2.1/24";
|
||||||
|
};
|
||||||
|
|
||||||
|
peers = mkOption {
|
||||||
|
type = types.listOf (types.submodule {
|
||||||
|
options = {
|
||||||
|
publicKey = mkOption { type = types.str; };
|
||||||
|
allowedIPs = mkOption { type = types.listOf types.str; };
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [ pkgs.wireguard-tools ];
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d /etc/wireguard 0700 root root - -"
|
||||||
|
"f /etc/wireguard/private.key 0600 root root - -"
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.services.wireguard-keygen = {
|
||||||
|
description = "Generate WireGuard private key";
|
||||||
|
before = [ "wg-quick-wg0.service" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
if [ ! -s /etc/wireguard/private.key ]; then
|
||||||
|
${pkgs.wireguard-tools}/bin/wg genkey > /etc/wireguard/private.key
|
||||||
|
chmod 600 /etc/wireguard/private.key
|
||||||
|
echo "Public key: $(${pkgs.wireguard-tools}/bin/wg pubkey < /etc/wireguard/private.key)"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.wg-quick.interfaces.wg0 = {
|
||||||
|
privateKeyFile = "/etc/wireguard/private.key";
|
||||||
|
address = [ cfg.address ];
|
||||||
|
listenPort = 51820;
|
||||||
|
|
||||||
|
preUp = ''
|
||||||
|
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT
|
||||||
|
${pkgs.iptables}/bin/iptables -A FORWARD -o wg0 -j ACCEPT
|
||||||
|
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.2.2.0/24 -o eth0 -j MASQUERADE
|
||||||
|
'';
|
||||||
|
|
||||||
|
postDown = ''
|
||||||
|
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT
|
||||||
|
${pkgs.iptables}/bin/iptables -D FORWARD -o wg0 -j ACCEPT
|
||||||
|
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.2.2.0/24 -o eth0 -j MASQUERADE
|
||||||
|
'';
|
||||||
|
|
||||||
|
peers = map (peer: {
|
||||||
|
inherit (peer) publicKey allowedIPs;
|
||||||
|
}) cfg.peers;
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall = {
|
||||||
|
allowedUDPPorts = [ 51820 ];
|
||||||
|
trustedInterfaces = [ "wg0" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
boot.kernel.sysctl = {
|
||||||
|
"net.ipv4.ip_forward" = 1;
|
||||||
|
"net.ipv6.conf.all.forwarding" = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,203 +0,0 @@
|
||||||
# NOTE: Private key file at: `/etc/wireguard/private.key` with mode 600
|
|
||||||
# Generate with: `wg genkey > /etc/wireguard/private.key`
|
|
||||||
|
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.services.wireguard-custom;
|
|
||||||
in
|
|
||||||
|
|
||||||
{
|
|
||||||
options.services.wireguard-custom = {
|
|
||||||
enable = mkEnableOption "WireGuard VPN";
|
|
||||||
|
|
||||||
mode = mkOption {
|
|
||||||
type = types.enum [ "server" "client" ];
|
|
||||||
description = "Whether to run as server (hub) or client (spoke)";
|
|
||||||
};
|
|
||||||
|
|
||||||
interface = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "wg0";
|
|
||||||
description = "WireGuard interface name";
|
|
||||||
};
|
|
||||||
|
|
||||||
listenPort = mkOption {
|
|
||||||
type = types.port;
|
|
||||||
default = 51820;
|
|
||||||
description = "UDP port to listen on (server mode only)";
|
|
||||||
};
|
|
||||||
|
|
||||||
privateKeyFile = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "/etc/wireguard/private.key";
|
|
||||||
description = "Path to private key file";
|
|
||||||
};
|
|
||||||
|
|
||||||
serverConfig = mkOption {
|
|
||||||
type = types.submodule {
|
|
||||||
options = {
|
|
||||||
address = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
example = "10.2.2.1/24";
|
|
||||||
description = "Server IP address with CIDR";
|
|
||||||
};
|
|
||||||
|
|
||||||
peers = mkOption {
|
|
||||||
type = types.listOf (types.submodule {
|
|
||||||
options = {
|
|
||||||
name = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "Peer name for identification";
|
|
||||||
};
|
|
||||||
|
|
||||||
publicKey = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "Peer's public key";
|
|
||||||
};
|
|
||||||
|
|
||||||
allowedIPs = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
description = "IP addresses this peer is allowed to use";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
default = [];
|
|
||||||
description = "List of client peers";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
description = "Server-specific configuration";
|
|
||||||
};
|
|
||||||
|
|
||||||
clientConfig = mkOption {
|
|
||||||
type = types.submodule {
|
|
||||||
options = {
|
|
||||||
address = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
example = "10.2.2.20/24";
|
|
||||||
description = "Client IP address with CIDR";
|
|
||||||
};
|
|
||||||
|
|
||||||
serverPublicKey = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "Server's public key";
|
|
||||||
};
|
|
||||||
|
|
||||||
serverEndpoint = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
example = "vpn.example.com:51820";
|
|
||||||
description = "Server endpoint (host:port)";
|
|
||||||
};
|
|
||||||
|
|
||||||
allowedIPs = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [ "10.2.2.0/24" ];
|
|
||||||
description = "IP ranges to route through the tunnel";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
description = "Client-specific configuration";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
# Install WireGuard tools
|
|
||||||
environment.systemPackages = with pkgs; [ wireguard-tools ];
|
|
||||||
|
|
||||||
# Create private key file if it doesn't exist
|
|
||||||
systemd.tmpfiles.rules = [
|
|
||||||
"d /etc/wireguard 0700 root root - -"
|
|
||||||
"f ${cfg.privateKeyFile} 0600 root root - -"
|
|
||||||
];
|
|
||||||
|
|
||||||
# Generate private key on first run
|
|
||||||
systemd.services.wireguard-keygen = {
|
|
||||||
description = "Generate WireGuard private key";
|
|
||||||
before = [ "wg-quick-${cfg.interface}.service" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
};
|
|
||||||
script = ''
|
|
||||||
if [ ! -s ${cfg.privateKeyFile} ]; then
|
|
||||||
echo "Generating WireGuard private key..."
|
|
||||||
${pkgs.wireguard-tools}/bin/wg genkey > ${cfg.privateKeyFile}
|
|
||||||
chmod 600 ${cfg.privateKeyFile}
|
|
||||||
echo "Private key generated. Public key:"
|
|
||||||
${pkgs.wireguard-tools}/bin/wg pubkey < ${cfg.privateKeyFile}
|
|
||||||
echo "Please add this public key to your peer configurations."
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# WireGuard interface configuration (combined server and client)
|
|
||||||
networking.wg-quick.interfaces = {
|
|
||||||
${cfg.interface} = mkMerge [
|
|
||||||
# Common configuration
|
|
||||||
{
|
|
||||||
privateKeyFile = cfg.privateKeyFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Server-specific configuration
|
|
||||||
(mkIf (cfg.mode == "server") {
|
|
||||||
address = [ cfg.serverConfig.address ];
|
|
||||||
listenPort = cfg.listenPort;
|
|
||||||
|
|
||||||
# Enable IP forwarding and NAT for server
|
|
||||||
preUp = ''
|
|
||||||
${pkgs.iptables}/bin/iptables -A FORWARD -i ${cfg.interface} -j ACCEPT
|
|
||||||
${pkgs.iptables}/bin/iptables -A FORWARD -o ${cfg.interface} -j ACCEPT
|
|
||||||
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.2.2.0/24 -o eth0 -j MASQUERADE
|
|
||||||
'';
|
|
||||||
|
|
||||||
postDown = ''
|
|
||||||
${pkgs.iptables}/bin/iptables -D FORWARD -i ${cfg.interface} -j ACCEPT
|
|
||||||
${pkgs.iptables}/bin/iptables -D FORWARD -o ${cfg.interface} -j ACCEPT
|
|
||||||
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.2.2.0/24 -o eth0 -j MASQUERADE
|
|
||||||
'';
|
|
||||||
|
|
||||||
peers = map (peer: {
|
|
||||||
publicKey = peer.publicKey;
|
|
||||||
allowedIPs = peer.allowedIPs;
|
|
||||||
}) cfg.serverConfig.peers;
|
|
||||||
})
|
|
||||||
|
|
||||||
# Client-specific configuration
|
|
||||||
(mkIf (cfg.mode == "client") {
|
|
||||||
address = [ cfg.clientConfig.address ];
|
|
||||||
|
|
||||||
peers = [{
|
|
||||||
publicKey = cfg.clientConfig.serverPublicKey;
|
|
||||||
allowedIPs = cfg.clientConfig.allowedIPs;
|
|
||||||
endpoint = cfg.clientConfig.serverEndpoint;
|
|
||||||
persistentKeepalive = 25;
|
|
||||||
}];
|
|
||||||
})
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Firewall configuration
|
|
||||||
networking.firewall = mkMerge [
|
|
||||||
# Server firewall rules
|
|
||||||
(mkIf (cfg.mode == "server") {
|
|
||||||
allowedUDPPorts = [ cfg.listenPort ];
|
|
||||||
trustedInterfaces = [ cfg.interface ];
|
|
||||||
})
|
|
||||||
|
|
||||||
# Client firewall rules
|
|
||||||
(mkIf (cfg.mode == "client") {
|
|
||||||
trustedInterfaces = [ cfg.interface ];
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
# Enable IP forwarding for server
|
|
||||||
boot.kernel.sysctl = mkIf (cfg.mode == "server") {
|
|
||||||
"net.ipv4.ip_forward" = 1;
|
|
||||||
"net.ipv6.conf.all.forwarding" = 1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue