{self, ...}: { flake.overlays.korrosync = final: prev: { korrosync = final.callPackage ./_derivation.nix {}; }; flake.nixosModules.korrosync-overlay = { nixpkgs.overlays = [self.overlays.korrosync]; }; perSystem = {pkgs, ...}: { packages.korrosync = pkgs.callPackage ./_derivation.nix {}; }; flake.nixosModules.korrosync = { config, lib, pkgs, ... }: let cfg = config.services.korrosync; in { options.services.korrosync = { enable = lib.mkEnableOption "Enable KOrrosync service"; enable-service = lib.mkOption { type = lib.types.bool; description = "Enable korrosync service"; example = true; default = true; }; enable-configured-binary = lib.mkEnableOption "Put a korrosync binary into system-packges using the set configuration options."; data-path = lib.mkOption { type = lib.types.path; description = "The path where korrosync saves it's data."; example = "/var/lib/korrosync"; default = "/var/lib/korrosync"; }; user = lib.mkOption { type = lib.types.singleLineStr; description = "The user under with korrosync runs."; example = "korrosync"; default = "korrosync"; }; group = lib.mkOption { type = lib.types.singleLineStr; description = "The group under with korrosync runs."; example = "korrosync"; default = "korrosync"; }; listen-address = lib.mkOption { description = "The listen address of the korrosync server"; type = lib.types.singleLineStr; example = "0.0.0.0"; default = "127.0.0.1"; }; listen-port = lib.mkOption { description = "The listen port of the korrosync server"; type = lib.types.int; example = 3000; default = 3000; }; rate-limit-per-second = lib.mkOption { type = lib.types.int; description = "Rate limit replenishment rate per second"; example = 2; default = 2; }; rate-limit-burst-size = lib.mkOption { type = lib.types.int; description = "Maximum burst size before rate limiting"; example = 5; default = 5; }; }; imports = [ self.nixosModules.korrosync-overlay ]; config = lib.mkIf cfg.enable { # User setup users.users = lib.mkIf (cfg.user == "korrosync") { korrosync = { description = "Korrosync service"; useDefaultShell = true; group = cfg.group; isSystemUser = true; }; }; users.groups = lib.mkIf (cfg.group == "korrosync") { korrosync = {}; }; # Pre-configured binary environment.systemPackages = lib.mkIf cfg.enable-configured-binary [ (let envVars = config.systemd.services.korrosync.environment; in pkgs.writeShellScriptBin "korrosync" '' export KORROSYNC_DB_PATH="${envVars.KORROSYNC_DB_PATH}" export KORROSYNC_SERVER_ADDRESS="${envVars.KORROSYNC_SERVER_ADDRESS}" export KORROSYNC_USE_TLS="${envVars.KORROSYNC_USE_TLS}" export KORROSYNC_RATE_LIMIT_PER_SECOND="${envVars.KORROSYNC_RATE_LIMIT_PER_SECOND}" export KORROSYNC_RATE_LIMIT_BURST_SIZE="${envVars.KORROSYNC_RATE_LIMIT_BURST_SIZE}" exec ${pkgs.korrosync}/bin/korrosync "$@" '') ]; # base service systemd.services.korrosync = { enable = cfg.enable-service; description = "Korrosync - KOReader Sync Server"; after = ["network.target"]; wantedBy = ["multi-user.target"]; environment = { KORROSYNC_DB_PATH = "${cfg.data-path}/db.redb"; KORROSYNC_SERVER_ADDRESS = "${cfg.listen-address}:${toString cfg.listen-port}"; KORROSYNC_USE_TLS = "false"; KORROSYNC_RATE_LIMIT_PER_SECOND = "${toString cfg.rate-limit-per-second}"; KORROSYNC_RATE_LIMIT_BURST_SIZE = "${toString cfg.rate-limit-burst-size}"; }; serviceConfig = { Type = "simple"; User = cfg.user; Group = cfg.group; ExecStart = "${pkgs.korrosync}/bin/korrosync serve"; Restart = "on-failure"; RestartSec = "5s"; NoNewPrivileges = true; PrivateTmp = true; ProtectSystem = "strict"; ProtectHome = true; ReadWritePaths = cfg.data-path; }; }; # Initialize data directory systemd.services.korrosync-init = { description = "Initialize Korrosync databases"; wantedBy = ["korrosync.service"]; before = ["korrosync.service"]; serviceConfig = { Type = "oneshot"; ExecStart = pkgs.writeShellScript "korrosync-init" '' if [ ! -d ${cfg.data-path} ]; then echo "Creating Korrosync base directory \"${cfg.data-path}\"" mkdir ${cfg.data-path} chmod 770 ${cfg.data-path} chown ${cfg.user}:${cfg.group} ${cfg.data-path} fi ''; RemainAfterExit = true; }; }; }; }; }