]> git.immae.eu Git - perso/Immae/Config/Nix/NUR.git/blame - modules/websites/php-application.nix
Finish moving aten php configuration to dedicated module
[perso/Immae/Config/Nix/NUR.git] / modules / websites / php-application.nix
CommitLineData
969cc469
IB
1{ lib, config, ... }:
2with lib;
3let
4 cfg = config.services.phpApplication;
55ebe7be 5 cfgByEnv = lists.groupBy (x: x.websiteEnv) (builtins.attrValues cfg.apps);
969cc469
IB
6in
7{
55ebe7be
IB
8 options = with types; {
9 services.phpApplication.apps = mkOption {
969cc469
IB
10 default = {};
11 description = ''
12 php applications to define
13 '';
14 type = attrsOf (submodule {
15 options = {
16 varDir = mkOption {
17 type = nullOr path;
18 description = ''
19 Path to application’s vardir.
20 '';
21 };
22 mode = mkOption {
23 type = str;
24 default = "0700";
25 description = ''
26 Mode to apply to the vardir
27 '';
28 };
29 phpSession = mkOption {
30 type = bool;
31 default = true;
32 description = "Handle phpsession files separately in vardir";
33 };
55ebe7be
IB
34 phpListen = mkOption {
35 type = nullOr str;
36 default = null;
37 description = "Name of the socket to listen to. Defaults to app name if null";
38 };
39 phpPool = mkOption {
40 type = lines;
41 default = "";
42 description = "Pool configuration to append";
43 };
44 phpOptions = mkOption {
45 type = lines;
46 default = "";
47 description = "php configuration to append";
48 };
49 phpOpenbasedir = mkOption {
50 type = listOf path;
51 default = [];
52 description = ''
53 paths to add to php open_basedir configuration in addition to app and vardir
54 '';
55 };
56 phpWatchFiles = mkOption {
57 type = listOf path;
58 default = [];
59 description = ''
60 Path to other files to watch to trigger preStart scripts
61 '';
62 };
969cc469
IB
63 websiteEnv = mkOption {
64 type = str;
65 description = ''
66 website instance name to use
67 '';
68 };
69 httpdUser = mkOption {
70 type = str;
71 default = config.services.httpd.user;
72 description = ''
73 httpd user to run the prestart scripts as.
74 '';
75 };
76 httpdGroup = mkOption {
77 type = str;
78 default = config.services.httpd.group;
79 description = ''
80 httpd group to run the prestart scripts as.
81 '';
82 };
55ebe7be
IB
83 httpdWatchFiles = mkOption {
84 type = listOf path;
85 default = [];
86 description = ''
87 Path to other files to watch to trigger httpd reload
88 '';
89 };
969cc469
IB
90 app = mkOption {
91 type = path;
92 description = ''
93 Path to application root
94 '';
95 };
96 webappName = mkOption {
97 type = nullOr str;
55ebe7be 98 default = null;
969cc469
IB
99 description = ''
100 Alias name for the app, to be used in services.websites.webappDirs
101 '';
102 };
103 webRoot = mkOption {
104 type = nullOr path;
105 description = ''
106 Path to the web root path of the application. May differ from the application itself (usually a subdirectory)
107 '';
108 };
109 preStartActions = mkOption {
110 type = listOf str;
111 default = [];
112 description = ''
113 List of actions to run as apache user at preStart when
114 whatchFiles or app dir changed.
115 '';
116 };
117 serviceDeps = mkOption {
118 type = listOf str;
119 default = [];
120 description = ''
121 List of systemd services this application depends on
122 '';
123 };
969cc469
IB
124 };
125 });
126 };
55ebe7be
IB
127 # Read-only variables
128 services.phpApplication.phpListenPaths = mkOption {
129 type = attrsOf path;
130 default = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair
131 name "/run/phpfpm/${if icfg.phpListen == null then name else icfg.phpListen}.sock"
132 ) cfg.apps;
133 readOnly = true;
134 description = ''
135 Full paths to listen for php
136 '';
137 };
138 services.phpApplication.webappDirs = mkOption {
139 type = attrsOf path;
140 default = attrsets.filterAttrs (n: v: builtins.hasAttr n cfg.apps) config.services.websites.webappDirsPaths;
141 readOnly = true;
142 description = ''
143 Stable name webapp dirs for httpd
144 '';
145 };
969cc469
IB
146 };
147
148 config = {
589aeb92 149 services.websites.env = attrsets.mapAttrs' (name: cfgs: attrsets.nameValuePair
969cc469
IB
150 name {
151 modules = [ "proxy_fcgi" ];
55ebe7be 152 watchPaths = builtins.concatLists (map (c: c.httpdWatchFiles) cfgs);
969cc469
IB
153 }
154 ) cfgByEnv;
155
55ebe7be
IB
156 services.phpfpm.pools = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair
157 name {
158 listen = cfg.phpListenPaths."${name}";
159 extraConfig = ''
160 user = ${icfg.httpdUser}
161 group = ${icfg.httpdGroup}
162 listen.owner = ${icfg.httpdUser}
163 listen.group = ${icfg.httpdGroup}
164 ${optionalString (icfg.phpSession) ''
165 php_admin_value[session.save_path] = "${icfg.varDir}/phpSessions"''}
166 php_admin_value[open_basedir] = "${builtins.concatStringsSep ":" ([icfg.app icfg.varDir] ++ icfg.phpOpenbasedir)}"
167 '' + icfg.phpPool;
168 phpOptions = config.services.phpfpm.phpOptions + icfg.phpOptions;
169 }
170 ) cfg.apps;
171
589aeb92 172 services.websites.webappDirs = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair
55ebe7be
IB
173 (if icfg.webappName == null then name else icfg.webappName) icfg.webRoot
174 ) (attrsets.filterAttrs (n: v: !isNull v.webRoot) cfg.apps);
969cc469
IB
175
176 systemd.services = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair
177 "phpfpm-${name}" {
178 after = lib.mkAfter icfg.serviceDeps;
179 wants = icfg.serviceDeps;
180 preStart = lib.mkAfter (optionalString (!isNull icfg.varDir) ''
181 watchFilesChanged() {
55ebe7be 182 ${optionalString (builtins.length icfg.phpWatchFiles == 0) "return 1"}
969cc469
IB
183 [ ! -f "${icfg.varDir}"/watchedFiles ] \
184 || ! sha512sum -c --status ${icfg.varDir}/watchedFiles
185 }
186 appDirChanged() {
187 [ ! -f "${icfg.varDir}/currentWebappDir" -o \
188 "${icfg.app}" != "$(cat ${icfg.varDir}/currentWebappDir 2>/dev/null)" ]
189 }
190 updateWatchFiles() {
55ebe7be
IB
191 ${optionalString (builtins.length icfg.phpWatchFiles == 0) "return 0"}
192 sha512sum ${builtins.concatStringsSep " " icfg.phpWatchFiles} > ${icfg.varDir}/watchedFiles
969cc469
IB
193 }
194
195 if watchFilesChanged || appDirChanged; then
196 pushd ${icfg.app} > /dev/null
197 ${builtins.concatStringsSep "\n " (map (c: "/run/wrappers/bin/sudo -u ${icfg.httpdUser} ${c}") icfg.preStartActions) }
198 popd > /dev/null
199 echo -n "${icfg.app}" > ${icfg.varDir}/currentWebappDir
200 updateWatchFiles
201 fi
202 '');
203 }
55ebe7be 204 ) cfg.apps;
969cc469
IB
205
206 system.activationScripts = attrsets.mapAttrs' (name: icfg: attrsets.nameValuePair
207 name {
208 deps = [];
209 text = optionalString (!isNull icfg.varDir) ''
210 install -m ${icfg.mode} -o ${icfg.httpdUser} -g ${icfg.httpdGroup} -d ${icfg.varDir}
211 '' + optionalString (icfg.phpSession) ''
212 install -m 0700 -o ${icfg.httpdUser} -g ${icfg.httpdGroup} -d ${icfg.varDir}/phpSessions
213 '';
214 }
55ebe7be 215 ) cfg.apps;
969cc469
IB
216 };
217}