commit fbee55c569762077aa4aba936302a5916cdef54d parent 80f0f019d528db308ef77f7ad05e1005cef2ba8c Author: mtmn <miro@haravara.org> Date: Mon, 8 Jun 2026 20:55:09 +0200 nix: spring cleanup and whatnot Diffstat:
27 files changed, 350 insertions(+), 232 deletions(-)
diff --git a/hosts/nixaran/configuration.nix b/hosts/nixaran/configuration.nix Binary files differ. diff --git a/hosts/void/overlays/config/shell/rc/void b/hosts/void/overlays/config/shell/rc/void Binary files differ. diff --git a/modules/nixos/base.nix b/modules/nixos/base.nix @@ -29,10 +29,6 @@ }; }; - users.groups.storage-users = { - gid = 2000; - }; - users.users.${username} = { isNormalUser = true; shell = pkgs.zsh; diff --git a/modules/services/bazel-cache.nix b/modules/services/bazel-cache.nix @@ -13,26 +13,32 @@ in { listenAddress = lib.mkOption { type = lib.types.str; default = "127.0.0.1"; + description = "Address for the Bazel cache to listen on"; }; port = lib.mkOption { type = lib.types.port; default = 9820; + description = "Port for the Bazel cache to listen on"; }; dataDir = lib.mkOption { type = lib.types.str; default = "/var/lib/bazel-cache"; + description = "Directory for storing cached data"; }; domain = lib.mkOption { type = lib.types.str; + description = "Domain for the Bazel cache instance"; }; basicAuthUser = lib.mkOption { type = lib.types.str; + description = "Username for basic HTTP authentication"; }; basicAuthHash = lib.mkOption { type = lib.types.str; + description = "Bcrypt password hash for basic HTTP authentication"; }; }; @@ -56,11 +62,13 @@ in { }; }; - users.users.bazel-remote = { - isSystemUser = true; - group = "bazel-remote"; + users = { + users.bazel-remote = { + isSystemUser = true; + group = "bazel-remote"; + }; + groups.bazel-remote = {}; }; - users.groups.bazel-remote = {}; services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' basic_auth { diff --git a/modules/services/cinny.nix b/modules/services/cinny.nix @@ -11,6 +11,7 @@ in { enable = lib.mkEnableOption "Cinny Matrix client (Configuration only, served via Caddy)"; domain = lib.mkOption { type = lib.types.str; + description = "Domain for the Cinny web client"; }; authLabel = haravara.authLabelOption; }; diff --git a/modules/services/corpus.nix b/modules/services/corpus.nix @@ -20,15 +20,18 @@ in { port = lib.mkOption { type = lib.types.port; default = 8321; + description = "Port for the Corpus service to listen on"; }; domain = lib.mkOption { type = lib.types.str; + description = "Domain for the Corpus instance"; }; dataDir = lib.mkOption { type = lib.types.str; default = "/var/lib/corpus"; + description = "Directory for Corpus state data"; }; secretFile = lib.mkOption { @@ -61,11 +64,13 @@ in { }; }; - users.users.corpus = { - isSystemUser = true; - group = "corpus"; + users = { + users.corpus = { + isSystemUser = true; + group = "corpus"; + }; + groups.corpus = {}; }; - users.groups.corpus = {}; services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' encode zstd gzip diff --git a/modules/services/couchdb.nix b/modules/services/couchdb.nix @@ -10,13 +10,26 @@ in { enable = lib.mkEnableOption "CouchDB database server"; adminUser = lib.mkOption { type = lib.types.str; + description = "CouchDB admin username"; }; adminPassFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; + description = "Path to a file containing the CouchDB admin password"; }; publicDomain = lib.mkOption { type = lib.types.str; + description = "Public domain for the CouchDB Fauxton UI (set to null to disable)"; + }; + port = lib.mkOption { + type = lib.types.port; + default = 5984; + description = "Port for CouchDB to listen on"; + }; + bindAddress = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + description = "Address for CouchDB to bind to"; }; authLabel = haravara.authLabelOption; }; @@ -25,20 +38,18 @@ in { services = { couchdb = { enable = true; - bindAddress = "127.0.0.1"; - inherit (cfg) adminUser; + inherit (cfg) bindAddress adminUser; adminPass = null; - }; - - couchdb.extraConfig = { - chttpd.bind_address = "127.0.0.1"; - httpd.bind_address = "127.0.0.1"; - httpd.enable_cors = true; - cors = { - origins = "*"; - credentials = true; - methods = "GET, POST, PUT, DELETE, HEAD, OPTIONS"; - headers = "accept, authorization, content-type, origin, referer"; + extraConfig = { + chttpd.bind_address = cfg.bindAddress; + httpd.bind_address = cfg.bindAddress; + httpd.enable_cors = true; + cors = { + origins = "*"; + credentials = true; + methods = "GET, POST, PUT, DELETE, HEAD, OPTIONS"; + headers = "accept, authorization, content-type, origin, referer"; + }; }; }; @@ -46,10 +57,10 @@ in { "${cfg.publicDomain}".extraConfig = '' handle /_utils* { ${haravara.mkAuthImport cfg.authLabel} - reverse_proxy localhost:5984 + reverse_proxy ${cfg.bindAddress}:${toString cfg.port} } handle { - reverse_proxy localhost:5984 + reverse_proxy ${cfg.bindAddress}:${toString cfg.port} } ''; }; diff --git a/modules/services/dex.nix b/modules/services/dex.nix @@ -9,31 +9,48 @@ in { enable = lib.mkEnableOption "Dex - Identity Provider"; domain = lib.mkOption { type = lib.types.str; + description = "Domain for the Dex instance"; }; adminEmail = lib.mkOption { type = lib.types.str; + description = "Admin user email address"; }; adminPasswordHash = lib.mkOption { type = lib.types.str; + description = "Bcrypt hash of the admin user password"; }; adminUsername = lib.mkOption { type = lib.types.str; default = "admin"; + description = "Admin user username"; }; adminUserID = lib.mkOption { type = lib.types.str; + description = "Unique user ID for the admin account"; }; redirectURIs = lib.mkOption { type = lib.types.listOf lib.types.str; + description = "List of allowed OIDC redirect URIs"; }; expiry = lib.mkOption { type = lib.types.attrsOf lib.types.str; default = {}; + description = "Token expiry configuration passed to Dex"; }; clientSecretFile = lib.mkOption { type = lib.types.path; description = "Path to the Dex OIDC client secret file"; }; + address = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1:5556"; + description = "Address for Dex to listen on"; + }; + telemetryAddress = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1:5558"; + description = "Address for Dex telemetry endpoint"; + }; }; config = lib.mkIf cfg.enable { @@ -49,8 +66,8 @@ in { config.file = "/var/lib/dex/dex.db"; }; - web.http = "127.0.0.1:5556"; - telemetry.http = "127.0.0.1:5558"; + web.http = cfg.address; + telemetry.http = cfg.telemetryAddress; staticClients = [ { @@ -83,7 +100,7 @@ in { }; services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' - reverse_proxy 127.0.0.1:5556 + reverse_proxy ${cfg.address} ''; }; } diff --git a/modules/services/filestash.nix b/modules/services/filestash.nix Binary files differ. diff --git a/modules/services/forgejo.nix b/modules/services/forgejo.nix @@ -26,9 +26,31 @@ in { }; config = lib.mkIf cfg.enable { - users.users.forgejo = { - isSystemUser = true; - group = lib.mkForce "storage-users"; + users = { + users.forgejo = { + isSystemUser = true; + group = lib.mkForce "forgejo"; + }; + }; + + systemd = { + tmpfiles.rules = [ + "d /data/forgejo 0700 forgejo forgejo -" + "d /data/forgejo/repositories 0700 forgejo forgejo -" + "d /var/lib/forgejo 0700 forgejo forgejo -" + "d /var/lib/forgejo/custom 0700 forgejo forgejo -" + "d /var/lib/forgejo/custom/conf 0700 forgejo forgejo -" + ]; + + services.forgejo = { + serviceConfig.TimeoutSec = 3600; + }; + }; + + fileSystems."/var/lib/forgejo/repositories" = { + device = "/data/forgejo/repositories"; + fsType = "none"; + options = ["bind" "nofail"]; }; services = { @@ -95,26 +117,16 @@ in { } handle @cli_paths { - reverse_proxy 127.0.0.1:3482 + reverse_proxy 127.0.0.1:${toString cfg.httpPort} } handle { import remote_auth - reverse_proxy 127.0.0.1:3482 + reverse_proxy 127.0.0.1:${toString cfg.httpPort} } ''; }; - systemd.services.forgejo = { - serviceConfig.TimeoutSec = 3600; - }; - networking.firewall.allowedTCPPorts = [cfg.sshPort]; - - systemd.tmpfiles.rules = [ - "d /var/lib/forgejo 0700 forgejo storage-users -" - "d /var/lib/forgejo/custom 0700 forgejo storage-users -" - "d /var/lib/forgejo/custom/conf 0700 forgejo storage-users -" - ]; }; } diff --git a/modules/services/headscale.nix b/modules/services/headscale.nix @@ -9,6 +9,7 @@ in { enable = lib.mkEnableOption "Headscale service"; initUser = lib.mkOption { type = lib.types.str; + description = "Username for the initial Headscale admin user"; }; domain = lib.mkOption { type = lib.types.str; diff --git a/modules/services/heisenbridge.nix b/modules/services/heisenbridge.nix @@ -14,10 +14,15 @@ in { }; config = lib.mkIf cfg.enable { + systemd.services.heisenbridge = { + after = ["matrix-conduit.service"]; + requires = ["matrix-conduit.service"]; + }; + services.heisenbridge = { enable = true; address = "127.0.0.1"; - homeserver = "http://localhost:6167"; + homeserver = "http://localhost:${toString config.services.matrix-conduit.settings.global.port}"; inherit (cfg) owner; }; }; diff --git a/modules/services/listenbrainz-mpd.nix b/modules/services/listenbrainz-mpd.nix @@ -25,28 +25,38 @@ in { apiUrl = lib.mkOption { type = lib.types.str; default = "https://api.listenbrainz.org"; + description = "ListenBrainz API URL"; }; genresAsFolksonomy = lib.mkOption { type = lib.types.bool; default = false; + description = "Submit genre tags as ListenBrainz folksonomy tags"; }; mpdAddress = lib.mkOption { type = lib.types.str; default = "localhost:6695"; + description = "MPD address to connect to"; }; mpdPassword = lib.mkOption { type = lib.types.str; default = ""; + description = "Password for MPD authentication"; }; mpdPort = lib.mkOption { type = lib.types.port; default = 37281; + description = "MPD port"; }; mpdHostFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; description = "Path to the secret file containing MPD_HOST"; }; + dataDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/listenbrainz-mpd"; + description = "Directory for ListenBrainz MPD state data"; + }; }; config = lib.mkIf cfg.enable { @@ -57,7 +67,7 @@ in { environment = { MPD_PORT = toString cfg.mpdPort; - XDG_DATA_HOME = "/var/lib/listenbrainz-mpd"; + XDG_DATA_HOME = cfg.dataDir; }; serviceConfig = { diff --git a/modules/services/matrix.nix b/modules/services/matrix.nix @@ -20,6 +20,11 @@ in { type = lib.types.str; description = "The target domain for the root redirect"; }; + dataDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/matrix-conduit"; + description = "Directory for Conduit state data"; + }; registrationTokenFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; @@ -48,7 +53,7 @@ in { # Basic directory setup for Conduit systemd.tmpfiles.rules = [ - "d /var/lib/matrix-conduit/appservices 0700 conduit conduit -" + "d ${cfg.dataDir}/appservices 0700 conduit conduit -" ]; services.caddy.virtualHosts."${cfg.serverName}" = { diff --git a/modules/services/miniflux.nix b/modules/services/miniflux.nix @@ -9,6 +9,12 @@ in { enable = lib.mkEnableOption "Miniflux RSS Reader"; domain = lib.mkOption { type = lib.types.str; + description = "Domain for the Miniflux instance"; + }; + address = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1:8931"; + description = "Address for Miniflux to listen on"; }; credentialsFile = lib.mkOption { type = lib.types.path; @@ -20,7 +26,7 @@ in { services.miniflux = { enable = true; config = { - LISTEN_ADDR = "127.0.0.1:8931"; + LISTEN_ADDR = cfg.address; RUN_MIGRATIONS = 1; CREATE_ADMIN = 0; }; @@ -28,7 +34,7 @@ in { }; services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' - reverse_proxy 127.0.0.1:8931 + reverse_proxy ${cfg.address} ''; }; } diff --git a/modules/services/monitoring/default.nix b/modules/services/monitoring/default.nix @@ -20,9 +20,11 @@ in { grafanaDomain = lib.mkOption { type = lib.types.str; + description = "Domain for the Grafana dashboard"; }; victoriaDomain = lib.mkOption { type = lib.types.str; + description = "Domain for VictoriaMetrics"; }; authLabel = haravara.authLabelOption; grafanaSecretKeyFile = lib.mkOption { @@ -32,6 +34,16 @@ in { victoriametrics = { enable = lib.mkEnableOption "VictoriaMetrics time-series database" // {default = true;}; + address = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1:8428"; + description = "Address for VictoriaMetrics to listen on"; + }; + dataDir = lib.mkOption { + type = lib.types.str; + default = "/data/victoriametrics"; + description = "Directory for VictoriaMetrics data"; + }; extraScrapeConfigs = lib.mkOption { type = lib.types.listOf lib.types.attrs; default = []; @@ -41,26 +53,43 @@ in { }; config = lib.mkIf cfg.enable { - users.groups.victoriametrics = lib.mkIf cfg.victoriametrics.enable {}; - users.users.victoriametrics = lib.mkIf cfg.victoriametrics.enable { - isSystemUser = true; - group = "victoriametrics"; - extraGroups = ["storage-users"]; + users = { + groups.victoriametrics = lib.mkIf cfg.victoriametrics.enable {}; + users.victoriametrics = lib.mkIf cfg.victoriametrics.enable { + isSystemUser = true; + group = "victoriametrics"; + }; + }; + + systemd = { + tmpfiles.rules = lib.optionals cfg.victoriametrics.enable [ + "d ${cfg.victoriametrics.dataDir} - victoriametrics victoriametrics -" + ]; + + services.victoriametrics = lib.mkIf cfg.victoriametrics.enable { + after = ["var-lib-victoriametrics.mount"]; + requires = ["var-lib-victoriametrics.mount"]; + serviceConfig = { + User = "victoriametrics"; + Group = "victoriametrics"; + StateDirectory = lib.mkForce ""; + DynamicUser = lib.mkForce false; + ReadWritePaths = ["/var/lib/victoriametrics"]; + }; + }; }; - systemd.services.victoriametrics = lib.mkIf cfg.victoriametrics.enable { - serviceConfig = { - User = "victoriametrics"; - Group = "victoriametrics"; - StateDirectory = lib.mkForce ""; - DynamicUser = lib.mkForce false; - ReadWritePaths = ["/var/lib/victoriametrics"]; + fileSystems = lib.optionalAttrs cfg.victoriametrics.enable { + "/var/lib/victoriametrics" = { + device = cfg.victoriametrics.dataDir; + fsType = "none"; + options = ["bind" "nofail"]; }; }; services.victoriametrics = lib.mkIf cfg.victoriametrics.enable { enable = true; - listenAddress = "127.0.0.1:8428"; + listenAddress = cfg.victoriametrics.address; extraOptions = lib.optional cfg.vmalert.enable "-vmalert.proxyURL=http://127.0.0.1:${toString cfg.vmalert.port}"; @@ -83,28 +112,28 @@ in { metrics_path = "/metrics"; } ]) + ++ lib.optional config.services.haravara.seaweedfs.enable { + job_name = "seaweedfs"; + static_configs = [ + { + targets = [ + "127.0.0.1:9324" + "127.0.0.1:9325" + "127.0.0.1:9326" + "127.0.0.1:9327" + ]; + } + ]; + } ++ [ { - job_name = "seaweedfs"; - static_configs = [ - { - targets = [ - "127.0.0.1:9324" - "127.0.0.1:9325" - "127.0.0.1:9326" - "127.0.0.1:9327" - ]; - } - ]; - } - { job_name = "caddy"; static_configs = [{targets = ["127.0.0.1:2019"];}]; } ] ++ lib.optional cfg.loki.enable { job_name = "loki"; - static_configs = [{targets = ["127.0.0.1:3100"];}]; + static_configs = [{targets = ["127.0.0.1:${toString cfg.loki.port}"];}]; } ++ lib.optional config.services.haravara.corpus.enable { job_name = "corpus"; @@ -126,7 +155,7 @@ in { services.caddy.virtualHosts = lib.optionalAttrs cfg.victoriametrics.enable { "${cfg.victoriaDomain}".extraConfig = '' ${authSnippet} - reverse_proxy 127.0.0.1:8428 + reverse_proxy ${cfg.victoriametrics.address} ''; }; }; diff --git a/modules/services/monitoring/grafana.nix b/modules/services/monitoring/grafana.nix @@ -35,12 +35,12 @@ url = "https://grafana.com/api/dashboards/9578/revisions/4/download"; sha256 = "16jvazvjswiyn281z4r7wmwb18841d3ar24951538kma28l05izy"; } - { - name = "seaweedfs.json"; - url = "https://raw.githubusercontent.com/chrislusf/seaweedfs/c9100a7213e27963f58a0ba783c9598a177384b6/other/metrics/grafana_seaweedfs.json"; - sha256 = "e364d113fed54127cbda10c4c2809d99a90dcc38bcd949b91846d0831e1a68e4"; - } ] + ++ lib.optional config.services.haravara.seaweedfs.enable { + name = "seaweedfs.json"; + url = "https://raw.githubusercontent.com/chrislusf/seaweedfs/c9100a7213e27963f58a0ba783c9598a177384b6/other/metrics/grafana_seaweedfs.json"; + sha256 = "e364d113fed54127cbda10c4c2809d99a90dcc38bcd949b91846d0831e1a68e4"; + } ++ [ { name = "caddy.json"; diff --git a/modules/services/monitoring/loki.nix b/modules/services/monitoring/loki.nix @@ -8,6 +8,16 @@ in { options.services.haravara.monitoring.loki = { enable = lib.mkEnableOption "Loki log aggregation and Alloy collector" // {default = true;}; + port = lib.mkOption { + type = lib.types.port; + default = 3100; + description = "Port for Loki HTTP listener"; + }; + dataDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/loki"; + description = "Directory for Loki storage"; + }; }; config = lib.mkIf (cfg.enable && cfg.loki.enable) { @@ -16,14 +26,14 @@ in { configuration = { server = { http_listen_address = "127.0.0.1"; - http_listen_port = 3100; + http_listen_port = cfg.loki.port; grpc_listen_address = "127.0.0.1"; }; auth_enabled = false; common = { instance_addr = "127.0.0.1"; - path_prefix = "/var/lib/loki"; + path_prefix = cfg.loki.dataDir; replication_factor = 1; ring.kvstore.store = "inmemory"; }; @@ -39,7 +49,7 @@ in { } ]; - storage_config.filesystem.directory = "/var/lib/loki/chunks"; + storage_config.filesystem.directory = "${cfg.loki.dataDir}/chunks"; }; }; @@ -50,7 +60,7 @@ in { loki.write "default" { endpoint { - url = "http://127.0.0.1:3100/loki/api/v1/push" + url = "http://127.0.0.1:${toString cfg.loki.port}/loki/api/v1/push" } } diff --git a/modules/services/oauth2-proxy.nix b/modules/services/oauth2-proxy.nix @@ -1,7 +1,6 @@ { config, lib, - pkgs, ... }: let cfg = config.services.haravara.oauth2-proxy; @@ -14,9 +13,16 @@ in { }; cookieDomains = lib.mkOption { type = lib.types.listOf lib.types.str; + description = "List of domains for the OAuth2 proxy cookie"; }; oidcIssuer = lib.mkOption { type = lib.types.str; + description = "OIDC issuer URL for the upstream identity provider"; + }; + port = lib.mkOption { + type = lib.types.port; + default = 4180; + description = "Port for OAuth2 Proxy to listen on"; }; clientSecretFile = lib.mkOption { type = lib.types.path; @@ -49,7 +55,7 @@ in { insecure-oidc-skip-issuer-verification = "true"; code-challenge-method = "S256"; whitelist-domain = lib.concatStringsSep "," cfg.cookieDomains; - http-address = "127.0.0.1:4180"; + http-address = "127.0.0.1:${toString cfg.port}"; set-xauthrequest = "true"; pass-user-headers = "true"; insecure-oidc-allow-unverified-email = "true"; @@ -65,15 +71,13 @@ in { services.caddy.virtualHosts = lib.genAttrs cfg.domains (_: { extraConfig = '' - reverse_proxy 127.0.0.1:4180 + reverse_proxy 127.0.0.1:${toString cfg.port} ''; }); - # Ensure dex is ready before starting oauth2-proxy systemd.services.oauth2-proxy = { after = ["dex.service"]; requires = ["dex.service"]; - serviceConfig.ExecStartPre = "${pkgs.bash}/bin/bash -c 'while ! ${pkgs.netcat}/bin/nc -z 127.0.0.1 5556; do sleep 1; done'"; }; }; } diff --git a/modules/services/radicale.nix b/modules/services/radicale.nix @@ -4,12 +4,22 @@ ... }: let cfg = config.services.haravara.radicale; - port = 5232; in { options.services.haravara.radicale = { enable = lib.mkEnableOption "Radicale CalDAV/CardDAV server"; domain = lib.mkOption { type = lib.types.str; + description = "Domain for the Radicale instance"; + }; + port = lib.mkOption { + type = lib.types.port; + default = 5232; + description = "Port for Radicale to listen on"; + }; + dataDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/radicale/collections"; + description = "Directory for Radicale storage"; }; htpasswdFile = lib.mkOption { type = lib.types.path; @@ -21,18 +31,18 @@ in { services.radicale = { enable = true; settings = { - server.hosts = ["127.0.0.1:${toString port}"]; + server.hosts = ["127.0.0.1:${toString cfg.port}"]; auth = { type = "htpasswd"; htpasswd_filename = cfg.htpasswdFile; htpasswd_encryption = "bcrypt"; }; - storage.filesystem_folder = "/var/lib/radicale/collections"; + storage.filesystem_folder = cfg.dataDir; }; }; services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' - reverse_proxy 127.0.0.1:${toString port} + reverse_proxy 127.0.0.1:${toString cfg.port} ''; }; } diff --git a/modules/services/redlib.nix b/modules/services/redlib.nix @@ -11,9 +11,11 @@ in { port = lib.mkOption { type = lib.types.port; default = 7828; + description = "Port to expose Redlib on"; }; domain = lib.mkOption { type = lib.types.str; + description = "Domain for the Redlib instance"; }; authLabel = haravara.authLabelOption; }; diff --git a/modules/services/searxng.nix b/modules/services/searxng.nix @@ -11,8 +11,19 @@ in { enable = lib.mkEnableOption "SearXNG search engine"; domain = lib.mkOption { type = lib.types.str; + description = "Domain for the SearXNG instance"; }; authLabel = haravara.authLabelOption; + port = lib.mkOption { + type = lib.types.port; + default = 8899; + description = "Port for SearXNG to listen on"; + }; + bindAddress = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + description = "Address for SearXNG to bind to"; + }; secretKeyFile = lib.mkOption { type = lib.types.path; description = "Path to file containing SEARX_SECRET_KEY"; @@ -27,8 +38,8 @@ in { environmentFile = cfg.secretKeyFile; settings = { server = { - port = 8899; - bind_address = "127.0.0.1"; + inherit (cfg) port; + bind_address = cfg.bindAddress; secret_key = "@SEARX_SECRET_KEY@"; }; ui = { @@ -40,7 +51,7 @@ in { services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' ${haravara.mkAuthImport cfg.authLabel} - reverse_proxy 127.0.0.1:8899 + reverse_proxy ${cfg.bindAddress}:${toString cfg.port} ''; }; } diff --git a/modules/services/seaweedfs.nix b/modules/services/seaweedfs.nix @@ -20,12 +20,22 @@ in { }; config = lib.mkIf cfg.enable { - users.users.seaweedfs = { - isSystemUser = true; - group = "storage-users"; + users = { + groups.seaweedfs = {}; + users.seaweedfs = { + isSystemUser = true; + group = "seaweedfs"; + }; }; systemd = { + tmpfiles.rules = [ + "d ${cfg.dataDir} 0755 seaweedfs seaweedfs -" + "d ${cfg.dataDir}/master 0755 seaweedfs seaweedfs -" + "d ${cfg.dataDir}/volume 0755 seaweedfs seaweedfs -" + "d ${cfg.dataDir}/filer 0755 seaweedfs seaweedfs -" + ]; + services = { seaweedfs-master = { description = "SeaweedFS Master"; @@ -34,7 +44,7 @@ in { serviceConfig = { User = "seaweedfs"; - Group = "storage-users"; + Group = "seaweedfs"; ExecStart = "${pkgs.seaweedfs}/bin/weed master -mdir=${cfg.dataDir}/master -port=9333 -ip=127.0.0.1 -ip.bind=127.0.0.1 -metricsPort=9324"; Restart = "always"; }; @@ -48,7 +58,7 @@ in { serviceConfig = { User = "seaweedfs"; - Group = "storage-users"; + Group = "seaweedfs"; ExecStart = "${pkgs.seaweedfs}/bin/weed volume -dir=${cfg.dataDir}/volume -max=100 -port=8080 -ip=127.0.0.1 -ip.bind=127.0.0.1 -master=127.0.0.1:9333 -index=leveldb -metricsPort=9325"; Restart = "always"; }; @@ -62,7 +72,7 @@ in { serviceConfig = { User = "seaweedfs"; - Group = "storage-users"; + Group = "seaweedfs"; ExecStart = "${pkgs.seaweedfs}/bin/weed filer -port=8888 -ip=127.0.0.1 -ip.bind=127.0.0.1 -master=127.0.0.1:9333 -defaultStoreDir=${cfg.dataDir}/filer -metricsPort=9326"; Restart = "always"; }; @@ -76,7 +86,7 @@ in { serviceConfig = { User = "seaweedfs"; - Group = "storage-users"; + Group = "seaweedfs"; ExecStart = "${pkgs.seaweedfs}/bin/weed s3 -port=8333 -ip.bind=0.0.0.0 -filer=127.0.0.1:8888 -metricsPort=9327"; Restart = "always"; IPAddressAllow = ["127.0.0.1" "::1" "10.88.0.0/16"]; @@ -92,7 +102,7 @@ in { serviceConfig = { User = "seaweedfs"; - Group = "storage-users"; + Group = "seaweedfs"; ExecStart = "${pkgs.seaweedfs}/bin/weed admin -port=23646 -master=127.0.0.1:9333"; Restart = "always"; IPAddressAllow = ["127.0.0.1" "::1"]; diff --git a/modules/services/shirts.nix b/modules/services/shirts.nix @@ -16,23 +16,34 @@ in { port = lib.mkOption { type = lib.types.port; default = 8721; + description = "Port for the Shirts service to listen on"; }; host = lib.mkOption { type = lib.types.str; default = "127.0.0.1"; + description = "Host address for the Shirts service to bind to"; }; baseUrl = lib.mkOption { type = lib.types.str; + description = "Base URL for the Shirts shortener"; }; authTokenFile = lib.mkOption { type = lib.types.path; + description = "Path to a file containing the authentication token"; }; domain = lib.mkOption { type = lib.types.str; + description = "Domain for the Shirts instance"; + }; + + dataDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/shirts"; + description = "Directory for Shirts state data"; }; }; @@ -47,10 +58,10 @@ in { HOST = cfg.host; ERL_EPMD_ADDRESS = "127.0.0.1"; BASE_URL = cfg.baseUrl; - DB_PATH = "/var/lib/shirts/shortener.db"; + DB_PATH = "${cfg.dataDir}/shortener.db"; RELEASE_COOKIE = "shirts-cookie"; RELEASE_NODE = "shirts@localhost"; - RELEASE_TMP = "/var/lib/shirts/tmp"; + RELEASE_TMP = "${cfg.dataDir}/tmp"; ERL_AFLAGS = "-kernel inet_dist_use_interface '{127,0,0,1}'"; }; @@ -67,7 +78,7 @@ in { User = "shirts"; Group = "shirts"; StateDirectory = "shirts"; - WorkingDirectory = "/var/lib/shirts"; + WorkingDirectory = cfg.dataDir; RuntimeDirectory = "shirts"; SuccessExitStatus = [0 143]; KillMode = "mixed"; @@ -75,11 +86,13 @@ in { }; }; - users.users.shirts = { - isSystemUser = true; - group = "shirts"; + users = { + users.shirts = { + isSystemUser = true; + group = "shirts"; + }; + groups.shirts = {}; }; - users.groups.shirts = {}; services.caddy.virtualHosts = { "${cfg.domain}".extraConfig = '' diff --git a/modules/services/soju.nix b/modules/services/soju.nix @@ -6,8 +6,6 @@ ... }: let cfg = config.services.haravara.soju; - stateDir = "/var/lib/soju"; - runtimeDir = "/run/soju"; # Define the paths for the TLS cert and key. # We prefer systemd credentials which are populated from Caddy's certs. @@ -22,10 +20,10 @@ configFile = pkgs.writeText "soju.conf" '' listen ${lib.concatStringsSep "\nlisten " cfg.listen} - ${lib.optionalString cfg.adminSocket.enable "listen unix+admin://${runtimeDir}/admin"} + ${lib.optionalString cfg.adminSocket.enable "listen unix+admin://${cfg.runtimeDir}/admin"} hostname ${cfg.hostName} ${lib.optionalString (certPath != null) "tls ${certPath} ${keyPath}"} - ${lib.optionalString cfg.enableMessageLogging "message-store fs ${stateDir}/logs"} + ${lib.optionalString cfg.enableMessageLogging "message-store fs ${cfg.stateDir}/logs"} http-origin ${lib.concatStringsSep " " cfg.httpOrigins} accept-proxy-ip ${lib.concatStringsSep " " cfg.acceptProxyIP} @@ -37,7 +35,7 @@ ''; # Path to Caddy's certificates - caddyCertDir = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${cfg.domain}"; + caddyCertDir = "${cfg.acme.caddyCertDir}/${cfg.domain}"; in { options.services.haravara.soju = { enable = lib.mkEnableOption "soju IRC bouncer"; @@ -89,6 +87,11 @@ in { default = cfg.domain; description = "The domain name of the certificates in Caddy's storage."; }; + caddyCertDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory"; + description = "Path to Caddy's ACME certificate directory"; + }; }; enableMessageLogging = lib.mkOption { @@ -120,6 +123,18 @@ in { default = ""; description = "Lines added verbatim to the generated configuration file."; }; + + stateDir = lib.mkOption { + type = lib.types.str; + default = "/var/lib/soju"; + description = "Directory for soju state data"; + }; + + runtimeDir = lib.mkOption { + type = lib.types.str; + default = "/run/soju"; + description = "Runtime directory for soju"; + }; }; config = lib.mkIf cfg.enable { @@ -145,7 +160,7 @@ in { ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; StateDirectory = "soju"; RuntimeDirectory = "soju"; - WorkingDirectory = stateDir; + WorkingDirectory = cfg.stateDir; # Load certs from Caddy's storage LoadCredential = lib.optionals cfg.acme.enable [ diff --git a/modules/services/storage-box.nix b/modules/services/storage-box.nix @@ -54,100 +54,30 @@ in { config = lib.mkIf cfg.enable { environment.systemPackages = [pkgs.cifs-utils]; - systemd.tmpfiles.rules = lib.concatLists [ - [ - "d ${cfg.mountPoint} - - - -" - "d ${cfg.mountPoint}/nixaran - - - -" - ] - (lib.optionals config.services.haravara.forgejo.enable [ - "d ${cfg.mountPoint}/nixaran/forgejo 0700 forgejo storage-users -" - "d ${cfg.mountPoint}/nixaran/forgejo/repositories 0700 forgejo storage-users -" - ]) - (lib.optionals config.services.haravara.monitoring.enable [ - "d ${cfg.mountPoint}/nixaran/victoriametrics - - - -" - ]) - (lib.optionals config.services.haravara.syncthing.enable [ - "d ${cfg.mountPoint}/nixaran/syncthing 0750 syncthing storage-users -" - "d ${cfg.mountPoint}/nixaran/syncthing/mobius 0750 syncthing storage-users -" - ]) - (lib.optionals config.services.haravara.seaweedfs.enable [ - "d ${cfg.mountPoint}/seanix 0755 seaweedfs storage-users -" - "d ${cfg.mountPoint}/seanix/master 0755 seaweedfs storage-users -" - "d ${cfg.mountPoint}/seanix/volume 0755 seaweedfs storage-users -" - "d ${cfg.mountPoint}/seanix/filer 0755 seaweedfs storage-users -" - ]) + systemd.tmpfiles.rules = [ + "d ${cfg.mountPoint} - - - -" ]; - fileSystems = - { - "${cfg.mountPoint}" = { - device = "//${cfg.hostname}/${cfg.share}"; - fsType = "cifs"; - options = [ - "credentials=${cfg.passwordFile}" - "iocharset=utf8" - "rw" - "file_mode=0770" - "dir_mode=0770" - "uid=${toString cfg.uid}" - "gid=${toString cfg.gid}" - "noperm" - "vers=3.0" - "mfsymlinks" - "_netdev" - "seal" - "nofail" - "x-systemd.automount" - "noauto" - ]; - }; - } - // lib.optionalAttrs config.services.haravara.forgejo.enable { - "/var/lib/forgejo/repositories" = { - device = "${cfg.mountPoint}/nixaran/forgejo/repositories"; - fsType = "none"; - options = ["bind" "nofail"]; - depends = [cfg.mountPoint]; - }; - } - // lib.optionalAttrs config.services.haravara.monitoring.enable { - "/var/lib/victoriametrics" = { - device = "${cfg.mountPoint}/nixaran/victoriametrics"; - fsType = "none"; - options = ["bind" "nofail"]; - depends = [cfg.mountPoint]; - }; - }; - - systemd.services = let - mountUnit = "${lib.replaceStrings ["-" "/"] ["\\x2d" "-"] (lib.removePrefix "/" cfg.mountPoint)}.mount"; - in - lib.mkMerge [ - (lib.mkIf config.services.haravara.seaweedfs.enable (let - swfsCfg = config.services.haravara.seaweedfs; - in - lib.optionalAttrs (lib.hasPrefix cfg.mountPoint swfsCfg.dataDir) { - seaweedfs-master.after = [mountUnit]; - seaweedfs-master.requires = [mountUnit]; - seaweedfs-volume.after = [mountUnit]; - seaweedfs-volume.requires = [mountUnit]; - seaweedfs-filer.after = [mountUnit]; - seaweedfs-filer.requires = [mountUnit]; - })) - (lib.mkIf config.services.haravara.forgejo.enable { - forgejo.after = ["var-lib-forgejo-repositories.mount"]; - forgejo.requires = ["var-lib-forgejo-repositories.mount"]; - }) - (lib.mkIf config.services.haravara.monitoring.enable { - victoriametrics.after = ["var-lib-victoriametrics.mount"]; - victoriametrics.requires = ["var-lib-victoriametrics.mount"]; - }) - (lib.mkIf config.services.haravara.syncthing.enable { - syncthing.after = [mountUnit]; - syncthing.requires = [mountUnit]; - syncthing-s3-sync.after = [mountUnit]; - syncthing-s3-sync.requires = [mountUnit]; - }) + fileSystems."${cfg.mountPoint}" = { + device = "//${cfg.hostname}/${cfg.share}"; + fsType = "cifs"; + options = [ + "credentials=${cfg.passwordFile}" + "iocharset=utf8" + "rw" + "file_mode=0770" + "dir_mode=0770" + "uid=${toString cfg.uid}" + "gid=${toString cfg.gid}" + "noperm" + "vers=3.0" + "mfsymlinks" + "_netdev" + "seal" + "nofail" + "x-systemd.automount" + "noauto" ]; + }; }; } diff --git a/modules/services/syncthing.nix b/modules/services/syncthing.nix @@ -57,6 +57,33 @@ in { }; config = lib.mkIf cfg.enable { + systemd = { + tmpfiles.rules = [ + "d /data/syncthing 0750 syncthing syncthing -" + "d /data/syncthing/mobius 0750 syncthing syncthing -" + ]; + + services.syncthing-s3-sync = { + description = "Pull s3://mobius into syncthing folder"; + after = ["network-online.target" "syncthing.service"] ++ lib.optionals config.services.haravara.seaweedfs.enable ["seaweedfs-s3.service"]; + wants = ["network-online.target"] ++ lib.optionals config.services.haravara.seaweedfs.enable ["seaweedfs-s3.service"]; + serviceConfig = { + Type = "oneshot"; + User = "syncthing"; + EnvironmentFile = cfg.s3CredentialsFile; + ExecStart = s3SyncScript; + }; + }; + + timers.syncthing-s3-sync = { + wantedBy = ["timers.target"]; + timerConfig = { + OnActiveSec = "5m"; + OnUnitActiveSec = cfg.syncInterval; + }; + }; + }; + services.syncthing = { enable = true; openDefaultPorts = true; @@ -72,26 +99,6 @@ in { }; }; - systemd.services.syncthing-s3-sync = { - description = "Pull s3://mobius into syncthing folder"; - after = ["network-online.target" "syncthing.service"]; - wants = ["network-online.target"]; - serviceConfig = { - Type = "oneshot"; - User = "syncthing"; - EnvironmentFile = cfg.s3CredentialsFile; - ExecStart = s3SyncScript; - }; - }; - - systemd.timers.syncthing-s3-sync = { - wantedBy = ["timers.target"]; - timerConfig = { - OnActiveSec = "5m"; - OnUnitActiveSec = cfg.syncInterval; - }; - }; - services.caddy.virtualHosts."${cfg.domain}".extraConfig = '' ${haravara.mkAuthImport cfg.authLabel} reverse_proxy 127.0.0.1:${toString cfg.guiPort} {