{ lib, ... }: with lib; (evalModules { modules = [ { options.configurations = mkOption { description = "My configurations."; type = with types; attrsOf ( submodule ( { name, ... }: { freeformType = attrs; options = let mkConfigurationTypeOption = type: mkOption { description = "Whether the machine's functional type is a ${type} one."; type = bool; default = false; }; in { hostname = mkOption { description = "The machine's hostname."; type = str; default = name; readOnly = true; }; stateVersion = mkOption { description = "Machine's Nixpkgs state version."; type = str; default = trivial.release; }; deviceIcon = mkOption { description = "Device icon to be used with nix-topology."; type = nullOr (either path str); default = null; }; system = mkOption { description = "The machine's system."; type = nullOr (enum platforms.all); default = null; }; isHeadless = mkConfigurationTypeOption "headless"; isHeadful = mkConfigurationTypeOption "headful"; isOther = mkConfigurationTypeOption "other"; ipv4 = { address = mkOption { description = "The machine's public IPv4 address."; type = nullOr str; default = null; }; prefixLength = mkOption { description = "The machine's public IPv4 prefix length."; type = nullOr int; default = null; }; gatewayAddress = mkOption { description = "The machine's public IPv4 gateway address."; type = nullOr str; default = null; }; }; ipv6 = { address = mkOption { description = "The machine's public IPv6 address."; type = nullOr str; default = null; }; prefixLength = mkOption { description = "The machine's public IPv6 prefix length."; type = nullOr int; default = null; }; gatewayAddress = mkOption { description = "The machine's public IPv6 gateway address."; type = nullOr str; default = null; }; }; wireguard = { ipv4.address = mkOption { description = "The machine's internal IPv4 addresses."; type = nullOr str; default = null; }; ipv6.address = mkOption { description = "The machine's internal IPv6 addresses."; type = nullOr str; default = null; }; publicKey = mkOption { description = "The machine's public key."; type = nullOr str; default = null; }; }; # TODO Automate filling of this from the NSD service module. # Right now I need to copy domain definitions from there to here # manually. # # Something like taking `config.services.nsd.zones[$domain]` and # filtering for actual subdomains. We can remove this option # altogether then. domains = mkOption { description = "External domains that resolve to this address."; type = listOf str; default = [ ]; }; syncthing.id = mkOption { description = "Syncthing ID."; type = nullOr str; default = null; }; }; } ) ); default = { }; }; config = { _module.freeformType = types.attrs; fullname = "Firstname Lastname"; username = "azahi"; domain = { azahi = "azahi.cc"; rohan = "rohan.net"; gondor = "gondor.net"; shire = "shire.net"; }; email = "frodo@${my.domain.gondor}"; pgp = { key = "@PGP_KEY@"; fingerprint = "@PGP_FINGERPRINT@"; grip = "@PGP_GRIP@"; }; ssh = rec { type = "ed25519"; id = my.email; key = "ssh-${type} @PUBLIC_KEY@ ${id}"; }; hashedPassword = "@HASHED_PASSWORD@"; configurations = { # VPS in Germany. manwe = { stateVersion = "24.05"; deviceIcon = "devices.cloud-server"; system = "x86_64-linux"; isHeadless = true; ipv4 = { gatewayAddress = "@IPV4_ADDRESS@"; address = "@IPV4_ADDRESS@"; prefixLength = 22; }; ipv6 = { gatewayAddress = "@IPV6_ADDRESS@"; address = "@IPV6_ADDRESS@]"; prefixLength = 64; }; wireguard = { ipv4.address = "10.69.0.1"; ipv6.address = "fd69::0:1"; publicKey = "@PUBLIC_KEY@"; }; domains = with my.domain; [ "alertmanager.${shire}" "frodo.${rohan}" "frodo.${gondor}" "bitwarden.${shire}" "git.${azahi}" "git.${shire}" "grafana.${shire}" "irc.${shire}" "loki.${shire}" "ntfy.${shire}" "plausible.${shire}" "prometheus.${shire}" "radicale.${shire}" "rss-bridge.${shire}" "start.local" "uptime.${shire}" "vaultwarden.${shire}" azahi rohan gondor shire ]; }; # VPS in Germany. varda = { stateVersion = "24.05"; deviceIcon = "devices.cloud-server"; system = "x86_64-linux"; isHeadless = true; ipv4 = { gatewayAddress = "@IPV4_ADDRESS@"; address = "@IPV4_ADDRESS@"; prefixLength = 22; }; ipv6 = { gatewayAddress = "@IPV6_ADDRESS@"; address = "@IPV6_ADDRESS@"; prefixLength = 64; }; wireguard = { ipv4.address = "10.69.1.1"; ipv6.address = "fd69::1:1"; publicKey = "@PUBLIC_KEY@"; }; }; # VPS in France. yavanna = { stateVersion = "24.05"; deviceIcon = "devices.cloud-server"; system = "x86_64-linux"; isHeadless = true; ipv4 = { gatewayAddress = "@IPV4_ADDRESS@"; address = "@IPV4_ADDRESS@"; prefixLength = 24; }; ipv6 = { gatewayAddress = "@IPV6_ADDRESS@"; address = "@IPV6_ADDRESS@"; prefixLength = 128; }; wireguard = { ipv4.address = "10.69.1.2"; ipv6.address = "fd69::1:2"; publicKey = "@PUBLIC_KEY@"; }; domains = with my.domain; [ "flood.${shire}" "jackett.${shire}" "lidarr.${shire}" ]; syncthing.id = "@SYNCTHING_ID@"; }; # VPS in Russia. tulkas = { stateVersion = "24.05"; deviceIcon = "devices.cloud-server"; system = "x86_64-linux"; isHeadless = true; ipv4 = { gatewayAddress = "@IPV4_ADDRESS@"; address = "@IPV4_ADDRESS@"; prefixLength = 32; }; ipv6 = { gatewayAddress = "@IPV6_ADDRESS@"; address = "@IPV6_ADDRESS@"; prefixLength = 64; }; wireguard = { ipv4.address = "10.69.0.4"; ipv6.address = "fd69::0:4"; publicKey = "@PUBLIC_KEY@"; }; }; # A beefy desktop: 7950x/rx6750xt/128GB. eonwe = { stateVersion = "24.05"; deviceIcon = "devices.desktop"; system = "x86_64-linux"; isHeadful = true; wireguard = { ipv4.address = "10.69.3.1"; ipv6.address = "fd69::3:1"; publicKey = "@PUBLIC_KEY@"; }; syncthing.id = "@SYNCTHING_ID@"; }; # ThinkPad X1 Nano Gen 3. ilmare = { stateVersion = "24.05"; deviceIcon = "devices.laptop"; system = "x86_64-linux"; isHeadful = true; wireguard = { ipv4.address = "10.69.4.1"; ipv6.address = "fd69::4:1"; publicKey = "@PUBLIC_KEY@"; }; syncthing.id = "@SYNCTHING_ID@"; }; # Google Pixel 7a w/ GrapheneOS. lungorthin = { isOther = true; wireguard = { ipv4.address = "10.69.5.2"; ipv6.address = "fd69::5:2"; publicKey = "@PUBLIC_KEY@"; }; syncthing.id = "@SYNCTHING_ID@"; }; }; }; } ]; }).config