From c041862fbe8fe5ff8a1465d74d13f3a14cf79b6f Mon Sep 17 00:00:00 2001 From: arcnmx Date: Sun, 21 Jan 2024 16:26:45 -0800 Subject: [PATCH] feat(reimu): nfs --- modules/nixos/kanidm.nix | 5 +++ nixos/nfs.nix | 57 ++++++++++++++++++++++++ nixos/samba.nix | 95 ++++++++++++++++++++++++++++++++++++++++ nixos/secrets/samba.yaml | 84 +++++++++++++++++++++++++++++++++++ systems/reimu/nfs.nix | 51 +++++++++++++++++++++ systems/reimu/nixos.nix | 4 ++ tf/cloudflare_records.tf | 4 ++ tf/proxmox_vms.tf | 4 +- 8 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 nixos/nfs.nix create mode 100644 nixos/samba.nix create mode 100644 nixos/secrets/samba.yaml create mode 100644 systems/reimu/nfs.nix diff --git a/modules/nixos/kanidm.nix b/modules/nixos/kanidm.nix index 0afd133a..55485357 100644 --- a/modules/nixos/kanidm.nix +++ b/modules/nixos/kanidm.nix @@ -5,6 +5,7 @@ ... }: let inherit (lib) mkIf mkMerge mkBefore mkDefault mkOptionDefault mkEnableOption mkOption; + inherit (lib.strings) splitString concatMapStringsSep; cfg = config.services.kanidm; in { options.services.kanidm = with lib.types; { @@ -43,6 +44,10 @@ in { type = port; default = 3636; }; + baseDn = mkOption { + type = str; + default = concatMapStringsSep "," (part: "dc=${part}") (splitString "." cfg.serverSettings.domain); + }; }; }; }; diff --git a/nixos/nfs.nix b/nixos/nfs.nix new file mode 100644 index 00000000..c9869781 --- /dev/null +++ b/nixos/nfs.nix @@ -0,0 +1,57 @@ +{ + config, + lib, + access, + ... +}: let + inherit (lib.modules) mkIf mkDefault; + inherit (lib.lists) optional; + inherit (lib.strings) concatStringsSep concatMapStringsSep splitString; + cfg = config.services.nfs; + openPorts = [ + (mkIf cfg.server.enable 2049) + (mkIf config.services.rpcbind.enable 111) + (mkIf (cfg.server.statdPort != null) cfg.server.statdPort) + (mkIf (cfg.server.lockdPort != null) cfg.server.lockdPort) + (mkIf (cfg.server.mountdPort != null) cfg.server.mountdPort) + ]; + enableLdap = false; + system = access.systemFor "tei"; + inherit (system.services) kanidm; +in { + services.nfs = { + server = { + enable = mkDefault true; + statdPort = mkDefault 4000; + lockdPort = mkDefault 4001; + mountdPort = mkDefault 4002; + }; + idmapd.settings = { + General.Domain = mkDefault config.networking.domain; + Translation.GSS-Methods = concatStringsSep "," ( + [ "static" ] + ++ optional enableLdap "umich_ldap" + ++ [ "nsswitch" ] + ); + Static = { + }; + UMICH_SCHEMA = mkIf enableLdap { + LDAP_server = "ldap.local.${config.networking.domain}"; + LDAP_use_ssl = true; + LDAP_ca_cert = "/etc/ssl/certs/ca-bundle.crt"; + LDAP_base = kanidm.server.ldap.baseDn; + NFSv4_person_objectclass = "account"; + NFSv4_group_objectclass = "group"; + NFSv4_name_attr = "name"; + NFSv4_group_attr = "name"; + NFSv4_uid_attr = "gidnumber"; + NFSv4_gid_attr = "gidnumber"; + LDAP_canonicalize_name = false; + }; + }; + }; + networking.firewall.interfaces.local = { + allowedTCPPorts = openPorts; + allowedUDPPorts = openPorts; + }; +} diff --git a/nixos/samba.nix b/nixos/samba.nix new file mode 100644 index 00000000..bf11b099 --- /dev/null +++ b/nixos/samba.nix @@ -0,0 +1,95 @@ +{ + config, + lib, + access, + pkgs, + ... +}: let + inherit (lib.modules) mkIf mkMerge mkDefault; + inherit (lib.lists) any; + inherit (lib.strings) hasInfix; + inherit (config.services) samba samba-wsdd; + system = access.systemFor "tei"; + inherit (system.services) kanidm; + enableLdap = false; + hasIpv4 = any (hasInfix ".") config.systemd.network.networks.eth0.address or [ ]; +in { + services.samba = { + openFirewall = mkDefault true; + enable = mkDefault true; + enableWinbindd = mkDefault false; + enableNmbd = mkDefault hasIpv4; + securityType = mkDefault "user"; + package = mkIf enableLdap (mkDefault (pkgs.samba.override { + enableLDAP = true; + })); + extraConfig = mkMerge [ + '' + workgroup = GENSOKYO + local master = no + preferred master = no + winbind offline logon = yes + winbind scan trusted domains = no + winbind use default domain = yes + domain master = no + valid users = nobody, arc, kat, @nfs + map to guest = Bad User + guest account = nobody + '' + (mkIf hasIpv4 '' + remote announce = 10.1.1.255/GENSOKYO + '') + (mkIf enableLdap '' + idmap config * : backend = ldap + idmap config * : range = 1000 - 2000 + idmap config * : read only = yes + idmap config * : ldap_url = ldaps://ldap.local.${config.networking.domain} + idmap config * : ldap_base_dn = ${kanidm.server.ldap.baseDn} + passdb backend = ldapsam:"ldaps://ldap.local.${config.networking.domain}" + ldap ssl = off + ldap admin dn = name=anonymous,${kanidm.server.ldap.baseDn} + ldap suffix = ${kanidm.server.ldap.baseDn} + ntlm auth = disabled + encrypt passwords = no + '') + (mkIf (!enableLdap) '' + passdb backend = smbpasswd:${config.sops.secrets.smbpasswd.path} + idmap config * : backend = nss + idmap config * : range = 1000 - 2000 + idmap config * : read only = yes + '') + ]; + }; + + systemd.services.samba-smbd = mkIf samba.enable { + serviceConfig.ExecStartPre = let + ldap-pass = pkgs.writeShellScript "smb-ldap-pass" '' + ${samba.package}/bin/smbpasswd -c /etc/samba/smb.conf -w anonymous + ''; + in mkIf enableLdap [ + "${ldap-pass}" + ]; + }; + + services.samba-wsdd = mkIf samba.enable { + enable = mkDefault true; + openFirewall = mkDefault true; + hostname = mkDefault config.networking.hostName; + }; + + networking.firewall.interfaces.local = { + allowedTCPPorts = mkMerge [ + (mkIf samba.enable [ 139 445 ]) + (mkIf samba-wsdd.enable [ 5357 ]) + ]; + allowedUDPPorts = mkMerge [ + (mkIf samba.enable [ 137 138 ]) + (mkIf samba-wsdd.enable [ 3702 ]) + ]; + }; + + sops.secrets.smbpasswd = { + sopsFile = mkDefault ./secrets/samba.yaml; + #path = "/var/lib/samba/private/smbpasswd"; + }; +} diff --git a/nixos/secrets/samba.yaml b/nixos/secrets/samba.yaml new file mode 100644 index 00000000..7c79ae78 --- /dev/null +++ b/nixos/secrets/samba.yaml @@ -0,0 +1,84 @@ +smbpasswd: ENC[AES256_GCM,data:9dpSVTTjpUKyNlo/8BhQbjyTqblkr1hF17ML0fpqik/1W75sDmn9enRfR7GtTKztRTxAbRTXS9yP9+ngIJREF1XG6gERK95H7cYm00Ep1D23qz66caWW1VuYYH0damnVhEkAfJO2t1yhbqA0uWy9WToAyOfyh2XJgrLe14P0rYw9QPjrpqxByXb29lNpINVuZKLWXbresqH6X9Rqd63tT6kRXtMVMdyPypEvMuM7N6/UjHFgCgNW2Fdfch1VSPwxj/C3Z1ZOIRz9AMQu3lU=,iv:xl8VAaeF1zYplm0XHDU8H5fMmxKSko9hdGO2971F01Q=,tag:HK6DMGrhiz7OGs5e/6Sr5Q==,type:str] +sops: + shamir_threshold: 1 + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age12ze362pu5mza6ef9akrptr7hfe4auaqul4rkta7kyy2tnrstqensgmujeq + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhbjVBS0hTTDhNZnZJL2ll + VXlmajBORDB3RXJjc1NVdUw5MklFVTcyQ2tZCnI3WjlsYXZReXNKaEUzbjM1aTc2 + SkI2Ty9UeW5ZUFVpYkQrMitIdVhNcWsKLS0tIGoreGVyZG1WOXV3amhpTzZQdU5J + c3JjRTB4WlNnOTIwWTQ3ekFGTnRpMU0K1+JW7nWR7whXqWIL45K6HDejp69e9Xfo + yXw9l9FxM2YR3UwvTs4k0i2gSov3eYuWaFAefuXUQJ9DO0/AvijUVQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age176uyyyk7veqnzmm8xzwfhf0u23m6hm02cldlfkldunqe6std0gcq6lg057 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyOVFBek1Wc21VUStPWU1x + Q3d0cERQc2xEeUF1RDgwM0JlVWpZRlErT2pRCktLUTZJOTBwcC84VzJTT0lhYm9Z + YWVCRTgvck0wMzd6QTRrcDVkdVI2c1UKLS0tIDN6bkQvaUsvMVhJYUo2cHhnRVMw + VTRwZkM1MElmb3dpQXNGaDFaeFJ5Wm8Kwj5x13KgEzNkw/s3Wq3R0KL3mFJxPZ1e + Evr2dIqrn0lg5QLfooNxJH3sowyDrUXUey/P1KPPePzOoJV+jHxs8g== + -----END AGE ENCRYPTED FILE----- + - recipient: age1a2quf2ekkj94ygu7wgvhrvh44fwn32c0l2cwvgvjh23wst90s54szdsvgr + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiejUrcnhlN3dReEVlZ3Ir + VndoRmFSRGdqK0IzaTVodCs5WGdXZXFuVVE0CitPTUdHTnVRS2l2V3lLTHBoa3M3 + cnN5ekFKbnpReWYvU1BFMmg1bHJUWlEKLS0tIDB4eTJvVkU3T0xGR3JhSk5PQlYr + ejAvVlpucjFPSmdoem9hWTdWSDN1SG8K81BjXmwtiwvVdW9eSD+jRZIZwmlVJYHn + qy6zuEkTBkQxpMrE3110mHP46JyJPbJvYcFlqOfqKNGyXdWzsge35A== + -----END AGE ENCRYPTED FILE----- + - recipient: age16klpkaut5759dut8mdm3jn0rnp8w6kxyvs9n6ntqrdsayjtd7upqlvw489 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaZzJxSUNyZ2RCeTlCdGlv + bDBzVWVWZzREVEFsNTJlYlZLaEpmSm5hQkVNCldHU3RnZFljaDkyRnlJNW1kME1R + cFlNRmkzOWNWMjFmQW44eitkbW9iU2MKLS0tIHJvVEYySHZlVmxrdXNzajQvR0JT + VitlT3d6d1FOSzFKTFRIWDU3cmJ2aXMKDN7HPa6pQSZd21cLvfk+sYvLqZm9eN+7 + K1v7M9MXLY+nh1YGGbtDbWHh09p8g37tS1OwgGAiETh+z7hWsGHYdw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-01-30T23:29:25Z" + mac: ENC[AES256_GCM,data:I/ijClic5JxlFV3ICyMczq3t4xo5V2trhl5B97HIwrgmDGtKeCiHjQc9TE/OtunvLUXaH3W8zjHWCsJDT+pFD0YO6EVo4G0MtJe35GNMsDT1x2Uwny13tTxWjKtjmP9lqB0I+cv4uL42vbt7Bdl3lv3jw0Hz/2wvlvnSUpPdFMo=,iv:YnVT6FvBhw5P1IBDNlRuxE9lk8tCsxR2JzHSYMA6dr8=,tag:MVayewWg5Ny/5lPwu90B9w==,type:str] + pgp: + - created_at: "2024-01-30T22:23:56Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMA82M54yws73UARAAuAS0M2xKX7X7LPgDSOBp9XP24dpQbXPvEGntJn/j4v0z + y6XlC4ObLa401cilGn/wrDFfB3i2USQUEDhWgOJjLfkDcmIRmg8s9yXDA2H4E4+Y + Qjdb4b7Kind1Bu7jx2oe05mEbGEhtLK1QMGpXzWUWAgcaYI1+rC9IzpILRSIaCjH + xHOE/BaQ/jBEIX5Sia2uxoONlhawpa2q1AgVFRTKD2gY3qr0YXh0b1cakzRr/Enr + 1HZlhCE01egsHEDh4+dADSbMH7yp08Cf5eyJ7l8sQUgddA6il90pnuMFPNvuNyV/ + lSjrBed+lgwOIxBQtHIsAbPgjiXtO85tQEb108mgc1Qoht4gJOvqglZdryIGNo1r + 9Pif5LCrldr8qlmDAn+u9WAwlGseTnC7jKXVxBnQUkUzsGxZkizTK13DAA0FpePs + 0bkfaN9gvogR0lQAAF9RsH683wKzmUvcBfRdK3RFVWumzJKx5aslwT0sqYnfFmYz + wG4Octf69Xv1HJhpFJT0h/Q94BckPNxoOBcJI79Rt5bfWa4FMxu5H+yc9z6ZtoyH + QL56j4OcYihSN15A+aOT1e7HZSHqqp8GLrXz5WIWYnB/BgR6XvMFTFiCPUcUp3Qa + sAtmxKQhbrasJ7uzjujp/RqlDSStbTPRyq/w9194e8zOu9SFFp/JjppzAxpn8N/S + XgEXPGlTZePKHtqAtgcklPaqccneVuwd/ZO8V08fqRq9t1wUjDQaqiBVIa0mYnhj + lub4umPrK5i5F/rff6I9GjyOFAdkYAzWV879QoWxz66JwGIBd7+SBomdC7VqCqU= + =n45a + -----END PGP MESSAGE----- + fp: CD8CE78CB0B3BDD4 + - created_at: "2024-01-30T22:23:56Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQEMA2W9MER3HLb7AQf/Rjgb5xBLwv5CHT3PQekiHZl1wpK+ysgdOqIWNeks+DcE + DZtD1MLQ86TX4r7e8geDG729VQyIVMxbT5HQkOxpU1vCBuiZ+gDycKfULFTk6/iQ + xh517MmWWz6ntQo6PPzHW88cUYF6YzvE1M7HS5u82dc5i5RY22VKMppPPZYEQlxo + N3TgglzXRX7172a77bpqnRxGzcsw7+WLORuYjOyzS6CqMtq2OHEQQ/vYNjo/F0Uz + ufSSr25tSumEA4PwC2Pq+rCLRKeckzMh7R1gQwG+LzAcqI5zvOUqNBixZaXrz4gh + pJhllj//33Xhxt9g9C63Uuq3b3E3YffbUzCa/5gN4dJeAUNZXlDcnqqMmLLNXXH3 + LzcToDjHhxoxmJESD5Rv4d4sqECfNbk+wvZtvQbrJE9pO6tvQsWfui27arTeCWmP + 2nOmk4gOLWzukSZKu9PtiSwJYSHTQ4QISWrEmdkq6g== + =7Cbb + -----END PGP MESSAGE----- + fp: 65BD3044771CB6FB + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/systems/reimu/nfs.nix b/systems/reimu/nfs.nix new file mode 100644 index 00000000..dddf23f4 --- /dev/null +++ b/systems/reimu/nfs.nix @@ -0,0 +1,51 @@ +{ + config, + lib, + ... +}: let + kyuuto = "/mnt/kyuuto-media"; + kyuuto-transfer = kyuuto + "/transfer"; + inherit (lib.lists) optionals; + inherit (lib.strings) concatStringsSep; + inherit (config.networking.access) cidrForNetwork; +in { + services.nfs.server.exports = let + mapPerm = perm: map (addr: "${addr}(${perm})"); + toPerms = concatStringsSep " "; + localAddrs = cidrForNetwork.loopback.all ++ cidrForNetwork.local.all; + tailAddrs = optionals config.services.tailscale.enable cidrForNetwork.tail.all; + allAddrs = localAddrs ++ tailAddrs; + kyuutoPerms = + mapPerm "ro" localAddrs + ++ mapPerm "rw" tailAddrs; + transferPerms = mapPerm "rw" allAddrs; + in '' + ${kyuuto} ${toPerms kyuutoPerms} + ${kyuuto-transfer} ${toPerms transferPerms} + ''; + + services.samba.shares = { + kyuuto-transfer = { + path = kyuuto-transfer; + writeable = "yes"; + browseable = "yes"; + public = "yes"; + "guest only" = "yes"; + comment = "Kyuuto Media Transfer Area"; + }; + kyuuto-access = { + path = kyuuto; + writeable = false; + browseable = "yes"; + public = "yes"; + comment = "Kyuuto Media Access"; + }; + kyuuto-media = { + path = kyuuto; + writeable = "yes"; + browseable = "yes"; + public = "no"; + comment = "Kyuuto Media"; + }; + }; +} diff --git a/systems/reimu/nixos.nix b/systems/reimu/nixos.nix index 2642f803..e4a52c37 100644 --- a/systems/reimu/nixos.nix +++ b/systems/reimu/nixos.nix @@ -5,8 +5,12 @@ imports = let inherit (meta) nixos; in [ + nixos.sops nixos.base nixos.reisen-ct + nixos.nfs + nixos.samba + ./nfs.nix ]; systemd.network.networks.eth0 = { diff --git a/tf/cloudflare_records.tf b/tf/cloudflare_records.tf index bbdbb4dd..77331ae2 100644 --- a/tf/cloudflare_records.tf +++ b/tf/cloudflare_records.tf @@ -32,6 +32,10 @@ module "reimu_system_records" { zone_id = cloudflare_zone.gensokyo-zone_zone.id zone_zone = cloudflare_zone.gensokyo-zone_zone.zone local_v6 = "fd0a::be24:11ff:fec4:66a8" + local_subdomains = [ + "nfs", + "smb", + ] } module "tewi_system_records" { diff --git a/tf/proxmox_vms.tf b/tf/proxmox_vms.tf index 15e11c70..0635fb42 100644 --- a/tf/proxmox_vms.tf +++ b/tf/proxmox_vms.tf @@ -54,7 +54,7 @@ resource "proxmox_virtual_environment_container" "reimu" { started = false lifecycle { - ignore_changes = [started] + ignore_changes = [started, description] } } @@ -77,7 +77,7 @@ resource "terraform_data" "proxmox_reimu_config" { provisioner "remote-exec" { inline = [ - "sudo /opt/infra/bin/lxc-config ${proxmox_virtual_environment_container.reimu.vm_id} unprivileged 0 features 'nesting=1,mount=nfs,mknod=1' lxc.mount.entry '/dev/net/tun dev/net/tun none bind,optional,create=file'", + "sudo /opt/infra/bin/lxc-config ${proxmox_virtual_environment_container.reimu.vm_id} unprivileged 0 features 'nesting=1,mount=nfs,mknod=1' lxc.mount.entry '/dev/net/tun dev/net/tun none bind,optional,create=file' lxc.mount.entry '/mnt/kyuuto-media mnt/kyuuto-media none bind,optional,create=dir'", ] } }