1 { config, pkgs, lib, ... }:
5 cfg = config.services.tandoor-recipes;
8 # SECRET_KEY through an env file
10 GUNICORN_CMD_ARGS = "--bind=${cfg.address}:${toString cfg.port}";
13 MEDIA_ROOT = "/var/lib/tandoor-recipes";
14 } // optionalAttrs (config.time.timeZone != null) {
15 TZ = config.time.timeZone;
17 lib.mapAttrs (_: toString) cfg.extraConfig
20 manage = pkgs.writeShellScript "manage" ''
21 set -o allexport # Export the following env vars
22 ${lib.toShellVars env}
23 eval "$(${config.systemd.package}/bin/systemctl show -pUID,GID,MainPID tandoor-recipes.service)"
24 exec ${pkgs.util-linux}/bin/nsenter \
25 -t $MainPID -m -S $UID -G $GID --wdns=${env.MEDIA_ROOT} \
26 ${pkg}/bin/tandoor-recipes "$@"
30 meta.maintainers = with maintainers; [ ambroisie ];
32 options.services.tandoor-recipes = {
34 type = lib.types.bool;
37 Enable Tandoor Recipes.
39 When started, the Tandoor Recipes database is automatically created if
40 it doesn't exist and updated if the package has changed. Both tasks are
41 achieved by running a Django migration.
43 A script to manage the instance (by wrapping Django's manage.py) is linked to
44 `/var/lib/tandoor-recipes/tandoor-recipes-manage`.
50 default = "localhost";
51 description = "Web interface address.";
57 description = "Web interface port.";
60 extraConfig = mkOption {
64 Extra tandoor recipes config options.
66 See [the example dot-env file](https://raw.githubusercontent.com/vabene1111/recipes/master/.env.template)
67 for available options.
74 package = mkPackageOption pkgs "tandoor-recipes" { };
77 config = mkIf cfg.enable {
78 systemd.services.tandoor-recipes = {
79 description = "Tandoor Recipes server";
83 ${pkg.python.pkgs.gunicorn}/bin/gunicorn recipes.wsgi
85 Restart = "on-failure";
87 User = "tandoor_recipes";
88 Group = "tandoor_recipes";
90 StateDirectory = "tandoor-recipes";
91 WorkingDirectory = env.MEDIA_ROOT;
92 RuntimeDirectory = "tandoor-recipes";
95 "${config.environment.etc."ssl/certs/ca-certificates.crt".source}:/etc/ssl/certs/ca-certificates.crt"
103 CapabilityBoundingSet = "";
104 LockPersonality = true;
105 MemoryDenyWriteExecute = true;
106 PrivateDevices = true;
109 ProtectControlGroups = true;
111 ProtectHostname = true;
112 ProtectKernelLogs = true;
113 ProtectKernelModules = true;
114 ProtectKernelTunables = true;
115 RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
116 RestrictNamespaces = true;
117 RestrictRealtime = true;
118 SystemCallArchitectures = "native";
119 # gunicorn needs setuid
120 SystemCallFilter = [ "@system-service" "~@privileged" "@resources" "@setuid" "@keyring" ];
122 } // lib.optionalAttrs (cfg.port < 1024) {
123 AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
124 CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
127 wantedBy = [ "multi-user.target" ];
130 ln -sf ${manage} tandoor-recipes-manage
132 # Let django migrate the DB as needed
133 ${pkg}/bin/tandoor-recipes migrate
136 environment = env // {
137 PYTHONPATH = "${pkg.python.pkgs.makePythonPath pkg.propagatedBuildInputs}:${pkg}/lib/tandoor-recipes";