-{ lib, pkgs, config, mylibs, myconfig, ... }:
+{ lib, pkgs, config, myconfig, ... }:
let
cfg = config.services.myWebsites;
www_root = "/run/current-system/webapps/_www";
theme_root = "/run/current-system/webapps/_theme";
- makeService = name: cfg: let
- toVhost = vhostConf: {
- enableSSL = true;
- sslServerCert = "/var/lib/acme/${vhostConf.certName}/cert.pem";
- sslServerKey = "/var/lib/acme/${vhostConf.certName}/key.pem";
- sslServerChain = "/var/lib/acme/${vhostConf.certName}/fullchain.pem";
- logFormat = "combinedVhost";
- listen = map (ip: { inherit ip; port = 443; }) cfg.ips;
- hostName = builtins.head vhostConf.hosts;
- serverAliases = builtins.tail vhostConf.hosts or [];
- documentRoot = vhostConf.root;
- extraConfig = builtins.concatStringsSep "\n" vhostConf.extraConfig;
- };
- nosslVhost = {
- listen = map (ip: { inherit ip; port = 80; }) cfg.ips;
- hostName = "nossl.immae.eu";
- enableSSL = false;
- logFormat = "combinedVhost";
- documentRoot = www_root;
+ apacheConfig = {
+ gzip = {
+ modules = [ "deflate" "filter" ];
extraConfig = ''
- <Directory ${www_root}>
- DirectoryIndex nossl.html
- AllowOverride None
- Require all granted
-
- RewriteEngine on
- RewriteRule ^/(.+) / [L]
- </Directory>
- '';
+ AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript
+ '';
};
- redirectVhost = { # Should go last, catchall http -> https redirect
- listen = map (ip: { inherit ip; port = 80; }) cfg.ips;
- hostName = "redirectSSL";
- serverAliases = [ "*" ];
- enableSSL = false;
- logFormat = "combinedVhost";
- documentRoot = "/var/lib/acme/acme-challenge";
+ macros = {
+ modules = [ "macro" ];
+ };
+ stats = {
extraConfig = ''
- RewriteEngine on
- RewriteCond "%{REQUEST_URI}" "!^/\.well-known"
- RewriteRule ^(.+) https://%{HTTP_HOST}$1 [R=301]
- # To redirect in specific "VirtualHost *:80", do
- # RedirectMatch 301 ^/((?!\.well-known.*$).*)$ https://host/$1
- # rather than rewrite
+ <Macro Stats %{domain}>
+ Alias /webstats ${config.services.webstats.dataDir}/%{domain}
+ <Directory ${config.services.webstats.dataDir}/%{domain}>
+ DirectoryIndex index.html
+ AllowOverride None
+ Require all granted
+ </Directory>
+ <Location /webstats>
+ Use LDAPConnect
+ Require ldap-group cn=%{domain},ou=stats,cn=httpd,ou=services,dc=immae,dc=eu
+ </Location>
+ </Macro>
'';
};
- fallbackVhost = toVhost { # Should go first, default choice
- certName = "eldiron";
- hosts = ["eldiron.immae.eu" ];
- root = www_root;
- extraConfig = [ "DirectoryIndex index.htm" ];
+ ldap = {
+ modules = [ "ldap" "authnz_ldap" ];
+ extraConfig = ''
+ <IfModule ldap_module>
+ LDAPSharedCacheSize 500000
+ LDAPCacheEntries 1024
+ LDAPCacheTTL 600
+ LDAPOpCacheEntries 1024
+ LDAPOpCacheTTL 600
+ </IfModule>
+
+ Include /var/secrets/apache-ldap
+ '';
};
- in rec {
- enable = true;
- listen = map (ip: { inherit ip; port = 443; }) cfg.ips;
- stateDir = "/run/httpd_${name}";
- logPerVirtualHost = true;
- multiProcessingModule = "worker";
- adminAddr = "httpd@immae.eu";
- logFormat = "combinedVhost";
- extraModules = pkgs.lib.lists.unique (pkgs.lib.lists.flatten cfg.modules);
- extraConfig = builtins.concatStringsSep "\n" cfg.extraConfig;
- virtualHosts = [ fallbackVhost ]
- ++ lib.optionals (name == "tools") [ nosslVhost ]
- ++ (pkgs.lib.attrsets.mapAttrsToList (n: v: toVhost v) cfg.vhostConfs)
- ++ [ redirectVhost ];
- };
- makeServiceOptions = name: {
- enable = lib.mkEnableOption "enable websites in ${name}";
- ips = lib.mkOption {
- type = lib.types.listOf lib.types.string;
- default = let
- ips = myconfig.env.servers.eldiron.ips.${name};
- in
- [ips.ip4] ++ (ips.ip6 or []);
- description = "${name} ips to listen to";
+ global = {
+ extraConfig = (pkgs.webapps.apache-default.override { inherit www_root;}).apacheConfig;
};
- modules = lib.mkOption {
- type = lib.types.listOf (lib.types.str);
- default = [];
+ apaxy = {
+ extraConfig = (pkgs.webapps.apache-theme.override { inherit theme_root; }).apacheConfig;
};
- extraConfig = lib.mkOption {
- type = lib.types.listOf (lib.types.lines);
- default = [];
+ http2 = {
+ modules = [ "http2" ];
+ extraConfig = ''
+ Protocols h2 http/1.1
+ '';
};
- vhostConfs = lib.mkOption {
- type = lib.types.attrsOf (lib.types.submodule {
- options = {
- certName = lib.mkOption { type = lib.types.string; };
- hosts = lib.mkOption { type = lib.types.listOf lib.types.string; };
- root = lib.mkOption { type = lib.types.nullOr lib.types.path; };
- extraConfig = lib.mkOption { type = lib.types.listOf lib.types.lines; default = []; };
- };
- });
+ customLog = {
+ extraConfig = ''
+ LogFormat "%v:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedVhost
+ '';
};
};
- makeModules = cfg: pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig);
- makeExtraConfig = cfg: (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig));
+ makeModules = lib.lists.flatten (lib.attrsets.mapAttrsToList (n: v: v.modules or []) apacheConfig);
+ makeExtraConfig = (builtins.filter (x: x != null) (lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) apacheConfig));
in
{
imports = [
- ./chloe
- ./ludivine
- ./aten
- ./piedsjaloux
- ./connexionswing
- ./tellesflorian
- ./emilia
- ./capitaines
- ./ftp/jerome.nix
- ./ftp/nassime.nix
- ./ftp/florian.nix
- ./ftp/denisejerome.nix
- ./ftp/leila.nix
- ./ftp/immae.nix
- ./ftp/release.nix
- ./ftp/temp.nix
- ./tools/db
+ ./tools/db.nix
./tools/tools
./tools/dav
- ./tools/cloud
+ ./tools/cloud.nix
./tools/git
- ./tools/mastodon
- ./tools/mediagoblin
- ./tools/diaspora
- ./tools/ether
- ./tools/peertube
- # built using:
- # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
- # Removed allGranted
- # And removed users / groups
- ./apache/httpd_prod.nix
- ./apache/httpd_inte.nix
- # except for this one for users/groups
- ./apache/httpd_tools.nix
- # Adapted from base phpfpm
- ./phpfpm
+ ./tools/mastodon.nix
+ ./tools/mediagoblin.nix
+ ./tools/diaspora.nix
+ ./tools/ether.nix
+ ./tools/peertube.nix
];
- options.services.myWebsites = {
- production = makeServiceOptions "production";
- integration = makeServiceOptions "integration";
- tools = makeServiceOptions "main";
-
- apacheConfig = lib.mkOption {
- type = lib.types.attrsOf (lib.types.submodule {
- options = {
- modules = lib.mkOption {
- type = lib.types.listOf (lib.types.str);
- default = [];
- };
- extraConfig = lib.mkOption {
- type = lib.types.nullOr lib.types.lines;
- default = null;
- };
- };
- });
- default = {};
- description = "Extra global config";
- };
-
- };
-
config = {
+ users.users.wwwrun.extraGroups = [ "keys" ];
networking.firewall.allowedTCPPorts = [ 80 443 ];
nixpkgs.overlays = [ (self: super: rec {
# '';
});
phpPackages = super.php72Packages.override { inherit php; };
- composerEnv = import ./commons/composer-env.nix {
- inherit (self) stdenv writeTextFile fetchurl php unzip;
- };
}) ];
services.myWebsites.tools.databases.enable = true;
services.myWebsites.tools.etherpad-lite.enable = true;
services.myWebsites.tools.peertube.enable = true;
- services.myWebsites.Chloe.production.enable = cfg.production.enable;
- services.myWebsites.Ludivine.production.enable = cfg.production.enable;
- services.myWebsites.Aten.production.enable = cfg.production.enable;
- services.myWebsites.PiedsJaloux.production.enable = cfg.production.enable;
- services.myWebsites.Connexionswing.production.enable = cfg.production.enable;
- services.myWebsites.Jerome.production.enable = cfg.production.enable;
- services.myWebsites.Nassime.production.enable = cfg.production.enable;
- services.myWebsites.Florian.production.enable = cfg.production.enable;
- services.myWebsites.Leila.production.enable = cfg.production.enable;
- services.myWebsites.DeniseJerome.production.enable = cfg.production.enable;
- services.myWebsites.Emilia.production.enable = cfg.production.enable;
- services.myWebsites.Capitaines.production.enable = cfg.production.enable;
- services.myWebsites.Immae.production.enable = cfg.production.enable;
- services.myWebsites.Release.production.enable = cfg.production.enable;
- services.myWebsites.Temp.production.enable = cfg.production.enable;
-
- services.myWebsites.Chloe.integration.enable = cfg.integration.enable;
- services.myWebsites.Ludivine.integration.enable = cfg.integration.enable;
- services.myWebsites.Aten.integration.enable = cfg.integration.enable;
- services.myWebsites.PiedsJaloux.integration.enable = cfg.integration.enable;
- services.myWebsites.Connexionswing.integration.enable = cfg.integration.enable;
- services.myWebsites.TellesFlorian.integration.enable = true;
- services.myWebsites.Florian.integration.enable = true;
-
- services.myWebsites.apacheConfig = {
- gzip = {
- modules = [ "deflate" "filter" ];
- extraConfig = ''
- AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript
- '';
- };
- macros = {
- modules = [ "macro" ];
- };
- stats = {
- extraConfig = ''
- <Macro Stats %{domain}>
- Alias /awstats /var/lib/goaccess/%{domain}
- <Directory /var/lib/goaccess/%{domain}>
- DirectoryIndex index.html
- AllowOverride None
- Require all granted
- </Directory>
- <Location /awstats>
- Use LDAPConnect
- Require ldap-group cn=%{domain},ou=stats,cn=httpd,ou=services,dc=immae,dc=eu
- </Location>
- </Macro>
- '';
- };
- ldap = {
- modules = [ "ldap" "authnz_ldap" ];
- extraConfig = ''
- <IfModule ldap_module>
- LDAPSharedCacheSize 500000
- LDAPCacheEntries 1024
- LDAPCacheTTL 600
- LDAPOpCacheEntries 1024
- LDAPOpCacheTTL 600
+ secrets.keys = [{
+ dest = "apache-ldap";
+ user = "wwwrun";
+ group = "wwwrun";
+ permissions = "0400";
+ text = ''
+ <Macro LDAPConnect>
+ <IfModule authnz_ldap_module>
+ AuthLDAPURL ldap://ldap.immae.eu:389/dc=immae,dc=eu STARTTLS
+ AuthLDAPBindDN cn=httpd,ou=services,dc=immae,dc=eu
+ AuthLDAPBindPassword "${myconfig.env.httpd.ldap.password}"
+ AuthType Basic
+ AuthName "Authentification requise (Acces LDAP)"
+ AuthBasicProvider ldap
</IfModule>
-
- <Macro LDAPConnect>
- <IfModule authnz_ldap_module>
- AuthLDAPURL ldap://ldap.immae.eu:389/dc=immae,dc=eu STARTTLS
- AuthLDAPBindDN cn=httpd,ou=services,dc=immae,dc=eu
- AuthLDAPBindPassword "${myconfig.env.httpd.ldap.password}"
- AuthType Basic
- AuthName "Authentification requise (Acces LDAP)"
- AuthBasicProvider ldap
- </IfModule>
- </Macro>
+ </Macro>
'';
- };
- global = {
- extraConfig = ''
- ErrorDocument 500 /maintenance_immae.html
- ErrorDocument 501 /maintenance_immae.html
- ErrorDocument 502 /maintenance_immae.html
- ErrorDocument 503 /maintenance_immae.html
- ErrorDocument 504 /maintenance_immae.html
- Alias /maintenance_immae.html ${www_root}/maintenance_immae.html
- ProxyPass /maintenance_immae.html !
-
- AliasMatch "(.*)/googleb6d69446ff4ca3e5.html" ${www_root}/googleb6d69446ff4ca3e5.html
- <Directory ${www_root}>
- AllowOverride None
- Require all granted
- </Directory>
- '';
- };
- apaxy = {
- extraConfig = ''
- <Macro Apaxy %{folder} %{ignored}>
- Alias /theme ${theme_root}
- <Directory ${theme_root}>
- Options -Indexes
- AllowOverride None
- Require all granted
- </Directory>
-
- # mod_autoindex
- <Directory %{folder}>
- Options Indexes
- AllowOverride None
- Require all granted
-
- # Inspired from Apaxy by @adamwhitcroft
-
- IndexOptions +Charset=UTF-8 +FancyIndexing +IgnoreCase +FoldersFirst +XHTML +HTMLTable +SuppressRules +SuppressDescription +NameWidth=* +IconsAreLinks +ShowForbidden
-
- IndexHeadInsert "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />"
-
- IndexIgnoreReset ON
- IndexIgnore /theme .htaccess %{ignored}
-
- AddIcon /theme/icons/blank.png ^^BLANKICON^^
- AddIcon /theme/icons/folder.png ^^DIRECTORY^^
- AddIcon /theme/icons/folder-home.png ..
-
- AddIconByType (TXT,/theme/icons/text.png) text/*
- AddIconByType (IMG,/theme/icons/image.png) image/*
- AddIconByType (SND,/theme/icons/audio.png) audio/*
- AddIconByType (VID,/theme/icons/video.png) video/*
-
- AddIcon /theme/icons/archive.png .7z .bz2 .cab .gz .tar
- AddIcon /theme/icons/audio.png .aac .aif .aifc .aiff .ape .au .flac .iff .m4a .mid .mp3 .mpa .ra .wav .wma .f4a .f4b .oga .ogg .xm .it .s3m .mod
- AddIcon /theme/icons/bin.png .bin .hex
- AddIcon /theme/icons/bmp.png .bmp
- AddIcon /theme/icons/c.png .c
- AddIcon /theme/icons/calc.png .xlsx .xlsm .xltx .xltm .xlam .xlr .xls .csv
- AddIcon /theme/icons/cd.png .iso
- AddIcon /theme/icons/cpp.png .cpp
- AddIcon /theme/icons/css.png .css .sass .scss
- AddIcon /theme/icons/deb.png .deb
- AddIcon /theme/icons/doc.png .doc .docx .docm .dot .dotx .dotm .log .msg .odt .pages .rtf .tex .wpd .wps
- AddIcon /theme/icons/draw.png .svg .svgz
- AddIcon /theme/icons/eps.png .ai .eps
- AddIcon /theme/icons/exe.png .exe
- AddIcon /theme/icons/gif.png .gif
- AddIcon /theme/icons/h.png .h
- AddIcon /theme/icons/html.png .html .xhtml .shtml .htm .URL .url
- AddIcon /theme/icons/ico.png .ico
- AddIcon /theme/icons/java.png .jar
- AddIcon /theme/icons/jpg.png .jpg .jpeg .jpe
- AddIcon /theme/icons/js.png .js .json
- AddIcon /theme/icons/markdown.png .md
- AddIcon /theme/icons/package.png .pkg .dmg
- AddIcon /theme/icons/pdf.png .pdf
- AddIcon /theme/icons/php.png .php .phtml
- AddIcon /theme/icons/playlist.png .m3u .m3u8 .pls .pls8
- AddIcon /theme/icons/png.png .png
- AddIcon /theme/icons/ps.png .ps
- AddIcon /theme/icons/psd.png .psd
- AddIcon /theme/icons/py.png .py
- AddIcon /theme/icons/rar.png .rar
- AddIcon /theme/icons/rb.png .rb
- AddIcon /theme/icons/rpm.png .rpm
- AddIcon /theme/icons/rss.png .rss
- AddIcon /theme/icons/script.png .bat .cmd .sh
- AddIcon /theme/icons/sql.png .sql
- AddIcon /theme/icons/tiff.png .tiff .tif
- AddIcon /theme/icons/text.png .txt .nfo
- AddIcon /theme/icons/video.png .asf .asx .avi .flv .mkv .mov .mp4 .mpg .rm .srt .swf .vob .wmv .m4v .f4v .f4p .ogv
- AddIcon /theme/icons/xml.png .xml
- AddIcon /theme/icons/zip.png .zip
- DefaultIcon /theme/icons/default.png
-
- HeaderName /theme/header.html
- ReadmeName /theme/footer.html
- IndexStyleSheet /theme/style.css
- </Directory>
- </Macro>
- '';
- };
- http2 = {
- modules = [ "http2" ];
- extraConfig = ''
- Protocols h2 http/1.1
- '';
- };
- customLog = {
- extraConfig = ''
- LogFormat "%v:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedVhost
- '';
- };
- };
+ }];
system.activationScripts = {
httpd = ''
- install -d -m 0755 /var/lib/acme/acme-challenge
+ install -d -m 0755 ${config.security.acme.directory}/acme-challenge
install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions
install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/adminer
+ install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/tmp/adminer
install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/mantisbt
install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/davical
+ install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/phpldapadmin
'';
};
adminer = pkgs.callPackage ./commons/adminer.nix {};
in ''
mkdir -p $out/webapps
- ln -s ${../../www} $out/webapps/_www
- ln -s ${./apache/theme} $out/webapps/_theme
+ ln -s ${pkgs.webapps.apache-default.www} $out/webapps/_www
+ ln -s ${pkgs.webapps.apache-theme.theme} $out/webapps/_theme
ln -s ${adminer.webRoot} $out/webapps/${adminer.apache.webappName}
'';
- services.myPhpfpm = {
+ services.phpfpm = {
phpPackage = pkgs.php;
phpOptions = ''
session.save_path = "/var/lib/php/sessions"
post_max_size = 20M
- session.gc_maxlifetime = 60*60*24*15
- session.cache_expire = 60*24*30
+ ; 15 days (seconds)
+ session.gc_maxlifetime = 1296000
+ ; 30 days (minutes)
+ session.cache_expire = 43200
'';
extraConfig = ''
log_level = notice
'';
};
- services.httpdProd = makeService "production" config.services.myWebsites.production;
- services.myWebsites.production.modules = makeModules cfg;
- services.myWebsites.production.extraConfig = makeExtraConfig cfg;
+ services.websites.production = {
+ enable = true;
+ adminAddr = "httpd@immae.eu";
+ httpdName = "Prod";
+ ips =
+ let ips = myconfig.env.servers.eldiron.ips.production;
+ in [ips.ip4] ++ (ips.ip6 or []);
+ modules = makeModules;
+ extraConfig = makeExtraConfig;
+ fallbackVhost = {
+ certName = "eldiron";
+ hosts = ["eldiron.immae.eu" ];
+ root = www_root;
+ extraConfig = [ "DirectoryIndex index.htm" ];
+ };
+ };
- services.httpdInte = makeService "integration" config.services.myWebsites.integration;
- services.myWebsites.integration.modules = makeModules cfg;
- services.myWebsites.integration.extraConfig = makeExtraConfig cfg;
+ services.websites.integration = {
+ enable = true;
+ adminAddr = "httpd@immae.eu";
+ httpdName = "Inte";
+ ips =
+ let ips = myconfig.env.servers.eldiron.ips.integration;
+ in [ips.ip4] ++ (ips.ip6 or []);
+ modules = makeModules;
+ extraConfig = makeExtraConfig;
+ fallbackVhost = {
+ certName = "eldiron";
+ hosts = ["eldiron.immae.eu" ];
+ root = www_root;
+ extraConfig = [ "DirectoryIndex index.htm" ];
+ };
+ };
- services.httpdTools = makeService "tools" config.services.myWebsites.tools;
- services.myWebsites.tools.modules = makeModules cfg;
- services.myWebsites.tools.extraConfig = makeExtraConfig cfg ++
- [ ''
- RedirectMatch ^/licen[cs]es?_et_tip(ping)?$ https://www.immae.eu/licences_et_tip.html
- RedirectMatch ^/licen[cs]es?_and_tip(ping)?$ https://www.immae.eu/licenses_and_tipping.html
- RedirectMatch ^/licen[cs]es?$ https://www.immae.eu/licenses_and_tipping.html
- RedirectMatch ^/tip(ping)?$ https://www.immae.eu/licenses_and_tipping.html
- RedirectMatch ^/(mentions|mentions_legales|legal)$ https://www.immae.eu/mentions.html
- RedirectMatch ^/CGU$ https://www.immae.eu/CGU
- ''
- ]
- ;
+ services.websites.tools = {
+ enable = true;
+ adminAddr = "httpd@immae.eu";
+ httpdName = "Tools";
+ ips =
+ let ips = myconfig.env.servers.eldiron.ips.main;
+ in [ips.ip4] ++ (ips.ip6 or []);
+ modules = makeModules;
+ extraConfig = makeExtraConfig ++
+ [ ''
+ RedirectMatch ^/licen[cs]es?_et_tip(ping)?$ https://www.immae.eu/licences_et_tip.html
+ RedirectMatch ^/licen[cs]es?_and_tip(ping)?$ https://www.immae.eu/licenses_and_tipping.html
+ RedirectMatch ^/licen[cs]es?$ https://www.immae.eu/licenses_and_tipping.html
+ RedirectMatch ^/tip(ping)?$ https://www.immae.eu/licenses_and_tipping.html
+ RedirectMatch ^/(mentions|mentions_legales|legal)$ https://www.immae.eu/mentions.html
+ RedirectMatch ^/CGU$ https://www.immae.eu/CGU
+ ''
+ ];
+ nosslVhost = {
+ enable = true;
+ host = "nossl.immae.eu";
+ };
+ fallbackVhost = {
+ certName = "eldiron";
+ hosts = ["eldiron.immae.eu" ];
+ root = www_root;
+ extraConfig = [ "DirectoryIndex index.htm" ];
+ };
+ };
};
}