mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-01-03 19:43:30 +00:00
cb10fe8aaf
Systemd units with `PrivateUsers` set get their capabilities within the user namespace only [1]. As a result they do cannot bind to privileged ports even though they *appear* like they should be able to. The units in this commit [2] set `PrivateUsers` unconditionally so binding to privileged ports is currently impossible. Granting them CAP_NET_BIND_SERVICE is useless and misleading any reader of those modules. Technically, this commit also hardens these modules ever so slightly. (There are corner cases where this could make sense (e.g. across units, using `JoinsNamspaceOf`) but this is arcane enough to not to be present in nixpkgs.) [1]: systemd.exec(5): PrivateUsers [2]: found using `rg -e 'PrivateUsers.?=\s+[^f][^a]' -l | xargs rg -e '\bCAP_' -l`
139 lines
4.0 KiB
Nix
139 lines
4.0 KiB
Nix
{ config, pkgs, lib, ... }:
|
|
|
|
with lib;
|
|
let
|
|
cfg = config.services.tandoor-recipes;
|
|
pkg = cfg.package;
|
|
|
|
# SECRET_KEY through an env file
|
|
env = {
|
|
GUNICORN_CMD_ARGS = "--bind=${cfg.address}:${toString cfg.port}";
|
|
DEBUG = "0";
|
|
DEBUG_TOOLBAR = "0";
|
|
MEDIA_ROOT = "/var/lib/tandoor-recipes";
|
|
} // optionalAttrs (config.time.timeZone != null) {
|
|
TZ = config.time.timeZone;
|
|
} // (
|
|
lib.mapAttrs (_: toString) cfg.extraConfig
|
|
);
|
|
|
|
manage = pkgs.writeShellScript "manage" ''
|
|
set -o allexport # Export the following env vars
|
|
${lib.toShellVars env}
|
|
eval "$(${config.systemd.package}/bin/systemctl show -pUID,GID,MainPID tandoor-recipes.service)"
|
|
exec ${pkgs.util-linux}/bin/nsenter \
|
|
-t $MainPID -m -S $UID -G $GID --wdns=${env.MEDIA_ROOT} \
|
|
${pkg}/bin/tandoor-recipes "$@"
|
|
'';
|
|
in
|
|
{
|
|
meta.maintainers = with maintainers; [ ambroisie ];
|
|
|
|
options.services.tandoor-recipes = {
|
|
enable = mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Enable Tandoor Recipes.
|
|
|
|
When started, the Tandoor Recipes database is automatically created if
|
|
it doesn't exist and updated if the package has changed. Both tasks are
|
|
achieved by running a Django migration.
|
|
|
|
A script to manage the instance (by wrapping Django's manage.py) is linked to
|
|
`/var/lib/tandoor-recipes/tandoor-recipes-manage`.
|
|
'';
|
|
};
|
|
|
|
address = mkOption {
|
|
type = types.str;
|
|
default = "localhost";
|
|
description = "Web interface address.";
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 8080;
|
|
description = "Web interface port.";
|
|
};
|
|
|
|
extraConfig = mkOption {
|
|
type = types.attrs;
|
|
default = { };
|
|
description = ''
|
|
Extra tandoor recipes config options.
|
|
|
|
See [the example dot-env file](https://raw.githubusercontent.com/vabene1111/recipes/master/.env.template)
|
|
for available options.
|
|
'';
|
|
example = {
|
|
ENABLE_SIGNUP = "1";
|
|
};
|
|
};
|
|
|
|
package = mkPackageOption pkgs "tandoor-recipes" { };
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
systemd.services.tandoor-recipes = {
|
|
description = "Tandoor Recipes server";
|
|
|
|
serviceConfig = {
|
|
ExecStart = ''
|
|
${pkg.python.pkgs.gunicorn}/bin/gunicorn recipes.wsgi
|
|
'';
|
|
Restart = "on-failure";
|
|
|
|
User = "tandoor_recipes";
|
|
Group = "tandoor_recipes";
|
|
DynamicUser = true;
|
|
StateDirectory = "tandoor-recipes";
|
|
WorkingDirectory = env.MEDIA_ROOT;
|
|
RuntimeDirectory = "tandoor-recipes";
|
|
|
|
BindReadOnlyPaths = [
|
|
"${config.environment.etc."ssl/certs/ca-certificates.crt".source}:/etc/ssl/certs/ca-certificates.crt"
|
|
builtins.storeDir
|
|
"-/etc/resolv.conf"
|
|
"-/etc/nsswitch.conf"
|
|
"-/etc/hosts"
|
|
"-/etc/localtime"
|
|
"-/run/postgresql"
|
|
];
|
|
CapabilityBoundingSet = "";
|
|
LockPersonality = true;
|
|
MemoryDenyWriteExecute = true;
|
|
PrivateDevices = true;
|
|
PrivateUsers = true;
|
|
ProtectClock = true;
|
|
ProtectControlGroups = true;
|
|
ProtectHome = true;
|
|
ProtectHostname = true;
|
|
ProtectKernelLogs = true;
|
|
ProtectKernelModules = true;
|
|
ProtectKernelTunables = true;
|
|
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
|
RestrictNamespaces = true;
|
|
RestrictRealtime = true;
|
|
SystemCallArchitectures = "native";
|
|
# gunicorn needs setuid
|
|
SystemCallFilter = [ "@system-service" "~@privileged" "@resources" "@setuid" "@keyring" ];
|
|
UMask = "0066";
|
|
};
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
preStart = ''
|
|
ln -sf ${manage} tandoor-recipes-manage
|
|
|
|
# Let django migrate the DB as needed
|
|
${pkg}/bin/tandoor-recipes migrate
|
|
'';
|
|
|
|
environment = env // {
|
|
PYTHONPATH = "${pkg.python.pkgs.makePythonPath pkg.propagatedBuildInputs}:${pkg}/lib/tandoor-recipes";
|
|
};
|
|
};
|
|
};
|
|
}
|