]> git.immae.eu Git - perso/Immae/Config/Nix.git/blame - virtual/eldiron.nix
Continue moving websites: apache configuration and modules
[perso/Immae/Config/Nix.git] / virtual / eldiron.nix
CommitLineData
a1bb33c4
IB
1{
2 network = {
3 description = "Immae's network";
4 enableRollback = true;
5 };
6
4d4f13f4
IB
7 eldiron = { config, pkgs, mylibs, ... }:
8 with mylibs;
5c101474 9 let
712ccefd 10 mypkgs = pkgs.callPackage ./packages.nix {
eb770e14 11 inherit checkEnv fetchedGit fetchedGitPrivate fetchedGithub;
5c101474 12 };
ab5d04b8
IB
13 in
14 {
4d4f13f4
IB
15 _module.args = {
16 mylibs = import ../libs.nix;
17 };
18
19 imports = [
3013caf1 20 ./modules/certificates.nix
4d4f13f4
IB
21 ./modules/gitolite.nix
22 ./modules/gitweb.nix
23 ./modules/databases.nix
42429ef0 24 ./modules/websites.nix
4d4f13f4
IB
25 ];
26 services.myGitolite.enable = true;
27 services.myGitweb.enable = true;
28 services.myDatabases.enable = true;
42429ef0
IB
29 services.myWebsites.production.enable = true;
30 services.myWebsites.integration.enable = true;
4d4f13f4 31
91493dc0 32 nixpkgs.config.packageOverrides = oldpkgs: rec {
6f0d92b4
IB
33 goaccess = oldpkgs.goaccess.overrideAttrs(old: rec {
34 name = "goaccess-${version}";
35 version = "1.3";
36 src = pkgs.fetchurl {
37 url = "https://tar.goaccess.io/${name}.tar.gz";
38 sha256 = "16vv3pj7pbraq173wlxa89jjsd279004j4kgzlrsk1dz4if5qxwc";
39 };
40 configureFlags = old.configureFlags ++ [ "--enable-tcb=btree" ];
41 buildInputs = old.buildInputs ++ [ pkgs.tokyocabinet pkgs.bzip2 ];
42 });
91493dc0
IB
43 };
44
a1bb33c4
IB
45 networking = {
46 firewall = {
47 enable = true;
4d4f13f4 48 allowedTCPPorts = [ 22 80 443 9418 ];
a1bb33c4
IB
49 };
50 };
51
52 deployment = {
53 targetEnv = "hetzner";
54 hetzner = {
55 #robotUser = "defined in HETZNER_ROBOT_USER";
56 #robotPass = "defined in HETZNER_ROBOT_PASS";
57 mainIPv4 = "176.9.151.89";
58 partitions = ''
59 clearpart --all --initlabel --drives=sda,sdb
60
61 part swap1 --recommended --label=swap1 --fstype=swap --ondisk=sda
62 part swap2 --recommended --label=swap2 --fstype=swap --ondisk=sdb
63
64 part raid.1 --grow --ondisk=sda
65 part raid.2 --grow --ondisk=sdb
66
67 raid / --level=1 --device=md0 --fstype=ext4 --label=root raid.1 raid.2
68 '';
69 };
70 };
71
66b5bbf6
IB
72 environment.systemPackages = let
73 # FIXME: move it to nextcloud
74 occ = pkgs.writeScriptBin "nextcloud-occ" ''
75 #! ${pkgs.stdenv.shell}
76 cd ${mypkgs.nextcloud.webRoot}
77 NEXTCLOUD_CONFIG_DIR="${mypkgs.nextcloud.webRoot}/config" \
78 exec \
79 ${config.services.phpfpm.phpPackage}/bin/php \
80 -c ${config.services.phpfpm.phpPackage}/etc/php.ini \
81 occ $*
82 '';
83 in [
ce6ee3b8 84 pkgs.telnet
beeed847 85 pkgs.htop
ce6ee3b8 86 pkgs.vim
6f0d92b4 87 pkgs.goaccess
66b5bbf6 88 occ
ce6ee3b8
IB
89 ];
90
3013caf1
IB
91 security.acme.certs."eldiron".extraDomains = {
92 "db-1.immae.eu" = null;
93 "tools.immae.eu" = null;
94 "cloud.immae.eu" = null;
95 "dav.immae.eu" = null;
a1bb33c4
IB
96 };
97
5566d26d
IB
98 services.openssh.extraConfig = ''
99 AuthorizedKeysCommand /etc/ssh/ldap_authorized_keys
100 AuthorizedKeysCommandUser nobody
101 '';
102
beeed847 103 services.ympd = mypkgs.ympd.config // { enable = false; };
a05f8abe 104
58d1a782 105 services.phpfpm = {
beeed847 106 # FIXME: move session files to separate dirs
66b5bbf6
IB
107 # /!\ phppackage is used in nextcloud configuation
108 phpOptions = ''
c8e019b6
IB
109 session.save_path = "/var/lib/php/sessions"
110 session.gc_maxlifetime = 60*60*24*15
111 session.cache_expire = 60*24*30
66b5bbf6
IB
112 ; For nextcloud
113 extension=${pkgs.phpPackages.redis}/lib/php/extensions/redis.so
114 ; For nextcloud
115 extension=${pkgs.phpPackages.apcu}/lib/php/extensions/apcu.so
ec9ff2b8
IB
116 ; For nextcloud
117 zend_extension=${pkgs.php}/lib/php/extensions/opcache.so
66b5bbf6 118 '';
58d1a782
IB
119 extraConfig = ''
120 log_level = notice
121 '';
122 poolConfigs = {
27e22b76 123 adminer = mypkgs.adminer.phpFpm.pool;
66b5bbf6 124 nextcloud = mypkgs.nextcloud.phpFpm.pool;
50d8fa14 125 mantisbt = mypkgs.mantisbt.phpFpm.pool;
eb770e14 126 ttrss = mypkgs.ttrss.phpFpm.pool;
d252d718 127 roundcubemail = mypkgs.roundcubemail.phpFpm.pool;
d9998b44 128 davical = mypkgs.davical.phpFpm.pool;
58d1a782
IB
129 };
130 };
131
65fe7543 132 system.activationScripts = {
66b5bbf6 133 nextcloud = mypkgs.nextcloud.activationScript;
eb770e14 134 ttrss = mypkgs.ttrss.activationScript;
d252d718 135 roundcubemail = mypkgs.roundcubemail.activationScript;
5dd28b43
IB
136 httpd = ''
137 install -d -m 0755 /var/lib/acme/acme-challenge
c8e019b6
IB
138 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions
139 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/adminer
140 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/mantisbt
eb770e14 141 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/ttrss
1635a4ae 142 install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/davical
5dd28b43 143 '';
6bd6d033 144 # FIXME: initial sync
6f0d92b4
IB
145 goaccess = ''
146 mkdir -p /var/lib/goaccess
147 mkdir -p /var/lib/goaccess/aten.pro
34e2fd14
IB
148 mkdir -p /var/lib/goaccess/ludivinecassal.com
149 mkdir -p /var/lib/goaccess/piedsjaloux.fr
6bd6d033 150 mkdir -p /var/lib/goaccess/osteopathe-cc.fr
527e32ad 151 mkdir -p /var/lib/goaccess/connexionswing.com
6f0d92b4 152 '';
5566d26d
IB
153 };
154
155 environment.etc."ssh/ldap_authorized_keys" = let
156 ldap_authorized_keys =
5c101474
IB
157 assert checkEnv "NIXOPS_SSHD_LDAP_PASSWORD";
158 wrap {
5566d26d
IB
159 name = "ldap_authorized_keys";
160 file = ./ldap_authorized_keys.sh;
161 vars = {
162 LDAP_PASS = builtins.getEnv "NIXOPS_SSHD_LDAP_PASSWORD";
163 GITOLITE_SHELL = "${pkgs.gitolite}/bin/gitolite-shell";
164 ECHO = "${pkgs.coreutils}/bin/echo";
165 };
166 paths = [ pkgs.openldap pkgs.stdenv.shellPackage pkgs.gnugrep pkgs.gnused pkgs.coreutils ];
167 };
168 in {
169 enable = true;
170 mode = "0755";
171 user = "root";
172 source = ldap_authorized_keys;
65fe7543
IB
173 };
174
7611e4e2
IB
175 services.gitDaemon = {
176 enable = true;
177 user = "gitolite";
178 group = "gitolite";
179 basePath = "${mypkgs.git.web.varDir}/repositories";
180 };
181
beeed847 182 # FIXME: logrotate
58d1a782 183 services.httpd = let
b7cd7e4b 184 withConf = domain: {
58d1a782 185 enableSSL = true;
5dd28b43 186 sslServerCert = "/var/lib/acme/${domain}/cert.pem";
58d1a782
IB
187 sslServerKey = "/var/lib/acme/${domain}/key.pem";
188 sslServerChain = "/var/lib/acme/${domain}/fullchain.pem";
b7cd7e4b
IB
189 logFormat = "combinedVhost";
190 listen = [ { ip = "*"; port = 443; } ];
58d1a782 191 };
42429ef0 192 apacheConfig = config.services.myWebsites.apacheConfig;
58d1a782 193 in rec {
a1bb33c4 194 enable = true;
58d1a782
IB
195 logPerVirtualHost = true;
196 multiProcessingModule = "worker";
197 adminAddr = "httpd@immae.eu";
b7cd7e4b 198 logFormat = "combinedVhost";
25fd1d16
IB
199 extraModules = pkgs.lib.lists.unique (
200 mypkgs.adminer.apache.modules ++
66b5bbf6 201 mypkgs.nextcloud.apache.modules ++
5f3e023d 202 mypkgs.ympd.apache.modules ++
cf80b4f2 203 mypkgs.git.web.apache.modules ++
50d8fa14 204 mypkgs.mantisbt.apache.modules ++
eb770e14 205 mypkgs.ttrss.apache.modules ++
d252d718 206 mypkgs.roundcubemail.apache.modules ++
42429ef0 207 pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) apacheConfig));
94818b75 208 extraConfig = builtins.concatStringsSep "\n"
42429ef0 209 (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) apacheConfig));
58d1a782 210 virtualHosts = [
b7cd7e4b 211 (withConf "eldiron" // {
58d1a782 212 hostName = "eldiron.immae.eu";
1d4ccb2c
IB
213 documentRoot = ./www;
214 extraConfig = ''
215 DirectoryIndex index.htm
216 '';
58d1a782 217 })
b7cd7e4b 218 (withConf "eldiron" // {
58d1a782
IB
219 hostName = "db-1.immae.eu";
220 documentRoot = null;
27e22b76 221 extraConfig = builtins.concatStringsSep "\n" [
1bb2ff2c 222 mypkgs.adminer.apache.vhostConf
27e22b76 223 ];
58d1a782 224 })
b7cd7e4b 225 (withConf "eldiron" // {
e379fd29
IB
226 hostName = "tools.immae.eu";
227 documentRoot = null;
228 extraConfig = builtins.concatStringsSep "\n" [
1bb2ff2c 229 mypkgs.adminer.apache.vhostConf
a05f8abe 230 mypkgs.ympd.apache.vhostConf
eb770e14 231 mypkgs.ttrss.apache.vhostConf
d252d718 232 mypkgs.roundcubemail.apache.vhostConf
43b726ed
IB
233 ];
234 })
235 (withConf "eldiron" // {
236 hostName = "dav.immae.eu";
237 documentRoot = null;
238 extraConfig = builtins.concatStringsSep "\n" [
1635a4ae 239 mypkgs.infcloud.apache.vhostConf
d9998b44 240 mypkgs.davical.apache.vhostConf
e379fd29
IB
241 ];
242 })
b7cd7e4b 243 (withConf "eldiron" // {
65fe7543
IB
244 hostName = "connexionswing.immae.eu";
245 serverAliases = [ "sandetludo.immae.eu" ];
246 documentRoot = mypkgs.connexionswing_dev.webRoot;
247 extraConfig = builtins.concatStringsSep "\n" [
248 mypkgs.connexionswing_dev.apache.vhostConf
249 ];
250 })
527e32ad
IB
251 (withConf "connexionswing" // {
252 hostName = "connexionswing.com";
253 serverAliases = [ "sandetludo.com" "www.connexionswing.com" "www.sandetludo.com" ];
254 documentRoot = mypkgs.connexionswing_prod.webRoot;
255 extraConfig = builtins.concatStringsSep "\n" [
256 mypkgs.connexionswing_prod.apache.vhostConf
257 ];
258 })
e42ba74f
IB
259 (withConf "eldiron" // {
260 hostName = "ludivine.immae.eu";
261 documentRoot = mypkgs.ludivinecassal_dev.webRoot;
262 extraConfig = builtins.concatStringsSep "\n" [
263 mypkgs.ludivinecassal_dev.apache.vhostConf
264 ];
265 })
266 (withConf "ludivinecassal" // {
267 hostName = "ludivinecassal.com";
268 serverAliases = [ "www.ludivinecassal.com" ];
269 documentRoot = mypkgs.ludivinecassal_prod.webRoot;
270 extraConfig = builtins.concatStringsSep "\n" [
271 mypkgs.ludivinecassal_prod.apache.vhostConf
272 ];
273 })
34e2fd14
IB
274 (withConf "eldiron" // {
275 hostName = "piedsjaloux.immae.eu";
276 documentRoot = mypkgs.piedsjaloux_dev.webRoot;
277 extraConfig = builtins.concatStringsSep "\n" [
278 mypkgs.piedsjaloux_dev.apache.vhostConf
279 ];
280 })
281 (withConf "piedsjaloux" // {
282 hostName = "piedsjaloux.fr";
283 serverAliases = [ "www.piedsjaloux.fr" ];
284 documentRoot = mypkgs.piedsjaloux_prod.webRoot;
285 extraConfig = builtins.concatStringsSep "\n" [
286 mypkgs.piedsjaloux_prod.apache.vhostConf
287 ];
288 })
7d8b50d3
IB
289 (withConf "eldiron" // {
290 hostName = "chloe.immae.eu";
291 documentRoot = mypkgs.chloe_dev.webRoot;
292 extraConfig = builtins.concatStringsSep "\n" [
293 mypkgs.chloe_dev.apache.vhostConf
294 ];
295 })
6bd6d033 296 (withConf "chloe" // {
7d8b50d3
IB
297 hostName = "osteopathe-cc.fr";
298 serverAliases = [ "www.osteopathe-cc.fr" ];
299 documentRoot = mypkgs.chloe_prod.webRoot;
300 extraConfig = builtins.concatStringsSep "\n" [
301 mypkgs.chloe_prod.apache.vhostConf
302 ];
303 })
6c672f34
IB
304 (withConf "eldiron" // {
305 hostName = "dev.aten.pro";
306 documentRoot = mypkgs.aten_dev.webRoot;
307 extraConfig = builtins.concatStringsSep "\n" [
308 mypkgs.aten_dev.apache.vhostConf
309 ];
310 })
311 (withConf "aten" // {
312 hostName = "aten.pro";
313 serverAliases = [ "www.aten.pro" ];
314 documentRoot = mypkgs.aten_prod.webRoot;
315 extraConfig = builtins.concatStringsSep "\n" [
316 mypkgs.aten_prod.apache.vhostConf
317 ];
318 })
b7cd7e4b 319 (withConf "eldiron" // {
66b5bbf6
IB
320 hostName = "cloud.immae.eu";
321 documentRoot = mypkgs.nextcloud.webRoot;
322 extraConfig = builtins.concatStringsSep "\n" [
323 mypkgs.nextcloud.apache.vhostConf
324 ];
325 })
b7cd7e4b 326 (withConf "eldiron" // {
cf80b4f2
IB
327 hostName = "git.immae.eu";
328 documentRoot = mypkgs.git.web.webRoot;
329 extraConfig = builtins.concatStringsSep "\n" [
330 mypkgs.git.web.apache.vhostConf
50d8fa14 331 mypkgs.mantisbt.apache.vhostConf
cf80b4f2
IB
332 ] + ''
333 RewriteEngine on
334 RewriteCond %{REQUEST_URI} ^/releases
335 RewriteRule /releases(.*) https://release.immae.eu$1 [P,L]
336 '';
337 })
58d1a782
IB
338 { # Should go last, default fallback
339 listen = [ { ip = "*"; port = 80; } ];
340 hostName = "redirectSSL";
341 serverAliases = [ "*" ];
342 enableSSL = false;
b7cd7e4b 343 logFormat = "combinedVhost";
58d1a782
IB
344 documentRoot = "/var/lib/acme/acme-challenge";
345 extraConfig = ''
346 RewriteEngine on
347 RewriteCond "%{REQUEST_URI}" "!^/\.well-known"
348 RewriteRule ^(.+) https://%{HTTP_HOST}$1 [R=301]
349 # To redirect in specific "VirtualHost *:80", do
350 # RedirectMatch 301 ^/((?!\.well-known.*$).*)$ https://host/$1
351 # rather than rewrite
352 '';
353 }
43b726ed 354 ];
58d1a782
IB
355 };
356
6f0d92b4
IB
357 services.cron = {
358 enable = true;
359 systemCronJobs = let
6bd6d033 360 stats = domain: conf: let
0facadb8
IB
361 d = pkgs.writeScriptBin "stats-${domain}" ''
362 #!${pkgs.stdenv.shell}
363 set -e
364 shopt -s nullglob
365 date_regex=$(LC_ALL=C date -d yesterday +'%d\/%b\/%Y')
366 TMPFILE=$(mktemp)
367 trap "rm -f $TMPFILE" EXIT
368
369 cat /var/log/httpd/access_log-${domain} | sed -n "/\\[$date_regex/ p" > $TMPFILE
370 for i in /var/log/httpd/access_log-${domain}*.gz; do
371 zcat "$i" | sed -n "/\\[$date_regex/ p" >> $TMPFILE
372 done
373 goaccess $TMPFILE --no-progress -o /var/lib/goaccess/${domain}/index.html -p ${conf}
374 '';
6bd6d033 375 in "${d}/bin/stats-${domain}";
56991aa7
IB
376 # FIXME: running several goaccess simultaneously seems to be
377 # bugged?
6f0d92b4
IB
378 in [
379 "5 0 * * * root ${stats "aten.pro" ./packages/aten_goaccess.conf}"
56991aa7
IB
380 "6 0 * * * root ${stats "ludivinecassal.com" ./packages/ludivinecassal_goaccess.conf}"
381 "7 0 * * * root ${stats "piedsjaloux.fr" ./packages/piedsjaloux_goaccess.conf}"
382 "8 0 * * * root ${stats "osteopathe-cc.fr" ./packages/chloe_goaccess.conf}"
383 "9 0 * * * root ${stats "connexionswing.com" ./packages/connexionswing_goaccess.conf}"
6f0d92b4
IB
384 ];
385 };
eb770e14
IB
386
387 systemd.services.tt-rss = {
388 description = "Tiny Tiny RSS feeds update daemon";
389 serviceConfig = {
390 User = "wwwrun";
391 ExecStart = "${pkgs.php}/bin/php ${mypkgs.ttrss.webRoot}/update.php --daemon";
392 StandardOutput = "syslog";
393 StandardError = "syslog";
394 PermissionsStartOnly = true;
395 };
396
397 wantedBy = [ "multi-user.target" ];
398 requires = ["postgresql.service"];
399 after = ["network.target" "postgresql.service"];
400 };
a1bb33c4
IB
401 };
402}