Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(nixos/calibre-server): Add new http & auth options #216497

Merged
merged 1 commit into from Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions nixos/doc/manual/release-notes/rl-2311.section.md
Expand Up @@ -78,6 +78,8 @@

- `services.prometheus.exporters` has a new exporter to monitor electrical power consumption based on PowercapRAPL sensor called [Scaphandre](https://github.com/hubblo-org/scaphandre), see [#239803](https://github.com/NixOS/nixpkgs/pull/239803) for more details.

- The module `services.calibre-server` has new options to configure the `host`, `port`, `auth.enable`, `auth.mode` and `auth.userDb` path, see [#216497](https://github.com/NixOS/nixpkgs/pull/216497/) for more details.

## Nixpkgs internals {#sec-release-23.11-nixpkgs-internals}

- The `qemu-vm.nix` module by default now identifies block devices via
Expand Down
94 changes: 77 additions & 17 deletions nixos/modules/services/misc/calibre-server.nix
Expand Up @@ -6,6 +6,17 @@ let

cfg = config.services.calibre-server;

documentationLink = "https://manual.calibre-ebook.com";
generatedDocumentationLink = documentationLink + "/generated/en/calibre-server.html";

execFlags = (concatStringsSep " "
(mapAttrsToList (k: v: "${k} ${toString v}") (filterAttrs (name: value: value != null) {
"--listen-on" = cfg.host;
"--port" = cfg.port;
"--auth-mode" = cfg.auth.mode;
"--userdb" = cfg.auth.userDb;
}) ++ [(optionalString (cfg.auth.enable == true) "--enable-auth")])
);
in

{
Expand All @@ -18,52 +29,100 @@ in
)
];

###### interface

options = {
services.calibre-server = {

enable = mkEnableOption (lib.mdDoc "calibre-server");
package = lib.mkPackageOptionMD pkgs "calibre" { };

libraries = mkOption {
type = types.listOf types.path;
default = [ "/var/lib/calibre-server" ];
description = lib.mdDoc ''
Make sure each library path is initialized before service startup.
The directories of the libraries to serve. They must be readable for the user under which the server runs.
See the [calibredb documentation](${documentationLink}/generated/en/calibredb.html#add) for details.
'';
type = types.listOf types.path;
};

user = mkOption {
description = lib.mdDoc "The user under which calibre-server runs.";
type = types.str;
default = "calibre-server";
description = lib.mdDoc "The user under which calibre-server runs.";
};

group = mkOption {
description = lib.mdDoc "The group under which calibre-server runs.";
type = types.str;
default = "calibre-server";
description = lib.mdDoc "The group under which calibre-server runs.";
};

};
};
host = mkOption {
type = types.str;
default = "0.0.0.0";
example = "::1";
description = lib.mdDoc ''
The interface on which to listen for connections.
See the [calibre-server documentation](${generatedDocumentationLink}#cmdoption-calibre-server-listen-on) for details.
'';
};

port = mkOption {
default = 8080;
type = types.port;
description = lib.mdDoc ''
The port on which to listen for connections.
See the [calibre-server documentation](${generatedDocumentationLink}#cmdoption-calibre-server-port) for details.
'';
};

auth = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Password based authentication to access the server.
See the [calibre-server documentation](${generatedDocumentationLink}#cmdoption-calibre-server-enable-auth) for details.
'';
};

###### implementation
mode = mkOption {
type = types.enum [ "auto" "basic" "digest" ];
default = "auto";
description = lib.mdDoc ''
Choose the type of authentication used.
Set the HTTP authentication mode used by the server.
See the [calibre-server documentation](${generatedDocumentationLink}#cmdoption-calibre-server-auth-mode) for details.
'';
};

userDb = mkOption {
default = null;
type = types.nullOr types.path;
description = lib.mdDoc ''
Choose users database file to use for authentication.
Make sure users database file is initialized before service startup.
See the [calibre-server documentation](${documentationLink}/server.html#managing-user-accounts-from-the-command-line-only) for details.
'';
};
};
};
};

config = mkIf cfg.enable {

systemd.services.calibre-server = {
description = "Calibre Server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = cfg.user;
Restart = "always";
ExecStart = "${pkgs.calibre}/bin/calibre-server ${lib.concatStringsSep " " cfg.libraries}";
};

description = "Calibre Server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = cfg.user;
Restart = "always";
ExecStart = "${cfg.package}/bin/calibre-server ${lib.concatStringsSep " " cfg.libraries} ${execFlags}";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if the /bin/calibre-server is required

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package calibre contains multiple executables and calibre-server is not the default one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. If needed, the meta attribute mainProgram can be set in the derivation so it's not needed here.

};

};

environment.systemPackages = [ pkgs.calibre ];

users.users = optionalAttrs (cfg.user == "calibre-server") {
Expand All @@ -83,4 +142,5 @@ in

};

meta.maintainers = with lib.maintainers; [ gaelreyrol ];
}
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Expand Up @@ -151,6 +151,7 @@ in {
cage = handleTest ./cage.nix {};
cagebreak = handleTest ./cagebreak.nix {};
calibre-web = handleTest ./calibre-web.nix {};
calibre-server = handleTest ./calibre-server.nix {};
cassandra_3_0 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_3_0; };
cassandra_3_11 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_3_11; };
cassandra_4 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_4; };
Expand Down
104 changes: 104 additions & 0 deletions nixos/tests/calibre-server.nix
@@ -0,0 +1,104 @@
{ system ? builtins.currentSystem
, config ? { }
, pkgs ? import ../.. { inherit system config; }
}:

