diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 97e0ca92469f1..fc75f1f07e6db 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -81,6 +81,8 @@ - [duckdns](https://www.duckdns.org), free dynamic DNS. Available with [services.duckdns](options.html#opt-services.duckdns.enable) +- [gokapi](https://github.com/Forceu/Gokapi), Lightweight selfhosted Firefox Send alternative without public upload. AWS S3 supported. Available with [services.gokapi](options.html#opt-services.gokapi.enable) + - [nostr-rs-relay](https://git.sr.ht/~gheartsfield/nostr-rs-relay/), This is a nostr relay, written in Rust. Available as [services.nostr-rs-relay](options.html#opt-services.nostr-rs-relay.enable). - [Actual Budget](https://actualbudget.org/), a local-first personal finance app. Available as [services.actual](#opt-services.actual.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index b5b6fd8c0e2fe..af837bf3b01ef 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1089,6 +1089,7 @@ ./services/networking/go-neb.nix ./services/networking/go-shadowsocks2.nix ./services/networking/gobgpd.nix + ./services/networking/gokapi.nix ./services/networking/gvpe.nix ./services/networking/hans.nix ./services/networking/harmonia.nix diff --git a/nixos/modules/services/networking/gokapi.nix b/nixos/modules/services/networking/gokapi.nix new file mode 100644 index 0000000000000..823b54593cdcc --- /dev/null +++ b/nixos/modules/services/networking/gokapi.nix @@ -0,0 +1,136 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.services.gokapi; + settingsFormat = pkgs.formats.json { }; + userSettingsFile = settingsFormat.generate "generated-config.json" cfg.settings; +in +{ + options.services.gokapi = { + enable = lib.mkEnableOption "Lightweight selfhosted Firefox Send alternative without public upload. AWS S3 supported."; + + mutableSettings = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Allow changes to the program config made by the program to persist between restarts. If disabled all required values must be set using nix, and all changes to config format over application updates must be resolved by user."; + }; + + package = lib.mkPackageOption pkgs "gokapi" { }; + + environment = lib.mkOption { + type = lib.types.submodule { + freeformType = lib.types.attrsOf (lib.types.either lib.types.str lib.types.int); + options = { + GOKAPI_CONFIG_DIR = lib.mkOption { + type = lib.types.str; + default = "%S/gokapi/config"; + description = "Sets the directory for the config file."; + }; + GOKAPI_CONFIG_FILE = lib.mkOption { + type = lib.types.str; + default = "config.json"; + description = "Sets the filename for the config file."; + }; + GOKAPI_DATA_DIR = lib.mkOption { + type = lib.types.str; + default = "%S/gokapi/data"; + description = "Sets the directory for the data."; + }; + GOKAPI_PORT = lib.mkOption { + type = lib.types.str; + default = "53842"; + description = "Sets the port of the service."; + }; + }; + }; + default = { }; + description = "Environment variables to be set for the gokapi service. Can use systemd specifiers. For full list see https://gokapi.readthedocs.io/en/latest/advanced.html#environment-variables"; + }; + settings = lib.mkOption { + type = lib.types.submodule { + freeformType = settingsFormat.type; + options = { }; + }; + default = { }; + description = '' + Configuration settings for the generated config json file. + See https://gokapi.readthedocs.io/en/latest/advanced.html#config-json for more information + ''; + }; + settingsFile = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = '' + Path to config file to parse and append to settings. Largely useful for loading secrets from a file not in the nix store. Can use systemd specifiers. See https://gokapi.readthedocs.io/en/latest/advanced.html#config-json for more information + ''; + }; + + }; + + config = lib.mkIf cfg.enable { + systemd.services.gokapi = { + wantedBy = [ "default.target" ]; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + inherit (cfg) environment; + unitConfig = { + Description = "gokapi service"; + }; + serviceConfig = { + ExecStartPre = + let + updateScript = lib.getExe ( + pkgs.writeShellApplication { + name = "merge-config"; + runtimeInputs = with pkgs; [ jq ]; + text = '' + echo "Running merge-config" + mutableSettings="$1" + statefulSettingsFile="$2" + settingsFile="$3" + if [ "$mutableSettings" == "true" ]; + then + if [ -f "$statefulSettingsFile" ]; then + echo "Updating stateful config file" + merged="$(jq -s '.[0] * .[1]' "$statefulSettingsFile" ${userSettingsFile})" + echo "$merged" > "$statefulSettingsFile" + fi + else + echo "Overwriting stateful config file" + mkdir -p "$(dirname "$statefulSettingsFile")" + cat ${userSettingsFile} > "$statefulSettingsFile" + fi + if [ "$settingsFile" != "null" ]; then + echo "Merging settings file into current stateful settings file" + merged="$(jq -s '.[0] * .[1]' "$statefulSettingsFile" "$settingsFile")" + echo "$merged" > "$statefulSettingsFile" + fi + ''; + } + ); + in + lib.strings.concatStringsSep " " [ + "${updateScript}" + (lib.boolToString cfg.mutableSettings) + "${cfg.environment.GOKAPI_CONFIG_DIR}/${cfg.environment.GOKAPI_CONFIG_FILE}" + (if (cfg.settingsFile == null) then "null" else cfg.settingsFile) + ]; + ExecStart = lib.getExe cfg.package; + RestartSec = 30; + DynamicUser = true; + PrivateTmp = true; + StateDirectory = "gokapi"; + CacheDirectory = "gokapi"; + Restart = "on-failure"; + }; + }; + }; + meta.maintainers = with lib.maintainers; [ + delliott + ]; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 56653b64e5c7b..8cccb6196bcea 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -397,6 +397,7 @@ in { gobgpd = handleTest ./gobgpd.nix {}; gocd-agent = handleTest ./gocd-agent.nix {}; gocd-server = handleTest ./gocd-server.nix {}; + gokapi = handleTest ./gokapi.nix {}; gollum = handleTest ./gollum.nix {}; gonic = handleTest ./gonic.nix {}; google-oslogin = handleTest ./google-oslogin {}; diff --git a/nixos/tests/gokapi.nix b/nixos/tests/gokapi.nix new file mode 100644 index 0000000000000..e6800ad6f34ca --- /dev/null +++ b/nixos/tests/gokapi.nix @@ -0,0 +1,26 @@ +import ./make-test-python.nix ( + { pkgs, lib, ... }: + let + port = 6000; + in + { + name = "gokapi"; + + meta.maintainers = with lib.maintainers; [ delliott ]; + + nodes.machine = + { pkgs, ... }: + { + services.gokapi = { + enable = true; + environment.GOKAPI_PORT = toString port; + }; + }; + + testScript = '' + machine.wait_for_unit("gokapi.service") + machine.wait_for_open_port(${toString port}) + machine.succeed("curl --fail http://localhost:${toString port}/") + ''; + } +) diff --git a/pkgs/by-name/go/gokapi/package.nix b/pkgs/by-name/go/gokapi/package.nix new file mode 100644 index 0000000000000..05e904344edb1 --- /dev/null +++ b/pkgs/by-name/go/gokapi/package.nix @@ -0,0 +1,72 @@ +{ + lib, + buildGoModule, + fetchFromGitHub, + nixosTests, + nix-update-script, + versionCheckHook, +}: + +buildGoModule rec { + pname = "gokapi"; + version = "1.9.6"; + + src = fetchFromGitHub { + owner = "Forceu"; + repo = "Gokapi"; + tag = "v${version}"; + hash = "sha256-RDEvKh3tUun7wt1nhtCim95wEN9V9RlztZ9zcw9nS1o="; + }; + + vendorHash = "sha256-9GRAlgng+yq7q0VQz374jIOCjeDIIDD631BglM/FsQQ="; + + preBuild = '' + # This is the go generate is ran in the upstream builder, but we have to run the components seperately for things to work. + # go generate ./... + # Hopefully at some point this is no longer necessary + + # Enter package dir, to match behaviour of go:generate + cd ./cmd/gokapi/ + go run "../../build/go-generate/updateVersionNumbers.go" + # Ran by go-generate, but breaks build in nix + # As it tries to download "golang.org/x/exp/slices" + # go run "../../build/go-generate/updateProtectedUrls.go" + go run "../../build/go-generate/buildWasm.go" + # Must specify go root to import wasm_exec.js + GOROOT="$(go env GOROOT)" go run "../../build/go-generate/copyStaticFiles.go" + # Return to toplevel before build + cd ../.. + ''; + + subPackages = [ + "cmd/gokapi" + ]; + + ldflags = [ + "-s" + "-w" + ]; + + nativeInstallCheckInputs = [ versionCheckHook ]; + versionCheckProgramArg = "--version"; + doInstallCheck = true; + + passthru = { + tests = { + inherit (nixosTests) gokapi; + }; + updateScript = nix-update-script { }; + }; + + meta = { + description = "Lightweight selfhosted Firefox Send alternative without public upload. AWS S3 supported"; + homepage = "https://github.com/Forceu/Gokapi"; + changelog = "https://github.com/Forceu/Gokapi/releases/tag/v${version}"; + license = lib.licenses.agpl3Only; + platforms = lib.platforms.linux; + maintainers = with lib.maintainers; [ + delliott + ]; + mainProgram = "gokapi"; + }; +}