diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
index 0d3c3f2a0dab..85329c11413f 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
@@ -92,6 +92,13 @@
snapraid.
+
+
+ Hockeypuck,
+ a OpenPGP Key Server. Available as
+ services.hockeypuck.
+
+
diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md
index 1d037e2c5cac..4034def5f3d0 100644
--- a/nixos/doc/manual/release-notes/rl-2111.section.md
+++ b/nixos/doc/manual/release-notes/rl-2111.section.md
@@ -28,6 +28,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- [snapraid](https://www.snapraid.it/), a backup program for disk arrays.
Available as [snapraid](#opt-snapraid.enable).
+- [Hockeypuck](https://github.com/hockeypuck/hockeypuck), a OpenPGP Key Server. Available as [services.hockeypuck](#opt-services.hockeypuck.enable).
+
## Backward Incompatibilities {#sec-release-21.11-incompatibilities}
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index ad1bccd54289..13463359a66e 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -886,6 +886,7 @@
./services/security/fprot.nix
./services/security/haka.nix
./services/security/haveged.nix
+ ./services/security/hockeypuck.nix
./services/security/hologram-server.nix
./services/security/hologram-agent.nix
./services/security/munge.nix
diff --git a/nixos/modules/services/security/hockeypuck.nix b/nixos/modules/services/security/hockeypuck.nix
new file mode 100644
index 000000000000..686634c8add8
--- /dev/null
+++ b/nixos/modules/services/security/hockeypuck.nix
@@ -0,0 +1,104 @@
+{ config, lib, pkgs, ... }:
+
+let
+ cfg = config.services.hockeypuck;
+ settingsFormat = pkgs.formats.toml { };
+in {
+ meta.maintainers = with lib.maintainers; [ etu ];
+
+ options.services.hockeypuck = {
+ enable = lib.mkEnableOption "Hockeypuck OpenPGP Key Server";
+
+ port = lib.mkOption {
+ default = 11371;
+ type = lib.types.port;
+ description = "HKP port to listen on.";
+ };
+
+ settings = lib.mkOption {
+ type = settingsFormat.type;
+ default = { };
+ example = lib.literalExample ''
+ {
+ hockeypuck = {
+ loglevel = "INFO";
+ logfile = "/var/log/hockeypuck/hockeypuck.log";
+ indexTemplate = "''${pkgs.hockeypuck-web}/share/templates/index.html.tmpl";
+ vindexTemplate = "''${pkgs.hockeypuck-web}/share/templates/index.html.tmpl";
+ statsTemplate = "''${pkgs.hockeypuck-web}/share/templates/stats.html.tmpl";
+ webroot = "''${pkgs.hockeypuck-web}/share/webroot";
+
+ hkp.bind = ":''${toString cfg.port}";
+
+ openpgp.db = {
+ driver = "postgres-jsonb";
+ dsn = "database=hockeypuck host=/var/run/postgresql sslmode=disable";
+ };
+ };
+ }
+ '';
+ description = ''
+ Configuration file for hockeypuck, here you can override
+ certain settings (loglevel and
+ openpgp.db.dsn) by just setting those values.
+
+ For other settings you need to use lib.mkForce to override them.
+
+ This service doesn't provision or enable postgres on your
+ system, it rather assumes that you enable postgres and create
+ the database yourself.
+
+ Example:
+
+ services.postgresql = {
+ enable = true;
+ ensureDatabases = [ "hockeypuck" ];
+ ensureUsers = [{
+ name = "hockeypuck";
+ ensurePermissions."DATABASE hockeypuck" = "ALL PRIVILEGES";
+ }];
+ };
+
+ '';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ services.hockeypuck.settings.hockeypuck = {
+ loglevel = lib.mkDefault "INFO";
+ logfile = "/var/log/hockeypuck/hockeypuck.log";
+ indexTemplate = "${pkgs.hockeypuck-web}/share/templates/index.html.tmpl";
+ vindexTemplate = "${pkgs.hockeypuck-web}/share/templates/index.html.tmpl";
+ statsTemplate = "${pkgs.hockeypuck-web}/share/templates/stats.html.tmpl";
+ webroot = "${pkgs.hockeypuck-web}/share/webroot";
+
+ hkp.bind = ":${toString cfg.port}";
+
+ openpgp.db = {
+ driver = "postgres-jsonb";
+ dsn = lib.mkDefault "database=hockeypuck host=/var/run/postgresql sslmode=disable";
+ };
+ };
+
+ users.users.hockeypuck = {
+ isSystemUser = true;
+ description = "Hockeypuck user";
+ };
+
+ systemd.services.hockeypuck = {
+ description = "Hockeypuck OpenPGP Key Server";
+ after = [ "network.target" "postgresql.target" ];
+ wantedBy = [ "multi-user.target" ];
+ serviceConfig = {
+ WorkingDirectory = "/var/lib/hockeypuck";
+ User = "hockeypuck";
+ ExecStart = "${pkgs.hockeypuck}/bin/hockeypuck -config ${settingsFormat.generate "config.toml" cfg.settings}";
+ Restart = "always";
+ RestartSec = "5s";
+ LogsDirectory = "hockeypuck";
+ LogsDirectoryMode = "0755";
+ StateDirectory = "hockeypuck";
+ };
+ };
+ };
+}
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index fd502a473b10..746139c48169 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -174,6 +174,7 @@ in
hitch = handleTest ./hitch {};
hledger-web = handleTest ./hledger-web.nix {};
hocker-fetchdocker = handleTest ./hocker-fetchdocker {};
+ hockeypuck = handleTest ./hockeypuck.nix { };
home-assistant = handleTest ./home-assistant.nix {};
hostname = handleTest ./hostname.nix {};
hound = handleTest ./hound.nix {};
diff --git a/nixos/tests/hockeypuck.nix b/nixos/tests/hockeypuck.nix
new file mode 100644
index 000000000000..79313f314fd2
--- /dev/null
+++ b/nixos/tests/hockeypuck.nix
@@ -0,0 +1,63 @@
+import ./make-test-python.nix ({ lib, pkgs, ... }:
+let
+ gpgKeyring = (pkgs.runCommandNoCC "gpg-keyring" { buildInputs = [ pkgs.gnupg ]; } ''
+ mkdir -p $out
+ export GNUPGHOME=$out
+ cat > foo <OpenPGP Keyserver" in response, "HTML title not found"
+
+ # Copy the keyring
+ machine.succeed("cp -R ${gpgKeyring} /tmp/GNUPGHOME")
+
+ # Extract our GPG key id
+ keyId = machine.succeed("GNUPGHOME=/tmp/GNUPGHOME gpg --list-keys | grep dsa1024 --after-context=1 | grep -v dsa1024").strip()
+
+ # Send the key to our local keyserver
+ machine.succeed("GNUPGHOME=/tmp/GNUPGHOME gpg --keyserver hkp://127.0.0.1:11371 --send-keys " + keyId)
+
+ # Recieve the key from our local keyserver to a separate directory
+ machine.succeed("GNUPGHOME=$(mktemp -d) gpg --keyserver hkp://127.0.0.1:11371 --recv-keys " + keyId)
+ '';
+})
diff --git a/pkgs/servers/hockeypuck/server.nix b/pkgs/servers/hockeypuck/server.nix
new file mode 100644
index 000000000000..cf48fd5716c9
--- /dev/null
+++ b/pkgs/servers/hockeypuck/server.nix
@@ -0,0 +1,21 @@
+{ lib, buildGoModule, fetchFromGitHub, nixosTests }:
+
+let
+ sources = (import ./sources.nix) { inherit fetchFromGitHub; };
+in
+buildGoModule {
+ inherit (sources) pname version src;
+
+ modRoot = "src/hockeypuck/";
+ vendorSha256 = null;
+ doCheck = false; # Uses networking for tests
+
+ passthru.tests = nixosTests.hockeypuck;
+
+ meta = with lib; {
+ description = "OpenPGP Key Server";
+ homepage = "https://github.com/hockeypuck/hockeypuck";
+ license = licenses.agpl3Plus;
+ maintainers = [ maintainers.etu ];
+ };
+}
diff --git a/pkgs/servers/hockeypuck/sources.nix b/pkgs/servers/hockeypuck/sources.nix
new file mode 100644
index 000000000000..b504cd331410
--- /dev/null
+++ b/pkgs/servers/hockeypuck/sources.nix
@@ -0,0 +1,16 @@
+{ fetchFromGitHub }:
+
+let
+ pname = "hockeypuck";
+ version = "2.1.0";
+in
+{
+ inherit version pname;
+
+ src = fetchFromGitHub {
+ owner = pname;
+ repo = pname;
+ rev = version;
+ sha256 = "0da3ffbqck0dr7d89gy2yillp7g9a4ziyjlvrm8vgkkg2fs8dlb1";
+ };
+}
diff --git a/pkgs/servers/hockeypuck/web.nix b/pkgs/servers/hockeypuck/web.nix
new file mode 100644
index 000000000000..32f2b1acd22e
--- /dev/null
+++ b/pkgs/servers/hockeypuck/web.nix
@@ -0,0 +1,28 @@
+{ stdenv, lib, fetchFromGitHub, nixosTests }:
+
+let
+ sources = (import ./sources.nix) { inherit fetchFromGitHub; };
+in
+stdenv.mkDerivation {
+ pname = "${sources.pname}-web";
+
+ inherit (sources) version src;
+
+ dontBuild = true; # We should just copy the web templates
+
+ installPhase = ''
+ mkdir -p $out/share/
+
+ cp -vr contrib/webroot $out/share/
+ cp -vr contrib/templates $out/share/
+ '';
+
+ passthru.tests = nixosTests.hockeypuck;
+
+ meta = with lib; {
+ description = "OpenPGP Key Server web resources";
+ homepage = "https://github.com/hockeypuck/hockeypuck";
+ license = licenses.gpl3Plus;
+ maintainers = [ maintainers.etu ];
+ };
+}
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 732931d778f9..247726bad020 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -5827,6 +5827,10 @@ in
lua = lua5;
});
+ hockeypuck = callPackage ../servers/hockeypuck/server.nix { };
+
+ hockeypuck-web = callPackage ../servers/hockeypuck/web.nix { };
+
holochain-go = callPackage ../servers/holochain-go { };
homesick = callPackage ../tools/misc/homesick { };