let
inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest;
inherit (pkgs.lib) concatStringsSep maintainers mapAttrs mkMerge
removeSuffix splitString;

tests = {
default = {
calibreConfig = {};
calibreScript = ''
wait_for_unit("calibre-server.service")
'';
};
customLibrary = {
calibreConfig = {
libraries = [ "/var/lib/calibre-data" ];
};
calibreScript = ''
succeed("ls -la /var/lib/calibre-data")
wait_for_unit("calibre-server.service")
'';
};
multipleLibraries = {
calibreConfig = {
libraries = [ "/var/lib/calibre-data" "/var/lib/calibre-server" ];
};
calibreScript = ''
succeed("ls -la /var/lib/calibre-data")
succeed("ls -la /var/lib/calibre-server")
wait_for_unit("calibre-server.service")
'';
};
hostAndPort = {
calibreConfig = {
host = "127.0.0.1";
port = 8888;
};
calibreScript = ''
wait_for_unit("calibre-server.service")
wait_for_open_port(8888)
succeed("curl --fail http://127.0.0.1:8888")
'';
};
basicAuth = {
calibreConfig = {
host = "127.0.0.1";
port = 8888;
auth = {
enable = true;
mode = "basic";
};
};
calibreScript = ''
wait_for_unit("calibre-server.service")
wait_for_open_port(8888)
fail("curl --fail http://127.0.0.1:8888")
'';
};
};
in
mapAttrs
(test: testConfig: (makeTest (
let
nodeName = testConfig.nodeName or test;
calibreConfig = {
enable = true;
libraries = [ "/var/lib/calibre-server" ];
} // testConfig.calibreConfig or {};
librariesInitScript = path: ''
${nodeName}.execute("touch /tmp/test.epub")
${nodeName}.execute("zip -r /tmp/test.zip /tmp/test.epub")
${nodeName}.execute("mkdir -p ${path}")
${nodeName}.execute("calibredb add -d --with-library ${path} /tmp/test.zip")
'';
in
{
name = "calibre-server-${test}";

nodes.${nodeName} = mkMerge [{
environment.systemPackages = [ pkgs.zip ];
services.calibre-server = calibreConfig;
} testConfig.calibreProvider or { }];

testScript = ''
${nodeName}.start()
${concatStringsSep "\n" (map librariesInitScript calibreConfig.libraries)}
${concatStringsSep "\n" (map (line:
if (builtins.substring 0 1 line == " " || builtins.substring 0 1 line == ")")
then line
else "${nodeName}.${line}"
) (splitString "\n" (removeSuffix "\n" testConfig.calibreScript)))}
${nodeName}.shutdown()
'';

meta = with maintainers; {
maintainers = [ gaelreyrol ];
};
}
)))
tests