nixpkgs/nixos/modules/services/misc/bepasty.nix
2024-08-30 23:00:14 +02:00

178 lines
5.5 KiB
Nix

{ config, lib, pkgs, ... }:
let
gunicorn = pkgs.python3Packages.gunicorn;
bepasty = pkgs.bepasty;
gevent = pkgs.python3Packages.gevent;
python = pkgs.python3Packages.python;
cfg = config.services.bepasty;
user = "bepasty";
group = "bepasty";
default_home = "/var/lib/bepasty";
in
{
options.services.bepasty = {
enable = lib.mkEnableOption "bepasty, a binary pastebin server";
servers = lib.mkOption {
default = {};
description = ''
configure a number of bepasty servers which will be started with
gunicorn.
'';
type = with lib.types ; attrsOf (submodule ({ config, ... } : {
options = {
bind = lib.mkOption {
type = lib.types.str;
description = ''
Bind address to be used for this server.
'';
example = "0.0.0.0:8000";
default = "127.0.0.1:8000";
};
dataDir = lib.mkOption {
type = lib.types.str;
description = ''
Path to the directory where the pastes will be saved to
'';
default = default_home+"/data";
};
defaultPermissions = lib.mkOption {
type = lib.types.str;
description = ''
default permissions for all unauthenticated accesses.
'';
example = "read,create,delete";
default = "read";
};
extraConfig = lib.mkOption {
type = lib.types.lines;
description = ''
Extra configuration for bepasty server to be appended on the
configuration.
see https://bepasty-server.readthedocs.org/en/latest/quickstart.html#configuring-bepasty
for all options.
'';
default = "";
example = ''
PERMISSIONS = {
'myadminsecret': 'admin,list,create,read,delete',
}
MAX_ALLOWED_FILE_SIZE = 5 * 1000 * 1000
'';
};
secretKey = lib.mkOption {
type = lib.types.str;
description = ''
server secret for safe session cookies, must be set.
Warning: this secret is stored in the WORLD-READABLE Nix store!
It's recommended to use {option}`secretKeyFile`
which takes precedence over {option}`secretKey`.
'';
default = "";
};
secretKeyFile = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
A file that contains the server secret for safe session cookies, must be set.
{option}`secretKeyFile` takes precedence over {option}`secretKey`.
Warning: when {option}`secretKey` is non-empty {option}`secretKeyFile`
defaults to a file in the WORLD-READABLE Nix store containing that secret.
'';
};
workDir = lib.mkOption {
type = lib.types.str;
description = ''
Path to the working directory (used for config and pidfile).
Defaults to the users home directory.
'';
default = default_home;
};
};
config = {
secretKeyFile = lib.mkDefault (
if config.secretKey != ""
then toString (pkgs.writeTextFile {
name = "bepasty-secret-key";
text = config.secretKey;
})
else null
);
};
}));
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ bepasty ];
# creates gunicorn systemd service for each configured server
systemd.services = lib.mapAttrs' (name: server:
lib.nameValuePair ("bepasty-server-${name}-gunicorn")
({
description = "Bepasty Server ${name}";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
restartIfChanged = true;
environment = let
penv = python.buildEnv.override {
extraLibs = [ bepasty gevent ];
};
in {
BEPASTY_CONFIG = "${server.workDir}/bepasty-${name}.conf";
PYTHONPATH= "${penv}/${python.sitePackages}/";
};
serviceConfig = {
Type = "simple";
PrivateTmp = true;
ExecStartPre = assert server.secretKeyFile != null; pkgs.writeScript "bepasty-server.${name}-init" ''
#!/bin/sh
mkdir -p "${server.workDir}"
mkdir -p "${server.dataDir}"
chown ${user}:${group} "${server.workDir}" "${server.dataDir}"
cat > ${server.workDir}/bepasty-${name}.conf <<EOF
SITENAME="${name}"
STORAGE_FILESYSTEM_DIRECTORY="${server.dataDir}"
SECRET_KEY="$(cat "${server.secretKeyFile}")"
DEFAULT_PERMISSIONS="${server.defaultPermissions}"
${server.extraConfig}
EOF
'';
ExecStart = ''${gunicorn}/bin/gunicorn bepasty.wsgi --name ${name} \
-u ${user} \
-g ${group} \
--workers 3 --log-level=info \
--bind=${server.bind} \
--pid ${server.workDir}/gunicorn-${name}.pid \
-k gevent
'';
};
})
) cfg.servers;
users.users.${user} =
{ uid = config.ids.uids.bepasty;
group = group;
home = default_home;
};
users.groups.${group}.gid = config.ids.gids.bepasty;
};
}