diff --git a/common/admins.nix b/common/admins.nix new file mode 100644 index 0000000..685411e --- /dev/null +++ b/common/admins.nix @@ -0,0 +1,11 @@ +{ + users.users.root.openssh.authorizedKeys.keys = [ + # delroth + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII3tjB4KYDok3KlWxdBp/yEmqhhmybd+w0VO4xUwLKKV" + # raito + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcEkYM1r8QVNM/G5CxJInEdoBCWjEHHDdHlzDYNSUIdHHsn04QY+XI67AdMCm8w30GZnLUIj5RiJEWXREUApby0GrfxGGcy8otforygfgtmuUKAUEHdU2MMwrQI7RtTZ8oQ0USRGuqvmegxz3l5caVU7qGvBllJ4NUHXrkZSja2/51vq80RF4MKkDGiz7xUTixI2UcBwQBCA/kQedKV9G28EH+1XfvePqmMivZjl+7VyHsgUVj9eRGA1XWFw59UPZG8a7VkxO/Eb3K9NF297HUAcFMcbY6cPFi9AaBgu3VC4eetDnoN/+xT1owiHi7BReQhGAy/6cdf7C/my5ehZwD" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0xMwWedkKosax9+7D2OlnMxFL/eV4CvFZLsbLptpXr" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKiXXYkhRh+s7ixZ8rvG8ntIqd6FELQ9hh7HoaHQJRPU" + "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJFsZ7PMDt80tYXHyScQajNhqH4wuYg/o0OxfOHaZD4rXuT0VIKflKH1M9LslfHWIEH3XNeqhQOziH9r+Ny5JcM=" + ]; +} diff --git a/common/base-server.nix b/common/base-server.nix new file mode 100644 index 0000000..498b9e6 --- /dev/null +++ b/common/base-server.nix @@ -0,0 +1,22 @@ +{ lib, pkgs, ... }: { + nix.package = pkgs.lix; + services.openssh.enable = lib.mkForce true; + + networking.firewall.enable = true; + networking.firewall.logRefusedConnections = false; + networking.firewall.logReversePathDrops = true; + + services.nginx = { + recommendedOptimisation = lib.mkDefault true; + recommendedTlsSettings = lib.mkDefault true; + recommendedProxySettings = lib.mkDefault true; + recommendedGzipSettings = lib.mkDefault true; + }; + + nix.gc = { + automatic = true; + persistent = true; + dates = "daily"; + options = "--delete-older-than 30d"; + }; +} diff --git a/common/default.nix b/common/default.nix new file mode 100644 index 0000000..0054de1 --- /dev/null +++ b/common/default.nix @@ -0,0 +1,9 @@ +{ + imports = [ + ./admins.nix + ./raito-vm.nix + ./raito-proxy-aware-nginx.nix + ./base-server.nix + ./sysadmin + ]; +} diff --git a/common/raito-proxy-aware-nginx.nix b/common/raito-proxy-aware-nginx.nix new file mode 100644 index 0000000..59fb332 --- /dev/null +++ b/common/raito-proxy-aware-nginx.nix @@ -0,0 +1,35 @@ +# This enables an IPv6-only server which is proxied by kurisu.lahfa.xyz to have proper IPv4 logs via PROXY protocol. +{ config, lib, ... }: +let + inherit (lib) mkEnableOption mkIf; + cfg = config.bagel.raito.v6-proxy-awareness; + allowedUpstream = "2001:bc8:38ee:99::1/128"; +in + { + options.bagel.raito.v6-proxy-awareness.enable = mkEnableOption "the kurisu.lahfa.xyz's sniproxy awareness for NGINX"; + config = mkIf cfg.enable { + services.nginx = { + # IPv6-only server + defaultListen = [ + { addr = "[::0]"; proxyProtocol = true; port = 444; ssl = true; } + { addr = "[::0]"; port = 443; ssl = true; } + { addr = "[::0]"; port = 80; ssl = false; } + # Private networking + { addr = "127.0.0.1"; port = 80; ssl = false; } + { addr = "[::1]"; port = 80; ssl = false; } + ]; + + appendHttpConfig = '' + # Kurisu node + set_real_ip_from ${allowedUpstream}; + real_ip_header proxy_protocol; + ''; + }; + + # Move to nftables if firewall is enabled. + networking.nftables.enable = true; + networking.firewall.extraInputRules = '' + ip6 saddr ${allowedUpstream} tcp dport 444 accept + ''; + }; + } diff --git a/common/raito-vm.nix b/common/raito-vm.nix new file mode 100644 index 0000000..f9adc7d --- /dev/null +++ b/common/raito-vm.nix @@ -0,0 +1,155 @@ +{ lib, config, ... }: +let + cfg = config.bagel.hardware.raito-vm; + inherit (lib) mkEnableOption mkIf mkOption types; +in +{ + options.bagel.hardware.raito-vm = { + enable = mkEnableOption "Raito's VM hardware defaults"; + + networking = { + nat-lan-mac = mkOption { + type = types.nullOr types.str; + default = null; + description = "MAC address for the NAT-LAN interface, autoconfigured via DHCP"; + }; + + wan = { + address = mkOption { + type = types.str; + description = "IPv6 prefix for WAN. Ask Raito when in doubt."; + }; + mac = mkOption { + type = types.str; + description = "MAC address for the WAN interface."; + }; + }; + }; + }; + + config = mkIf cfg.enable { + services.qemuGuest.enable = true; + systemd.network.enable = true; + security.acme.defaults.email = "bagel-acme@lahfa.xyz"; + security.acme.acceptTerms = true; + + systemd.network.networks."10-nat-lan" = { + matchConfig.Name = "nat-lan"; + linkConfig.RequiredForOnline = true; + DHCP = "yes"; + }; + + systemd.network.links."10-nat-lan" = { + matchConfig.MACAddress = cfg.networking.nat-lan-mac; + linkConfig.Name = "nat-lan"; + }; + + systemd.network.networks."10-wan" = { + matchConfig.Name = "wan"; + linkConfig.RequiredForOnline = true; + networkConfig.Address = [ cfg.networking.wan.address ]; + }; + + systemd.network.links."10-wan" = { + matchConfig.MACAddress = cfg.networking.wan.mac; + linkConfig.Name = "wan"; + }; + + boot.loader.systemd-boot.enable = true; + + boot.initrd.kernelModules = [ + "virtio_balloon" + "virtio_console" + "virtio_rng" + ]; + + boot.initrd.availableKernelModules = [ + "9p" + "9pnet_virtio" + "ata_piix" + "nvme" + "sr_mod" + "uhci_hcd" + "virtio_blk" + "virtio_mmio" + "virtio_net" + "virtio_pci" + "virtio_scsi" + "xhci_pci" + ]; + + fileSystems."/boot" = { + device = "/dev/disk/by-label/BOOT"; + fsType = "vfat"; + }; + + swapDevices = [ { device = "/dev/disk/by-label/swap"; } ]; + + boot.initrd.luks.devices.root = { + device = "/dev/disk/by-label/root"; + + # WARNING: Leaks some metadata, see cryptsetup man page for --allow-discards. + # allowDiscards = true; + + # Set your own key with: + # cryptsetup luksChangeKey /dev/disk/by-label/root --key-file=/dev/zero --keyfile-size=1 + # You can then delete the rest of this block. + keyFile = "/dev/zero"; + keyFileSize = 1; + + fallbackToPassword = true; + }; + + fileSystems."/" = { + device = "/dev/mapper/root"; + fsType = "btrfs"; + options = [ + "subvol=root" + "compress=zstd" + "noatime" + ]; + }; + + fileSystems."/home" = { + device = "/dev/mapper/root"; + fsType = "btrfs"; + options = [ + "subvol=home" + "compress=zstd" + "noatime" + ]; + }; + + fileSystems."/nix" = { + device = "/dev/mapper/root"; + fsType = "btrfs"; + options = [ + "subvol=nix" + "compress=zstd" + "noatime" + ]; + neededForBoot = true; + }; + + fileSystems."/etc" = { + device = "/dev/mapper/root"; + fsType = "btrfs"; + options = [ + "subvol=etc" + "compress=zstd" + "noatime" + ]; + }; + + fileSystems."/var" = { + device = "/dev/mapper/root"; + fsType = "btrfs"; + options = [ + "subvol=var" + "compress=zstd" + "noatime" + ]; + neededForBoot = true; + }; + }; +} diff --git a/common/ssh-keys.nix b/common/ssh-keys.nix index 9310d4d..2b32b89 100644 --- a/common/ssh-keys.nix +++ b/common/ssh-keys.nix @@ -1,5 +1,11 @@ { - machines.bagel-box = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJW7jmkJ73tx9lsrz9UhqJIJdoqZGuhsHti55xny5/yp"; + machines = { + bagel-box = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJW7jmkJ73tx9lsrz9UhqJIJdoqZGuhsHti55xny5/yp"; + meta01 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM5t9gYorOWgpCFDJgb24pyCKIabGpeI2H/UfdvXODcT"; + }; - users.delroth = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII3tjB4KYDok3KlWxdBp/yEmqhhmybd+w0VO4xUwLKKV" ]; + users = { + delroth = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII3tjB4KYDok3KlWxdBp/yEmqhhmybd+w0VO4xUwLKKV" ]; + raito = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICaw9ihTG7ucB8P38XdalEWev8+q96e2yNm4B+/I9IJp" ]; + }; } diff --git a/common/sysadmin/default.nix b/common/sysadmin/default.nix new file mode 100644 index 0000000..f751705 --- /dev/null +++ b/common/sysadmin/default.nix @@ -0,0 +1,24 @@ +{ pkgs, config, lib, ... }: +let + inherit (lib) mkIf mkEnableOption; + cfg = config.bagel.sysadmin; +in + { + options.bagel.sysadmin.enable = mkEnableOption "sysadmin tooling"; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + wget + vim + tmux + rsync + fd + ripgrep + pv + kitty.terminfo + config.boot.kernelPackages.perf + tcpdump + ncdu + ] ++ lib.optional (lib.hasAttr "pwru" pkgs) pkgs.pwru; + }; + } diff --git a/flake.nix b/flake.nix index 324c6b5..4623b9d 100644 --- a/flake.nix +++ b/flake.nix @@ -37,6 +37,17 @@ ./hosts/bagel-box ]; }; + + meta01 = { + imports = [ + inputs.agenix.nixosModules.default + inputs.hydra.nixosModules.hydra + + ./services + ./common + ./hosts/meta01.nixpkgs.lahfa.xyz + ]; + }; }; }; } diff --git a/hosts/bagel-box/default.nix b/hosts/bagel-box/default.nix index 3897a03..eed24b1 100644 --- a/hosts/bagel-box/default.nix +++ b/hosts/bagel-box/default.nix @@ -45,16 +45,6 @@ security.acme.defaults.email = "bagel@delroth.net"; services.openssh.enable = true; - users.users.root.openssh.authorizedKeys.keys = [ - # delroth - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII3tjB4KYDok3KlWxdBp/yEmqhhmybd+w0VO4xUwLKKV" - # raito - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcEkYM1r8QVNM/G5CxJInEdoBCWjEHHDdHlzDYNSUIdHHsn04QY+XI67AdMCm8w30GZnLUIj5RiJEWXREUApby0GrfxGGcy8otforygfgtmuUKAUEHdU2MMwrQI7RtTZ8oQ0USRGuqvmegxz3l5caVU7qGvBllJ4NUHXrkZSja2/51vq80RF4MKkDGiz7xUTixI2UcBwQBCA/kQedKV9G28EH+1XfvePqmMivZjl+7VyHsgUVj9eRGA1XWFw59UPZG8a7VkxO/Eb3K9NF297HUAcFMcbY6cPFi9AaBgu3VC4eetDnoN/+xT1owiHi7BReQhGAy/6cdf7C/my5ehZwD" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0xMwWedkKosax9+7D2OlnMxFL/eV4CvFZLsbLptpXr" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKiXXYkhRh+s7ixZ8rvG8ntIqd6FELQ9hh7HoaHQJRPU" - "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJFsZ7PMDt80tYXHyScQajNhqH4wuYg/o0OxfOHaZD4rXuT0VIKflKH1M9LslfHWIEH3XNeqhQOziH9r+Ny5JcM=" - - ]; deployment.targetHost = "bagel-box.delroth.net"; } diff --git a/hosts/meta01.nixpkgs.lahfa.xyz/default.nix b/hosts/meta01.nixpkgs.lahfa.xyz/default.nix new file mode 100755 index 0000000..87007be --- /dev/null +++ b/hosts/meta01.nixpkgs.lahfa.xyz/default.nix @@ -0,0 +1,29 @@ +{ + networking.hostName = "meta01"; + networking.domain = "nixpkgs.lahfa.xyz"; + + time.timeZone = "Europe/Paris"; + + bagel.sysadmin.enable = true; + # netbox is proxied. + bagel.raito.v6-proxy-awareness.enable = true; + bagel.hardware.raito-vm = { + enable = true; + networking = { + nat-lan-mac = "bc:24:11:b2:96:d8"; + wan = { + address = "2001:bc8:38ee:100:1000::20/64"; + mac = "bc:24:11:64:cd:88"; + }; + }; + }; + bagel.services.netbox = { + enable = true; + domain = "netbox.nixpkgs.lahfa.xyz"; + }; + + i18n.defaultLocale = "fr_FR.UTF-8"; + + system.stateVersion = "24.05"; + deployment.targetHost = "meta01.nixpkgs.lahfa.xyz"; +} diff --git a/secrets.nix b/secrets.nix index d2977b6..1c49184 100644 --- a/secrets.nix +++ b/secrets.nix @@ -6,6 +6,7 @@ let secrets = with keys; { hydra-s3-credentials = [ machines.bagel-box ]; hydra-ssh-key-priv = [ machines.bagel-box ]; + netbox-environment = [ machines.netbox01 ]; }; in builtins.listToAttrs ( diff --git a/secrets/netbox-environment.age b/secrets/netbox-environment.age new file mode 100644 index 0000000..c5f5752 Binary files /dev/null and b/secrets/netbox-environment.age differ diff --git a/services/default.nix b/services/default.nix index a2de4bf..3a44ef3 100644 --- a/services/default.nix +++ b/services/default.nix @@ -2,5 +2,6 @@ imports = [ ./hydra ./postgres + ./netbox ]; } diff --git a/services/netbox/default.nix b/services/netbox/default.nix new file mode 100644 index 0000000..423bd0e --- /dev/null +++ b/services/netbox/default.nix @@ -0,0 +1,80 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + EnvironmentFile = [ config.age.secrets.netbox-environment.path ]; + cfg = config.bagel.services.netbox; + inherit (lib) mkEnableOption mkOption mkIf types; +in + +{ + options.bagel.services.netbox = { + enable = mkEnableOption "Netbox"; + domain = mkOption { + type = types.str; + }; + }; + + config = mkIf cfg.enable { + age.secrets.netbox-environment.file = ../../secrets/netbox-environment.age; + services = { + netbox = { + enable = true; + package = pkgs.netbox_3_7; + secretKeyFile = "/dev/null"; + listenAddress = "127.0.0.1"; + settings = { + ALLOWED_HOSTS = [ cfg.domain ]; + # REMOTE_AUTH_BACKEND = "social_core.backends.open_id_connect.OpenIdConnectAuth"; + }; + + extraConfig = lib.mkForce '' + from os import environ as env + + SECRET_KEY = env["SECRET_KEY"] + + # SOCIAL_AUTH_OIDC_OIDC_ENDPOINT = env["NETBOX_OIDC_URL"] + # SOCIAL_AUTH_OIDC_KEY = env["NETBOX_OIDC_KEY"] + # SOCIAL_AUTH_OIDC_SECRET = env["NETBOX_OIDC_SECRET"] + ''; + }; + + nginx = { + enable = true; + virtualHosts."${cfg.domain}" = { + enableACME = true; + forceSSL = true; + + locations."/".proxyPass = "http://${config.services.netbox.listenAddress}:${builtins.toString config.services.netbox.port}"; + locations."/static/".alias = "${config.services.netbox.dataDir}/static/"; + }; + }; + }; + + systemd.services = { + netbox.serviceConfig = { + inherit EnvironmentFile; + + TimeoutStartSec = 600; + }; + + netbox-housekeeping.serviceConfig = { + inherit EnvironmentFile; + }; + + netbox-rq.serviceConfig = { + inherit EnvironmentFile; + }; + }; + + users.users.nginx.extraGroups = [ "netbox" ]; + networking.firewall.allowedTCPPorts = [ + 443 + 80 + ]; + }; +}