atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
e2727527c1512040a2e2b3557386595e2af08ff5
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git

Blame: nix/module.nix

727d064fae38atagen2026-10-12 13:18 UTC1
self:
727d064fae38atagen2026-10-12 13:18 UTC2
{
727d064fae38atagen2026-10-12 13:18 UTC3
  config,
727d064fae38atagen2026-10-12 13:18 UTC4
  lib,
727d064fae38atagen2026-10-12 13:18 UTC5
  pkgs,
727d064fae38atagen2026-10-12 13:18 UTC6
  ...
727d064fae38atagen2026-10-12 13:18 UTC7
}:
727d064fae38atagen2026-10-12 13:18 UTC8
let
727d064fae38atagen2026-10-12 13:18 UTC9
  cfg = config.services.jelqd;
727d064fae38atagen2026-10-12 13:18 UTC10
  host = if lib.hasInfix ":" cfg.address then "[${cfg.address}]" else cfg.address;
727d064fae38atagen2026-10-12 13:18 UTC11
in
727d064fae38atagen2026-10-12 13:18 UTC12
{
727d064fae38atagen2026-10-12 13:18 UTC13
  options.services.jelqd = {
727d064fae38atagen2026-10-12 13:18 UTC14
    enable = lib.mkEnableOption "jelqd, a roguelike played entirely over HTTP";
727d064fae38atagen2026-10-12 13:18 UTC15
727d064fae38atagen2026-10-12 13:18 UTC16
    package = lib.mkOption {
727d064fae38atagen2026-10-12 13:18 UTC17
      type = lib.types.package;
727d064fae38atagen2026-10-12 13:18 UTC18
      default = self.packages.${pkgs.stdenv.hostPlatform.system}.default;
727d064fae38atagen2026-10-12 13:18 UTC19
      defaultText = lib.literalExpression "jelq.packages.\${pkgs.stdenv.hostPlatform.system}.default";
727d064fae38atagen2026-10-12 13:18 UTC20
      description = "The jelqd package to run.";
727d064fae38atagen2026-10-12 13:18 UTC21
    };
727d064fae38atagen2026-10-12 13:18 UTC22
727d064fae38atagen2026-10-12 13:18 UTC23
    address = lib.mkOption {
727d064fae38atagen2026-10-12 13:18 UTC24
      type = lib.types.str;
727d064fae38atagen2026-10-12 13:18 UTC25
      default = "127.0.0.1";
727d064fae38atagen2026-10-12 13:18 UTC26
      description = "Address to listen on.";
727d064fae38atagen2026-10-12 13:18 UTC27
    };
727d064fae38atagen2026-10-12 13:18 UTC28
727d064fae38atagen2026-10-12 13:18 UTC29
    port = lib.mkOption {
727d064fae38atagen2026-10-12 13:18 UTC30
      type = lib.types.port;
727d064fae38atagen2026-10-12 13:18 UTC31
      default = 6969;
727d064fae38atagen2026-10-12 13:18 UTC32
      description = "Port to listen on.";
727d064fae38atagen2026-10-12 13:18 UTC33
    };
727d064fae38atagen2026-10-12 13:18 UTC34
727d064fae38atagen2026-10-12 13:18 UTC35
    openFirewall = lib.mkOption {
727d064fae38atagen2026-10-12 13:18 UTC36
      type = lib.types.bool;
727d064fae38atagen2026-10-12 13:18 UTC37
      default = false;
727d064fae38atagen2026-10-12 13:18 UTC38
      description = "Open the listening port in the firewall.";
727d064fae38atagen2026-10-12 13:18 UTC39
    };
727d064fae38atagen2026-10-12 13:18 UTC40
727d064fae38atagen2026-10-12 13:18 UTC41
    dataDir = lib.mkOption {
727d064fae38atagen2026-10-12 13:18 UTC42
      type = lib.types.path;
727d064fae38atagen2026-10-12 13:18 UTC43
      default = "/var/lib/jelqd";
727d064fae38atagen2026-10-12 13:18 UTC44
      description = "Directory holding the sqlite database of finished runs.";
727d064fae38atagen2026-10-12 13:18 UTC45
    };
727d064fae38atagen2026-10-12 13:18 UTC46
727d064fae38atagen2026-10-12 13:18 UTC47
    oracle = lib.mkOption {
727d064fae38atagen2026-10-12 13:18 UTC48
      type = lib.types.enum [
727d064fae38atagen2026-10-12 13:18 UTC49
        "rng"
727d064fae38atagen2026-10-12 13:18 UTC50
        "clm"
727d064fae38atagen2026-10-12 13:18 UTC51
      ];
727d064fae38atagen2026-10-12 13:18 UTC52
      default = "rng";
727d064fae38atagen2026-10-12 13:18 UTC53
      description = "Where the oracle gets its answers.";
727d064fae38atagen2026-10-12 13:18 UTC54
    };
727d064fae38atagen2026-10-12 13:18 UTC55
727d064fae38atagen2026-10-12 13:18 UTC56
    clmUrl = lib.mkOption {
727d064fae38atagen2026-10-12 13:18 UTC57
      type = lib.types.str;
727d064fae38atagen2026-10-12 13:18 UTC58
      default = "http://127.0.0.1:8700/v1/systemone";
727d064fae38atagen2026-10-12 13:18 UTC59
      description = "CLM endpoint used when `oracle` is `clm`.";
727d064fae38atagen2026-10-12 13:18 UTC60
    };
727d064fae38atagen2026-10-12 13:18 UTC61
727d064fae38atagen2026-10-12 13:18 UTC62
    environmentFile = lib.mkOption {
727d064fae38atagen2026-10-12 13:18 UTC63
      type = lib.types.nullOr lib.types.path;
727d064fae38atagen2026-10-12 13:18 UTC64
      default = null;
727d064fae38atagen2026-10-12 13:18 UTC65
      example = "/run/secrets/jelqd.env";
727d064fae38atagen2026-10-12 13:18 UTC66
      description = ''
727d064fae38atagen2026-10-12 13:18 UTC67
        Environment file passed to the service, for setting `JELQD_SECRET`.
727d064fae38atagen2026-10-12 13:18 UTC68
        Without it the run-signing secret is regenerated on every restart
727d064fae38atagen2026-10-12 13:18 UTC69
        and live runs stop being accepted.
727d064fae38atagen2026-10-12 13:18 UTC70
      '';
727d064fae38atagen2026-10-12 13:18 UTC71
    };
727d064fae38atagen2026-10-12 13:18 UTC72
  };
727d064fae38atagen2026-10-12 13:18 UTC73
727d064fae38atagen2026-10-12 13:18 UTC74
  config = lib.mkIf cfg.enable {
727d064fae38atagen2026-10-12 13:18 UTC75
    users.users.jelqd = {
727d064fae38atagen2026-10-12 13:18 UTC76
      isSystemUser = true;
727d064fae38atagen2026-10-12 13:18 UTC77
      group = "jelqd";
727d064fae38atagen2026-10-12 13:18 UTC78
      home = cfg.dataDir;
727d064fae38atagen2026-10-12 13:18 UTC79
    };
727d064fae38atagen2026-10-12 13:18 UTC80
    users.groups.jelqd = { };
727d064fae38atagen2026-10-12 13:18 UTC81
727d064fae38atagen2026-10-12 13:18 UTC82
    systemd.tmpfiles.settings.jelqd = lib.mkIf (cfg.dataDir != "/var/lib/jelqd") {
727d064fae38atagen2026-10-12 13:18 UTC83
      ${cfg.dataDir}.d = {
727d064fae38atagen2026-10-12 13:18 UTC84
        user = "jelqd";
727d064fae38atagen2026-10-12 13:18 UTC85
        group = "jelqd";
727d064fae38atagen2026-10-12 13:18 UTC86
        mode = "0750";
727d064fae38atagen2026-10-12 13:18 UTC87
      };
727d064fae38atagen2026-10-12 13:18 UTC88
    };
727d064fae38atagen2026-10-12 13:18 UTC89
727d064fae38atagen2026-10-12 13:18 UTC90
    systemd.services.jelqd = {
727d064fae38atagen2026-10-12 13:18 UTC91
      description = "jelqd roguelike server";
727d064fae38atagen2026-10-12 13:18 UTC92
      wantedBy = [ "multi-user.target" ];
727d064fae38atagen2026-10-12 13:18 UTC93
      after = [ "network.target" ];
727d064fae38atagen2026-10-12 13:18 UTC94
      environment = {
727d064fae38atagen2026-10-12 13:18 UTC95
        JELQD_ADDR = "${host}:${toString cfg.port}";
727d064fae38atagen2026-10-12 13:18 UTC96
        JELQD_DB = "${cfg.dataDir}/jelqd.sqlite";
727d064fae38atagen2026-10-12 13:18 UTC97
        JELQD_ORACLE = cfg.oracle;
727d064fae38atagen2026-10-12 13:18 UTC98
      }
727d064fae38atagen2026-10-12 13:18 UTC99
      // lib.optionalAttrs (cfg.oracle == "clm") { JELQD_CLM_URL = cfg.clmUrl; };
727d064fae38atagen2026-10-12 13:18 UTC100
      serviceConfig = {
727d064fae38atagen2026-10-12 13:18 UTC101
        ExecStart = lib.getExe cfg.package;
727d064fae38atagen2026-10-12 13:18 UTC102
        User = "jelqd";
727d064fae38atagen2026-10-12 13:18 UTC103
        Group = "jelqd";
727d064fae38atagen2026-10-12 13:18 UTC104
        Restart = "on-failure";
727d064fae38atagen2026-10-12 13:18 UTC105
        EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
727d064fae38atagen2026-10-12 13:18 UTC106
        StateDirectory = lib.mkIf (cfg.dataDir == "/var/lib/jelqd") "jelqd";
727d064fae38atagen2026-10-12 13:18 UTC107
        StateDirectoryMode = "0750";
727d064fae38atagen2026-10-12 13:18 UTC108
        ReadWritePaths = [ cfg.dataDir ];
727d064fae38atagen2026-10-12 13:18 UTC109
        CapabilityBoundingSet = "";
727d064fae38atagen2026-10-12 13:18 UTC110
        LockPersonality = true;
727d064fae38atagen2026-10-12 13:18 UTC111
        MemoryDenyWriteExecute = true;
727d064fae38atagen2026-10-12 13:18 UTC112
        NoNewPrivileges = true;
727d064fae38atagen2026-10-12 13:18 UTC113
        PrivateDevices = true;
727d064fae38atagen2026-10-12 13:18 UTC114
        PrivateTmp = true;
727d064fae38atagen2026-10-12 13:18 UTC115
        ProtectClock = true;
727d064fae38atagen2026-10-12 13:18 UTC116
        ProtectControlGroups = true;
727d064fae38atagen2026-10-12 13:18 UTC117
        ProtectHome = true;
727d064fae38atagen2026-10-12 13:18 UTC118
        ProtectHostname = true;
727d064fae38atagen2026-10-12 13:18 UTC119
        ProtectKernelLogs = true;
727d064fae38atagen2026-10-12 13:18 UTC120
        ProtectKernelModules = true;
727d064fae38atagen2026-10-12 13:18 UTC121
        ProtectKernelTunables = true;
727d064fae38atagen2026-10-12 13:18 UTC122
        ProtectProc = "invisible";
727d064fae38atagen2026-10-12 13:18 UTC123
        ProtectSystem = "strict";
727d064fae38atagen2026-10-12 13:18 UTC124
        RestrictAddressFamilies = [
727d064fae38atagen2026-10-12 13:18 UTC125
          "AF_INET"
727d064fae38atagen2026-10-12 13:18 UTC126
          "AF_INET6"
727d064fae38atagen2026-10-12 13:18 UTC127
        ];
727d064fae38atagen2026-10-12 13:18 UTC128
        RestrictNamespaces = true;
727d064fae38atagen2026-10-12 13:18 UTC129
        RestrictRealtime = true;
727d064fae38atagen2026-10-12 13:18 UTC130
        RestrictSUIDSGID = true;
727d064fae38atagen2026-10-12 13:18 UTC131
        SystemCallArchitectures = "native";
727d064fae38atagen2026-10-12 13:18 UTC132
        SystemCallFilter = [
727d064fae38atagen2026-10-12 13:18 UTC133
          "@system-service"
727d064fae38atagen2026-10-12 13:18 UTC134
          "~@privileged"
727d064fae38atagen2026-10-12 13:18 UTC135
        ];
727d064fae38atagen2026-10-12 13:18 UTC136
        UMask = "0077";
727d064fae38atagen2026-10-12 13:18 UTC137
      };
727d064fae38atagen2026-10-12 13:18 UTC138
    };
727d064fae38atagen2026-10-12 13:18 UTC139
727d064fae38atagen2026-10-12 13:18 UTC140
    networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ];
727d064fae38atagen2026-10-12 13:18 UTC141
  };
727d064fae38atagen2026-10-12 13:18 UTC142
}