···5let
6 cfg = config.services.uwsgi;
78- python2Pkgs = pkgs.python2Packages.override {
9- python = pkgs.uwsgi.python2;
10- self = python2Pkgs;
11 };
1213- python3Pkgs = pkgs.python3Packages.override {
14- python = pkgs.uwsgi.python3;
15- self = python3Pkgs;
16- };
000000000000000000000000000000000000000001718- buildCfg = c: if builtins.typeOf c != "set" then builtins.readFile c else builtins.toJSON {
19- uwsgi =
20- if c.type == "normal"
21- then {
22- pythonpath =
23- (if c ? python2Packages
24- then builtins.map (x: "${x}/${pkgs.uwsgi.python2.sitePackages}") (c.python2Packages python2Pkgs)
25- else [])
26- ++ (if c ? python3Packages
27- then builtins.map (x: "${x}/${pkgs.uwsgi.python3.sitePackages}") (c.python3Packages python3Pkgs)
28- else []);
29- plugins = cfg.plugins;
30- } // removeAttrs c [ "type" "python2Packages" "python3Packages" ]
31- else if c.type == "emperor"
32- then {
33- emperor = if builtins.typeOf c.vassals != "set" then c.vassals
34- else pkgs.buildEnv {
35- name = "vassals";
36- paths = mapAttrsToList (n: c: pkgs.writeTextDir "${n}.json" (buildCfg c)) c.vassals;
37- };
38- } // removeAttrs c [ "type" "vassals" ]
39- else abort "type should be either 'normal' or 'emperor'";
40- };
4142- uwsgi = pkgs.uwsgi.override {
43- plugins = cfg.plugins;
44- };
00000000000000004546in {
47···71 vassals = {
72 moin = {
73 type = "normal";
74- python2Packages = self: with self; [ moinmoin ];
75 socket = "${config.services.uwsgi.runDir}/uwsgi.sock";
76 };
77 };
78 }
79 '';
80 description = ''
81- uWSGI configuration. This awaits either a path to file or a set which will be made into one.
82- If given a set, it awaits an attribute <literal>type</literal> which can be either <literal>normal</literal>
83- or <literal>emperor</literal>.
008485- For <literal>normal</literal> mode you can specify <literal>python2Packages</literal> and
86- <literal>python3Packages</literal> as functions from libraries set into lists of libraries.
87 For <literal>emperor</literal> mode, you should use <literal>vassals</literal> attribute
88 which should be either a set of names and configurations or a path to a directory.
00089 '';
90 };
91···118 '';
119 serviceConfig = {
120 Type = "notify";
121- ExecStart = "${uwsgi}/bin/uwsgi --uid ${cfg.user} --gid ${cfg.group} --json ${pkgs.writeText "uwsgi.json" (buildCfg cfg.instance)}";
122 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
123 ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
124 NotifyAccess = "main";
···5let
6 cfg = config.services.uwsgi;
78+ uwsgi = pkgs.uwsgi.override {
9+ plugins = cfg.plugins;
010 };
1112+ buildCfg = name: c:
13+ let
14+ plugins =
15+ if any (n: !any (m: m == n) cfg.plugins) (c.plugins or [])
16+ then throw "`plugins` attribute in UWSGI configuration contains plugins not in config.services.uwsgi.plugins"
17+ else c.plugins or cfg.plugins;
18+19+ hasPython = v: filter (n: n == "python${v}") plugins != [];
20+ hasPython2 = hasPython "2";
21+ hasPython3 = hasPython "3";
22+23+ python =
24+ if hasPython2 && hasPython3 then
25+ throw "`plugins` attribute in UWSGI configuration shouldn't contain both python2 and python3"
26+ else if hasPython2 then uwsgi.python2
27+ else if hasPython3 then uwsgi.python3
28+ else null;
29+30+ pythonPackages = pkgs.pythonPackages.override {
31+ inherit python;
32+ self = pythonPackages;
33+ };
34+35+ json = builtins.toJSON {
36+ uwsgi =
37+ if c.type == "normal"
38+ then {
39+ inherit plugins;
40+ } // removeAttrs c [ "type" "pythonPackages" ]
41+ // optionalAttrs (python != null) {
42+ pythonpath = "@PYTHONPATH@";
43+ env = (c.env or {}) // {
44+ PATH = optionalString (c ? env.PATH) "${c.env.PATH}:" + "@PATH@";
45+ };
46+ }
47+ else if c.type == "emperor"
48+ then {
49+ emperor = if builtins.typeOf c.vassals != "set" then c.vassals
50+ else pkgs.buildEnv {
51+ name = "vassals";
52+ paths = mapAttrsToList buildCfg c.vassals;
53+ };
54+ } // removeAttrs c [ "type" "vassals" ]
55+ else throw "`type` attribute in UWSGI configuration should be either 'normal' or 'emperor'";
56+ };
5758+ in
59+ if python == null || c.type != "normal"
60+ then pkgs.writeTextDir "${name}.json" json
61+ else pkgs.stdenv.mkDerivation {
62+ name = "uwsgi-config";
63+ inherit json;
64+ passAsFile = [ "json" ];
65+ nativeBuildInputs = [ pythonPackages.wrapPython ];
66+ pythonInputs = (c.pythonPackages or (self: [])) pythonPackages;
000000000000006768+ buildCommand = ''
69+ mkdir $out
70+ declare -A pythonPathsSeen=()
71+ program_PYTHONPATH=
72+ program_PATH=
73+ if [ -n "$pythonInputs" ]; then
74+ for i in $pythonInputs; do
75+ _addToPythonPath $i
76+ done
77+ fi
78+ # A hack to replace "@PYTHONPATH@" with a JSON list
79+ if [ -n "$program_PYTHONPATH" ]; then
80+ program_PYTHONPATH="\"''${program_PYTHONPATH//:/\",\"}\""
81+ fi
82+ substitute $jsonPath $out/${name}.json \
83+ --replace '"@PYTHONPATH@"' "[$program_PYTHONPATH]" \
84+ --subst-var-by PATH "$program_PATH"
85+ '';
86+ };
8788in {
89···113 vassals = {
114 moin = {
115 type = "normal";
116+ pythonPackages = self: with self; [ moinmoin ];
117 socket = "${config.services.uwsgi.runDir}/uwsgi.sock";
118 };
119 };
120 }
121 '';
122 description = ''
123+ uWSGI configuration. It awaits an attribute <literal>type</literal> inside which can be either
124+ <literal>normal</literal> or <literal>emperor</literal>.
125+126+ For <literal>normal</literal> mode you can specify <literal>pythonPackages</literal> as a function
127+ from libraries set into a list of libraries. <literal>pythonpath</literal> will be set accordingly.
12800129 For <literal>emperor</literal> mode, you should use <literal>vassals</literal> attribute
130 which should be either a set of names and configurations or a path to a directory.
131+132+ Other attributes will be used in configuration file as-is. Notice that you can redefine
133+ <literal>plugins</literal> setting here.
134 '';
135 };
136···163 '';
164 serviceConfig = {
165 Type = "notify";
166+ ExecStart = "${uwsgi}/bin/uwsgi --uid ${cfg.user} --gid ${cfg.group} --json ${buildCfg "server" cfg.instance}/server.json";
167 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
168 ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
169 NotifyAccess = "main";