{ lib, pkgs, config, ... }: let inherit (lib) mkEnableOption mkPackageOption mkOption types; cfg = config.services.c2fmzq-server; argsFormat = { type = with lib.types; attrsOf (nullOr (oneOf [ bool int str ])); generate = lib.cli.toGNUCommandLineShell { mkBool = k: v: [ "--${k}=${if v then "true" else "false"}" ]; }; }; in { options.services.c2fmzq-server = { enable = mkEnableOption "c2fmzq-server"; bindIP = mkOption { type = types.str; default = "127.0.0.1"; description = "The local address to use."; }; port = mkOption { type = types.port; default = 8080; description = "The local port to use."; }; passphraseFile = mkOption { type = types.str; example = "/run/secrets/c2fmzq/pwfile"; description = "Path to file containing the database passphrase"; }; package = mkPackageOption pkgs "c2fmzq" { }; settings = mkOption { type = types.submodule { freeformType = argsFormat.type; options = { address = mkOption { internal = true; type = types.str; default = "${cfg.bindIP}:${toString cfg.port}"; }; database = mkOption { type = types.str; default = "%S/c2fmzq-server/data"; description = "Path of the database"; }; verbose = mkOption { type = types.ints.between 1 3; default = 2; description = "The level of logging verbosity: 1:Error 2:Info 3:Debug"; }; }; }; description = '' Configuration for c2FmZQ-server passed as CLI arguments. Run {command}`c2FmZQ-server help` for supported values. ''; example = { verbose = 3; allow-new-accounts = true; auto-approve-new-accounts = true; encrypt-metadata = true; enable-webapp = true; }; }; }; config = lib.mkIf cfg.enable { systemd.services.c2fmzq-server = { description = "c2FmZQ-server"; documentation = [ "https://github.com/c2FmZQ/c2FmZQ/blob/main/README.md" ]; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network.target" "network-online.target" ]; serviceConfig = { ExecStart = "${lib.getExe cfg.package} ${argsFormat.generate cfg.settings}"; AmbientCapabilities = ""; CapabilityBoundingSet = ""; DynamicUser = true; Environment = "C2FMZQ_PASSPHRASE_FILE=%d/passphrase-file"; IPAccounting = true; IPAddressAllow = cfg.bindIP; IPAddressDeny = "any"; LoadCredential = "passphrase-file:${cfg.passphraseFile}"; LockPersonality = true; MemoryDenyWriteExecute = true; NoNewPrivileges = true; PrivateDevices = true; PrivateIPC = true; PrivateTmp = true; PrivateUsers = true; ProtectClock = true; ProtectControlGroups = true; ProtectHome = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectProc = "invisible"; ProtectSystem = "strict"; RemoveIPC = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; SocketBindAllow = cfg.port; SocketBindDeny = "any"; StateDirectory = "c2fmzq-server"; SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" "~@privileged @obsolete" ]; }; }; }; meta = { doc = ./c2fmzq-server.md; maintainers = with lib.maintainers; [ hmenke ]; }; }