diff options
Diffstat (limited to 'systems/eldiron/websites/cloud/farm.nix')
-rw-r--r-- | systems/eldiron/websites/cloud/farm.nix | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/systems/eldiron/websites/cloud/farm.nix b/systems/eldiron/websites/cloud/farm.nix new file mode 100644 index 0000000..df24cba --- /dev/null +++ b/systems/eldiron/websites/cloud/farm.nix | |||
@@ -0,0 +1,221 @@ | |||
1 | { lib, pkgs, config, ... }: | ||
2 | let | ||
3 | scfg = config.secrets.fullPaths; | ||
4 | cfg = config.myServices.tools.cloud.farm; | ||
5 | apacheUser = config.services.websites.env.production.user; | ||
6 | apacheGroup = config.services.websites.env.production.group; | ||
7 | additionalConfs = icfg: lib.attrsets.mapAttrs (n: v: pkgs.writeText "${n}.json" (builtins.toJSON v)) icfg.rootDir.otherConfig; | ||
8 | overrideConfig = icfg: pkgs.writeText "override.config.php" '' | ||
9 | <?php | ||
10 | $CONFIG = json_decode(file_get_contents("${icfg.configOverride}"), TRUE); | ||
11 | ''; | ||
12 | toVhost = icfg: '' | ||
13 | SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 | ||
14 | SetEnv NEXTCLOUD_CONFIG_DIR "${icfg.varDir}/config" | ||
15 | <Directory ${icfg.rootDir}> | ||
16 | AcceptPathInfo On | ||
17 | DirectoryIndex index.php | ||
18 | Options FollowSymlinks | ||
19 | Require all granted | ||
20 | AllowOverride all | ||
21 | |||
22 | <IfModule mod_headers.c> | ||
23 | Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" | ||
24 | </IfModule> | ||
25 | <FilesMatch "\.php$"> | ||
26 | CGIPassAuth on | ||
27 | SetHandler "proxy:unix:${config.services.phpfpm.pools.${icfg.phpPoolName}.socket}|fcgi://localhost" | ||
28 | </FilesMatch> | ||
29 | |||
30 | </Directory> | ||
31 | ''; | ||
32 | in | ||
33 | { | ||
34 | options.myServices.tools.cloud.farm = { | ||
35 | instances = lib.mkOption { | ||
36 | description = "Instances names for the nextcloud Farm"; | ||
37 | default = {}; | ||
38 | type = lib.types.attrsOf (lib.types.submodule ({ name, config, ... }: { | ||
39 | options = { | ||
40 | nextcloud = lib.mkOption { | ||
41 | description = "Nextcloud version to use"; | ||
42 | default = pkgs.webapps-nextcloud_27; | ||
43 | type = lib.types.package; | ||
44 | }; | ||
45 | apps = lib.mkOption { | ||
46 | description = "Applications to use"; | ||
47 | default = a: []; | ||
48 | #type = functionTo (listOf packages) | ||
49 | type = lib.types.unspecified; | ||
50 | }; | ||
51 | config = lib.mkOption { | ||
52 | description = "Config keys"; | ||
53 | default = {}; | ||
54 | type = lib.types.attrsOf lib.types.unspecified; | ||
55 | }; | ||
56 | secretsPath = lib.mkOption { | ||
57 | description = "Path in secrets to nextcloud config file"; | ||
58 | default = "websites/${name}/nextcloud"; | ||
59 | type = lib.types.str; | ||
60 | }; | ||
61 | configOverride = lib.mkOption { | ||
62 | description = "Path to config override"; | ||
63 | readOnly = true; | ||
64 | default = scfg."${config.secretsPath}"; | ||
65 | type = lib.types.path; | ||
66 | }; | ||
67 | phpPackage = lib.mkOption { | ||
68 | description = "PHP package to use"; | ||
69 | default = pkgs.php81; | ||
70 | type = lib.types.package; | ||
71 | apply = v: (v.withExtensions({ enabled, all }: enabled ++ [ all.redis all.apcu all.opcache all.imagick all.sysvsem ])).override { extraConfig = '' | ||
72 | apc.enable_cli = 1 | ||
73 | apc.enabled = 1 | ||
74 | ''; | ||
75 | }; | ||
76 | }; | ||
77 | rootDir = lib.mkOption { | ||
78 | description = "Instance root dirs"; | ||
79 | readOnly = true; | ||
80 | type = lib.types.package; | ||
81 | default = config.nextcloud.withApps config.apps; | ||
82 | }; | ||
83 | phpPoolName = lib.mkOption { | ||
84 | description = "Php pool name for the instance"; | ||
85 | readOnly = true; | ||
86 | type = lib.types.str; | ||
87 | default = "nextcloud_farm_" + name; | ||
88 | }; | ||
89 | phpBaseDir = lib.mkOption { | ||
90 | description = "Php basedir for the instance"; | ||
91 | readOnly = true; | ||
92 | type = lib.types.str; | ||
93 | default = builtins.concatStringsSep ":" ( | ||
94 | [ config.rootDir config.varDir ] | ||
95 | ++ config.rootDir.apps | ||
96 | ++ [ config.configOverride (overrideConfig config) ] | ||
97 | ++ (builtins.attrValues (additionalConfs config)) | ||
98 | ); | ||
99 | }; | ||
100 | varDir = lib.mkOption { | ||
101 | description = "Instance var dir"; | ||
102 | type = lib.types.path; | ||
103 | default = "/var/lib/nextcloud_farm/${name}"; | ||
104 | }; | ||
105 | vhost = lib.mkOption { | ||
106 | description = "Instance vhost config"; | ||
107 | readOnly = true; | ||
108 | type = lib.types.str; | ||
109 | default = toVhost config; | ||
110 | }; | ||
111 | }; | ||
112 | })); | ||
113 | }; | ||
114 | }; | ||
115 | |||
116 | config = lib.mkIf (builtins.length (builtins.attrNames cfg.instances) > 0) { | ||
117 | systemd.services = lib.mapAttrs' (k: v: lib.nameValuePair ("phpfpm-" + v.phpPoolName) { | ||
118 | after = lib.mkAfter [ "postgresql.service" ]; | ||
119 | wants = [ "postgresql.service" ]; | ||
120 | serviceConfig.ExecStartPre = | ||
121 | "+${pkgs.writeScript "phpfpm-nextcloud-${k}-pre-start" '' | ||
122 | #!${pkgs.stdenv.shell} | ||
123 | |||
124 | install -m 0755 -o wwwrun -g wwwrun -d ${v.varDir} -d ${v.varDir}/config | ||
125 | ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (n: f: | ||
126 | "ln -sf ${f} ${v.varDir}/config/${n}.json" | ||
127 | ) (additionalConfs v))} | ||
128 | ln -sf ${overrideConfig v} ${v.varDir}/config/override.config.php | ||
129 | ''}"; | ||
130 | }) cfg.instances; | ||
131 | services.phpfpm.pools = lib.mapAttrs' (k: v: lib.nameValuePair v.phpPoolName { | ||
132 | user = apacheUser; | ||
133 | group = apacheGroup; | ||
134 | settings = { | ||
135 | "listen.owner" = apacheUser; | ||
136 | "listen.group" = apacheGroup; | ||
137 | "pm" = "dynamic"; | ||
138 | "pm.max_children" = "60"; | ||
139 | "pm.start_servers" = "3"; | ||
140 | "pm.min_spare_servers" = "3"; | ||
141 | "pm.max_spare_servers" = "3"; | ||
142 | "pm.process_idle_timeout" = "60"; | ||
143 | |||
144 | "php_admin_value[output_buffering]" = "0"; | ||
145 | "php_admin_value[max_execution_time]" = "1800"; | ||
146 | "php_admin_value[zend_extension]" = "opcache"; | ||
147 | "php_value[apc.enable_cli]" = "1"; | ||
148 | "php_value[apc.enabled]" = "1"; | ||
149 | #already enabled by default? | ||
150 | #"php_value[opcache.enable]" = "1"; | ||
151 | "php_value[opcache.enable_cli]" = "1"; | ||
152 | "php_value[opcache.interned_strings_buffer]" = "32"; | ||
153 | "php_value[opcache.max_accelerated_files]" = "10000"; | ||
154 | "php_value[opcache.memory_consumption]" = "128"; | ||
155 | "php_value[opcache.save_comments]" = "1"; | ||
156 | "php_value[opcache.revalidate_freq]" = "1"; | ||
157 | "php_admin_value[memory_limit]" = "512M"; | ||
158 | |||
159 | "php_admin_value[open_basedir]" = "/run/wrappers/bin/sendmail:${v.phpBaseDir}:/proc/cpuinfo:/proc/meminfo:/dev/urandom:/proc/self/fd:/tmp"; | ||
160 | "php_admin_value[session.save_handler]" = "redis"; | ||
161 | "php_admin_value[session.save_path]" = "'unix:///run/redis-php-sessions/redis.sock?persistent=1&prefix=Tools:NextcloudFarm:${k}:'"; | ||
162 | }; | ||
163 | phpPackage = v.phpPackage; | ||
164 | }) cfg.instances; | ||
165 | environment.systemPackages = let | ||
166 | toOcc = name: icfg: pkgs.writeScriptBin "nextcloud-occ-${name}" '' | ||
167 | #! ${pkgs.stdenv.shell} | ||
168 | cd ${icfg.rootDir} | ||
169 | NEXTCLOUD_CONFIG_DIR="${icfg.varDir}/config" \ | ||
170 | exec \ | ||
171 | sudo -E -u wwwrun ${icfg.phpPackage}/bin/php \ | ||
172 | -d memory_limit=512M \ | ||
173 | -c ${icfg.phpPackage}/etc/php.ini \ | ||
174 | occ $* | ||
175 | ''; | ||
176 | in lib.mapAttrsToList toOcc cfg.instances; | ||
177 | services.cron = { | ||
178 | enable = true; | ||
179 | systemCronJobs = let | ||
180 | toScript = name: icfg: pkgs.writeScriptBin "nextcloud-cron" '' | ||
181 | #! ${pkgs.stdenv.shell} | ||
182 | export LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive | ||
183 | export PATH=/run/wrappers/bin:$PATH | ||
184 | export NEXTCLOUD_CONFIG_DIR="${icfg.varDir}/config" | ||
185 | ${icfg.phpPackage}/bin/php -c ${icfg.phpPackage}/etc/php.ini -d memory_limit=512M -f ${icfg.rootDir}/cron.php | ||
186 | ''; | ||
187 | toLine = name: icfg: '' | ||
188 | */5 * * * * wwwrun ${toScript name icfg}/bin/nextcloud-cron | ||
189 | ''; | ||
190 | in lib.mapAttrsToList toLine cfg.instances; | ||
191 | }; | ||
192 | |||
193 | secrets.keys = lib.mapAttrs' (name: v: lib.nameValuePair "${v.secretsPath}" { | ||
194 | user = "wwwrun"; | ||
195 | group = "wwwrun"; | ||
196 | permissions = "0600"; | ||
197 | # Be careful when editing that: config from this file takes | ||
198 | # precedence over the regular one, but if a key got removed, it my | ||
199 | # still exist in the default config file | ||
200 | text = builtins.toJSON ( { | ||
201 | "datadirectory" = if name == "immae" then v.varDir else "${v.varDir}/data"; | ||
202 | |||
203 | "appstoreenabled" = false; | ||
204 | "integrity.check.disabled" = true; | ||
205 | "updater.release.channel" = "stable"; | ||
206 | "upgrade.disable-web" = true; | ||
207 | |||
208 | "memcache.local" = "\\OC\\Memcache\\APCu"; | ||
209 | |||
210 | "htaccess.RewriteBase" = "/"; | ||
211 | |||
212 | "loglevel" = 2; | ||
213 | "logtimezone" = "Europe/Paris"; | ||
214 | |||
215 | "default_phone_region" = "FR"; | ||
216 | "skeletondirectory" = ""; | ||
217 | "theme" = ""; | ||
218 | } // v.config); | ||
219 | }) cfg.instances; | ||
220 | }; | ||
221 | } | ||