diff --git a/nixos/modules/services/web-servers/uwsgi.nix b/nixos/modules/services/web-servers/uwsgi.nix
index 3e18a6f0e986..e6c25e6215c1 100644
--- a/nixos/modules/services/web-servers/uwsgi.nix
+++ b/nixos/modules/services/web-servers/uwsgi.nix
@@ -5,44 +5,86 @@ with lib;
let
cfg = config.services.uwsgi;
- python2Pkgs = pkgs.python2Packages.override {
- python = pkgs.uwsgi.python2;
- self = python2Pkgs;
- };
-
- python3Pkgs = pkgs.python3Packages.override {
- python = pkgs.uwsgi.python3;
- self = python3Pkgs;
- };
-
- buildCfg = c: if builtins.typeOf c != "set" then builtins.readFile c else builtins.toJSON {
- uwsgi =
- if c.type == "normal"
- then {
- pythonpath =
- (if c ? python2Packages
- then builtins.map (x: "${x}/${pkgs.uwsgi.python2.sitePackages}") (c.python2Packages python2Pkgs)
- else [])
- ++ (if c ? python3Packages
- then builtins.map (x: "${x}/${pkgs.uwsgi.python3.sitePackages}") (c.python3Packages python3Pkgs)
- else []);
- plugins = cfg.plugins;
- } // removeAttrs c [ "type" "python2Packages" "python3Packages" ]
- else if c.type == "emperor"
- then {
- emperor = if builtins.typeOf c.vassals != "set" then c.vassals
- else pkgs.buildEnv {
- name = "vassals";
- paths = mapAttrsToList (n: c: pkgs.writeTextDir "${n}.json" (buildCfg c)) c.vassals;
- };
- } // removeAttrs c [ "type" "vassals" ]
- else abort "type should be either 'normal' or 'emperor'";
- };
-
uwsgi = pkgs.uwsgi.override {
plugins = cfg.plugins;
};
+ 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 uwsgi.python2
+ else if hasPython3 then uwsgi.python3
+ else null;
+
+ pythonPackages = pkgs.pythonPackages.override {
+ inherit python;
+ self = pythonPackages;
+ };
+
+ json = builtins.toJSON {
+ uwsgi =
+ if c.type == "normal"
+ then {
+ inherit plugins;
+ } // removeAttrs c [ "type" "pythonPackages" ]
+ // optionalAttrs (python != null) {
+ pythonpath = "@PYTHONPATH@";
+ env = (c.env or {}) // {
+ PATH = optionalString (c ? env.PATH) "${c.env.PATH}:" + "@PATH@";
+ };
+ }
+ 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
+ if python == null || c.type != "normal"
+ then pkgs.writeTextDir "${name}.json" json
+ else pkgs.stdenv.mkDerivation {
+ name = "uwsgi-config";
+ inherit json;
+ passAsFile = [ "json" ];
+ nativeBuildInputs = [ pythonPackages.wrapPython ];
+ pythonInputs = (c.pythonPackages or (self: [])) pythonPackages;
+
+ buildCommand = ''
+ mkdir $out
+ declare -A pythonPathsSeen=()
+ program_PYTHONPATH=
+ program_PATH=
+ if [ -n "$pythonInputs" ]; then
+ for i in $pythonInputs; do
+ _addToPythonPath $i
+ done
+ fi
+ # A hack to replace "@PYTHONPATH@" with a JSON list
+ if [ -n "$program_PYTHONPATH" ]; then
+ program_PYTHONPATH="\"''${program_PYTHONPATH//:/\",\"}\""
+ fi
+ substitute $jsonPath $out/${name}.json \
+ --replace '"@PYTHONPATH@"' "[$program_PYTHONPATH]" \
+ --subst-var-by PATH "$program_PATH"
+ '';
+ };
+
in {
options = {
@@ -71,21 +113,24 @@ in {
vassals = {
moin = {
type = "normal";
- python2Packages = self: with self; [ moinmoin ];
+ pythonPackages = self: with self; [ moinmoin ];
socket = "${config.services.uwsgi.runDir}/uwsgi.sock";
};
};
}
'';
description = ''
- uWSGI configuration. This awaits either a path to file or a set which will be made into one.
- If given a set, it awaits an attribute type which can be either normal
- or emperor.
+ uWSGI configuration. It awaits an attribute type inside which can be either
+ normal or emperor.
+
+ For normal mode you can specify pythonPackages as a function
+ from libraries set into a list of libraries. pythonpath will be set accordingly.
- For normal mode you can specify python2Packages and
- python3Packages as functions from libraries set into lists of libraries.
For emperor mode, you should use vassals 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
+ plugins setting here.
'';
};
@@ -118,7 +163,7 @@ in {
'';
serviceConfig = {
Type = "notify";
- ExecStart = "${uwsgi}/bin/uwsgi --uid ${cfg.user} --gid ${cfg.group} --json ${pkgs.writeText "uwsgi.json" (buildCfg cfg.instance)}";
+ ExecStart = "${uwsgi}/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";
diff --git a/pkgs/servers/uwsgi/default.nix b/pkgs/servers/uwsgi/default.nix
index abcbaa04b8c0..2d447d3c82a9 100644
--- a/pkgs/servers/uwsgi/default.nix
+++ b/pkgs/servers/uwsgi/default.nix
@@ -1,28 +1,35 @@
{ stdenv, lib, fetchurl, pkgconfig, jansson
-# plugins: list of strings, eg. [python2, python3]
+# plugins: list of strings, eg. [ "python2" "python3" ]
, plugins
-, pam, withPAM ? stdenv.isLinux
-, systemd, withSystemd ? stdenv.isLinux
+, pam, withPAM ? false
+, systemd, withSystemd ? false
, python2, python3, ncurses
}:
-let pythonPlugin = pkg : { name = "python${if pkg ? isPy2 then "2" else "3"}";
- interpreter = pkg;
+let pythonPlugin = pkg : lib.nameValuePair "python${if pkg ? isPy2 then "2" else "3"}" {
+ interpreter = pkg.interpreter;
path = "plugins/python";
- deps = [ pkg ncurses ];
+ inputs = [ pkg ncurses ];
install = ''
install -Dm644 uwsgidecorators.py $out/${pkg.sitePackages}/uwsgidecorators.py
${pkg.executable} -m compileall $out/${pkg.sitePackages}/
${pkg.executable} -O -m compileall $out/${pkg.sitePackages}/
'';
};
- available = [ (pythonPlugin python2)
+
+ available = lib.listToAttrs [
+ (pythonPlugin python2)
(pythonPlugin python3)
];
- needed = builtins.filter (x: lib.any (y: x.name == y) plugins) available;
-in
-assert builtins.filter (x: lib.all (y: y.name != x) available) plugins == [];
+ getPlugin = name:
+ let all = lib.concatStringsSep ", " (lib.attrNames available);
+ in if lib.hasAttr name available
+ then lib.getAttr name available // { inherit name; }
+ else throw "Unknown UWSGI plugin ${name}, available : ${all}";
+
+ needed = builtins.map getPlugin plugins;
+in
stdenv.mkDerivation rec {
name = "uwsgi-2.0.11.2";
@@ -34,17 +41,15 @@ stdenv.mkDerivation rec {
nativeBuildInputs = [ python3 pkgconfig ];
- buildInputs = with stdenv.lib;
- [ jansson ]
- ++ optional withPAM pam
- ++ optional withSystemd systemd
- ++ lib.concatMap (x: x.deps) needed
+ buildInputs = [ jansson ]
+ ++ lib.optional withPAM pam
+ ++ lib.optional withSystemd systemd
+ ++ lib.concatMap (x: x.inputs) needed
;
- basePlugins = with stdenv.lib;
- concatStringsSep ","
- ( optional withPAM "pam"
- ++ optional withSystemd "systemd_logger"
+ basePlugins = lib.concatStringsSep ","
+ ( lib.optional withPAM "pam"
+ ++ lib.optional withSystemd "systemd_logger"
);
passthru = {
@@ -59,12 +64,11 @@ stdenv.mkDerivation rec {
buildPhase = ''
mkdir -p $pluginDir
python3 uwsgiconfig.py --build nixos
- ${lib.concatMapStringsSep ";" (x: "${x.interpreter.interpreter} uwsgiconfig.py --plugin ${x.path} nixos ${x.name}") needed}
+ ${lib.concatMapStringsSep ";" (x: "${x.interpreter} uwsgiconfig.py --plugin ${x.path} nixos ${x.name}") needed}
'';
installPhase = ''
install -Dm755 uwsgi $out/bin/uwsgi
- #cp *_plugin.so $pluginDir || true
${lib.concatMapStringsSep "\n" (x: x.install) needed}
'';
diff --git a/pkgs/servers/uwsgi/nixos.ini b/pkgs/servers/uwsgi/nixos.ini
index 454eb51893fc..51bc6da33f6c 100644
--- a/pkgs/servers/uwsgi/nixos.ini
+++ b/pkgs/servers/uwsgi/nixos.ini
@@ -2,4 +2,5 @@
plugin_dir = @pluginDir@
main_plugin = @basePlugins@
json = true
+yaml = false
inherit = base
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index a7a0738a89c9..2d59b57977b1 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -3521,6 +3521,8 @@ let
uwsgi = callPackage ../servers/uwsgi {
plugins = [];
+ withPAM = stdenv.isLinux;
+ withSystemd = stdenv.isLinux;
};
vacuum = callPackage ../applications/networking/instant-messengers/vacuum {};