diff --git a/config/domain-config/fudo.org.nix b/config/domain-config/fudo.org.nix index 16c5490..3f46fb9 100644 --- a/config/domain-config/fudo.org.nix +++ b/config/domain-config/fudo.org.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, ... }@toplevel: with lib; let @@ -6,18 +6,25 @@ let localDomain = "fudo.org"; serviceSecrets = config.fudo.secrets.files.service-secrets."${hostname}"; + inherit (pkgs.lib) getDomainHosts getHostIpv4 getHostFqdn; + domain = config.fudo.domains."${localDomain}"; authentikHost = "legatus"; primaryNameserver = "germany"; + defaultHost = "germany"; + + mastodonHostname = "mastodon.fudo.org"; + in { imports = [ (import ./fudo.org/authentik.nix { inherit authentikHost; }) (import ./fudo.org/mastodon.nix { mastodonHost = "legatus"; - mastodonHostname = "mastodon.fudo.org"; + mastodonHostname = mastodonHostname; + mastodonWebDomain = "fudo.org"; mastodonOidcClientId = serviceSecrets."mastodon-oidc.clientid"; mastodonOidcClientSecret = serviceSecrets."mastodon-oidc.secret"; }) @@ -52,14 +59,22 @@ in { config = { # All Fudo hosts should redirect selby.ca to the selbyhomecentre website. services.nginx.virtualHosts = { + # Pass requests to selby on to selbyhomecentre "selby.ca".locations."/".return = "301 https://selbyhomecentre.com$request_uri"; "www.selby.ca".locations."/".return = "301 https://selbyhomecentre.com$request_uri"; - "selbyhomecentre.com".locations."/".return = - "301 https://selbyhomecentre.com$request_uri"; - "www.selbyhomecentre.com".locations."/".return = - "301 https://selbyhomecentre.com$request_uri"; + + # For Mastodon + "fudo.org".locations = { + "/.well-known/webfinger" = { + return = "301 http://${mastodonHostname}"; + extraConfig = "add_header Access-Control-Allow-Origin '*';"; + }; + "/.well-known/host-meta" = { + return = "301 https://${mastodonHostname}$request_uri"; + }; + }; }; fudo.services = { @@ -71,20 +86,54 @@ in { authoritative-dns = { enable = hostname == primaryNameserver; - nameservers = { primary = primaryNameserver; }; + nameservers = { + primary = primaryNameserver; + external = map (hostname: { + inherit (config.fudo.zones."fudo.org".hosts."${hostname}") + ipv4-address ipv6-address description; + }) [ "ns2-fudo" "ns3-fudo" "ns4-fudo" ]; + }; - zones = { + ip-host-map = let + networkHosts = getDomainHosts "fudo.org"; + ipHostPairs = + map (host: nameValuePair (getHostIpv4 host) (getHostFqdn host)) + networkHosts; + in listToAttrs ipHostPairs; + + zones = let + defaultDeets = { + inherit (config.fudo.zones."fudo.org".hosts."${defaultHost}") + ipv4-address ipv6-address sshfp-records; + description = "fudo.org"; + }; + in { "fudo.org" = { - default-host = "germany"; + default-host = defaultDeets; ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.org"; + reverse-zones = [ "208.81.1.128/28" "208.81.3.112/28" ]; + }; + "test.fudo.org" = { + default-host = defaultDeets; + ksk = + config.fudo.secrets.files.dns.key-signing-keys."test.fudo.org"; }; "selby.ca" = { - default-host = "germany"; - ksk = null; + default-host = defaultDeets; + ksk = config.fudo.secrets.files.dns.key-signing-keys."selby.ca"; }; - "selbyhomecentre.com" = { - default-host = "germany"; - ksk = null; + "fudo.ca" = { + default-host = defaultDeets; + ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.ca"; + }; + "fudo.im" = { + default-host = defaultDeets; + ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.im"; + }; + "stewartsoundservices.ca" = { + default-host = defaultDeets; + ksk = + config.fudo.secrets.files.dns.key-signing-keys."stewartsoundservices.ca"; }; }; }; diff --git a/config/domain-config/fudo.org/mail-server.nix b/config/domain-config/fudo.org/mail-server.nix index 7f91bd5..56c7ca6 100644 --- a/config/domain-config/fudo.org/mail-server.nix +++ b/config/domain-config/fudo.org/mail-server.nix @@ -5,7 +5,9 @@ { config, lib, pkgs, ... }: with lib; -let hostname = config.instance.hostname; +let + inherit (pkgs.lib) getHostIpv4 getHostIpv6; + hostname = config.instance.hostname; in { config = { @@ -17,28 +19,44 @@ in { zones."${primaryDomain}" = let mailserverDomain = config.fudo.hosts."${primaryMailserver}".domain; - mailserverZone = config.fudo.domains."${mailserverDomain}".zone; - mailserverIps = - config.fudo.zones."${mailserverZone}".hosts."${mailserver}"; + mailserver = + config.fudo.domains."${mailserverDomain}".primary-mailserver; + mailserverIps = { + ipv4-address = getHostIpv4 mailserver; + ipv6-address = getHostIpv6 mailserver; + }; + srvRecord = host: port: [{ inherit host port; }]; in { - hosts = { - imap = { - ipv4-address = mailserverIps.ipv4-address; - ipv6-address = mailserverIps.ipv6-address; + srv-records = { + tcp = { + imap = srvRecord "imap.${primaryDomain}" 143; + imaps = srvRecord "imap.${primaryDomain}" 993; + smtp = srvRecord "smtp.${primaryDomain}" 25; + submission = srvRecord "smtp.${primaryDomain}" 587; + submissions = srvRecord "smtp.${primaryDomain}" 465; }; - smtp = { - ipv4-address = mailserverIps.ipv4-address; - ipv6-address = mailserverIps.ipv6-address; - }; - mail = { - ipv4-address = mailserverIps.ipv4-address; - ipv6-address = mailserverIps.ipv6-address; + udp = { + smtp = srvRecord "smtp.${primaryDomain}" 25; + submission = srvRecord "smtp.${primaryDomain}" 587; }; }; - # FIXME: DKIM key!!! + + metric-records = genAttrs [ "dovecot" "postfix" "rspamd" ] + (_: srvRecord "mail-stats.${primaryDomain}" 443); + + hosts = { + imap = mailserverIps; + smtp = mailserverIps; + mail = mailserverIps; + mail-stats = mailserverIps; + }; verbatim-dns-records = [ dkimRecord ]; }; + metrics.prometheus.service-discovery-dns = + (genAttrs [ "dovecot" "postfix" "rspamd" ] + (metricType: [ "${metricType}._metrics._tcp.${primaryDomain}" ])); + mail = { enable = hostname == primaryMailserver; debug = true; diff --git a/config/domain-config/fudo.org/mastodon.nix b/config/domain-config/fudo.org/mastodon.nix index 877daad..82293ad 100644 --- a/config/domain-config/fudo.org/mastodon.nix +++ b/config/domain-config/fudo.org/mastodon.nix @@ -1,5 +1,5 @@ -{ mastodonHost, mastodonHostname, mastodonOidcClientId, mastodonOidcClientSecret -, ... }: +{ mastodonHost, mastodonHostname, mastodonWebDomain, mastodonOidcClientId +, mastodonOidcClientSecret, ... }: { config, lib, pkgs, ... }: @@ -13,8 +13,8 @@ in { services = { mastodonContainer = mkIf isMastodon { enable = true; - hostname = mastodonHostname; - web-domain = "fudo.org"; + hostname = mastodonWebDomain; + web-domain = mastodonHostname; version = "v4.1.6"; state-directory = "/state/services/mastodon"; smtp.server = "mail.fudo.org"; diff --git a/config/domain-config/fudo.org/nextcloud.nix b/config/domain-config/fudo.org/nextcloud.nix index 9ca2f00..9943743 100644 --- a/config/domain-config/fudo.org/nextcloud.nix +++ b/config/domain-config/fudo.org/nextcloud.nix @@ -38,6 +38,9 @@ in { proxyPass = "http://localhost:${toString port}"; proxyWebsockets = true; }; + extraConfig = '' + client_body_buffer_size 1024m; + ''; }; }; }; diff --git a/config/domain-config/informis.land.nix b/config/domain-config/informis.land.nix index d62b98d..fa70dc6 100644 --- a/config/domain-config/informis.land.nix +++ b/config/domain-config/informis.land.nix @@ -4,10 +4,14 @@ with lib; let hostname = config.instance.hostname; mailserver = "locum"; + primaryNameserver = "locum"; + defaultHost = "locum"; authentikHost = "locum"; userdbPasswd = pkgs.lib.passwd.stablerandom-passwd-file "userdb-passwd" config.instance.build-seed; + inherit (pkgs.lib) getDomainHosts getHostIpv4 getHostFqdn; + in { imports = [ (import ./informis.land/authentik.nix { inherit authentikHost; }) ]; @@ -40,20 +44,36 @@ in { '' mail._domainkey IN TXT ( "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKiTSUDxDPwMxLMT7wzR0ZaGuGzU1xnhti0zqi6xGJVxe9O8wfpX1vTSAasGYGzg5r24Hc8tSTogUgy0uJXsIbPBiqXj3WsoL/vf7+tAmrmZA4DQn1hN+C0R/7knhTNPWKnIAMqReAH/yf3XvFGmBMpU3UGRNGc2MoCQ4iXBcbsQIDAQAB" ) ; ----- DKIM key mail for all-domains-generic-key'' ]; - # srv-records = let srv-record = host: port: [{ inherit host port; }]; - # in { - # tcp = { - # imap = srv-record "imap.informis.land" 143; - # imaps = srv-record "imap.informis.land" 993; - - # smtp = srv-record "smtp.informis.land" 25; - # submission = srv-record "smtp.informis.land" 587; - # }; - # }; }; - services.dns.zones."informis.land" = { - default-host = pkgs.lib.getHostIpv4 "locum"; + services = { + authoritative-dns = { + enable = hostname == primaryNameserver; + + nameservers.primary = primaryNameserver; + + ip-host-map = let + networkHosts = getDomainHosts "informis.land"; + ipHostPairs = + map (host: nameValuePair (getHostIpv4 host) (getHostFqdn host)) + networkHosts; + in listToAttrs ipHostPairs; + + zones."informis.land" = { + default-host = { + inherit (config.fudo.zones."informis.land".hosts."${defaultHost}") + ipv4-address ipv6-address sshfp-records; + description = "informis.land"; + }; + ksk = + config.fudo.secrets.files.dns.key-signing-keys."informis.land"; + mail = { + smtp-servers = [ "smtp.informis.land" ]; + imap-servers = [ "imap.informis.land" ]; + }; + reverse-zones = [ "172.86.179.17/29" "190.2.134.0/24" ]; + }; + }; }; postgresql.package = pkgs.postgresql_15_gssapi; diff --git a/config/hardware/fimbria.nix b/config/hardware/fimbria.nix new file mode 100644 index 0000000..f285e7d --- /dev/null +++ b/config/hardware/fimbria.nix @@ -0,0 +1,89 @@ +{ config, lib, pkgs, modulesPath, ... }: + +{ + system.stateVersion = "23.05"; + + boot = { + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + initrd = { + availableKernelModules = + [ "xhci_pci" "ahci" "nvme" "usb_storage" "usbhid" "sd_mod" ]; + kernelModules = [ "dm-snapshot" ]; + }; + kernelModules = [ "kvm-intel" ]; + kernelPackages = pkgs.linuxPackages_latest; + }; + + fileSystems = { + "/" = { + device = "fimbria-root"; + fsType = "tmpfs"; + options = [ "mode=755" "noexec" ]; + }; + + "/boot" = { + device = "/dev/disk/by-label/FIM-BOOT"; + fsType = "vfat"; + options = [ "noexec" "noatime" ]; + }; + + "/nix" = { + device = "/dev/disk/by-label/fimbria-data"; + fsType = "btrfs"; + options = [ "subvol=@nix" "compress=zstd" "noatime" ]; + }; + + "/state" = { + device = "/dev/disk/by-label/fimbria-data"; + fsType = "btrfs"; + options = [ "subvol=@state" "compress=zstd" "noatime" "noexec" ]; + }; + + "/var/log" = { + device = "/dev/disk/by-label/fimbria-data"; + fsType = "btrfs"; + options = [ "subvol=@logs" "compress=zstd" "noatime" "noexec" ]; + }; + + "/var/lib/acme" = { + device = "/dev/disk/by-label/fimbria-data"; + fsType = "btrfs"; + options = [ "subvol=@acme" "compress=zstd" "noatime" "noexec" ]; + }; + + "/var/lib/private" = { + device = "/dev/disk/by-label/fimbria-data"; + fsType = "btrfs"; + options = [ "subvol=@private" "noexec" "noatime" ]; + neededForBoot = true; + }; + }; + + nix.settings.max-jobs = lib.mkDefault 4; + + swapDevices = [{ device = "/dev/disk/by-label/fimbria-swap"; }]; + + networking = { + useDHCP = false; + macvlans = { + intif0 = { + interface = "enp2s0"; + mode = "bridge"; + }; + }; + interfaces = { + intif0.macAddress = + pkgs.lib.network.generate-mac-address "fimbria" "enp2s0"; + }; + }; + + systemd.targets = { + sleep.enable = false; + suspend.enable = false; + hibernate.enable = false; + hybrid-sleep.enable = false; + }; +} diff --git a/config/hardware/germany.nix b/config/hardware/germany.nix index 96dc35f..1770e6b 100644 --- a/config/hardware/germany.nix +++ b/config/hardware/germany.nix @@ -97,6 +97,11 @@ in { mode = "bridge"; }; + dnsif0 = { + interface = "enp5s0f0"; + mode = "bridge"; + }; + extif1 = { interface = "enp5s0f1"; mode = "bridge"; diff --git a/config/host-config/fimbria.nix b/config/host-config/fimbria.nix new file mode 100644 index 0000000..291c02d --- /dev/null +++ b/config/host-config/fimbria.nix @@ -0,0 +1,124 @@ +{ config, lib, pkgs, ... }: + +with lib; +let primaryIp = "10.0.0.2"; +in { + config = { + networking = { + interfaces = { + enp1s0.useDHCP = true; + intif0 = { + useDHCP = false; + ipv4 = { + addresses = [{ + address = primaryIp; + prefixLength = 16; + }]; + routes = [{ + address = "192.168.86.0"; + prefixLength = 24; + via = "10.0.0.3"; + }]; + }; + }; + }; + enableIPv6 = false; + + firewall = { + # Until it becomes the gateway, this is necessary + enable = mkForce true; + allowedTCPPorts = [ 80 443 25565 config.services.murmur.port ]; + allowedUDPPorts = [ 25565 34197 ]; + }; + + nat.forwardPorts = [ + # Minecraft + { + destination = "10.0.0.12:25555"; + proto = "tcp"; + sourcePort = 25565; + } + { + destination = "10.0.0.12:25555"; + proto = "udp"; + sourcePort = 25565; + } + # Factorio + { + destination = "10.0.0.12:34197"; + proto = "udp"; + sourcePort = 34197; + } + ]; + }; + + fudo = { + hosts.fimbria.external-interfaces = [ "enp1s0" ]; + client.dns.external-interface = "enp1s0"; + services = { + local-network = { + enable = true; + internal-interfaces = [ "intif0" ]; + external-interface = "enp1s0"; + dns-filter-proxy.enable = true; + }; + + metrics = { + prometheus.state-directory = "/state/services/prometheus"; + }; + + auth.kerberos.state-directory = "/state/services/heimdal-kdc"; + }; + }; + + security.acme.defaults.email = "niten@fudo.org"; + + systemd.services.nginx.requires = [ "bind.service" ]; + + services = { + ## TODO: enable when ready + # nginx = { + # enable = true; + # recommendedGzipSettings = true; + # recommendedOptimisation = true; + # recommendedProxySettings = true; + + # virtualHosts = { + # "sea-home.fudo.link" = { + # enableACME = true; + # forceSSL = true; + # locations."/" = { + # proxyPass = "http://home-assist.sea.fudo.org/"; + # extraConfig = '' + # proxy_http_version 1.1; + # proxy_set_header Upgrade $http_upgrade; + # proxy_set_header Connection "Upgrade"; + # ''; + # }; + # }; + # }; + # }; + + murmur = { + enable = true; + port = 64738; + bonjour = true; + password = "thelittleschool"; + }; + + openssh = { + hostKeys = [ + { + path = "/state/ssh/ssh_host_ed25519_key"; + type = "ed25519"; + } + { + path = "/state/ssh/ssh_host_rsa_key"; + type = "rsa"; + bits = 4096; + } + ]; + }; + }; + }; +} diff --git a/config/host-config/germany.nix b/config/host-config/germany.nix index 10a61b5..70ae693 100644 --- a/config/host-config/germany.nix +++ b/config/host-config/germany.nix @@ -2,6 +2,7 @@ let primary-ip = "208.81.3.116"; + dns-ip = "208.81.3.120"; hostname = config.instance.hostname; host = config.fudo.hosts."${hostname}"; domainName = host.domain; @@ -17,11 +18,19 @@ in { interface = "extif0"; address = site.gateway-v4; }; - interfaces.extif0 = { - ipv4.addresses = [{ - address = primary-ip; - prefixLength = 28; - }]; + interfaces = { + extif0 = { + ipv4.addresses = [{ + address = primary-ip; + prefixLength = 28; + }]; + }; + dnsif0 = { + ipv4.addresses = [{ + address = dns-ip; + prefixLength = 32; + }]; + }; }; firewall = { enable = false; @@ -29,10 +38,34 @@ in { }; }; - systemd.tmpfiles.rules = [ - "L /etc/adjtime - - - - /state/etc/adjtime" - "d /state/services 0555 - - - -" - ]; + systemd = { + tmpfiles.rules = [ + "L /etc/adjtime - - - - /state/etc/adjtime" + "d /state/services 0555 - - - -" + ]; + + services.fudo-mail-sync = { + path = with pkgs; [ rsync openssh ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = pkgs.writeShellScript "fudo-mail-sync.sh" '' + ssh-add ~/.ssh/id_ed25519 + rsync -avz france.fudo.org:/srv/mail/mailboxes/ /state/services/mail/mail/ + chown 5025:5025 -R /state/services/mail/mail + chmod go-rwx -R /state/services/mail/mail + ''; + }; + }; + + timers.fudo-mail-sync = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnBootSec = "3h"; + OnUnitActiveSec = "3h"; + Unit = "fudo-mail-sync.service"; + }; + }; + }; security.acme.defaults.email = "admin@fudo.org"; @@ -66,6 +99,11 @@ in { }; authoritative-dns.state-directory = "/state/services/dns"; jabber.state-directory = "/state/services/jabber"; + metrics = { + prometheus.state-directory = "/state/services/prometheus"; + grafana.state-directory = "/state/services/grafana"; + }; + logging.loki.state-directory = "/state/services/loki"; }; }; }; diff --git a/config/host-config/jazz.nix b/config/host-config/jazz.nix index 92d17f0..a9fdcbb 100644 --- a/config/host-config/jazz.nix +++ b/config/host-config/jazz.nix @@ -16,6 +16,17 @@ in { "d ${stateDir}/lib/flatpak 755 root root - -" ]; + # i18n.inputMethod = { + # enabled = "fcitx5"; + # fcitx5.addons = with pkgs; [ fcitx5-chinese-addons fcitx5-rime ]; + # }; + + services.xserver = { + layout = "us"; + xkbVariant = mkForce ""; + xkbOptions = mkForce ""; + }; + fileSystems = { "/var/lib/cups" = { device = "${stateDir}/lib/cups"; diff --git a/config/host-config/locum.nix b/config/host-config/locum.nix index 8f0b71f..5f58d92 100644 --- a/config/host-config/locum.nix +++ b/config/host-config/locum.nix @@ -72,6 +72,7 @@ in { mail.state-directory = "/state/services/mail"; services = { + authoritative-dns.state-directory = "/state/services/dns"; auth = { kerberos.state-directory = "/state/services/kerberos"; ldap.state-directory = "/state/services/ldap"; diff --git a/config/host-config/nutboy3.nix b/config/host-config/nutboy3.nix index 8eabda2..f06b001 100644 --- a/config/host-config/nutboy3.nix +++ b/config/host-config/nutboy3.nix @@ -59,34 +59,15 @@ in { security.acme.defaults.email = "admin@fudo.org"; fudo = { - hosts.${hostname}.external-interfaces = [ "extif0" ]; - - secrets.host-secrets.${hostname} = let files = config.fudo.secrets.files; - in { - # heimdal-master-key = { - # source-file = files.realm-master-keys."FUDO.ORG"; - # target-file = "/run/heimdal/master-key"; - # user = config.fudo.auth.kdc.user; - # }; - - ldap-keytab = { - # files.service-keytabs.${hostname}.openldap; - source-file = extractFudoKeytab { - realm = domain.gssapi-realm; - principals = [ "ldap/${host-fqdn}" ]; - }; - target-file = "/run/openldap/ldap.keytab"; - user = config.services.openldap.user; - }; - }; + hosts."${hostname}".external-interfaces = [ "extif0" ]; acme.host-domains.${hostname} = { ${host-fqdn}.local-copies = { - openldap = { - user = config.services.openldap.user; - dependent-services = [ "openldap.service" ]; - part-of = [ config.fudo.auth.ldap-server.systemd-target ]; - }; + # openldap = { + # user = config.services.openldap.user; + # dependent-services = [ "openldap.service" ]; + # part-of = [ config.fudo.auth.ldap-server.systemd-target ]; + # }; postgresql = { user = postgresql-user; @@ -104,11 +85,11 @@ in { }; services = { - jabber = { - domain = "jabber.fudo.org"; - ldap.servers = [ "nutboy3.fudo.org" ]; - state-directory = "/state/ejabberd"; - }; + # jabber = { + # domain = "jabber.fudo.org"; + # ldap.servers = [ "nutboy3.fudo.org" ]; + # state-directory = "/state/ejabberd"; + # }; auth = { ldap.state-directory = "/state/auth/ldap"; diff --git a/config/host-config/nutboy3/cashew.nix b/config/host-config/nutboy3/cashew.nix index ad90ad5..e86cdd9 100644 --- a/config/host-config/nutboy3/cashew.nix +++ b/config/host-config/nutboy3/cashew.nix @@ -64,7 +64,6 @@ in { zones = { "fudo.org" = { - default-host = host-ipv4; verbatim-dns-records = [ # TODO: create these automatically "node._metrics._tcp IN SRV 0 0 443 france.fudo.org." @@ -79,7 +78,7 @@ in { "rspamd._metrics._tcp IN SRV 0 0 443 mail.fudo.org." ]; }; - "selby.ca" = { default-host = host-ipv4; }; + "selby.ca" = { }; }; }; diff --git a/config/host-config/system3.nix b/config/host-config/system3.nix index c38cb9b..903c414 100644 --- a/config/host-config/system3.nix +++ b/config/host-config/system3.nix @@ -46,6 +46,12 @@ in { }; }; + fonts.fontconfig = { + hinting = { enable = false; }; + subpixel.lcdfilter = "none"; + antialias = true; + }; + environment.etc = { nixos.source = "/etc/nixos-live"; NIXOS.source = "${state-dir}/etc/NIXOS"; diff --git a/config/profile-config/common-ui.nix b/config/profile-config/common-ui.nix index 7224b53..9a063a3 100644 --- a/config/profile-config/common-ui.nix +++ b/config/profile-config/common-ui.nix @@ -10,7 +10,7 @@ in { boot = { plymouth.enable = false; - tmpOnTmpfs = true; + tmp.useTmpfs = true; }; environment.systemPackages = with pkgs; [ adoptopenjdk-jre-openj9-bin-16 ]; diff --git a/config/profile-config/host/kerberos.nix b/config/profile-config/host/kerberos.nix index 6e9c2c3..057f91c 100644 --- a/config/profile-config/host/kerberos.nix +++ b/config/profile-config/host/kerberos.nix @@ -43,7 +43,8 @@ in { paths."${hostname}-keytab-watcher" = { wantedBy = [ "default.target" ]; description = "Watch host keytab for changes."; - after = [ "fudo-secrets.target" ]; + ## This might be creating a cycle? + # after = [ "fudo-secrets.target" ]; pathConfig = { PathChanged = host-keytab; Unit = "${hostname}-keytab-watcher.service"; @@ -56,14 +57,14 @@ in { "When host keytab is available or changed, activate copy job."; path = with pkgs; [ systemd ]; serviceConfig = { Type = "oneshot"; }; - after = [ "fudo-secrets.target" ]; + # after = [ "fudo-secrets.target" ]; script = "systemctl restart ${hostname}-copy-keytab.service"; }; "${hostname}-copy-keytab" = { description = "Copy the host krb5.keytab into place once it's available."; - after = [ "fudo-secrets.target" "fudo-secret-host-keytab.service" ]; + # after = [ "fudo-secrets.target" "fudo-secret-host-keytab.service" ]; wantedBy = [ "default.target" ]; serviceConfig = { Type = "oneshot"; diff --git a/config/profile-config/user/home-manager.nix b/config/profile-config/user/home-manager.nix new file mode 100644 index 0000000..fd36f7c --- /dev/null +++ b/config/profile-config/user/home-manager.nix @@ -0,0 +1,12 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + stateVersion = config.system.stateVersion; + users = (attrNames config.instance.local-users) ++ [ "root" ]; +in { + config = { + home-manager.users = + genAttrs users (_: { home = { inherit stateVersion; }; }); + }; +} diff --git a/config/service/authoritative-dns.nix b/config/service/authoritative-dns.nix index 3418b46..d57c0ff 100644 --- a/config/service/authoritative-dns.nix +++ b/config/service/authoritative-dns.nix @@ -9,45 +9,9 @@ let hostSecrets = config.fudo.secrets.host-secrets."${hostname}"; domainName = config.instance.local-domain; - # domain = config.fudo.domains."${domainName}"; - # primaryNameserver = domain.primaryNameserver; - # isPrimaryNameserver = primary-nameserver == hostname; zoneKeySecret = zone: "${zone}-ksk"; - nameserverOpts = { name, ... }: { - options = with types; { - hostname = mkOption { - type = str; - description = "Hostname of the external nameserver."; - default = name; - }; - - ipv4-address = mkOption { - type = nullOr str; - description = "Host ipv4 address of the external nameserver."; - default = null; - }; - - ipv6-address = mkOption { - type = nullOr str; - description = "Host ipv6 address of the external nameserver."; - default = null; - }; - - authoritative-hostname = mkOption { - type = nullOr str; - description = "Authoritative hostname of this nameserver."; - default = null; - }; - - description = mkOption { - type = str; - description = "Description of the external nameserver."; - }; - }; - }; - networkHostOpts = { options = with types; { hostname = mkOption { @@ -104,18 +68,32 @@ let default = null; }; - external-nameservers = mkOption { - type = listOf (submodule nameserverOpts); - description = "List of external nameserver clauses."; - default = [ ]; - }; - domain = mkOption { type = str; description = "Domain which this zone serves."; default = zoneName; }; + reverse-zones = mkOption { + type = listOf str; + description = "List of networks for which to generate reverse zones."; + default = [ ]; + }; + + mail = { + smtp-servers = mkOption { + type = listOf str; + description = "List of SMTP server for this zone."; + default = [ ]; + }; + + imap-servers = mkOption { + type = listOf str; + description = "List of IMAP server for this zone."; + default = [ ]; + }; + }; + ksk = mkOption { type = nullOr (submodule { options = { @@ -145,12 +123,22 @@ in { options.fudo.services.authoritative-dns = with types; { enable = mkEnableOption "Enable Authoritative DNS server."; + enable-notifications = + mkEnableOption "Enable notifications to secondary servers."; + zones = mkOption { type = attrsOf (submodule zoneOpts); description = "Map of served zone to extra zone details."; default = { }; }; + ip-host-map = mkOption { + type = attrsOf str; + description = + "Map of ip address to authoritative hostname, for reverse zones."; + default = { }; + }; + nameservers = { primary = mkOption { type = str; @@ -162,6 +150,12 @@ in { description = "List of internal secondary nameservers."; default = [ ]; }; + + external = mkOption { + type = listOf (submodule networkHostOpts); + description = "List of external secondary nameserver attributes."; + default = [ ]; + }; }; state-directory = mkOption { @@ -188,10 +182,6 @@ in { makeSrvRecord = port: host: { inherit port host; }; - # servedDomain = domain.primary-nameserver != null; - - # primaryNameserver = domain.primary-nameserver; - isPrimaryNameserver = hostname == cfg.nameservers.primary; internalNameserverHostnames = [ cfg.nameservers.primary ] @@ -206,27 +196,13 @@ in { "${domainName} nameserver ${hostname}.${hostDomain}."; }; - nameserverDeets = let - internalNameservers = map getNsDeets internalNameserverHostnames; - in internalNameservers ++ zoneCfg.external-nameservers; - - hasAuthHostname = nsHost: nsOpts: - (hasAttr "authoritative-hostname" nsOpts) - && (nsOpts.authoritative-hostname != null); + nameserverDeets = (map getNsDeets internalNameserverHostnames) + ++ cfg.nameservers.external; allNameservers = listToAttrs (imap1 (i: nsOpts: nameValuePair "ns${toString i}" nsOpts) nameserverDeets); - nameserverAliases = - mapAttrs (hostname: opts: "${opts.authoritative-hostname}.") - (filterAttrs hasAuthHostname allNameservers); - - nameserverHosts = mapAttrs (hostname: opts: { - inherit (opts) ipv4-address ipv6-address description; - }) (filterAttrs (hostname: opts: !hasAuthHostname hostname opts) - allNameservers); - dnsSrvRecords = let nameserverSrvRecords = mapAttrsToList (hostname: hostOpts: let @@ -240,65 +216,37 @@ in { udp.domain = nameserverSrvRecords; }; - mailSrvRecords = mkIf (!isNull domain.primary-mailserver) (let - mailDomainName = - config.fudo.hosts."${domain.primary-mailserver}".domain; + mailSrvRecords = let + mkRecords = port: servers: + map (host: { inherit host port; }) servers; in { tcp = { - smtp = [{ - host = "smtp.${mailDomainName}"; - port = 25; - }]; - imap = [{ - host = "imap.${mailDomainName}"; - port = 143; - }]; - imaps = [{ - host = "imap.${mailDomainName}"; - port = 993; - }]; - submission = [{ - host = "smtp.${mailDomainName}"; - port = 587; - }]; - submissions = [{ - host = "smtp.${mailDomainName}"; - port = 465; - }]; + smtp = mkRecords 25 zoneCfg.mail.smtp-servers; + submission = mkRecords 587 zoneCfg.mail.smtp-servers; + submissions = mkRecords 465 zoneCfg.mail.smtp-servers; + + imap = mkRecords 143 zoneCfg.mail.imap-servers; + imaps = mkRecords 993 zoneCfg.mail.imap-servers; }; udp = { - smtp = [{ - host = "smtp.${mailDomainName}"; - port = 25; - }]; - submission = [{ - host = "smtp.${mailDomainName}"; - port = 587; - }]; + smtp = mkRecords 25 zoneCfg.mail.smtp-servers; + submission = mkRecords 587 zoneCfg.mail.smtp-servers; }; - }); + }; in { gssapi-realm = mkIf (!isNull domain.gssapi-realm) domain.gssapi-realm; - hosts = nameserverHosts; - # Don't add mailservers: remember SSL! + hosts = allNameservers; - aliases = nameserverAliases; + mx = zoneCfg.mail.smtp-servers; - mx = optional (!isNull domain.primary-mailserver) (let - mailserverDomain = - config.fudo.hosts."${domain.primary-mailserver}".domain; - in "smtp.${mailserverDomain}"); + dmarc-report-address = "dmarc-report@${domainName}"; - dmarc-report-address = mkIf (!isNull domain.primary-mailserver) - "dmarc-report@${domainName}"; + default-host = zoneCfg.default-host; - nameservers = let - directExternal = attrValues nameserverAliases; - internal = map (hostname: "${hostname}.${domainName}.") - (attrNames nameserverHosts); - in internal ++ directExternal; + nameservers = map (hostname: "${hostname}.${domainName}.") + (attrNames allNameservers); srv-records = dnsSrvRecords // mailSrvRecords; @@ -322,15 +270,22 @@ in { timestamp = toString config.instance.build-timestamp; + ip-host-map = cfg.ip-host-map; + domains = mapAttrs' (zoneName: zoneCfg: nameValuePair zoneCfg.domain { ksk.key-file = mkIf (hasAttr (zoneKeySecret zoneName) hostSecrets) hostSecrets."${zoneKeySecret zoneName}".target-file; - zone = let baseZone = config.fudo.zones."${zoneName}"; - in baseZone // { - # FIXME: what's up? - # default-host = baseZone.hosts."${zoneCfg.default-host}"; + reverse-zones = zoneCfg.reverse-zones; + notify = mkIf cfg.enable-notifications { + ipv4 = concatMap + (ns: optional (ns.ipv4-address != null) ns.ipv4-address) + cfg.nameservers.external; + ipv6 = concatMap + (ns: optional (ns.ipv6-address != null) ns.ipv6-address) + cfg.nameservers.external; }; + zone = config.fudo.zones."${zoneName}"; }) cfg.zones; }; }; diff --git a/config/service/dns.nix b/config/service/dns.nix index 5582c03..01a454f 100644 --- a/config/service/dns.nix +++ b/config/service/dns.nix @@ -114,7 +114,7 @@ in { }; }; - config.fudo = { + config.fudo = mkIf (!isNull domain.primary-nameserver) { secrets.host-secrets."${hostname}" = mkIf is-primary-nameserver (mapAttrs' (zone: zone-cfg: nameValuePair (zoneKeySecret zone) { @@ -123,96 +123,98 @@ in { user = config.fudo.nsd.user; }) cfg.zones); - zones = mapAttrs (zone-name: zone-cfg: - let - domain-name = zone-cfg.domain; - domain = config.fudo.domains.${domain-name}; + zones = mkIf (hostname == primary-nameserver) (mapAttrs + (zone-name: zone-cfg: + let + domain-name = zone-cfg.domain; + domain = config.fudo.domains.${domain-name}; - make-srv-record = port: host: { inherit port host; }; + make-srv-record = port: host: { inherit port host; }; - served-domain = domain.primary-nameserver != null; + served-domain = domain.primary-nameserver != null; - primary-nameserver = domain.primary-nameserver; + primary-nameserver = domain.primary-nameserver; - is-primary-nameserver = hostname == primary-nameserver; + is-primary-nameserver = hostname == primary-nameserver; - internal-nameserver-hostnames = [ domain.primary-nameserver ] - ++ domain.secondary-nameservers; + internal-nameserver-hostnames = [ domain.primary-nameserver ] + ++ domain.secondary-nameservers; - get-host-deets = description: hostname: { - ipv4-address = pkgs.lib.network.host-ipv4 config hostname; - ipv6-address = pkgs.lib.network.host-ipv6 config hostname; - description = description; - }; + get-host-deets = description: hostname: { + ipv4-address = pkgs.lib.network.host-ipv4 config hostname; + ipv6-address = pkgs.lib.network.host-ipv6 config hostname; + description = description; + }; - get-ns-deets = hostname: - let - host-domain = config.fudo.hosts.${hostname}.domain; - desc = "${domain-name} nameserver ${hostname}.${host-domain}."; - in get-host-deets desc hostname; - - nameserver-deets = let - internal-nameservers = map get-ns-deets internal-nameserver-hostnames; - in internal-nameservers ++ zone-cfg.external-nameservers; - - has-auth-hostname = ns-host: ns-opts: - (hasAttr "authoritative-hostname" ns-opts) - && (ns-opts.authoritative-hostname != null); - - all-nameservers = listToAttrs - (imap1 (i: nsOpts: nameValuePair "ns${toString i}" nsOpts) - nameserver-deets); - - nameserver-aliases = - mapAttrs (hostname: opts: "${opts.authoritative-hostname}.") - (filterAttrs has-auth-hostname all-nameservers); - - nameserver-hosts = mapAttrs (hostname: opts: { - inherit (opts) ipv4-address ipv6-address description; - }) (filterAttrs (hostname: opts: !has-auth-hostname hostname opts) - all-nameservers); - - dns-srv-records = let - nameserver-srv-records = mapAttrsToList (hostname: hostOpts: + get-ns-deets = hostname: let - target-host = if (has-auth-hostname hostname hostOpts) then - "${hostOpts.authoritative-hostname}" - else - "${hostname}.${domain-name}"; - in make-srv-record 53 target-host) all-nameservers; + host-domain = config.fudo.hosts.${hostname}.domain; + desc = "${domain-name} nameserver ${hostname}.${host-domain}."; + in get-host-deets desc hostname; + + nameserver-deets = let + internal-nameservers = + map get-ns-deets internal-nameserver-hostnames; + in internal-nameservers ++ zone-cfg.external-nameservers; + + has-auth-hostname = ns-host: ns-opts: + (hasAttr "authoritative-hostname" ns-opts) + && (ns-opts.authoritative-hostname != null); + + all-nameservers = listToAttrs + (imap1 (i: nsOpts: nameValuePair "ns${toString i}" nsOpts) + nameserver-deets); + + nameserver-aliases = + mapAttrs (hostname: opts: "${opts.authoritative-hostname}.") + (filterAttrs has-auth-hostname all-nameservers); + + nameserver-hosts = mapAttrs (hostname: opts: { + inherit (opts) ipv4-address ipv6-address description; + }) (filterAttrs (hostname: opts: !has-auth-hostname hostname opts) + all-nameservers); + + dns-srv-records = let + nameserver-srv-records = mapAttrsToList (hostname: hostOpts: + let + target-host = if (has-auth-hostname hostname hostOpts) then + "${hostOpts.authoritative-hostname}" + else + "${hostname}.${domain-name}"; + in make-srv-record 53 target-host) all-nameservers; + in { + tcp.domain = nameserver-srv-records; + udp.domain = nameserver-srv-records; + }; + in { - tcp.domain = nameserver-srv-records; - udp.domain = nameserver-srv-records; - }; + gssapi-realm = domain.gssapi-realm; - in { - gssapi-realm = domain.gssapi-realm; + hosts = nameserver-hosts; - hosts = nameserver-hosts; + aliases = nameserver-aliases; - aliases = nameserver-aliases; + mx = optional (domain.primary-mailserver != null) (let + mail-domain-name = + config.fudo.hosts."${domain.primary-mailserver}".domain; + in "mail.${mail-domain-name}"); - mx = optional (domain.primary-mailserver != null) (let - mail-domain-name = - config.fudo.hosts."${domain.primary-mailserver}".domain; - in "mail.${mail-domain-name}"); + dmarc-report-address = "dmarc-report@${domain-name}"; - dmarc-report-address = "dmarc-report@${domain-name}"; + nameservers = let + direct-external = attrValues nameserver-aliases; + internal = map (hostname: "${hostname}.${domain-name}.") + (attrNames nameserver-hosts); + in internal ++ direct-external; - nameservers = let - direct-external = attrValues nameserver-aliases; - internal = map (hostname: "${hostname}.${domain-name}.") - (attrNames nameserver-hosts); - in internal ++ direct-external; + srv-records = dns-srv-records; # // mail-srv-records; - srv-records = dns-srv-records; # // mail-srv-records; - - verbatim-dns-records = let pthru = o: trace o o; - in mkIf (zone-cfg.ksk != null) [ - (pthru (readFile zone-cfg.ksk.public-key)) - (pthru (readFile zone-cfg.ksk.ds)) - ]; - }) cfg.zones; + verbatim-dns-records = let pthru = o: trace o o; + in mkIf (zone-cfg.ksk != null) [ + (pthru (readFile zone-cfg.ksk.public-key)) + (pthru (readFile zone-cfg.ksk.ds)) + ]; + }) cfg.zones); dns = { enable = is-primary-nameserver; diff --git a/config/service/fudo-auth.nix b/config/service/fudo-auth.nix index a11119b..424b9e2 100644 --- a/config/service/fudo-auth.nix +++ b/config/service/fudo-auth.nix @@ -73,7 +73,6 @@ in { systemd = { tmpfiles.rules = mkIf (kerberos-master || kerberos-slave) [ "d ${cfg.kerberos.state-directory} 0700 ${krb-user} ${krb-group} - -" - "f ${cfg.fudo.auth.kerberos.kdc.database} 0700 ${krb-user} ${krb-group} - -" ]; paths.heimdal-kdc-initialize = mkIf kerberos-master { @@ -84,7 +83,11 @@ in { }; services = { - heimdal-kdc-initialize = mkIf (kerberos-master || kerberos-slave) { + heimdal-kdc-initialize = mkIf (kerberos-master || kerberos-slave) (let + db = config.fudo.auth.kerberos.kdc.database; + principals = host-secrets.kdc-principals.target-file; + master-key = host-secrets.realm-master-key.target-file; + in { requires = [ host-secrets.kdc-principals.service host-secrets.realm-master-key.service @@ -95,14 +98,10 @@ in { ]; description = "Initialize and update the Heimdal KDC database."; path = with pkgs; [ kdcMergePrincipals coreutils ]; - serviceConfig = let - db = config.fudo.auth.kerberos.kdc.database; - principals = host-secrets.kdc-principals.target-file; - master-key = host-secrets.realm-master-key.target-file; - in { + serviceConfig = { User = krb-user; Group = krb-group; - Restart = "always"; + Type = "oneshot"; ExecStart = let init-db-cmd = concatStringsSep " " [ "${pkgs.kdcMergePrincipals}/bin/kdc-merge-principals" @@ -121,7 +120,7 @@ in { in "+${script}"; }; unitConfig.ConditionPathExists = [ db principals master-key ]; - }; + }); heimdal-kdc = mkIf kerberos-master { requires = [ "heimdal-kdc-initialize.service" ]; after = [ "heimdal-kdc-initialize.service" ]; diff --git a/flake.lock b/flake.lock index 53a6ce7..1723d33 100644 --- a/flake.lock +++ b/flake.lock @@ -74,11 +74,11 @@ ] }, "locked": { - "lastModified": 1696782511, - "narHash": "sha256-3UQTDuTbbkoaohJF5MeN3w9k3tw11yGfK69aGRTOv5E=", + "lastModified": 1699566671, + "narHash": "sha256-KHqewz+ZXx70MvSgFLFjuW9+hK6ZN+8+XJk6/2chqVM=", "ref": "refs/heads/master", - "rev": "007ccef4e35f68868bf17f3df2a075b57d422a4d", - "revCount": 51, + "rev": "68184b1f23b371f90d3c3b74f90de1e967127595", + "revCount": 85, "type": "git", "url": "https://git.fudo.org/fudo-public/authoritative-dns.git" }, @@ -1310,8 +1310,8 @@ "dnssec-ksks": { "flake": false, "locked": { - "lastModified": 1684298638, - "narHash": "sha256-jB53hHlzV/QvjedU38zpiZQl+43klmFsswMGhWonR7c=", + "lastModified": 1699562562, + "narHash": "sha256-PCCAHweKPWTuqdGi/J7jSAfXd4/niAiJDd0+MvOwOgY=", "path": "/secrets/dnssec", "type": "path" }, @@ -1323,8 +1323,8 @@ "domain-secrets": { "flake": false, "locked": { - "lastModified": 1697313293, - "narHash": "sha256-RugXjMCmbbJh+ekSnFMLJO2yrWMiwmoSrqs6agYJsGo=", + "lastModified": 1697492400, + "narHash": "sha256-kSxkncbrCfCqArzNHYnRSIFr4NkpY3EDIldyajD6wDY=", "path": "/secrets/domain-secrets", "type": "path" }, @@ -1365,11 +1365,11 @@ "ws-butler": "ws-butler" }, "locked": { - "lastModified": 1695346081, - "narHash": "sha256-ELuMibAhsgOEIzoPb9ZodYLcde0qSEP6ZuVIvFDIb6A=", + "lastModified": 1697814738, + "narHash": "sha256-mwQmykamvRuHmO6I2VTm8+TOIhhmgy2g5YrMjoCHawY=", "owner": "nix-community", "repo": "nix-doom-emacs", - "rev": "5bbefaee92c4277ff1961b333f9937f5180d15f3", + "rev": "c1c99cf41694440d76e31126dc394f52faeb691e", "type": "github" }, "original": { @@ -1450,11 +1450,11 @@ "nixpkgs": "nixpkgs_8" }, "locked": { - "lastModified": 1696807621, - "narHash": "sha256-VrcRmQxeoJQiCOwTVsr9FJJKz0v3cPgR+tHY1c0LmrM=", + "lastModified": 1699558182, + "narHash": "sha256-kWbn5DqGLUtdV2nFmVIQ9w6HExqHuYSi3stK+auWtz8=", "ref": "refs/heads/master", - "rev": "fec671e18b1434720ee02d1795acbb75ddfc9a12", - "revCount": 172, + "rev": "4688003535cb66705e772141ce9df0fd589056a1", + "revCount": 187, "type": "git", "url": "https://git.fudo.org/fudo-nix/entities.git" }, @@ -2234,11 +2234,11 @@ ] }, "locked": { - "lastModified": 1696807621, - "narHash": "sha256-VrcRmQxeoJQiCOwTVsr9FJJKz0v3cPgR+tHY1c0LmrM=", + "lastModified": 1699558182, + "narHash": "sha256-kWbn5DqGLUtdV2nFmVIQ9w6HExqHuYSi3stK+auWtz8=", "ref": "refs/heads/master", - "rev": "fec671e18b1434720ee02d1795acbb75ddfc9a12", - "revCount": 172, + "rev": "4688003535cb66705e772141ce9df0fd589056a1", + "revCount": 187, "type": "git", "url": "https://git.fudo.org/fudo-nix/entities.git" }, @@ -2259,11 +2259,11 @@ ] }, "locked": { - "lastModified": 1695588032, - "narHash": "sha256-GrxfUjnqnFTo4p+dLOf85eL0TK64Z7va5Pryp1GBGSI=", + "lastModified": 1699638724, + "narHash": "sha256-E0iO/2oenWuG+hwivnVEEJGA2H94e32Ciz3L/1gbVYk=", "ref": "refs/heads/master", - "rev": "77b3312641bc046d0dfeb2559acbeceb8c93465a", - "revCount": 354, + "rev": "c4455794bf6b1b498b79acd0ed4ff82bdf0349b9", + "revCount": 401, "type": "git", "url": "https://git.fudo.org/fudo-nix/home.git" }, @@ -2289,11 +2289,11 @@ }, "fudo-lib_2": { "locked": { - "lastModified": 1697264099, - "narHash": "sha256-sKhUS5yr4Xnhfj3LSEjeNYC2rEWd1APYf5mJUcYOmcA=", + "lastModified": 1699113600, + "narHash": "sha256-EX36PJZXNEmmtRA+M30FkWq1AD3ytI07VVCEu9maOYY=", "ref": "refs/heads/master", - "rev": "c629223e8592bcd72a30e034541ccca547e1dfad", - "revCount": 161, + "rev": "d4044d886a9b3e8b3964095a3307f784bae8aac0", + "revCount": 175, "type": "git", "url": "https://git.fudo.org/fudo-nix/lib.git" }, @@ -2323,11 +2323,11 @@ "unstableNixpkgs": "unstableNixpkgs" }, "locked": { - "lastModified": 1695580196, - "narHash": "sha256-EfA9zherzQ9YioayOldhr9TssjonmVGjwj5iceCQIWA=", + "lastModified": 1697077575, + "narHash": "sha256-UUkJhYv9L+Tj2EGupz54RMhdY5V7i6ai4spwjMC3y3M=", "ref": "refs/heads/master", - "rev": "87ada9aac42a45e3aaca8c4b47873003690449fb", - "revCount": 246, + "rev": "2cf977ff51b51771240afe930dbe65e3985f7504", + "revCount": 249, "type": "git", "url": "https://git.fudo.org/fudo-nix/pkgs.git" }, @@ -2393,8 +2393,8 @@ "utils": "utils_21" }, "locked": { - "lastModified": 1697313757, - "narHash": "sha256-WCJ/RuIiMgNjoh5nQ6ah4rS1pmEVs7U15upm5IFCF0g=", + "lastModified": 1699563326, + "narHash": "sha256-8u1+uLT1vtpQOZs1uq91BSTrnR5RS6o7C92RcECwsEg=", "path": "/secrets", "type": "path" }, @@ -2984,11 +2984,11 @@ ] }, "locked": { - "lastModified": 1697412875, - "narHash": "sha256-rJmQ1+5mDuA4nskjnDQ6KVRIS0c8nJ3SJaOrpdIx+I0=", + "lastModified": 1697483748, + "narHash": "sha256-ISHzsRnuISnDzmCqxjfD/RIaHVV0CyenLll/dQHjEDo=", "ref": "refs/heads/master", - "rev": "af3dbd0bed0da50d8b13d01256a328b15d9eb7c5", - "revCount": 245, + "rev": "bed75d392bf2829cdd674a608e74f0167a36e8b2", + "revCount": 250, "type": "git", "url": "https://git.fudo.org/fudo-public/mail-server.git" }, @@ -3007,11 +3007,11 @@ ] }, "locked": { - "lastModified": 1694066286, - "narHash": "sha256-SvONfQPwi3KbaVN+4/DW9VMYkqc1M6JkcxN7nPqdDDE=", + "lastModified": 1697731780, + "narHash": "sha256-J0cobvMii2EaS282zqkZ4dWnS43Rf31bSQl4taFlKbs=", "ref": "refs/heads/master", - "rev": "03a2e29832553385013006eaa9cc2c11ca129112", - "revCount": 39, + "rev": "628c81b2320cb19dafcc3a025588bc67e90a972a", + "revCount": 41, "type": "git", "url": "https://git.fudo.org/fudo-public/mastodon-container.git" }, @@ -3253,11 +3253,11 @@ "niten-doom-config": { "flake": false, "locked": { - "lastModified": 1684432992, - "narHash": "sha256-ex/H6we7BLjidBxo0n5EZ9YUflLr03sLWdf5YGsF6jU=", + "lastModified": 1699638681, + "narHash": "sha256-nfHEoSGTQrPQNFXp+7CljKTP98/CKqrQb049NZ4uPTs=", "ref": "refs/heads/master", - "rev": "47773717b06d21004db3dea96f2329f912ef8dd3", - "revCount": 64, + "rev": "7e5e35f66df30db7baa4dbee3f401395a498d99b", + "revCount": 67, "type": "git", "url": "https://git.fudo.org/niten/doom-emacs.git" }, @@ -3351,11 +3351,11 @@ }, "nixpkgsUnstable": { "locked": { - "lastModified": 1697059129, - "narHash": "sha256-9NJcFF9CEYPvHJ5ckE8kvINvI84SZZ87PvqMbH6pro0=", + "lastModified": 1699099776, + "narHash": "sha256-X09iKJ27mGsGambGfkKzqvw5esP1L/Rf8H3u3fCqIiU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5e4c2ada4fcd54b99d56d7bd62f384511a7e2593", + "rev": "85f1ba3e51676fa8cc604a3d863d729026a6b8eb", "type": "github" }, "original": { @@ -3548,11 +3548,11 @@ }, "nixpkgs_21": { "locked": { - "lastModified": 1697226376, - "narHash": "sha256-cumLLb1QOUtWieUnLGqo+ylNt3+fU8Lcv5Zl+tYbRUE=", + "lastModified": 1699596684, + "narHash": "sha256-XSXP8zjBZJBVvpNb2WmY0eW8O2ce+sVyj1T0/iBRIvg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "898cb2064b6e98b8c5499f37e81adbdf2925f7c5", + "rev": "da4024d0ead5d7820f6bd15147d3fe2a0c0cec73", "type": "github" }, "original": { @@ -3804,11 +3804,11 @@ "org": { "flake": false, "locked": { - "lastModified": 1695208951, - "narHash": "sha256-GdkBhWg/bIwnQk4/a/Ief+cFtDcUJEMNqiFYO3A5sus=", + "lastModified": 1695726851, + "narHash": "sha256-qgbjspklSoI8M3cbCJOcUdjuijRgsL/+PSyEOW9VX4I=", "owner": "emacs-straight", "repo": "org-mode", - "rev": "266aac1186256aaf3fb1bb1181ee83d548092d12", + "rev": "aa9177e1a8b039c357d369c1c9aaab710bb247a9", "type": "github" }, "original": { @@ -3890,11 +3890,11 @@ "revealjs": { "flake": false, "locked": { - "lastModified": 1695108593, - "narHash": "sha256-1Rb3w4Mpzv81pw7FaZHdQULK6+9oZIzeQ6uCD4PvjJM=", + "lastModified": 1695738029, + "narHash": "sha256-Z9c9Q41jMkj/DyXOiZYyIa7Gmn8VB8yauTyWrSsT+ps=", "owner": "hakimel", "repo": "reveal.js", - "rev": "db2523db277bea632c218a7d836f27079a1be7f9", + "rev": "88fbfc5751ad01e3f6adee5819eabeb9e73c3757", "type": "github" }, "original": { @@ -4014,11 +4014,11 @@ "utils": "utils_36" }, "locked": { - "lastModified": 1684442384, - "narHash": "sha256-YhV7DuTwSw4e3jceMAgA/kKYGH82Y/WwwHzrkYBaSW8=", + "lastModified": 1697581984, + "narHash": "sha256-ypR4v0GfoyrXqgRIS/lSqcaIDcLLDIg2WP+//csRr7E=", "ref": "refs/heads/master", - "rev": "b6fe2ce411856ec02c0717cfb19c51f0142e5e71", - "revCount": 11, + "rev": "ade2e1caa0b8a6e8182a2bd54aa5dc82ac1c60b6", + "revCount": 12, "type": "git", "url": "https://git.fudo.org/fudo-public/snooper.git" }, @@ -4030,8 +4030,8 @@ "ssh-keypairs": { "flake": false, "locked": { - "lastModified": 1696031940, - "narHash": "sha256-doC5gBLNiIH0EMwJ+wBfgTHGE+I1ausWhkMX3pqJxNQ=", + "lastModified": 1697914793, + "narHash": "sha256-AvjV3wozHvHbRDZqWkynL0F0n9kikNIEjpaiWCrqs4Q=", "path": "/secrets/ssh-keypairs", "type": "path" },