diff --git a/flake.nix b/flake.nix index 1794d4c..485b432 100644 --- a/flake.nix +++ b/flake.nix @@ -122,11 +122,10 @@ inherit (import ./nix/hosts.nix inputs) hosts - microvmConfigurations nixosConfigurations minimalConfigurations ; - nodes = self.nixosConfigurations // self.microvmConfigurations; + nodes = self.nixosConfigurations; inherit (lib.foldl' lib.recursiveUpdate {} diff --git a/hosts/testienix/fs.nix b/hosts/testienix/fs.nix index 5969322..e1f539c 100644 --- a/hosts/testienix/fs.nix +++ b/hosts/testienix/fs.nix @@ -115,6 +115,7 @@ }; fileSystems."/state".neededForBoot = true; + fileSystems."/persist".neededForBoot = true; fileSystems."/panzer/state".neededForBoot = true; fileSystems."/panzer/persist".neededForBoot = true; boot.initrd.luks.devices.enc-rpool.allowDiscards = true; diff --git a/hosts/testienix/secrets/generated/dhparams.pem.age b/hosts/testienix/secrets/generated/dhparams.pem.age new file mode 100644 index 0000000..1e96e67 Binary files /dev/null and b/hosts/testienix/secrets/generated/dhparams.pem.age differ diff --git a/lib/containers.nix b/lib/containers.nix index e2ca235..c0046a3 100644 --- a/lib/containers.nix +++ b/lib/containers.nix @@ -1,18 +1,30 @@ -_inputs: _self: super: { +inputs: _self: super: { lib = super.lib // { containers.mkConfig = name: config: super.lib.mkMerge [ { + config = { + imports = [ + ../modules/config/impermanence + ../modules/config/net.nix + ../modules/interface-naming.nix + + inputs.impermanence.nixosModules.impermanence + ]; + }; + bindMounts = { "state" = { mountPoint = "/state"; hostPath = "/state/containers/${name}"; + isReadOnly = false; }; "persist" = { mountPoint = "/persist"; hostPath = "/containers/${name}"; + isReadOnly = false; }; }; zfs.mountpoint = super.lib.mkDefault "/containers/${name}"; diff --git a/lib/test.nix b/lib/test.nix new file mode 100644 index 0000000..19d415e --- /dev/null +++ b/lib/test.nix @@ -0,0 +1,9 @@ +{ + config, + pkgs, + ... +}: { + networking.hostName = "lololo"; + programs.fuse.userAllowOther = true; + environment.systemPackages = [pkgs.hello]; +} diff --git a/modules/config/home-manager.nix b/modules/config/home-manager.nix index 210ec09..2f3988a 100644 --- a/modules/config/home-manager.nix +++ b/modules/config/home-manager.nix @@ -4,6 +4,7 @@ pkgs, ... }: { + imports = [./impermanence/users.nix]; home-manager = { useGlobalPkgs = true; useUserPackages = true; diff --git a/modules/config/impermanence/default.nix b/modules/config/impermanence/default.nix index 72bab29..1b31708 100644 --- a/modules/config/impermanence/default.nix +++ b/modules/config/impermanence/default.nix @@ -3,14 +3,16 @@ lib, pkgs, ... -}: { - imports = [./users.nix]; +}: let + onlyHost = + lib.mkIf (!config.boot.isContainer); +in { # to allow all users to access hm managed persistent folders programs.fuse.userAllowOther = true; environment.persistence."/state" = { hideMounts = true; - files = [ + files = onlyHost [ "/etc/machine-id" "/etc/ssh/ssh_host_ed25519_key" "/etc/ssh/ssh_host_ed25519_key.pub" @@ -25,20 +27,34 @@ mode = "0777"; } ] + ++ lib.lists.optionals config.security.acme.acceptTerms [ + { + directory = "/var/lib/acme"; + user = "acme"; + group = "acme"; + mode = "0755"; + } + ] ++ lib.lists.optionals config.hardware.bluetooth.enable [ "/var/lib/bluetooth" ]; }; + environment.persistence."/persist" = { + hideMounts = true; + directories = []; + }; # After importing the rpool, rollback the root system to be empty. - boot.initrd.systemd.services.impermanence-root = { - wantedBy = ["initrd.target"]; - after = ["zfs-import-rpool.service"]; - before = ["sysroot.mount"]; - unitConfig.DefaultDependencies = "no"; - serviceConfig = { - Type = "oneshot"; - ExecStart = "${pkgs.zfs}/bin/zfs rollback -r rpool/local/root@blank"; + boot.initrd.systemd.services.impermanence-root = + onlyHost + { + wantedBy = ["initrd.target"]; + after = ["zfs-import-rpool.service"]; + before = ["sysroot.mount"]; + unitConfig.DefaultDependencies = "no"; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.zfs}/bin/zfs rollback -r rpool/local/root@blank"; + }; }; - }; } diff --git a/modules/config/impermanence/users.nix b/modules/config/impermanence/users.nix index cfff0cc..8dbb34c 100644 --- a/modules/config/impermanence/users.nix +++ b/modules/config/impermanence/users.nix @@ -10,8 +10,10 @@ attrNames mkOption types + hasAttr mkMerge isAttrs + mkIf ; in { # Expose a home manager module for each user that allows extending diff --git a/modules/config/net.nix b/modules/config/net.nix index b1dc952..4760ef7 100644 --- a/modules/config/net.nix +++ b/modules/config/net.nix @@ -6,11 +6,13 @@ networking = { useNetworkd = true; dhcpcd.enable = false; + firewall.enable = true; # allow mdns port firewall.allowedUDPPorts = [5353]; - renameInterfacesByMac = + renameInterfacesByMac = lib.mkIf (!config.boot.isContainer) ( lib.mapAttrs (_: v: v.mac) - (config.secrets.secrets.local.networking.interfaces or {}); + (config.secrets.secrets.local.networking.interfaces or {}) + ); }; systemd.network = { enable = true; diff --git a/modules/config/users.nix b/modules/config/users.nix index b9e8181..d636936 100644 --- a/modules/config/users.nix +++ b/modules/config/users.nix @@ -18,6 +18,7 @@ avahi = uidGid 209; fwupd-refresh = uidGid 210; podman = uidGid 211; + acme = uidGid 212; systemd-oom = uidGid 300; systemd-coredump = uidGid 301; }; diff --git a/modules/services/acme.nix b/modules/services/acme.nix new file mode 100644 index 0000000..62e9adf --- /dev/null +++ b/modules/services/acme.nix @@ -0,0 +1,29 @@ +{ + config, + lib, + ... +}: { + age.secrets.cloudflare_token_acme = { + rekeyFile = ../../secrets/cloudflare/api_token.age; + mode = "440"; + group = "acme"; + }; + security.acme = { + acceptTerms = true; + defaults = { + email = config.secrets.secrets.global.devEmail; + dnsProvider = "cloudflare"; + dnsPropagationCheck = true; + reloadServices = ["nginx"]; + credentialFiles = { + "CF_DNS_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path; + "CF_ZONE_API_TOKEN_FILE" = config.age.secrets.cloudflare_token_acme.path; + }; + }; + }; + security.acme.certs = lib.flip lib.mapAttrs config.secrets.secrets.global.domains (_: value: { + domain = value; + extraDomainNames = ["*.${value}"]; + }); + users.groups.acme.members = ["nginx"]; +} diff --git a/modules/services/ddclient.nix b/modules/services/ddclient.nix new file mode 100644 index 0000000..f704d91 --- /dev/null +++ b/modules/services/ddclient.nix @@ -0,0 +1,14 @@ +{config, ...}: { + age.secrets.cloudflare_token_dns = { + rekeyFile = ../../secrets/cloudflare/api_token.age; + mode = "440"; + }; + services.ddclient = { + enable = true; + zone = config.secrets.secrets.global.domains.mail; + protocol = "Cloudflare"; + username = "token"; + passwordFile = config.age.secrets.cloudflare_token_dns.path; + domains = [config.secrets.secrets.global.domains.mail]; + }; +} diff --git a/modules/services/nextcloud.nix b/modules/services/nextcloud.nix index fea27c3..db4a784 100644 --- a/modules/services/nextcloud.nix +++ b/modules/services/nextcloud.nix @@ -1,9 +1,27 @@ { lib, stateVersion, + config, ... -}: { - imports = [./containers.nix]; +}: let + hostName = "nc.${config.secrets.secrets.global.domains.mail}"; +in { + imports = [./containers.nix ./nginx.nix ./ddclient.nix ./acme.nix]; + services.nginx = { + enable = true; + upstreams.nextcloud = { + servers."192.168.178.33:80" = {}; + extraConfig = '' + zone nextcloud 64k ; + keepalive 5 ; + ''; + }; + virtualHosts.${hostName} = { + forceSSL = true; + useACMEHost = "mail"; + locations."/".proxyPass = "http://nextcloud"; + }; + }; containers.nextcloud = lib.containers.mkConfig "nextcloud" { autoStart = true; zfs = { @@ -18,11 +36,41 @@ pkgs, ... }: { + systemd.network.networks = { + "lan01" = { + address = ["192.168.178.33/24"]; + gateway = ["192.168.178.1"]; + matchConfig.Name = "mv-lan01*"; + dns = ["192.168.178.2"]; + networkConfig = { + IPv6PrivacyExtensions = "yes"; + MulticastDNS = true; + }; + }; + }; services.nextcloud = { + inherit hostName; enable = true; package = pkgs.nextcloud27; - hostName = "localhost"; + configureRedis = true; config.adminpassFile = "${pkgs.writeText "adminpass" "test123"}"; # DON'T DO THIS IN PRODUCTION - the password file will be world-readable in the Nix Store! + extraApps = with config.services.nextcloud.package.packages.apps; { + inherit contacts calendar tasks; + }; + extraAppsEnable = true; + extraOptions.enabledPreviewProviders = [ + "OC\\Preview\\BMP" + "OC\\Preview\\GIF" + "OC\\Preview\\JPEG" + "OC\\Preview\\Krita" + "OC\\Preview\\MarkDown" + "OC\\Preview\\MP3" + "OC\\Preview\\OpenDocument" + "OC\\Preview\\PNG" + "OC\\Preview\\TXT" + "OC\\Preview\\XBitmap" + "OC\\Preview\\HEIC" + ]; }; system.stateVersion = stateVersion; diff --git a/modules/services/nginx.nix b/modules/services/nginx.nix index fc97783..6d03828 100644 --- a/modules/services/nginx.nix +++ b/modules/services/nginx.nix @@ -52,6 +52,8 @@ in { mode = "440"; group = "nginx"; }; + security.acme.acceptTerms = true; + security.acme.defaults.email = config.secrets.secrets.global.devEmail; # Sensible defaults for nginx services.nginx = { diff --git a/nix/hosts.nix b/nix/hosts.nix index f446731..f069a7b 100644 --- a/nix/hosts.nix +++ b/nix/hosts.nix @@ -58,7 +58,6 @@ inputs: let in { inherit hosts - microvmConfigurations nixosConfigurations minimalConfigurations ; diff --git a/secrets/cloudflare/api_token.age b/secrets/cloudflare/api_token.age new file mode 100644 index 0000000..88ecbfb --- /dev/null +++ b/secrets/cloudflare/api_token.age @@ -0,0 +1,13 @@ +age-encryption.org/v1 +-> X25519 j1vdwUZ+o5coMFAaOCyiS42rLq7FPX6xwuWmoHcN61U +m1QEYj4NW5IdNsFh26Uhwe2Sg1ggkvTYB92S4B2lC8M +-> piv-p256 XTQkUA AhjsxoVBz3h/1Sj+cwnT7gpcE6SDMhNOBMU9nP+gfC5G +a7E3dolF4QaxTVpJBOKA314INK32eTdDykDyRT+/8XQ +-> piv-p256 ZFgiIw Ah49xwjTzvroi4R90URbbE0yY15w+OvUsWZ2cQdYHs/w +4i6XZ8lwOeWinlU1IiCgUBTSWMzxuPyvYKRbz6GqNUk +-> piv-p256 ZFgiIw A49Cv751h0WJYL6qPceFVwjbGVpF668SGKVjHq/lQ4Rs +AAGD0jOCHIOAIBk872SJwe2mCx69xn/1ZjiswebgU0w +-> K("0$@8-grease z`/W }"_xiVH <~Bj._ + +--- /NUrs98fD72LqCIYVOzrUhFNhxGivAEOZ9pob65I2fI +8î:(#­–¥aô[8@BÊ4èÝ|ÍC7!³>Ù?¬Œ›`5á‰o‡Þr õB´ˆ°y`óAIJ;)÷Å&“)@ÝÎB²¹Ï¡ñ´¾Q \ No newline at end of file diff --git a/secrets/secrets.nix.age b/secrets/secrets.nix.age index b7d4eb4..31c01ea 100644 Binary files a/secrets/secrets.nix.age and b/secrets/secrets.nix.age differ