aboutsummaryrefslogtreecommitdiff
path: root/infra/libkookie/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
diff options
context:
space:
mode:
authorMx Kookie <kookie@spacekookie.de>2020-10-31 19:35:09 +0100
committerMx Kookie <kookie@spacekookie.de>2020-10-31 19:35:09 +0100
commitc4625b175f8200f643fd6e11010932ea44c78433 (patch)
treebce3f89888c8ac3991fa5569a878a9eab6801ccc /infra/libkookie/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
parent49f735974dd103039ddc4cb576bb76555164a9e7 (diff)
parentd661aa56a8843e991261510c1bb28fdc2f6975ae (diff)
Add 'infra/libkookie/' from commit 'd661aa56a8843e991261510c1bb28fdc2f6975ae'
git-subtree-dir: infra/libkookie git-subtree-mainline: 49f735974dd103039ddc4cb576bb76555164a9e7 git-subtree-split: d661aa56a8843e991261510c1bb28fdc2f6975ae
Diffstat (limited to 'infra/libkookie/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix')
-rw-r--r--infra/libkookie/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix183
1 files changed, 183 insertions, 0 deletions
diff --git a/infra/libkookie/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix b/infra/libkookie/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
new file mode 100644
index 000000000000..936e211ec713
--- /dev/null
+++ b/infra/libkookie/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
@@ -0,0 +1,183 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.uwsgi;
+
+ buildCfg = name: c:
+ let
+ plugins =
+ if any (n: !any (m: m == n) cfg.plugins) (c.plugins or [])
+ then throw "`plugins` attribute in UWSGI configuration contains plugins not in config.services.uwsgi.plugins"
+ else c.plugins or cfg.plugins;
+
+ hasPython = v: filter (n: n == "python${v}") plugins != [];
+ hasPython2 = hasPython "2";
+ hasPython3 = hasPython "3";
+
+ python =
+ if hasPython2 && hasPython3 then
+ throw "`plugins` attribute in UWSGI configuration shouldn't contain both python2 and python3"
+ else if hasPython2 then cfg.package.python2
+ else if hasPython3 then cfg.package.python3
+ else null;
+
+ pythonEnv = python.withPackages (c.pythonPackages or (self: []));
+
+ uwsgiCfg = {
+ uwsgi =
+ if c.type == "normal"
+ then {
+ inherit plugins;
+ } // removeAttrs c [ "type" "pythonPackages" ]
+ // optionalAttrs (python != null) {
+ pyhome = "${pythonEnv}";
+ env =
+ # Argh, uwsgi expects list of key-values there instead of a dictionary.
+ let env' = c.env or [];
+ getPath =
+ x: if hasPrefix "PATH=" x
+ then substring (stringLength "PATH=") (stringLength x) x
+ else null;
+ oldPaths = filter (x: x != null) (map getPath env');
+ in env' ++ [ "PATH=${optionalString (oldPaths != []) "${last oldPaths}:"}${pythonEnv}/bin" ];
+ }
+ else if c.type == "emperor"
+ then {
+ emperor = if builtins.typeOf c.vassals != "set" then c.vassals
+ else pkgs.buildEnv {
+ name = "vassals";
+ paths = mapAttrsToList buildCfg c.vassals;
+ };
+ } // removeAttrs c [ "type" "vassals" ]
+ else throw "`type` attribute in UWSGI configuration should be either 'normal' or 'emperor'";
+ };
+
+ in pkgs.writeTextDir "${name}.json" (builtins.toJSON uwsgiCfg);
+
+in {
+
+ options = {
+ services.uwsgi = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable uWSGI";
+ };
+
+ runDir = mkOption {
+ type = types.path;
+ default = "/run/uwsgi";
+ description = "Where uWSGI communication sockets can live";
+ };
+
+ package = mkOption {
+ type = types.package;
+ internal = true;
+ };
+
+ instance = mkOption {
+ type = with lib.types; let
+ valueType = nullOr (oneOf [
+ bool
+ int
+ float
+ str
+ (lazyAttrsOf valueType)
+ (listOf valueType)
+ (mkOptionType {
+ name = "function";
+ description = "function";
+ check = x: isFunction x;
+ merge = mergeOneOption;
+ })
+ ]) // {
+ description = "Json value or lambda";
+ emptyValue.value = {};
+ };
+ in valueType;
+ default = {
+ type = "normal";
+ };
+ example = literalExample ''
+ {
+ type = "emperor";
+ vassals = {
+ moin = {
+ type = "normal";
+ pythonPackages = self: with self; [ moinmoin ];
+ socket = "${config.services.uwsgi.runDir}/uwsgi.sock";
+ };
+ };
+ }
+ '';
+ description = ''
+ uWSGI configuration. It awaits an attribute <literal>type</literal> inside which can be either
+ <literal>normal</literal> or <literal>emperor</literal>.
+
+ For <literal>normal</literal> mode you can specify <literal>pythonPackages</literal> as a function
+ from libraries set into a list of libraries. <literal>pythonpath</literal> will be set accordingly.
+
+ For <literal>emperor</literal> mode, you should use <literal>vassals</literal> attribute
+ which should be either a set of names and configurations or a path to a directory.
+
+ Other attributes will be used in configuration file as-is. Notice that you can redefine
+ <literal>plugins</literal> setting here.
+ '';
+ };
+
+ plugins = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = "Plugins used with uWSGI";
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "uwsgi";
+ description = "User account under which uwsgi runs.";
+ };
+
+ group = mkOption {
+ type = types.str;
+ default = "uwsgi";
+ description = "Group account under which uwsgi runs.";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.uwsgi = {
+ wantedBy = [ "multi-user.target" ];
+ preStart = ''
+ mkdir -p ${cfg.runDir}
+ chown ${cfg.user}:${cfg.group} ${cfg.runDir}
+ '';
+ serviceConfig = {
+ Type = "notify";
+ ExecStart = "${cfg.package}/bin/uwsgi --uid ${cfg.user} --gid ${cfg.group} --json ${buildCfg "server" cfg.instance}/server.json";
+ ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+ ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
+ NotifyAccess = "main";
+ KillSignal = "SIGQUIT";
+ };
+ };
+
+ users.users = optionalAttrs (cfg.user == "uwsgi") {
+ uwsgi = {
+ group = cfg.group;
+ uid = config.ids.uids.uwsgi;
+ };
+ };
+
+ users.groups = optionalAttrs (cfg.group == "uwsgi") {
+ uwsgi.gid = config.ids.gids.uwsgi;
+ };
+
+ services.uwsgi.package = pkgs.uwsgi.override {
+ inherit (cfg) plugins;
+ };
+ };
+}