at 24.11-pre 4.0 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.soju; 7 stateDir = "/var/lib/soju"; 8 runtimeDir = "/run/soju"; 9 listen = cfg.listen 10 ++ optional cfg.adminSocket.enable "unix+admin://${runtimeDir}/admin"; 11 listenCfg = concatMapStringsSep "\n" (l: "listen ${l}") listen; 12 tlsCfg = optionalString (cfg.tlsCertificate != null) 13 "tls ${cfg.tlsCertificate} ${cfg.tlsCertificateKey}"; 14 logCfg = optionalString cfg.enableMessageLogging 15 "log fs ${stateDir}/logs"; 16 17 configFile = pkgs.writeText "soju.conf" '' 18 ${listenCfg} 19 hostname ${cfg.hostName} 20 ${tlsCfg} 21 db sqlite3 ${stateDir}/soju.db 22 ${logCfg} 23 http-origin ${concatStringsSep " " cfg.httpOrigins} 24 accept-proxy-ip ${concatStringsSep " " cfg.acceptProxyIP} 25 26 ${cfg.extraConfig} 27 ''; 28 29 sojuctl = pkgs.writeShellScriptBin "sojuctl" '' 30 exec ${cfg.package}/bin/sojuctl --config ${configFile} "$@" 31 ''; 32in 33{ 34 ###### interface 35 36 options.services.soju = { 37 enable = mkEnableOption "soju"; 38 39 package = mkPackageOption pkgs "soju" { }; 40 41 listen = mkOption { 42 type = types.listOf types.str; 43 default = [ ":6697" ]; 44 description = '' 45 Where soju should listen for incoming connections. See the 46 `listen` directive in 47 {manpage}`soju(1)`. 48 ''; 49 }; 50 51 hostName = mkOption { 52 type = types.str; 53 default = config.networking.hostName; 54 defaultText = literalExpression "config.networking.hostName"; 55 description = "Server hostname."; 56 }; 57 58 tlsCertificate = mkOption { 59 type = types.nullOr types.path; 60 default = null; 61 example = "/var/host.cert"; 62 description = "Path to server TLS certificate."; 63 }; 64 65 tlsCertificateKey = mkOption { 66 type = types.nullOr types.path; 67 default = null; 68 example = "/var/host.key"; 69 description = "Path to server TLS certificate key."; 70 }; 71 72 enableMessageLogging = mkOption { 73 type = types.bool; 74 default = true; 75 description = "Whether to enable message logging."; 76 }; 77 78 adminSocket.enable = mkOption { 79 type = types.bool; 80 default = true; 81 description = '' 82 Listen for admin connections from sojuctl at /run/soju/admin. 83 ''; 84 }; 85 86 httpOrigins = mkOption { 87 type = types.listOf types.str; 88 default = []; 89 description = '' 90 List of allowed HTTP origins for WebSocket listeners. The parameters are 91 interpreted as shell patterns, see 92 {manpage}`glob(7)`. 93 ''; 94 }; 95 96 acceptProxyIP = mkOption { 97 type = types.listOf types.str; 98 default = []; 99 description = '' 100 Allow the specified IPs to act as a proxy. Proxys have the ability to 101 overwrite the remote and local connection addresses (via the X-Forwarded-\* 102 HTTP header fields). The special name "localhost" accepts the loopback 103 addresses 127.0.0.0/8 and ::1/128. By default, all IPs are rejected. 104 ''; 105 }; 106 107 extraConfig = mkOption { 108 type = types.lines; 109 default = ""; 110 description = "Lines added verbatim to the configuration file."; 111 }; 112 }; 113 114 ###### implementation 115 116 config = mkIf cfg.enable { 117 assertions = [ 118 { 119 assertion = (cfg.tlsCertificate != null) == (cfg.tlsCertificateKey != null); 120 message = '' 121 services.soju.tlsCertificate and services.soju.tlsCertificateKey 122 must both be specified to enable TLS. 123 ''; 124 } 125 ]; 126 127 environment.systemPackages = [ sojuctl ]; 128 129 systemd.services.soju = { 130 description = "soju IRC bouncer"; 131 wantedBy = [ "multi-user.target" ]; 132 wants = [ "network-online.target" ]; 133 after = [ "network-online.target" ]; 134 serviceConfig = { 135 DynamicUser = true; 136 Restart = "always"; 137 ExecStart = "${cfg.package}/bin/soju -config ${configFile}"; 138 StateDirectory = "soju"; 139 RuntimeDirectory = "soju"; 140 }; 141 }; 142 }; 143 144 meta.maintainers = with maintainers; [ malte-v ]; 145}