diff --git a/modules/config/default.nix b/modules/config/default.nix index d51d29e..2c77619 100755 --- a/modules/config/default.nix +++ b/modules/config/default.nix @@ -287,6 +287,7 @@ in sslPath = "${var}/acme"; sopsPath = "${var}/secrets"; secretPath = "${var}/secrets"; + cachePath = "/var/cache"; dummy = ""; }; diff --git a/modules/config/instances/config/jellyfin.nix b/modules/config/instances/config/jellyfin.nix index a59f64c..377f3f9 100755 --- a/modules/config/instances/config/jellyfin.nix +++ b/modules/config/instances/config/jellyfin.nix @@ -5,6 +5,7 @@ let sslPath varPath mntPath + cachePath secretPath ; label = "Jellyfin"; @@ -53,6 +54,7 @@ in }; varPaths = { path0 = "${varPath}/${name}"; + path1 = "${cachePath}/${name}"; }; mntPaths = { path0 = "${mntPath}/${name}"; diff --git a/modules/home/cli/shell/zoxide/default.nix b/modules/home/cli/shell/zoxide/default.nix index 297be73..3921e26 100755 --- a/modules/home/cli/shell/zoxide/default.nix +++ b/modules/home/cli/shell/zoxide/default.nix @@ -1,40 +1,40 @@ { pkgs, - lib, - flake, - osConfig, + # lib, + # flake, + # osConfig, ... }: -let - inherit (flake.config.machines.devices) mars deimos; - hostname = osConfig.networking.hostName; +# let +# inherit (flake.config.machines.devices) mars deimos; +# hostname = osConfig.networking.hostName; - sharedPaths = '' - ${pkgs.zoxide}/bin/zoxide add ~/projects/dotfiles - ${pkgs.zoxide}/bin/zoxide add ~/downloads - ${pkgs.zoxide}/bin/zoxide add ~/projects - ${pkgs.zoxide}/bin/zoxide add /mnt/media/ceres/jellyfin - ${pkgs.zoxide}/bin/zoxide add /mnt/media/ceres/comfyui - ''; +# sharedPaths = '' +# ${pkgs.zoxide}/bin/zoxide add ~/projects/dotfiles +# ${pkgs.zoxide}/bin/zoxide add ~/downloads +# ${pkgs.zoxide}/bin/zoxide add ~/projects +# ${pkgs.zoxide}/bin/zoxide add /mnt/media/ceres/jellyfin +# ${pkgs.zoxide}/bin/zoxide add /mnt/media/ceres/comfyui +# ''; - desktopPaths = '' - ${pkgs.zoxide}/bin/zoxide add ~/projects/website - ${pkgs.zoxide}/bin/zoxide add ~/projects/workflowbuilder - ${pkgs.zoxide}/bin/zoxide add /mnt/media/storage - ''; +# desktopPaths = '' +# ${pkgs.zoxide}/bin/zoxide add ~/projects/website +# ${pkgs.zoxide}/bin/zoxide add ~/projects/workflowbuilder +# ${pkgs.zoxide}/bin/zoxide add /mnt/media/storage +# ''; - zoxidePaths = { - home.activation.initZoxidePaths = lib.hm.dag.entryAfter [ "writeBoundary" ] ( - if hostname == mars.name then - (sharedPaths + desktopPaths) - else if hostname == deimos.name then - sharedPaths - else - "" - ); - }; +# zoxidePaths = { +# home.activation.initZoxidePaths = lib.hm.dag.entryAfter [ "writeBoundary" ] ( +# if hostname == mars.name then +# (sharedPaths + desktopPaths) +# else if hostname == deimos.name then +# sharedPaths +# else +# "" +# ); +# }; -in +# in { programs.zoxide = { enable = true; @@ -44,4 +44,4 @@ in ]; }; } -// zoxidePaths +# // zoxidePaths diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index 6e92abc..f79996f 100755 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -44,15 +44,15 @@ in ceres = { imports = builtins.attrValues { inherit (modules) - acmeCeres + acme # audiobookshelf - caddyCeres + caddy # comfyui # filesorter # firefly-iii # forgejo # glance - # jellyfin + jellyfin # logrotate # mastodon microvm diff --git a/modules/nixos/services/acme/acmeCeres/default.nix b/modules/nixos/services/acme/acmeCeres/default.nix deleted file mode 100755 index edf1b9d..0000000 --- a/modules/nixos/services/acme/acmeCeres/default.nix +++ /dev/null @@ -1,87 +0,0 @@ -{ - config, - flake, - ... -}: -let - inherit (flake.config.people) user0; - inherit (flake.config.people.users.${user0}) email; - inherit (flake.config.services) instances; - domain0 = instances.web.domains.url0; - domain1 = instances.web.domains.url1; - domain4 = flake.inputs.linkpage.secrets.domains.projectsite; - service = instances.acme; - dns0 = instances.web.dns.provider0; - dns1 = instances.web.dns.provider1; - dns0Path = "dns/${dns0}"; - dns1Path = "dns/${dns1}"; -in -{ - security.acme = { - acceptTerms = true; - defaults = { - email = email.address0; - server = "https://acme-v02.api.letsencrypt.org/directory"; - }; - certs = - let - dnsConfig = provider: dns: { - dnsProvider = dns; - environmentFile = config.sops.secrets.${provider}.path; - }; - in - { - # "${instances.audiobookshelf.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.glance.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.jellyfin.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.ollama.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.searx.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.syncthing.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.vaultwarden.domains.url0}" = dnsConfig dns0Path dns0; # Moved to vaultwarden service module - # "${instances.prompter.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.comfyui.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.firefly-iii.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.opencloud.domains.url0}" = dnsConfig dns0Path dns0; - "${instances.forgejo.domains.url0}" = dnsConfig dns0Path dns0; - # "${instances.mastodon.domains.url0}" = dnsConfig dns0Path dns0; - # "${domain0}" = dnsConfig dns0Path dns0; - # "${domain1}" = dnsConfig dns0Path dns0; - # "${domain4}" = dnsConfig dns1Path dns1; - }; - }; - - sops = - let - dnsList = [ - dns0 - dns1 - ]; - secretList = [ - "pass" - ]; - sopsPath = secret: dns: { - path = "/var/lib/secrets/${instances.acme.name}/${dns}-${secret}"; - owner = "root"; - mode = "600"; - }; - in - { - secrets = builtins.listToAttrs ( - builtins.concatLists ( - map ( - dns: - map (secret: { - name = "dns/${dns}"; - value = sopsPath secret dns; - }) secretList - ) dnsList - ) - ); - }; - - systemd = { - tmpfiles.rules = [ - "Z ${service.sops.path0} 755 ${service.name} ${service.name} -" - ]; - }; -} diff --git a/modules/nixos/services/acme/acmeEris/default.nix b/modules/nixos/services/acme/acmeEris/default.nix deleted file mode 100755 index e88d6ac..0000000 --- a/modules/nixos/services/acme/acmeEris/default.nix +++ /dev/null @@ -1,75 +0,0 @@ -{ - config, - flake, - ... -}: -let - inherit (flake.config.people) user0; - inherit (flake.config.people.users.${user0}) email; - inherit (flake.config.services) instances; - service = instances.acme; - domain0 = instances.web.domains.url0; - dns0 = instances.web.dns.provider0; - dns0Path = "dns/${dns0}"; - instanceName = service: (instances.${service}.subdomain); - - dnsConfig = provider: dns: { - dnsProvider = dns; - directory = instances.acme.paths.path0; - environmentFile = config.sops.secrets.${provider}.path; - }; -in -{ - security.acme = { - acceptTerms = true; - defaults = { - email = email.address0; - server = "https://acme-v02.api.letsencrypt.org/directory"; - }; - certs = builtins.listToAttrs ( - (map - (service: { - name = "${instanceName service}.${domain0}"; - value = dnsConfig dns0Path dns0; - }) - [ - # instances.opencloud.name - ] - ) - ); - }; - sops = - let - dnsList = [ - dns0 - ]; - secretList = [ - "pass" - ]; - sopsPath = secret: dns: { - path = "/var/lib/secrets/${instances.acme.name}/${dns}-${secret}"; - owner = "root"; - mode = "600"; - }; - in - { - secrets = builtins.listToAttrs ( - builtins.concatLists ( - map ( - dns: - map (secret: { - name = "dns/${dns}"; - value = sopsPath secret dns; - }) secretList - ) dnsList - ) - ); - }; - - systemd = { - tmpfiles.rules = [ - "Z ${service.sops.path0} 755 ${service.name} ${service.name} -" - ]; - }; - -} diff --git a/modules/nixos/services/acme/default.nix b/modules/nixos/services/acme/default.nix index da65bd2..791b61e 100755 --- a/modules/nixos/services/acme/default.nix +++ b/modules/nixos/services/acme/default.nix @@ -1,11 +1,56 @@ +{ + flake, + ... +}: let - importList = - let - content = builtins.readDir ./.; - dirContent = builtins.filter (n: content.${n} == "directory") (builtins.attrNames content); - in - map (name: ./. + "/${name}") dirContent; + inherit (flake.config.people) user0; + inherit (flake.config.people.users.${user0}) email; + inherit (flake.config.services) instances; + service = instances.acme; + dns0 = instances.web.dns.provider0; + dns1 = instances.web.dns.provider1; in { - imports = importList; + security.acme = { + acceptTerms = true; + defaults = { + email = email.address0; + server = "https://acme-v02.api.letsencrypt.org/directory"; + }; + }; + + sops = + let + dnsList = [ + dns0 + dns1 + ]; + secretList = [ + "pass" + ]; + sopsPath = secret: dns: { + path = "/var/lib/secrets/${instances.acme.name}/${dns}-${secret}"; + owner = "root"; + mode = "600"; + }; + in + { + secrets = builtins.listToAttrs ( + builtins.concatLists ( + map ( + dns: + map (secret: { + name = "dns/${dns}"; + value = sopsPath secret dns; + }) secretList + ) dnsList + ) + ); + }; + + systemd = { + tmpfiles.rules = [ + "Z ${service.sops.path0} 755 ${service.name} ${service.name} -" + ]; + }; } diff --git a/modules/nixos/services/caddy/caddyCeres/default.nix b/modules/nixos/services/caddy/caddyCeres/default.nix deleted file mode 100755 index 4f7cd1d..0000000 --- a/modules/nixos/services/caddy/caddyCeres/default.nix +++ /dev/null @@ -1,25 +0,0 @@ -{ flake, ... }: -let - inherit (flake.config.services) instances; - - service = instances.caddy; -in -{ - services.caddy = { - enable = true; - }; - users.users.${service.name}.extraGroups = [ - "acme" - "mastodon" - "firefly-iii" - ]; - - networking = { - firewall = { - allowedTCPPorts = [ - service.ports.port0 - service.ports.port1 - ]; - }; - }; -} diff --git a/modules/nixos/services/caddy/caddyEris/default.nix b/modules/nixos/services/caddy/caddyEris/default.nix deleted file mode 100755 index d29e386..0000000 --- a/modules/nixos/services/caddy/caddyEris/default.nix +++ /dev/null @@ -1,25 +0,0 @@ -{ flake, ... }: -let - inherit (flake.config.services.instances) caddy; - - service = caddy; - -in -{ - services.caddy = { - enable = true; - }; - users.users.${service.name}.extraGroups = [ - "acme" - ]; - - networking = { - firewall = { - allowedTCPPorts = [ - service.ports.port0 - service.ports.port1 - service.ports.port2 - ]; - }; - }; -} diff --git a/modules/nixos/services/caddy/default.nix b/modules/nixos/services/caddy/default.nix index da65bd2..0cff934 100755 --- a/modules/nixos/services/caddy/default.nix +++ b/modules/nixos/services/caddy/default.nix @@ -1,11 +1,20 @@ +{ flake, ... }: let - importList = - let - content = builtins.readDir ./.; - dirContent = builtins.filter (n: content.${n} == "directory") (builtins.attrNames content); - in - map (name: ./. + "/${name}") dirContent; + inherit (flake.config.services) instances; + + service = instances.caddy; in { - imports = importList; + services.caddy = { + enable = true; + }; + + networking = { + firewall = { + allowedTCPPorts = [ + service.ports.port0 + service.ports.port1 + ]; + }; + }; } diff --git a/modules/nixos/services/jellyfin/default.nix b/modules/nixos/services/jellyfin/default.nix index cc2fc99..841f0f3 100755 --- a/modules/nixos/services/jellyfin/default.nix +++ b/modules/nixos/services/jellyfin/default.nix @@ -1,23 +1,133 @@ -{ flake, ... }: +{ + config, + flake, + ... +}: let inherit (flake.config.people) user0; - inherit (flake.config.machines.devices) ceres; - inherit (flake.config.services.instances) jellyfin web; - service = jellyfin; - localhost = web.localhost.address0; - host = service.domains.url0; + inherit (flake.config.services) instances; + serviceCfg = flake.config.services.instances.jellyfin; + hostCfg = flake.config.services.instances.web; + host = serviceCfg.domains.url0; + dns0 = instances.web.dns.provider0; + dns0Path = "dns/${dns0}"; in { + users.users.caddy.extraGroups = [ "acme" ]; + + security.acme.certs."${host}" = { + dnsProvider = dns0; + environmentFile = config.sops.secrets.${dns0Path}.path; + group = "caddy"; + }; + + microvm.vms.jellyin = { + autostart = true; + + restartIfChanged = true; + config = { + system.stateVersion = "24.05"; + time.timeZone = "America/Winnipeg"; + users.users.root.openssh.authorizedKeys.keys = flake.config.people.users.${user0}.sshKeys; + services = { + jellyfin = { + enable = true; + openFirewall = true; + user = user0; + }; + jellyseerr = { + openFirewall = true; + enable = true; + }; + + openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + PermitRootLogin = "prohibit-password"; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ + serviceCfg.ports.port0 + serviceCfg.ports.port1 + serviceCfg.ports.port2 + ]; + systemd.network = { + enable = true; + networks."20-lan" = { + matchConfig.Name = "enp0s5"; + addresses = [ + { Address = "${serviceCfg.interface.ip}/24"; } + ]; + routes = [ + { + Destination = "${hostCfg.localhost.address1}/0"; + Gateway = serviceCfg.interface.gate; + } + ]; + dns = [ + "1.1.1.1" + "8.8.8.8" + ]; + }; + }; + + systemd.services.systemd-networkd.wantedBy = [ "multi-user.target" ]; + microvm = { + vcpu = 4; + mem = 4096; + hypervisor = "qemu"; + interfaces = [ + { + type = "tap"; + id = serviceCfg.interface.id; + mac = serviceCfg.interface.mac; + } + { + type = "user"; + id = serviceCfg.interface.idUser; + mac = serviceCfg.interface.macUser; + } + ]; + forwardPorts = [ + { + from = "host"; + host.port = serviceCfg.interface.ssh; + guest.port = 22; + } + ]; + + shares = [ + { + mountPoint = "/nix/.ro-store"; + proto = "virtiofs"; + source = "/nix/store"; + tag = "read_only_nix_store"; + } + { + mountPoint = serviceCfg.varPaths.path0; + proto = "virtiofs"; + source = serviceCfg.mntPaths.path0; + tag = "service_data"; + } + { + mountPoint = serviceCfg.varPaths.path1; + proto = "virtiofs"; + source = "${serviceCfg.mntPaths.path0}/cache"; + tag = "service_cache"; + } + ]; + }; + }; + }; + + systemd.tmpfiles.rules = [ + "d ${serviceCfg.mntPaths.path0} 0755 root root -" + ]; + services = { - jellyfin = { - enable = true; - openFirewall = true; - user = user0; - }; - jellyseerr = { - openFirewall = true; - enable = true; - }; caddy = { virtualHosts = { "${host}" = { @@ -25,50 +135,12 @@ in redir /.well-known/carddav /remote.php/dav/ 301 redir /.well-known/caldav /remote.php/dav/ 301 - reverse_proxy ${localhost}:${toString service.ports.port0} + reverse_proxy ${serviceCfg.interface.ip}:${toString serviceCfg.ports.port0} - tls ${service.ssl.cert} ${service.ssl.key} + tls ${serviceCfg.ssl.cert} ${serviceCfg.ssl.key} ''; }; }; }; }; - - fileSystems = - let - settings = { - fsType = "none"; - options = [ - "bind" - ]; - depends = [ - ceres.storage0.mount - ]; - }; - in - { - "/var/lib/${service.name}" = { - device = service.paths.path0; - } - // settings; - "/var/cache/${service.name}" = { - device = "${service.paths.path1}"; - } - // settings; - }; - - systemd.tmpfiles.rules = [ - "Z ${service.paths.path0} 0755 ${user0} ${service.name} -" - "Z ${service.paths.path0} 0755 ${user0} ${service.name} -" - ]; - - networking = { - firewall = { - allowedTCPPorts = [ - service.ports.port0 - service.ports.port1 - service.ports.port2 - ]; - }; - }; } diff --git a/modules/nixos/services/vaultwarden/default.nix b/modules/nixos/services/vaultwarden/default.nix index 39cc9e8..a1c82b2 100755 --- a/modules/nixos/services/vaultwarden/default.nix +++ b/modules/nixos/services/vaultwarden/default.nix @@ -4,21 +4,15 @@ ... }: let - vaultwardenCfg = flake.config.services.instances.vaultwarden; - smtpCfg = flake.config.services.instances.smtp; inherit (flake.config.people) user0; inherit (flake.config.services) instances; - + serviceCfg = flake.config.services.instances.vaultwarden; + smtpCfg = flake.config.services.instances.smtp; + host = serviceCfg.domains.url0; dns0 = instances.web.dns.provider0; dns0Path = "dns/${dns0}"; in { - users.users.caddy.extraGroups = [ "acme" ]; - security.acme.certs."${vaultwardenCfg.domains.url0}" = { - dnsProvider = dns0; - environmentFile = config.sops.secrets.${dns0Path}.path; - group = "caddy"; - }; microvm.vms.vaultwarden = { autostart = true; @@ -32,13 +26,13 @@ in dbBackend = "sqlite"; config = { # Domain Configuration - DOMAIN = "https://${vaultwardenCfg.domains.url0}"; + DOMAIN = "https://${host}"; # Email Configuration SMTP_AUTH_MECHANISM = "Plain"; SMTP_EMBED_IMAGES = true; - SMTP_FROM = vaultwardenCfg.email.address0; - SMTP_FROM_NAME = vaultwardenCfg.label; + SMTP_FROM = serviceCfg.email.address0; + SMTP_FROM_NAME = serviceCfg.label; SMTP_HOST = smtpCfg.hostname; SMTP_PORT = smtpCfg.ports.port1; SMTP_SECURITY = smtpCfg.records.record1; @@ -57,11 +51,11 @@ in # Rocket (Web Server) Settings ROCKET_ADDRESS = "0.0.0.0"; - ROCKET_PORT = vaultwardenCfg.ports.port0; + ROCKET_PORT = serviceCfg.ports.port0; }; # Environment file with secrets (mounted from host) - environmentFile = "/run/secrets/vaultwarden/env"; + environmentFile = "/run/secrets/${serviceCfg.name}/env"; }; services.openssh = { @@ -78,18 +72,18 @@ in 139 # SMTP 587 # SMTP 2525 # SMTP - vaultwardenCfg.ports.port0 + serviceCfg.ports.port0 ]; systemd.network = { enable = true; networks."20-lan" = { matchConfig.Name = "enp0s5"; - addresses = [ { Address = "${vaultwardenCfg.interface.ip}/24"; } ]; + addresses = [ { Address = "${serviceCfg.interface.ip}/24"; } ]; routes = [ { Destination = "0.0.0.0/0"; - Gateway = vaultwardenCfg.interface.gate; + Gateway = serviceCfg.interface.gate; } ]; dns = [ @@ -108,19 +102,19 @@ in interfaces = [ { type = "tap"; - id = vaultwardenCfg.interface.id; - mac = vaultwardenCfg.interface.mac; + id = serviceCfg.interface.id; + mac = serviceCfg.interface.mac; } { type = "user"; - id = vaultwardenCfg.interface.idUser; - mac = vaultwardenCfg.interface.macUser; + id = serviceCfg.interface.idUser; + mac = serviceCfg.interface.macUser; } ]; forwardPorts = [ { from = "host"; - host.port = vaultwardenCfg.interface.ssh; + host.port = serviceCfg.interface.ssh; guest.port = 22; } ]; @@ -134,7 +128,7 @@ in { mountPoint = "/var/lib/bitwarden_rs"; proto = "virtiofs"; - source = vaultwardenCfg.mntPaths.path0; + source = serviceCfg.mntPaths.path0; tag = "vaultwarden_data"; } { @@ -148,22 +142,32 @@ in }; }; - systemd.tmpfiles.rules = [ - "d ${vaultwardenCfg.mntPaths.path0} 0755 root root -" - ]; - - services.caddy.virtualHosts."${vaultwardenCfg.domains.url0}" = { - extraConfig = '' - reverse_proxy ${vaultwardenCfg.interface.ip}:${toString vaultwardenCfg.ports.port0} { - header_up X-Real-IP {remote_host} - } - tls ${vaultwardenCfg.ssl.cert} ${vaultwardenCfg.ssl.key} - encode zstd gzip - ''; + security.acme.certs."${host}" = { + dnsProvider = dns0; + environmentFile = config.sops.secrets.${dns0Path}.path; + group = "caddy"; }; + services.caddy.virtualHosts = { + "${host}" = { + extraConfig = '' + reverse_proxy ${serviceCfg.interface.ip}:${toString serviceCfg.ports.port0} { + header_up X-Real-IP {remote_host} + } + tls ${serviceCfg.ssl.cert} ${serviceCfg.ssl.key} + encode zstd gzip + ''; + }; + }; + + users.users.caddy.extraGroups = [ "acme" ]; + + systemd.tmpfiles.rules = [ + "d ${serviceCfg.mntPaths.path0} 0755 root root -" + ]; + sops.secrets = { - "vaultwarden/env" = { + "${serviceCfg.name}/env" = { owner = "root"; mode = "0600"; }; diff --git a/systems/ceres/config/networking.nix b/systems/ceres/config/networking.nix index 53742a5..8396cd5 100755 --- a/systems/ceres/config/networking.nix +++ b/systems/ceres/config/networking.nix @@ -9,13 +9,10 @@ let wireguardService = instances.wireGuard; in { - # Enable microVM host microvm.host.enable = true; - # systemd-networkd for bridge management (required for TAP interfaces) systemd.network.enable = true; - # Bridge configuration for microVMs systemd.network.netdevs."10-br-vms" = { netdevConfig = { Name = "br-vms"; @@ -23,7 +20,6 @@ in }; }; - # Attach physical interface and tap interfaces to bridge systemd.network.networks."20-lan" = { matchConfig.Name = [ "enp10s0" @@ -34,7 +30,6 @@ in }; }; - # Bridge gets the host IP systemd.network.networks."30-br-vms" = { matchConfig.Name = "br-vms"; networkConfig = { @@ -47,12 +42,9 @@ in networking = { hostName = ceres.name; - # NetworkManager disabled - using declarative networking networkmanager.enable = false; nftables.enable = true; useDHCP = false; - # Network configuration handled by systemd-networkd bridge - firewall = { enable = true; allowedTCPPorts = [