commit ae597f7a33df0f3eeba4c1ea7476d7c70aefa1d1
parent 85d13dbd04204c7bc3a3dc7305b8267edb09d1d4
Author: mtmn <miro@haravara.org>
Date: Mon, 27 Apr 2026 23:21:39 +0200
chore: fix soju
Diffstat:
2 files changed, 64 insertions(+), 14 deletions(-)
diff --git a/hosts/nixaran/configuration.nix b/hosts/nixaran/configuration.nix
Binary files differ.
diff --git a/modules/services/soju.nix b/modules/services/soju.nix
@@ -8,18 +8,23 @@
stateDir = "/var/lib/soju";
runtimeDir = "/run/soju";
- listen = cfg.listen ++ lib.optional cfg.adminSocket.enable "unix+admin://${runtimeDir}/admin";
- listenCfg = lib.concatMapStringsSep "\n" (l: "listen ${l}") listen;
- tlsCfg = lib.optionalString (
- cfg.tlsCertificate != null
- ) "tls ${cfg.tlsCertificate} ${cfg.tlsCertificateKey}";
- logCfg = lib.optionalString cfg.enableMessageLogging "message-store fs ${stateDir}/logs";
+ # Define the paths for the TLS cert and key.
+ # We prefer systemd credentials which are populated from Caddy's certs.
+ certPath =
+ if cfg.acme.enable
+ then "/run/credentials/soju.service/cert.pem"
+ else cfg.tlsCertificate;
+ keyPath =
+ if cfg.acme.enable
+ then "/run/credentials/soju.service/key.pem"
+ else cfg.tlsCertificateKey;
configFile = pkgs.writeText "soju.conf" ''
- ${listenCfg}
+ listen ${lib.concatStringsSep "\nlisten " cfg.listen}
+ ${lib.optionalString (cfg.adminSocket.enable) "listen unix+admin://${runtimeDir}/admin"}
hostname ${cfg.hostName}
- ${tlsCfg}
- ${logCfg}
+ ${lib.optionalString (certPath != null) "tls ${certPath} ${keyPath}"}
+ ${lib.optionalString cfg.enableMessageLogging "message-store fs ${stateDir}/logs"}
http-origin ${lib.concatStringsSep " " cfg.httpOrigins}
accept-proxy-ip ${lib.concatStringsSep " " cfg.acceptProxyIP}
@@ -29,6 +34,9 @@
sojuctl = pkgs.writeShellScriptBin "sojuctl" ''
exec ${lib.getExe' cfg.package "sojuctl"} --config ${configFile} "$@"
'';
+
+ # Path to Caddy's certificates
+ caddyCertDir = "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${cfg.domain}";
in {
options.services.haravara.soju = {
enable = lib.mkEnableOption "soju IRC bouncer";
@@ -77,6 +85,15 @@ in {
description = "Path to server TLS certificate key.";
};
+ acme = {
+ enable = lib.mkEnableOption "Use Caddy-managed ACME certificates for soju";
+ certificateDomain = lib.mkOption {
+ type = lib.types.str;
+ default = cfg.domain;
+ description = "The domain name of the certificates in Caddy's storage.";
+ };
+ };
+
enableMessageLogging = lib.mkOption {
type = lib.types.bool;
default = true;
@@ -121,21 +138,54 @@ in {
systemd.services.soju = {
description = "soju IRC bouncer";
wantedBy = ["multi-user.target"];
- wants = ["network-online.target"];
- after = ["network-online.target"];
+ wants = ["network-online.target" "caddy.service"];
+ after = ["network-online.target" "caddy.service"];
documentation = ["man:soju(1)"];
serviceConfig = {
DynamicUser = true;
Restart = "always";
- ExecStart = "${lib.getExe' cfg.package "soju"} -config ${configFile}";
- ExecReload = "${lib.getExe' pkgs.coreutils "kill"} -HUP $MAINPID";
+ ExecStart = "${cfg.package}/bin/soju -config ${configFile}";
+ ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
StateDirectory = "soju";
RuntimeDirectory = "soju";
WorkingDirectory = stateDir;
+
+ # Load certs from Caddy's storage
+ LoadCredential = lib.optionals cfg.acme.enable [
+ "cert.pem:${caddyCertDir}/${cfg.domain}.crt"
+ "key.pem:${caddyCertDir}/${cfg.domain}.key"
+ ];
+
+ SupplementaryGroups = lib.optional cfg.acme.enable "caddy";
+
+ # Hardening
+ CapabilityBoundingSet = "";
+ DeviceAllow = "";
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ NoNewPrivileges = true;
+ PrivateDevices = true;
+ PrivateMounts = true;
+ PrivateTmp = true;
+ ProtectClock = true;
+ ProtectControlGroups = true;
+ ProtectHome = true;
+ ProtectHostname = true;
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ ProtectProc = "invisible";
+ ProtectSystem = "strict";
+ RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"];
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ SystemCallArchitectures = "native";
+ SystemCallFilter = ["@system-service" "~@privileged"];
};
};
- services.caddy.virtualHosts."${cfg.domain}".extraConfig = ''
+ services.caddy.virtualHosts."${cfg.domain}".extraConfig = lib.mkOrder 500 ''
${lib.optionalString (cfg.authLabel != null) "import ${
if cfg.authLabel == "default"
then "auth"