gokapi: add module, test, release docs

Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
This commit is contained in:
Darragh Elliott 2025-01-11 17:26:55 +00:00
parent 9fe236c0ec
commit 46666bba62
6 changed files with 176 additions and 13 deletions

View file

@ -142,6 +142,8 @@
- [victorialogs][https://docs.victoriametrics.com/victorialogs/], log database from VictoriaMetrics. Available as [services.victorialogs](#opt-services.victorialogs.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).
- [Prometheus Node Cert Exporter](https://github.com/amimof/node-cert-exporter), a prometheus exporter to check for SSL cert expiry. Available under [services.prometheus.exporters.node-cert](#opt-services.prometheus.exporters.node-cert.enable).

View file

@ -1116,6 +1116,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

View file

@ -0,0 +1,143 @@
{
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";
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.port;
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" ];
environment = lib.mapAttrs (_: value: toString value) 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
];
}

View file

@ -479,6 +479,7 @@ in {
gobgpd = handleTest ./gobgpd.nix {};
gocd-agent = handleTest ./gocd-agent.nix {};
gocd-server = handleTest ./gocd-server.nix {};
gokapi = runTest ./gokapi.nix;
gollum = handleTest ./gollum.nix {};
gonic = handleTest ./gonic.nix {};
google-oslogin = handleTest ./google-oslogin {};

22
nixos/tests/gokapi.nix Normal file
View file

@ -0,0 +1,22 @@
{ lib, ... }:
let
port = 6000;
in
{
name = "gokapi";
meta.maintainers = with lib.maintainers; [ delliott ];
nodes.machine = {
services.gokapi = {
enable = true;
environment.GOKAPI_PORT = port;
};
};
testScript = ''
machine.wait_for_unit("gokapi.service")
machine.wait_for_open_port(${toString port})
machine.succeed("curl --fail http://localhost:${toString port}/")
'';
}

View file

@ -20,21 +20,15 @@ buildGoModule rec {
vendorHash = "sha256-9GRAlgng+yq7q0VQz374jIOCjeDIIDD631BglM/FsQQ=";
# This is the go generate is ran in the upstream builder, but we have to run the components separately for things to work.
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
go run ../../build/go-generate/updateVersionNumbers.go
# Tries to download "golang.org/x/exp/slices"
# go run ../../build/go-generate/updateProtectedUrls.go
go run ../../build/go-generate/buildWasm.go
# Must be 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 ../..
'';
@ -59,7 +53,7 @@ buildGoModule rec {
};
meta = {
description = "Lightweight selfhosted Firefox Send alternative without public upload. AWS S3 supported";
description = "Lightweight selfhosted Firefox Send alternative without public upload";
homepage = "https://github.com/Forceu/Gokapi";
changelog = "https://github.com/Forceu/Gokapi/releases/tag/v${version}";
license = lib.licenses.agpl3Only;