From 96659af197072c921c6063021788ad5d32fb6b3f Mon Sep 17 00:00:00 2001 From: Tom Hubrecht Date: Tue, 2 Apr 2024 12:16:53 +0200 Subject: nixos/crabfit: init --- nixos/modules/module-list.nix | 1 + nixos/modules/services/web-apps/crabfit.nix | 171 ++++++++++++++++++++++++++++ nixos/tests/all-tests.nix | 1 + nixos/tests/crabfit.nix | 33 ++++++ 4 files changed, 206 insertions(+) create mode 100644 nixos/modules/services/web-apps/crabfit.nix create mode 100644 nixos/tests/crabfit.nix (limited to 'nixos') 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/") + ''; + } +) -- cgit 1.4.1