about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorTom Hubrecht <tom@hubrecht.ovh>2024-04-02 12:16:53 +0200
committerTom Hubrecht <tom@hubrecht.ovh>2024-04-13 18:51:02 +0200
commit96659af197072c921c6063021788ad5d32fb6b3f (patch)
treea3dc88632627d6add6a1279295cef3498c45cb6b /nixos
parent600fcb2070fc30ff978dcf6fb57d81c6212b4aac (diff)
nixos/crabfit: init
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/services/web-apps/crabfit.nix171
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/crabfit.nix33
4 files changed, 206 insertions, 0 deletions
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 914a31dfe1b3a..ae0c1682b35e0 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -1309,6 +1309,7 @@
   ./services/web-apps/cloudlog.nix
   ./services/web-apps/code-server.nix
   ./services/web-apps/convos.nix
+  ./services/web-apps/crabfit.nix
   ./services/web-apps/davis.nix
   ./services/web-apps/dex.nix
   ./services/web-apps/discourse.nix
diff --git a/nixos/modules/services/web-apps/crabfit.nix b/nixos/modules/services/web-apps/crabfit.nix
new file mode 100644
index 0000000000000..d58027a6965df
--- /dev/null
+++ b/nixos/modules/services/web-apps/crabfit.nix
@@ -0,0 +1,171 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+
+let
+  inherit (lib)
+    literalExpression
+    mkEnableOption
+    mkIf
+    mkOption
+    mkPackageOption
+    ;
+
+  inherit (lib.types)
+    attrsOf
+    package
+    port
+    str
+    ;
+
+  cfg = config.services.crabfit;
+in
+
+{
+  options.services.crabfit = {
+    enable = mkEnableOption "Crab Fit, a meeting scheduler based on peoples' availability";
+
+    frontend = {
+      package = mkPackageOption pkgs "crabfit-frontend" { };
+
+      finalDrv = mkOption {
+        readOnly = true;
+        type = package;
+        default = cfg.frontend.package.override {
+          api_url = "https://${cfg.api.host}";
+          frontend_url = cfg.frontend.host;
+        };
+
+        defaultText = literalExpression ''
+          cfg.package.override {
+            api_url = "https://''${cfg.api.host}";
+            frontend_url = cfg.frontend.host;
+          };
+        '';
+
+        description = ''
+          The patched frontend, using the correct urls for the API and frontend.
+        '';
+      };
+
+      environment = mkOption {
+        type = attrsOf str;
+        default = { };
+        description = ''
+          Environment variables for the crabfit frontend.
+        '';
+      };
+
+      host = mkOption {
+        type = str;
+        description = ''
+          The hostname of the frontend.
+        '';
+      };
+
+      port = mkOption {
+        type = port;
+        default = 3001;
+        description = ''
+          The internal listening port of the frontend.
+        '';
+      };
+    };
+
+    api = {
+      package = mkPackageOption pkgs "crabfit-api" { };
+
+      environment = mkOption {
+        type = attrsOf str;
+        default = { };
+        description = ''
+          Environment variables for the crabfit API.
+        '';
+      };
+
+      host = mkOption {
+        type = str;
+        description = ''
+          The hostname of the API.
+        '';
+      };
+
+      port = mkOption {
+        type = port;
+        default = 3000;
+        description = ''
+          The internal listening port of the API.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services = {
+      crabfit-api = {
+        description = "The API for Crab Fit.";
+
+        wantedBy = [ "multi-user.target" ];
+        after = [ "postgresql.service" ];
+
+        serviceConfig = {
+          # TODO: harden
+          ExecStart = lib.getExe cfg.api.package;
+          User = "crabfit";
+        };
+
+        environment = {
+          API_LISTEN = "127.0.0.1:${builtins.toString cfg.api.port}";
+          DATABASE_URL = "postgres:///crabfit?host=/run/postgresql";
+          FRONTEND_URL = "https://${cfg.frontend.host}";
+        } // cfg.api.environment;
+      };
+
+      crabfit-frontend = {
+        description = "The frontend for Crab Fit.";
+
+        wantedBy = [ "multi-user.target" ];
+
+        serviceConfig = {
+          # TODO: harden
+          CacheDirectory = "crabfit";
+          DynamicUser = true;
+          ExecStart = "${lib.getExe pkgs.nodejs} standalone/server.js";
+          WorkingDirectory = cfg.frontend.finalDrv;
+        };
+
+        environment = {
+          NEXT_PUBLIC_API_URL = "https://${cfg.api.host}";
+          PORT = builtins.toString cfg.frontend.port;
+        } // cfg.frontend.environment;
+      };
+    };
+
+    users = {
+      groups.crabfit = { };
+
+      users.crabfit = {
+        group = "crabfit";
+        isSystemUser = true;
+      };
+    };
+
+    services = {
+      postgresql = {
+        enable = true;
+
+        ensureDatabases = [ "crabfit" ];
+
+        ensureUsers = [
+          {
+            name = "crabfit";
+            ensureDBOwnership = true;
+          }
+        ];
+      };
+    };
+  };
+}
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 80edf70ee11c7..385d5a9f1fb95 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -226,6 +226,7 @@ in {
   corerad = handleTest ./corerad.nix {};
   coturn = handleTest ./coturn.nix {};
   couchdb = handleTest ./couchdb.nix {};
+  crabfit = handleTest ./crabfit.nix {};
   cri-o = handleTestOn ["aarch64-linux" "x86_64-linux"] ./cri-o.nix {};
   cups-pdf = handleTest ./cups-pdf.nix {};
   curl-impersonate = handleTest ./curl-impersonate.nix {};
diff --git a/nixos/tests/crabfit.nix b/nixos/tests/crabfit.nix
new file mode 100644
index 0000000000000..0cd0741f6fa4b
--- /dev/null
+++ b/nixos/tests/crabfit.nix
@@ -0,0 +1,33 @@
+import ./make-test-python.nix (
+  { lib, pkgs, ... }:
+
+  {
+    name = "crabfit";
+
+    meta.maintainers = with lib.maintainers; [ thubrecht ];
+
+    nodes = {
+      machine =
+        { pkgs, ... }:
+        {
+          services.crabfit = {
+            enable = true;
+
+            frontend.host = "http://127.0.0.1:3001";
+            api.host = "127.0.0.1:3000";
+          };
+        };
+    };
+
+    # TODO: Add a reverse proxy and a dns entry for testing
+    testScript = ''
+      machine.wait_for_unit("crabfit-api")
+      machine.wait_for_unit("crabfit-frontend")
+
+      machine.wait_for_open_port(3000)
+      machine.wait_for_open_port(3001)
+
+      machine.succeed("curl -f http://localhost:3001/")
+    '';
+  }
+)