From 431e145992ad20d34eb95da4f0257735d951516d Mon Sep 17 00:00:00 2001 From: Danilo Reyes Date: Tue, 28 Oct 2025 13:30:35 -0600 Subject: [PATCH] Add Linode host configuration and WireGuard setup - Introduced new configuration files for Linode host, including hardware configuration, toggles, and WireGuard settings. - Updated flake.nix to include the new images.nix file for Linode image generation. - Adjusted SSH key paths and secrets management for WireGuard to ensure proper integration with the new host setup. - Enhanced firewall rules and NAT configuration for WireGuard to improve security and connectivity. --- flake.nix | 1 + hosts/linode/configuration.nix | 50 +++++++++++++ hosts/linode/hardware-configuration.nix | 47 ++++++++++++ hosts/linode/toggles.nix | 25 +++++++ hosts/linode/wireguard-linode.nix | 72 +++++++++++++++++++ hosts/server/configuration.nix | 6 +- modules/modules.nix | 1 + modules/services/wireguard.nix | 12 ++-- parts/core.nix | 5 +- parts/hosts.nix | 1 + parts/images.nix | 8 +++ .../{ed25519_vps.pub => ed25519_linode.pub} | 0 secrets/wireguard.yaml | 16 +++-- 13 files changed, 225 insertions(+), 19 deletions(-) create mode 100644 hosts/linode/configuration.nix create mode 100644 hosts/linode/hardware-configuration.nix create mode 100644 hosts/linode/toggles.nix create mode 100644 hosts/linode/wireguard-linode.nix create mode 100644 parts/images.nix rename secrets/ssh/{ed25519_vps.pub => ed25519_linode.pub} (100%) diff --git a/flake.nix b/flake.nix index 5619e78..ebad635 100644 --- a/flake.nix +++ b/flake.nix @@ -67,6 +67,7 @@ ./parts/hosts.nix ./parts/packages.nix ./parts/devshells.nix + ./parts/images.nix ]; }; } diff --git a/hosts/linode/configuration.nix b/hosts/linode/configuration.nix new file mode 100644 index 0000000..640aa05 --- /dev/null +++ b/hosts/linode/configuration.nix @@ -0,0 +1,50 @@ +{ + pkgs, + config, + inputs, + ... +}: +{ + imports = [ + ./hardware-configuration.nix + ./wireguard-linode.nix + ../../config/base.nix + ]; + my = import ./toggles.nix { inherit config inputs; } // { + nix.cores = 2; + users.nixremote.enable = false; + network.firewall = { + enabledServicePorts = true; + additionalPorts = [ ]; + }; + }; + networking.hostName = "linode"; + services.openssh = { + enable = true; + openFirewall = true; + startWhenNeeded = false; + settings = { + PasswordAuthentication = false; + PermitRootLogin = "prohibit-password"; + KbdInteractiveAuthentication = false; + }; + }; + security.fail2ban = { + enable = true; + maxretry = 5; + bantime = "1h"; + }; + environment.systemPackages = builtins.attrValues { + inherit (pkgs) + htop + iotop + tcpdump + wireguard-tools + ; + }; + system.autoUpgrade = { + enable = true; + dates = "weekly"; + allowReboot = true; + }; +} diff --git a/hosts/linode/hardware-configuration.nix b/hosts/linode/hardware-configuration.nix new file mode 100644 index 0000000..5df0d0d --- /dev/null +++ b/hosts/linode/hardware-configuration.nix @@ -0,0 +1,47 @@ +{ lib, modulesPath, ... }: +{ + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + boot = { + tmp.cleanOnBoot = true; + kernel.sysctl = { + "net.core.default_qdisc" = "fq"; + "net.ipv4.tcp_congestion_control" = "bbr"; + "net.ipv4.conf.all.rp_filter" = 1; + "net.ipv4.conf.default.rp_filter" = 1; + "net.ipv4.icmp_echo_ignore_broadcasts" = 1; + "net.ipv4.conf.all.accept_source_route" = 0; + "net.ipv6.conf.all.accept_source_route" = 0; + "net.ipv4.conf.all.send_redirects" = 0; + "net.ipv4.tcp_syncookies" = 1; + }; + loader.grub = { + enable = true; + device = "/dev/sda"; + }; + kernelModules = [ + "virtio_pci" + "virtio_blk" + "virtio_net" + ]; + initrd = { + availableKernelModules = [ + "virtio_pci" + "virtio_scsi" + "virtio_blk" + "virtio_net" + "9p" + "9pnet_virtio" + ]; + kernelModules = [ ]; + }; + extraModulePackages = [ ]; + }; + fileSystems."/" = { + device = "/dev/sda"; + fsType = "ext4"; + }; + swapDevices = [ { device = "/dev/sdb"; } ]; + networking.useDHCP = lib.mkDefault true; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.enableRedistributableFirmware = true; +} diff --git a/hosts/linode/toggles.nix b/hosts/linode/toggles.nix new file mode 100644 index 0000000..4d68238 --- /dev/null +++ b/hosts/linode/toggles.nix @@ -0,0 +1,25 @@ +_: { + timeZone = "America/Mexico_City"; + locale = "en_US.UTF-8"; + wireguard.enable = true; + network.enable = true; + secureHost = true; + ips = { + vps = "51.222.141.104"; + wg-vps = "10.77.0.1"; + wg-server = "10.77.0.2"; + wg-friend1 = "10.8.0.2"; + wg-friends = "10.8.0.0"; + }; + interfaces = { + linode = "eth0"; + }; + dev = { + nix.enable = true; + sh.enable = true; + }; + shell = { + tools.enable = true; + config.enable = true; + }; +} diff --git a/hosts/linode/wireguard-linode.nix b/hosts/linode/wireguard-linode.nix new file mode 100644 index 0000000..cf22e11 --- /dev/null +++ b/hosts/linode/wireguard-linode.nix @@ -0,0 +1,72 @@ +{ + config, + lib, + pkgs, + ... +}: +{ + config = lib.mkIf config.my.services.wireguard.enable { + sops.secrets."wireguard/linode/private" = { + sopsFile = ../../secrets/wireguard.yaml; + }; + networking = { + nat = { + enable = true; + externalInterface = config.my.interfaces.${config.networking.hostName}; + internalInterfaces = [ "wg0" ]; + }; + firewall = { + allowedUDPPorts = [ 51820 ]; + extraCommands = '' + iptables -I FORWARD 1 -s ${config.my.ips.wg-friend1} -d ${config.my.ips.wg-server} -p tcp --dport 22000 -j ACCEPT + iptables -I FORWARD 2 -s ${config.my.ips.wg-server} -d ${config.my.ips.wg-friend1} -p tcp --sport 22000 -m state --state ESTABLISHED,RELATED -j ACCEPT + iptables -I FORWARD 3 -s ${config.my.ips.wg-friends}/24 -d 10.77.0.0/24 -j DROP + iptables -I FORWARD 4 -s 10.77.0.0/24 -d ${config.my.ips.wg-friends}/24 -j DROP + iptables -A FORWARD -s ${config.my.ips.wg-friends}/24 -o ${ + config.my.interfaces.${config.networking.hostName} + } -j ACCEPT + iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT + ''; + extraStopCommands = '' + iptables -D FORWARD -s ${config.my.ips.wg-friend1} -d ${config.my.ips.wg-server} -p tcp --dport 22000 -j ACCEPT 2>/dev/null || true + iptables -D FORWARD -s ${config.my.ips.wg-server} -d ${config.my.ips.wg-friend1} -p tcp --sport 22000 -m state --state ESTABLISHED,RELATED -j ACCEPT 2>/dev/null || true + iptables -D FORWARD -s ${config.my.ips.wg-friends}/24 -d 10.77.0.0/24 -j DROP 2>/dev/null || true + iptables -D FORWARD -s 10.77.0.0/24 -d ${config.my.ips.wg-friends}/24 -j DROP 2>/dev/null || true + iptables -D FORWARD -s ${config.my.ips.wg-friends}/24 -o ${ + config.my.interfaces.${config.networking.hostName} + } -j ACCEPT 2>/dev/null || true + iptables -D FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT 2>/dev/null || true + ''; + }; + wireguard.interfaces.wg0 = { + ips = [ + "${config.my.ips.wg-vps}/24" + "${config.my.ips.wg-friends}/24" + ]; + listenPort = 51820; + privateKeyFile = config.sops.secrets."wireguard/linode/private".path; + postSetup = "${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s ${config.my.ips.wg-friends}/24 -o ${ + config.my.interfaces.${config.networking.hostName} + } -j MASQUERADE"; + postShutdown = "${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s ${config.my.ips.wg-friends}/24 -o ${ + config.my.interfaces.${config.networking.hostName} + } -j MASQUERADE 2>/dev/null || true"; + peers = [ + { + publicKey = "OUiqluRaS4hmGvLJ3csQrnIM3Zzet50gsqtTABaUkH4="; + allowedIPs = [ "${config.my.ips.wg-server}/32" ]; + } + { + publicKey = "rFgT6TXzRazK6GMazMNGjtOvzAAPST0LvCfN7QXsLho="; + allowedIPs = [ "${config.my.ips.wg-friend1}/32" ]; + } + ]; + }; + }; + boot.kernel.sysctl = { + "net.ipv4.ip_forward" = 1; + "net.ipv6.conf.all.forwarding" = 1; + }; + environment.systemPackages = [ pkgs.wireguard-tools ]; + }; +} diff --git a/hosts/server/configuration.nix b/hosts/server/configuration.nix index 14f6ae1..c48422b 100644 --- a/hosts/server/configuration.nix +++ b/hosts/server/configuration.nix @@ -37,7 +37,7 @@ supportedFeatures = config.my.nix.features; } ]; - sops.secrets."vps/home/private" = lib.mkIf config.my.secureHost { + sops.secrets."wireguard/server/private" = lib.mkIf config.my.secureHost { sopsFile = ../../secrets/wireguard.yaml; }; networking = { @@ -48,14 +48,14 @@ }; wireguard.interfaces.wg0 = lib.mkIf config.my.secureHost { ips = [ "${config.my.ips.wg-server}/32" ]; - privateKeyFile = config.sops.secrets."vps/home/private".path; + privateKeyFile = config.sops.secrets."wireguard/server/private".path; peers = [ { publicKey = "dFbiSekBwnZomarcS31o5+w6imHjMPNCipkfc2fZ3GY="; endpoint = "${config.my.ips.vps}:51820"; allowedIPs = [ "${config.my.ips.wg-vps}/32" - "${config.my.ips.wg-friends}/24" # all friends + "${config.my.ips.wg-friends}/24" ]; persistentKeepalive = 25; } diff --git a/modules/modules.nix b/modules/modules.nix index 4d50b2d..61f10e5 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -63,6 +63,7 @@ in server = "enp0s31f6"; miniserver = "enp2s0"; workstation = "enp5s0"; + linode = "eth0"; }; description = "Set of network interface names for all my computers."; }; diff --git a/modules/services/wireguard.nix b/modules/services/wireguard.nix index 505f829..d05254d 100644 --- a/modules/services/wireguard.nix +++ b/modules/services/wireguard.nix @@ -11,7 +11,7 @@ in { options.my.services.wireguard.enable = lib.mkEnableOption "WireGuard VPN configuration"; config = lib.mkIf (config.my.services.wireguard.enable && config.my.secureHost) { - sops.secrets."wireguard/private".sopsFile = ../../secrets/wireguard.yaml; + sops.secrets."wireguard/server/private".sopsFile = ../../secrets/wireguard.yaml; networking = { firewall.allowedUDPPorts = [ port ]; nat = { @@ -22,13 +22,9 @@ in wireguard.interfaces.wg0 = { ips = [ "10.100.0.1/24" ]; listenPort = port; - postSetup = '' - ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o ${interface} -j MASQUERADE - ''; - postShutdown = '' - ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.100.0.0/24 -o ${interface} -j MASQUERADE - ''; - privateKeyFile = config.sops.secrets."wireguard/private".path; + postSetup = "${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o ${interface} -j MASQUERADE"; + postShutdown = "${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.100.0.0/24 -o ${interface} -j MASQUERADE"; + privateKeyFile = config.sops.secrets."wireguard/server/private".path; peers = [ { publicKey = "ciupBjCcIpd3K5vlzNMJC8iiyNqB9xXwkSC6UXPKP3g="; diff --git a/parts/core.nix b/parts/core.nix index 5bf0119..55eb0d3 100644 --- a/parts/core.nix +++ b/parts/core.nix @@ -141,7 +141,7 @@ in ips: hostName: lib: builtins.attrNames ips |> builtins.filter ( - name: !(lib.hasPrefix "wg-" name) && name != "vps" && name != "router" && name != hostName + name: !(lib.hasPrefix "wg-" name) && name != "linode" && name != "router" && name != hostName ); shellConditional = shellType: bashContent: zshContent: @@ -204,9 +204,8 @@ in miniserver = ../secrets/ssh/ed25519_miniserver.pub; galaxy = ../secrets/ssh/ed25519_galaxy.pub; phone = ../secrets/ssh/ed25519_phone.pub; - vps = ../secrets/ssh/ed25519_vps.pub; + linode = ../secrets/ssh/ed25519_linode.pub; emacs = ../secrets/ssh/ed25519_emacs.pub; - # Build user keys (nixremote) nixworkstation = ../secrets/ssh/ed25519_nixworkstation.pub; nixserver = ../secrets/ssh/ed25519_nixserver.pub; nixminiserver = ../secrets/ssh/ed25519_nixminiserver.pub; diff --git a/parts/hosts.nix b/parts/hosts.nix index e72b2ad..0bbbc42 100644 --- a/parts/hosts.nix +++ b/parts/hosts.nix @@ -6,5 +6,6 @@ server = inputs.self.lib.createConfig "server" inputs.nixpkgs-small; galaxy = inputs.self.lib.createConfig "galaxy" inputs.nixpkgs-small; emacs = inputs.self.lib.createConfig "emacs" inputs.nixpkgs; + linode = inputs.self.lib.createConfig "linode" inputs.nixpkgs-small; }; } diff --git a/parts/images.nix b/parts/images.nix new file mode 100644 index 0000000..8df4a8d --- /dev/null +++ b/parts/images.nix @@ -0,0 +1,8 @@ +{ inputs, ... }: +{ + flake.packages.x86_64-linux.linode-image = inputs.nixos-generators.nixosGenerate { + system = "x86_64-linux"; + modules = [ inputs.self.nixosConfigurations.linode.config.system.build.toplevel.outPath ]; + format = "linode"; + }; +} diff --git a/secrets/ssh/ed25519_vps.pub b/secrets/ssh/ed25519_linode.pub similarity index 100% rename from secrets/ssh/ed25519_vps.pub rename to secrets/ssh/ed25519_linode.pub diff --git a/secrets/wireguard.yaml b/secrets/wireguard.yaml index 602174b..fd5f3f0 100644 --- a/secrets/wireguard.yaml +++ b/secrets/wireguard.yaml @@ -1,6 +1,12 @@ wireguard: - private: ENC[AES256_GCM,data:wwggc9T88gK/EMmjPauf14DZGUnfipBpfN3FnlPhsO6FtVmK2aad/D0/Rqw=,iv:Q15iiEOFRa3bPf7NfZcEZOgEqnjIJPenYgE6c6HRYI8=,tag:x+auLhc/FDhxZxzWmcrX9Q==,type:str] - public: ENC[AES256_GCM,data:uelp1opnLR5EfvNBSA3Sk33ktMoG6+Pvj7oKYtdlCpXMZel9O8G7P4X5S2M=,iv:AQECJmnXSc2MM0pT8ZJtA51pn+tvhhyAxFDMBH/H6wA=,tag:yWsnQbHaeiXyPLbpxMZwsg==,type:str] + linode: + private: ENC[AES256_GCM,data:PejimzNOiJGlTbMZjlyZIFYCnhu/ZAisG/we03ZJo8VO4cwclm+ztXCE89c=,iv:iw3hIUxMyx7rIQ56Nc4zPXBdRn8HYL44AXOu57VfiX0=,tag:zZcGrTU+1k6FRtTG5zj4pw==,type:str] + public: ENC[AES256_GCM,data:G3p/wGLeNq8/icpKbIUGEMC/l8rqptUv7tpB2md+fmo0UJieK3s3lWy79u8=,iv:4LQ8RfT3VkzdrxkOn+XROKdnBqdhbBdRzw+x/j+t/BY=,tag:+s4eCnDp6XSE+w4wlB+QLA==,type:str] + server: + private: ENC[AES256_GCM,data:owBMyfOeeizHMbRp7yqaE95otpyEsH5HUk0RcltEqgzvTGfTWBLP8ZvMhPA=,iv:KtGd+w4WtRGJ6ux+70SOU6eq21Ak4r0obFimvPWWSjE=,tag:2eYP41vhKNyUi/3zyOY+Vg==,type:str] + public: ENC[AES256_GCM,data:9GcLl+xpcZZ7XU4c0eDqvUjc9VVvs8C4ZhRUfB9WjuGIu3we/Syxh8pGC8c=,iv:IdXada3p+GVpLgm9mOGjAObPPFfXzSNVfBm01Liyz4s=,tag:uzB5BpVNT4F+wUO3gwsunQ==,type:str] + private_old: ENC[AES256_GCM,data:T6SIjKfNJSyapmF1IFkoSBT0S8/bsvbivRqbS8FubQ0UnZ+SfMRIEHVPXgg=,iv:OnQw4OKfRmDhOzBUq834oqTDCobE5RW2EKqFYUf1Xt8=,tag:4hJ8pumr4KDMyM1Sygy57g==,type:str] + public_old: ENC[AES256_GCM,data:teRFtsuKyrK/D5yag+RyHCsrtuuK1S0rC9By9I+eMCTGh00Jiw7T/kEdGm0=,iv:A8JAcZekzDnP+PNhH1YKigBhNVSKqsRC0UbIr+Af5ec=,tag:m852G+0tdrqzpY1J6YBxrg==,type:str] vps: server: private: ENC[AES256_GCM,data:wrP/069tuQs3ObYE8Q0MNVxe3+4vZ2HIImoIdZpj1uPgdBknboX1wmANv/k=,iv:FJL5KumHos8PoXra+BB2Uc6YedsF6MD3wWyuugXzJ+E=,tag:nVuTrW2P7JvnWnv6H1SmdQ==,type:str] @@ -46,7 +52,7 @@ sops: KzZFSWprL0l0MDdVdEVKbEV5eklZdTAK/1ZyGvElfp+LVloSR6aJUtvrgU0CrzaJ SQtO7vc4oDedkiTz6LKySta+uyn3e17Jzdyy9nU2D/Q5X+CpKGP3cg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-09-08T00:14:52Z" - mac: ENC[AES256_GCM,data:O2herKRy4k9ZMuPzzPF5QlBC2isXdRoIsbYLJ/6X7esxtxxgNuAljx4SCR6UMT7pl3G2E33cnnBEkuAIy6SMXOaZNfOuAEJXaCwpRwCXu26lrcTf6n7UdP36GWfIRsR4utD5/vv66ch6MqmQWkW7E5zydy5dOv+BJ4XS/50OUQs=,iv:TscYNQaeI+mBxyobxI1O4wUzRtA27pvjXz27kqMJhA0=,tag:zx/xrYAWJCxYz5HRTKzYfQ==,type:str] + lastmodified: "2025-10-28T19:13:03Z" + mac: ENC[AES256_GCM,data:Mp6sgr6VwoQqnOmqloCAeKuL/8kB4vNLxk94AXAzX1z/Wq+R3Y3I6Yh3hB+QeTRW8nJ5hmGjAEeVzFtjRFP7EcL3KKY3B7s7TU1O+I3lWYMgNuCG6+Z7do62x/1ZyeCGMRQDIc6Xzu13ktyxf4AeVxg/7w0qBHbt3QVa18UM08U=,iv:4jJ5mDEeNgSwd+ekzDuF1z8pSNy04M1XEPr7TIIrZ2M=,tag:ZwiHCXKQWONsBJ9NGsYo1w==,type:str] unencrypted_suffix: _unencrypted - version: 3.10.2 + version: 3.11.0