From 43b726ed3ba5e9a5ce91f7b39ffbe895d3ada18b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Wed, 9 Jan 2019 19:52:27 +0100 Subject: [PATCH 01/16] Use dav.immae.eu for calendar-related sites --- virtual/eldiron.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index 506e29d..7dbca92 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -125,6 +125,7 @@ "dev.aten.pro" = null; "piedsjaloux.immae.eu" = null; "chloe.immae.eu" = null; + "dav.immae.eu" = null; }; }; "ludivinecassal" = { @@ -465,6 +466,12 @@ mypkgs.ympd.apache.vhostConf mypkgs.ttrss.apache.vhostConf mypkgs.roundcubemail.apache.vhostConf + ]; + }) + (withConf "eldiron" // { + hostName = "dav.immae.eu"; + documentRoot = null; + extraConfig = builtins.concatStringsSep "\n" [ mypkgs.infcloud.apache.vhostConf mypkgs.davical.apache.vhostConf ]; @@ -580,7 +587,7 @@ # rather than rewrite ''; } - ]; + ]; }; security.pam.services = let -- 2.41.0 From 4d4f13f4a8e7df6480da895d80d487c891441745 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Wed, 9 Jan 2019 23:35:11 +0100 Subject: [PATCH 02/16] Move some elements to separate modules --- virtual/eldiron.nix | 176 ++---------------- virtual/modules/databases.nix | 133 +++++++++++++ virtual/modules/gitolite.nix | 73 ++++++++ .../gitolite}/gitolite_ldap_groups.sh | 0 virtual/modules/gitweb.nix | 21 +++ .../gitweb/theme}/git-favicon.png | Bin .../gitweb/theme}/git-logo.png | Bin .../gitweb/theme}/gitweb.css | 0 .../gitweb => modules/gitweb/theme}/gitweb.js | 0 9 files changed, 243 insertions(+), 160 deletions(-) create mode 100644 virtual/modules/databases.nix create mode 100644 virtual/modules/gitolite.nix rename virtual/{packages => modules/gitolite}/gitolite_ldap_groups.sh (100%) create mode 100644 virtual/modules/gitweb.nix rename virtual/{packages/gitweb => modules/gitweb/theme}/git-favicon.png (100%) rename virtual/{packages/gitweb => modules/gitweb/theme}/git-logo.png (100%) rename virtual/{packages/gitweb => modules/gitweb/theme}/gitweb.css (100%) rename virtual/{packages/gitweb => modules/gitweb/theme}/gitweb.js (100%) diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index 7dbca92..acd2cbd 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -4,44 +4,28 @@ enableRollback = true; }; - eldiron = { config, pkgs, ... }: - with import ../libs.nix; + eldiron = { config, pkgs, mylibs, ... }: + with mylibs; let mypkgs = pkgs.callPackage ./packages.nix { inherit checkEnv fetchedGit fetchedGitPrivate fetchedGithub; }; in { + _module.args = { + mylibs = import ../libs.nix; + }; + + imports = [ + ./modules/gitolite.nix + ./modules/gitweb.nix + ./modules/databases.nix + ]; + services.myGitolite.enable = true; + services.myGitweb.enable = true; + services.myDatabases.enable = true; + nixpkgs.config.packageOverrides = oldpkgs: rec { - gitolite = oldpkgs.gitolite.overrideAttrs(old: rec { - name = "gitolite-${version}"; - version = "3.6.10"; - src = pkgs.fetchFromGitHub { - owner = "sitaramc"; - repo = "gitolite"; - rev = "v${version}"; - sha256 = "0p2697mn6rwm03ndlv7q137zczai82n41aplq1g006ii7f12xy8h"; - }; - }); - gitweb = oldpkgs.gitweb.overrideAttrs(old: { - installPhase = old.installPhase + '' - cp -r ${./packages/gitweb} $out/gitweb-theme; - ''; - }); - postgresql = postgresql111; - postgresql111 = oldpkgs.postgresql100.overrideAttrs(old: rec { - passthru = old.passthru // { psqlSchema = "11.0"; }; - name = "postgresql-11.1"; - src = pkgs.fetchurl { - url = "mirror://postgresql/source/v11.1/${name}.tar.bz2"; - sha256 = "026v0sicsh7avzi45waf8shcbhivyxmi7qgn9fd1x0vl520mx0ch"; - }; - }); - mariadb = mariadbPAM; - mariadbPAM = oldpkgs.mariadb.overrideAttrs(old: rec { - cmakeFlags = old.cmakeFlags ++ [ "-DWITH_AUTHENTICATION_PAM=ON" ]; - buildInputs = old.buildInputs ++ [ pkgs.pam ]; - }); goaccess = oldpkgs.goaccess.overrideAttrs(old: rec { name = "goaccess-${version}"; version = "1.3"; @@ -57,7 +41,7 @@ networking = { firewall = { enable = true; - allowedTCPPorts = [ 22 80 443 3306 5432 9418 ]; + allowedTCPPorts = [ 22 80 443 9418 ]; }; }; @@ -116,7 +100,6 @@ allowKeysForGroup = true; extraDomains = { "db-1.immae.eu" = null; - "git.immae.eu" = null; "tools.immae.eu" = null; "connexionswing.immae.eu" = null; "sandetludo.immae.eu" = null; @@ -197,32 +180,6 @@ AuthorizedKeysCommandUser nobody ''; - users.users.wwwrun.extraGroups = [ "gitolite" ]; - - users.users.gitolite.packages = let - python-packages = python-packages: with python-packages; [ - simplejson - urllib3 - ]; - in - [ - (pkgs.python3.withPackages python-packages) - ]; - # FIXME: after initial install, need to - # (1) copy rc file (adjust gitolite_ldap_groups.sh) - # (2) (mark old readonly and) sync repos except gitolite-admin - # rsync -av --exclude=gitolite-admin.git old:/var/lib/gitolite/repositories /var/lib/gitolite/ - # chown -R gitolite:gitolite /var/lib/gitolite - # (3) push force the gitolite-admin to new location (from external point) - # Don't use an existing key, it will take precedence over - # gitolite-admin - # (4) su -u gitolite gitolite setup - services.gitolite = { - enable = true; - # FIXME: key from ./ssh - adminPubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXqRbiHw7QoHADNIEuo4nUT9fSOIEBMdJZH0bkQAxXyJFyCM1IMz0pxsHV0wu9tdkkr36bPEUj2aV5bkYLBN6nxcV2Y49X8bjOSCPfx3n6Own1h+NeZVBj4ZByrFmqCbTxUJIZ2bZKcWOFncML39VmWdsVhNjg0X4NBBehqXRIKr2gt3E/ESAxTYJFm0BnU0baciw9cN0bsRGqvFgf5h2P48CIAfwhVcGmPQnnAwabnosYQzRWxR0OygH5Kd8mePh6FheIRIigfXsDO8f/jdxwut8buvNIf3m5EBr3tUbTsvM+eV3M5vKGt7sk8T64DVtepTSdOOWtp+47ktsnHOMh immae@immae.eu"; - }; - services.ympd = mypkgs.ympd.config // { enable = false; }; services.phpfpm = { @@ -288,29 +245,6 @@ mkdir -p /run/redis chown redis /run/redis ''; - gitolite = - assert checkEnv "NIXOPS_GITOLITE_LDAP_PASSWORD"; - let - gitolite_ldap_groups = wrap { - name = "gitolite_ldap_groups.sh"; - file = ./packages/gitolite_ldap_groups.sh; - vars = { - LDAP_PASS = builtins.getEnv "NIXOPS_GITOLITE_LDAP_PASSWORD"; - }; - paths = [ pkgs.openldap pkgs.stdenv.shellPackage pkgs.gnugrep pkgs.coreutils ]; - }; - in { - deps = [ "users" ]; - text = '' - if [ -d /var/lib/gitolite ]; then - ln -sf ${gitolite_ldap_groups} /var/lib/gitolite/gitolite_ldap_groups.sh - chmod g+rx /var/lib/gitolite - fi - if [ -f /var/lib/gitolite/projects.list ]; then - chmod g+r /var/lib/gitolite/projects.list - fi - ''; - }; # FIXME: initial sync goaccess = '' mkdir -p /var/lib/goaccess @@ -590,84 +524,6 @@ ]; }; - security.pam.services = let - pam_ldap = pkgs.pam_ldap; - pam_ldap_mysql = assert checkEnv "NIXOPS_MYSQL_PAM_PASSWORD"; - pkgs.writeText "mysql.conf" '' - host ldap.immae.eu - base dc=immae,dc=eu - binddn cn=mysql,cn=pam,ou=services,dc=immae,dc=eu - bindpw ${builtins.getEnv "NIXOPS_MYSQL_PAM_PASSWORD"} - pam_filter memberOf=cn=users,cn=mysql,cn=pam,ou=services,dc=immae,dc=eu - ''; - in [ - { - name = "mysql"; - text = '' - # https://mariadb.com/kb/en/mariadb/pam-authentication-plugin/ - auth required ${pam_ldap}/lib/security/pam_ldap.so config=${pam_ldap_mysql} - account required ${pam_ldap}/lib/security/pam_ldap.so config=${pam_ldap_mysql} - ''; - } - ]; - - # FIXME: backup - # Nextcloud: 14 - services.redis = rec { - enable = true; - bind = "127.0.0.1"; - unixSocket = "/run/redis/redis.sock"; - extraConfig = '' - unixsocketperm 777 - maxclients 1024 - ''; - }; - - # FIXME: initial sync - # FIXME: backup - # FIXME: restart after pam - # FIXME: pam access doesn’t work (because of php module) - # FIXME: ssl - services.mysql = rec { - enable = true; - package = pkgs.mariadb; - }; - - # FIXME: initial sync - # FIXME: backup - # FIXME: ssl - services.postgresql = rec { - enable = true; - package = pkgs.postgresql; - enableTCPIP = true; - extraConfig = '' - max_connections = 100 - wal_level = logical - shared_buffers = 128MB - max_wal_size = 1GB - min_wal_size = 80MB - log_timezone = 'Europe/Paris' - datestyle = 'iso, mdy' - timezone = 'Europe/Paris' - lc_messages = 'en_US.UTF-8' - lc_monetary = 'en_US.UTF-8' - lc_numeric = 'en_US.UTF-8' - lc_time = 'en_US.UTF-8' - default_text_search_config = 'pg_catalog.english' - # ssl = on - # ssl_cert_file = '/var/lib/acme/eldiron/fullchain.pem' - # ssl_key_file = '/var/lib/acme/eldiron/key.pem' - ''; - authentication = '' - local all postgres ident - local all all md5 - host all all samehost md5 - host all all 178.33.252.96/32 md5 - host all all 188.165.209.148/32 md5 - #host all all all pam - ''; - }; - services.cron = { enable = true; systemCronJobs = let diff --git a/virtual/modules/databases.nix b/virtual/modules/databases.nix new file mode 100644 index 0000000..25bd645 --- /dev/null +++ b/virtual/modules/databases.nix @@ -0,0 +1,133 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myDatabases; +in { + options.services.myDatabases = { + enable = lib.mkEnableOption "my databases service"; + postgresql = { + enable = lib.mkOption { + default = cfg.enable; + example = true; + description = "Whether to enable postgresql database"; + type = lib.types.bool; + }; + }; + + mariadb = { + enable = lib.mkOption { + default = cfg.enable; + example = true; + description = "Whether to enable mariadb database"; + type = lib.types.bool; + }; + }; + + redis = { + enable = lib.mkOption { + default = cfg.enable; + example = true; + description = "Whether to enable redis database"; + type = lib.types.bool; + }; + }; + }; + + config = lib.mkIf cfg.enable { + nixpkgs.config.packageOverrides = oldpkgs: rec { + postgresql = postgresql111; + postgresql111 = oldpkgs.postgresql100.overrideAttrs(old: rec { + passthru = old.passthru // { psqlSchema = "11.0"; }; + name = "postgresql-11.1"; + src = pkgs.fetchurl { + url = "mirror://postgresql/source/v11.1/${name}.tar.bz2"; + sha256 = "026v0sicsh7avzi45waf8shcbhivyxmi7qgn9fd1x0vl520mx0ch"; + }; + }); + mariadb = mariadbPAM; + mariadbPAM = oldpkgs.mariadb.overrideAttrs(old: rec { + cmakeFlags = old.cmakeFlags ++ [ "-DWITH_AUTHENTICATION_PAM=ON" ]; + buildInputs = old.buildInputs ++ [ pkgs.pam ]; + }); + }; + + networking.firewall.allowedTCPPorts = [ 3306 5432 ]; + + # FIXME: initial sync + # FIXME: backup + # FIXME: restart after pam + # FIXME: pam access doesn’t work (because of php module) + # FIXME: ssl + services.mysql = rec { + enable = cfg.mariadb.enable; + package = pkgs.mariadb; + }; + + # FIXME: initial sync + # FIXME: backup + # FIXME: ssl + services.postgresql = rec { + enable = cfg.postgresql.enable; + package = pkgs.postgresql; + enableTCPIP = true; + extraConfig = '' + max_connections = 100 + wal_level = logical + shared_buffers = 128MB + max_wal_size = 1GB + min_wal_size = 80MB + log_timezone = 'Europe/Paris' + datestyle = 'iso, mdy' + timezone = 'Europe/Paris' + lc_messages = 'en_US.UTF-8' + lc_monetary = 'en_US.UTF-8' + lc_numeric = 'en_US.UTF-8' + lc_time = 'en_US.UTF-8' + default_text_search_config = 'pg_catalog.english' + # ssl = on + # ssl_cert_file = '/var/lib/acme/eldiron/fullchain.pem' + # ssl_key_file = '/var/lib/acme/eldiron/key.pem' + ''; + authentication = '' + local all postgres ident + local all all md5 + host all all samehost md5 + host all all 178.33.252.96/32 md5 + host all all 188.165.209.148/32 md5 + #host all all all pam + ''; + }; + + security.pam.services = let + pam_ldap = pkgs.pam_ldap; + pam_ldap_mysql = assert mylibs.checkEnv "NIXOPS_MYSQL_PAM_PASSWORD"; + pkgs.writeText "mysql.conf" '' + host ldap.immae.eu + base dc=immae,dc=eu + binddn cn=mysql,cn=pam,ou=services,dc=immae,dc=eu + bindpw ${builtins.getEnv "NIXOPS_MYSQL_PAM_PASSWORD"} + pam_filter memberOf=cn=users,cn=mysql,cn=pam,ou=services,dc=immae,dc=eu + ''; + in [ + { + name = "mysql"; + text = '' + # https://mariadb.com/kb/en/mariadb/pam-authentication-plugin/ + auth required ${pam_ldap}/lib/security/pam_ldap.so config=${pam_ldap_mysql} + account required ${pam_ldap}/lib/security/pam_ldap.so config=${pam_ldap_mysql} + ''; + } + ]; + + # FIXME: backup + # Nextcloud: 14 + services.redis = rec { + enable = config.services.myDatabases.redis.enable; + bind = "127.0.0.1"; + unixSocket = "/run/redis/redis.sock"; + extraConfig = '' + unixsocketperm 777 + maxclients 1024 + ''; + }; + }; +} diff --git a/virtual/modules/gitolite.nix b/virtual/modules/gitolite.nix new file mode 100644 index 0000000..85c7be1 --- /dev/null +++ b/virtual/modules/gitolite.nix @@ -0,0 +1,73 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myGitolite; +in { + options.services.myGitolite = { + enable = lib.mkEnableOption "my gitolite service"; + }; + + config = lib.mkIf cfg.enable { + nixpkgs.config.packageOverrides = oldpkgs: rec { + gitolite = oldpkgs.gitolite.overrideAttrs(old: rec { + name = "gitolite-${version}"; + version = "3.6.10"; + src = pkgs.fetchFromGitHub { + owner = "sitaramc"; + repo = "gitolite"; + rev = "v${version}"; + sha256 = "0p2697mn6rwm03ndlv7q137zczai82n41aplq1g006ii7f12xy8h"; + }; + }); + }; + + system.activationScripts.gitolite = + assert mylibs.checkEnv "NIXOPS_GITOLITE_LDAP_PASSWORD"; + let + gitolite_ldap_groups = mylibs.wrap { + name = "gitolite_ldap_groups.sh"; + file = ./gitolite/gitolite_ldap_groups.sh; + vars = { + LDAP_PASS = builtins.getEnv "NIXOPS_GITOLITE_LDAP_PASSWORD"; + }; + paths = [ pkgs.openldap pkgs.stdenv.shellPackage pkgs.gnugrep pkgs.coreutils ]; + }; + in { + deps = [ "users" ]; + text = '' + if [ -d /var/lib/gitolite ]; then + ln -sf ${gitolite_ldap_groups} /var/lib/gitolite/gitolite_ldap_groups.sh + chmod g+rx /var/lib/gitolite + fi + if [ -f /var/lib/gitolite/projects.list ]; then + chmod g+r /var/lib/gitolite/projects.list + fi + ''; + }; + + users.users.wwwrun.extraGroups = [ "gitolite" ]; + + users.users.gitolite.packages = let + python-packages = python-packages: with python-packages; [ + simplejson + urllib3 + ]; + in + [ + (pkgs.python3.withPackages python-packages) + ]; + # FIXME: after initial install, need to + # (1) copy rc file (adjust gitolite_ldap_groups.sh) + # (2) (mark old readonly and) sync repos except gitolite-admin + # rsync -av --exclude=gitolite-admin.git old:/var/lib/gitolite/repositories /var/lib/gitolite/ + # chown -R gitolite:gitolite /var/lib/gitolite + # (3) push force the gitolite-admin to new location (from external point) + # Don't use an existing key, it will take precedence over + # gitolite-admin + # (4) su -u gitolite gitolite setup + services.gitolite = { + enable = true; + # FIXME: key from ./ssh + adminPubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXqRbiHw7QoHADNIEuo4nUT9fSOIEBMdJZH0bkQAxXyJFyCM1IMz0pxsHV0wu9tdkkr36bPEUj2aV5bkYLBN6nxcV2Y49X8bjOSCPfx3n6Own1h+NeZVBj4ZByrFmqCbTxUJIZ2bZKcWOFncML39VmWdsVhNjg0X4NBBehqXRIKr2gt3E/ESAxTYJFm0BnU0baciw9cN0bsRGqvFgf5h2P48CIAfwhVcGmPQnnAwabnosYQzRWxR0OygH5Kd8mePh6FheIRIigfXsDO8f/jdxwut8buvNIf3m5EBr3tUbTsvM+eV3M5vKGt7sk8T64DVtepTSdOOWtp+47ktsnHOMh immae@immae.eu"; + }; + }; +} diff --git a/virtual/packages/gitolite_ldap_groups.sh b/virtual/modules/gitolite/gitolite_ldap_groups.sh similarity index 100% rename from virtual/packages/gitolite_ldap_groups.sh rename to virtual/modules/gitolite/gitolite_ldap_groups.sh diff --git a/virtual/modules/gitweb.nix b/virtual/modules/gitweb.nix new file mode 100644 index 0000000..f3ef1bd --- /dev/null +++ b/virtual/modules/gitweb.nix @@ -0,0 +1,21 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myGitweb; +in { + options.services.myGitweb = { + enable = lib.mkEnableOption "my gitweb service"; + }; + + config = lib.mkIf cfg.enable { + security.acme.certs."eldiron".extraDomains."git.immae.eu" = null; + + nixpkgs.config.packageOverrides = oldpkgs: rec { + gitweb = oldpkgs.gitweb.overrideAttrs(old: { + installPhase = old.installPhase + '' + cp -r ${./gitweb/theme} $out/gitweb-theme; + ''; + }); + }; + + }; +} diff --git a/virtual/packages/gitweb/git-favicon.png b/virtual/modules/gitweb/theme/git-favicon.png similarity index 100% rename from virtual/packages/gitweb/git-favicon.png rename to virtual/modules/gitweb/theme/git-favicon.png diff --git a/virtual/packages/gitweb/git-logo.png b/virtual/modules/gitweb/theme/git-logo.png similarity index 100% rename from virtual/packages/gitweb/git-logo.png rename to virtual/modules/gitweb/theme/git-logo.png diff --git a/virtual/packages/gitweb/gitweb.css b/virtual/modules/gitweb/theme/gitweb.css similarity index 100% rename from virtual/packages/gitweb/gitweb.css rename to virtual/modules/gitweb/theme/gitweb.css diff --git a/virtual/packages/gitweb/gitweb.js b/virtual/modules/gitweb/theme/gitweb.js similarity index 100% rename from virtual/packages/gitweb/gitweb.js rename to virtual/modules/gitweb/theme/gitweb.js -- 2.41.0 From 3013caf18db83d43a1703b1a74cb484f70bab3a8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Thu, 10 Jan 2019 00:40:53 +0100 Subject: [PATCH 03/16] Start moving websites to their own modules: certificates --- virtual/eldiron.nix | 110 ++++---------------- virtual/modules/certificates.nix | 30 ++++++ virtual/modules/websites/aten.nix | 28 +++++ virtual/modules/websites/chloe.nix | 27 +++++ virtual/modules/websites/connexionswing.nix | 31 ++++++ virtual/modules/websites/ludivine.nix | 27 +++++ virtual/modules/websites/piedsjaloux.nix | 28 +++++ 7 files changed, 192 insertions(+), 89 deletions(-) create mode 100644 virtual/modules/certificates.nix create mode 100644 virtual/modules/websites/aten.nix create mode 100644 virtual/modules/websites/chloe.nix create mode 100644 virtual/modules/websites/connexionswing.nix create mode 100644 virtual/modules/websites/ludivine.nix create mode 100644 virtual/modules/websites/piedsjaloux.nix diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index acd2cbd..5dafe6e 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -17,13 +17,29 @@ }; imports = [ + ./modules/certificates.nix ./modules/gitolite.nix ./modules/gitweb.nix ./modules/databases.nix + ./modules/websites/chloe.nix + ./modules/websites/ludivine.nix + ./modules/websites/aten.nix + ./modules/websites/piedsjaloux.nix + ./modules/websites/connexionswing.nix ]; services.myGitolite.enable = true; services.myGitweb.enable = true; services.myDatabases.enable = true; + services.myWebsites.Chloe.production.enable = true; + services.myWebsites.Chloe.integration.enable = true; + services.myWebsites.Ludivine.production.enable = true; + services.myWebsites.Ludivine.integration.enable = true; + services.myWebsites.Aten.production.enable = true; + services.myWebsites.Aten.integration.enable = true; + services.myWebsites.PiedsJaloux.production.enable = true; + services.myWebsites.PiedsJaloux.integration.enable = true; + services.myWebsites.Connexionswing.production.enable = true; + services.myWebsites.Connexionswing.integration.enable = true; nixpkgs.config.packageOverrides = oldpkgs: rec { goaccess = oldpkgs.goaccess.overrideAttrs(old: rec { @@ -84,95 +100,11 @@ occ ]; - # FIXME: doesn't work with httpd? - security.acme.preliminarySelfsigned = true; - security.acme.certs = { - # FIXME: /!\ To create a new certificate, create it before using - # it in httpd - "eldiron" = { - webroot = "/var/lib/acme/acme-challenge"; - email = "ismael@bouya.org"; - domain = "eldiron.immae.eu"; - plugins = [ "cert.pem" "chain.pem" "fullchain.pem" "full.pem" "key.pem" "account_key.json" ]; - postRun = '' - systemctl reload httpd.service - ''; - allowKeysForGroup = true; - extraDomains = { - "db-1.immae.eu" = null; - "tools.immae.eu" = null; - "connexionswing.immae.eu" = null; - "sandetludo.immae.eu" = null; - "cloud.immae.eu" = null; - "ludivine.immae.eu" = null; - "dev.aten.pro" = null; - "piedsjaloux.immae.eu" = null; - "chloe.immae.eu" = null; - "dav.immae.eu" = null; - }; - }; - "ludivinecassal" = { - webroot = "/var/lib/acme/acme-challenge"; - email = "ismael@bouya.org"; - domain = "ludivinecassal.com"; - plugins = [ "cert.pem" "chain.pem" "fullchain.pem" "full.pem" "key.pem" "account_key.json" ]; - postRun = '' - systemctl reload httpd.service - ''; - extraDomains = { - "www.ludivinecassal.com" = null; - }; - }; - "aten" = { - webroot = "/var/lib/acme/acme-challenge"; - email = "ismael@bouya.org"; - domain = "aten.pro"; - plugins = [ "cert.pem" "chain.pem" "fullchain.pem" "full.pem" "key.pem" "account_key.json" ]; - postRun = '' - systemctl reload httpd.service - ''; - extraDomains = { - "www.aten.pro" = null; - }; - }; - "piedsjaloux" = { - webroot = "/var/lib/acme/acme-challenge"; - email = "ismael@bouya.org"; - domain = "piedsjaloux.fr"; - plugins = [ "cert.pem" "chain.pem" "fullchain.pem" "full.pem" "key.pem" "account_key.json" ]; - postRun = '' - systemctl reload httpd.service - ''; - extraDomains = { - "www.piedsjaloux.fr" = null; - }; - }; - "chloe" = { - webroot = "/var/lib/acme/acme-challenge"; - email = "ismael@bouya.org"; - domain = "osteopathe-cc.fr"; - plugins = [ "cert.pem" "chain.pem" "fullchain.pem" "full.pem" "key.pem" "account_key.json" ]; - postRun = '' - systemctl reload httpd.service - ''; - extraDomains = { - "www.osteopathe-cc.fr" = null; - }; - }; - "connexionswing" = { - webroot = "/var/lib/acme/acme-challenge"; - email = "ismael@bouya.org"; - domain = "connexionswing.com"; - plugins = [ "cert.pem" "chain.pem" "fullchain.pem" "full.pem" "key.pem" "account_key.json" ]; - postRun = '' - systemctl reload httpd.service - ''; - extraDomains = { - "www.connexionswing.com" = null; - "sandetludo.com" = null; - "www.sandetludo.com" = null; - }; - }; + security.acme.certs."eldiron".extraDomains = { + "db-1.immae.eu" = null; + "tools.immae.eu" = null; + "cloud.immae.eu" = null; + "dav.immae.eu" = null; }; services.openssh.extraConfig = '' diff --git a/virtual/modules/certificates.nix b/virtual/modules/certificates.nix new file mode 100644 index 0000000..a9d6d99 --- /dev/null +++ b/virtual/modules/certificates.nix @@ -0,0 +1,30 @@ +{ lib, pkgs, config, mylibs, ... }: +{ + options.services.myCertificates = { + certConfig = lib.mkOption { + default = { + webroot = "/var/lib/acme/acme-challenge"; + email = "ismael@bouya.org"; + postRun = '' + systemctl reload httpd.service + ''; + plugins = [ "cert.pem" "chain.pem" "fullchain.pem" "full.pem" "key.pem" "account_key.json" ]; + }; + description = "Default configuration for certificates"; + }; + }; + + config = { + # FIXME: doesn't work with httpd? + security.acme.preliminarySelfsigned = true; + + security.acme.certs = { + # FIXME: /!\ To create a new certificate, create it before using + # it in httpd + "eldiron" = config.services.myCertificates.certConfig // { + domain = "eldiron.immae.eu"; + allowKeysForGroup = true; + }; + }; + }; +} diff --git a/virtual/modules/websites/aten.nix b/virtual/modules/websites/aten.nix new file mode 100644 index 0000000..7567289 --- /dev/null +++ b/virtual/modules/websites/aten.nix @@ -0,0 +1,28 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myWebsites.Aten; +in { + options.services.myWebsites.Aten = { + production = { + enable = lib.mkEnableOption "enable Aten's website in production"; + }; + integration = { + enable = lib.mkEnableOption "enable Aten's website in integration"; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.production.enable { + security.acme.certs."aten" = config.services.myCertificates.certConfig // { + domain = "aten.pro"; + extraDomains = { + "www.aten.pro" = null; + }; + }; + }) + (lib.mkIf cfg.integration.enable { + security.acme.certs."eldiron".extraDomains."dev.aten.pro" = null; + }) + ]; +} + diff --git a/virtual/modules/websites/chloe.nix b/virtual/modules/websites/chloe.nix new file mode 100644 index 0000000..2c0c65d --- /dev/null +++ b/virtual/modules/websites/chloe.nix @@ -0,0 +1,27 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myWebsites.Chloe; +in { + options.services.myWebsites.Chloe = { + production = { + enable = lib.mkEnableOption "enable Chloe's website in production"; + }; + integration = { + enable = lib.mkEnableOption "enable Chloe's website in integration"; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.production.enable { + security.acme.certs."chloe" = config.services.myCertificates.certConfig // { + domain = "osteopathe-cc.fr"; + extraDomains = { + "www.osteopathe-cc.fr" = null; + }; + }; + }) + (lib.mkIf cfg.integration.enable { + security.acme.certs."eldiron".extraDomains."chloe.immae.eu" = null; + }) + ]; +} diff --git a/virtual/modules/websites/connexionswing.nix b/virtual/modules/websites/connexionswing.nix new file mode 100644 index 0000000..ed6799f --- /dev/null +++ b/virtual/modules/websites/connexionswing.nix @@ -0,0 +1,31 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myWebsites.Connexionswing; +in { + options.services.myWebsites.Connexionswing = { + production = { + enable = lib.mkEnableOption "enable Connexionswing's website in production"; + }; + integration = { + enable = lib.mkEnableOption "enable Connexionswing's website in integration"; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.production.enable { + security.acme.certs."connexionswing" = config.services.myCertificates.certConfig // { + domain = "connexionswing.com"; + extraDomains = { + "www.connexionswing.com" = null; + "sandetludo.com" = null; + "www.sandetludo.com" = null; + }; + }; + }) + (lib.mkIf cfg.integration.enable { + security.acme.certs."eldiron".extraDomains."sandetludo.immae.eu" = null; + security.acme.certs."eldiron".extraDomains."connexionswing.immae.eu" = null; + }) + ]; +} + diff --git a/virtual/modules/websites/ludivine.nix b/virtual/modules/websites/ludivine.nix new file mode 100644 index 0000000..5729c09 --- /dev/null +++ b/virtual/modules/websites/ludivine.nix @@ -0,0 +1,27 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myWebsites.Ludivine; +in { + options.services.myWebsites.Ludivine = { + production = { + enable = lib.mkEnableOption "enable Ludivine's website in production"; + }; + integration = { + enable = lib.mkEnableOption "enable Ludivine's website in integration"; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.production.enable { + security.acme.certs."ludivinecassal" = config.services.myCertificates.certConfig // { + domain = "ludivinecassal.com"; + extraDomains = { + "www.ludivinecassal.com" = null; + }; + }; + }) + (lib.mkIf cfg.integration.enable { + security.acme.certs."eldiron".extraDomains."ludivine.immae.eu" = null; + }) + ]; +} diff --git a/virtual/modules/websites/piedsjaloux.nix b/virtual/modules/websites/piedsjaloux.nix new file mode 100644 index 0000000..849df63 --- /dev/null +++ b/virtual/modules/websites/piedsjaloux.nix @@ -0,0 +1,28 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myWebsites.PiedsJaloux; +in { + options.services.myWebsites.PiedsJaloux = { + production = { + enable = lib.mkEnableOption "enable PiedsJaloux's website in production"; + }; + integration = { + enable = lib.mkEnableOption "enable PiedsJaloux's website in integration"; + }; + }; + + config = lib.mkMerge [ + (lib.mkIf cfg.production.enable { + security.acme.certs."piedsjaloux" = config.services.myCertificates.certConfig // { + domain = "piedsjaloux.fr"; + extraDomains = { + "www.piedsjaloux.fr" = null; + }; + }; + }) + (lib.mkIf cfg.integration.enable { + security.acme.certs."eldiron".extraDomains."piedsjaloux.immae.eu" = null; + }) + ]; +} + -- 2.41.0 From 86f6924f021869c1fd8e4e2a7930d50f04f921df Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Thu, 10 Jan 2019 00:58:47 +0100 Subject: [PATCH 04/16] Move websites to their own modules: php config and scripts --- virtual/eldiron.nix | 20 -------------------- virtual/modules/websites/aten.nix | 9 +++++++++ virtual/modules/websites/chloe.nix | 9 +++++++++ virtual/modules/websites/connexionswing.nix | 9 +++++++++ virtual/modules/websites/ludivine.nix | 10 ++++++++++ virtual/modules/websites/piedsjaloux.nix | 9 +++++++++ 6 files changed, 46 insertions(+), 20 deletions(-) diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index 5dafe6e..7189c39 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -133,16 +133,6 @@ ''; poolConfigs = { adminer = mypkgs.adminer.phpFpm.pool; - connexionswing_dev = mypkgs.connexionswing_dev.phpFpm.pool; - connexionswing_prod = mypkgs.connexionswing_prod.phpFpm.pool; - ludivinecassal_dev = mypkgs.ludivinecassal_dev.phpFpm.pool; - ludivinecassal_prod = mypkgs.ludivinecassal_prod.phpFpm.pool; - piedsjaloux_dev = mypkgs.piedsjaloux_dev.phpFpm.pool; - piedsjaloux_prod = mypkgs.piedsjaloux_prod.phpFpm.pool; - chloe_dev = mypkgs.chloe_dev.phpFpm.pool; - chloe_prod = mypkgs.chloe_prod.phpFpm.pool; - aten_dev = mypkgs.aten_dev.phpFpm.pool; - aten_prod = mypkgs.aten_prod.phpFpm.pool; nextcloud = mypkgs.nextcloud.phpFpm.pool; mantisbt = mypkgs.mantisbt.phpFpm.pool; ttrss = mypkgs.ttrss.phpFpm.pool; @@ -152,16 +142,6 @@ }; system.activationScripts = { - connexionswing_dev = mypkgs.connexionswing_dev.activationScript; - connexionswing_prod = mypkgs.connexionswing_prod.activationScript; - ludivinecassal_dev = mypkgs.ludivinecassal_dev.activationScript; - ludivinecassal_prod = mypkgs.ludivinecassal_prod.activationScript; - piedsjaloux_dev = mypkgs.piedsjaloux_dev.activationScript; - piedsjaloux_prod = mypkgs.piedsjaloux_prod.activationScript; - chloe_dev = mypkgs.chloe_dev.activationScript; - chloe_prod = mypkgs.chloe_prod.activationScript; - aten_dev = mypkgs.aten_dev.activationScript; - aten_prod = mypkgs.aten_prod.activationScript; nextcloud = mypkgs.nextcloud.activationScript; ttrss = mypkgs.ttrss.activationScript; roundcubemail = mypkgs.roundcubemail.activationScript; diff --git a/virtual/modules/websites/aten.nix b/virtual/modules/websites/aten.nix index 7567289..88a9857 100644 --- a/virtual/modules/websites/aten.nix +++ b/virtual/modules/websites/aten.nix @@ -1,5 +1,9 @@ { lib, pkgs, config, mylibs, ... }: let + aten = pkgs.callPackage ../../packages/aten.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + aten_dev = aten { environment = "dev"; }; + aten_prod = aten { environment = "prod"; }; + cfg = config.services.myWebsites.Aten; in { options.services.myWebsites.Aten = { @@ -19,9 +23,14 @@ in { "www.aten.pro" = null; }; }; + + services.phpfpm.poolConfigs.aten_prod = aten_prod.phpFpm.pool; + system.activationScripts.aten_prod = aten_prod.activationScript; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."dev.aten.pro" = null; + services.phpfpm.poolConfigs.aten_dev = aten_dev.phpFpm.pool; + system.activationScripts.aten_dev = aten_dev.activationScript; }) ]; } diff --git a/virtual/modules/websites/chloe.nix b/virtual/modules/websites/chloe.nix index 2c0c65d..9b5c5ca 100644 --- a/virtual/modules/websites/chloe.nix +++ b/virtual/modules/websites/chloe.nix @@ -1,5 +1,9 @@ { lib, pkgs, config, mylibs, ... }: let + chloe = pkgs.callPackage ../../packages/chloe.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + chloe_dev = chloe { environment = "dev"; }; + chloe_prod = chloe { environment = "prod"; }; + cfg = config.services.myWebsites.Chloe; in { options.services.myWebsites.Chloe = { @@ -19,9 +23,14 @@ in { "www.osteopathe-cc.fr" = null; }; }; + + services.phpfpm.poolConfigs.chloe_prod = chloe_prod.phpFpm.pool; + system.activationScripts.chloe_prod = chloe_prod.activationScript; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."chloe.immae.eu" = null; + services.phpfpm.poolConfigs.chloe_dev = chloe_dev.phpFpm.pool; + system.activationScripts.chloe_dev = chloe_dev.activationScript; }) ]; } diff --git a/virtual/modules/websites/connexionswing.nix b/virtual/modules/websites/connexionswing.nix index ed6799f..e4b9c0e 100644 --- a/virtual/modules/websites/connexionswing.nix +++ b/virtual/modules/websites/connexionswing.nix @@ -1,5 +1,9 @@ { lib, pkgs, config, mylibs, ... }: let + connexionswing = pkgs.callPackage ../../packages/connexionswing.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + connexionswing_dev = connexionswing { environment = "dev"; }; + connexionswing_prod = connexionswing { environment = "prod"; }; + cfg = config.services.myWebsites.Connexionswing; in { options.services.myWebsites.Connexionswing = { @@ -21,10 +25,15 @@ in { "www.sandetludo.com" = null; }; }; + + services.phpfpm.poolConfigs.connexionswing_prod = connexionswing_prod.phpFpm.pool; + system.activationScripts.connexionswing_prod = connexionswing_prod.activationScript; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."sandetludo.immae.eu" = null; security.acme.certs."eldiron".extraDomains."connexionswing.immae.eu" = null; + services.phpfpm.poolConfigs.connexionswing_dev = connexionswing_dev.phpFpm.pool; + system.activationScripts.connexionswing_dev = connexionswing_dev.activationScript; }) ]; } diff --git a/virtual/modules/websites/ludivine.nix b/virtual/modules/websites/ludivine.nix index 5729c09..9d6b693 100644 --- a/virtual/modules/websites/ludivine.nix +++ b/virtual/modules/websites/ludivine.nix @@ -1,5 +1,9 @@ { lib, pkgs, config, mylibs, ... }: let + ludivinecassal = pkgs.callPackage ../../packages/ludivinecassal.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + ludivinecassal_dev = ludivinecassal { environment = "dev"; }; + ludivinecassal_prod = ludivinecassal { environment = "prod"; }; + cfg = config.services.myWebsites.Ludivine; in { options.services.myWebsites.Ludivine = { @@ -19,9 +23,15 @@ in { "www.ludivinecassal.com" = null; }; }; + + services.phpfpm.poolConfigs.ludivinecassal_prod = ludivinecassal_prod.phpFpm.pool; + system.activationScripts.ludivinecassal_prod = ludivinecassal_prod.activationScript; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."ludivine.immae.eu" = null; + + services.phpfpm.poolConfigs.ludivinecassal_dev = ludivinecassal_dev.phpFpm.pool; + system.activationScripts.ludivinecassal_dev = ludivinecassal_dev.activationScript; }) ]; } diff --git a/virtual/modules/websites/piedsjaloux.nix b/virtual/modules/websites/piedsjaloux.nix index 849df63..f2b17ad 100644 --- a/virtual/modules/websites/piedsjaloux.nix +++ b/virtual/modules/websites/piedsjaloux.nix @@ -1,5 +1,9 @@ { lib, pkgs, config, mylibs, ... }: let + piedsjaloux = pkgs.callPackage ../../packages/piedsjaloux.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + piedsjaloux_dev = piedsjaloux { environment = "dev"; }; + piedsjaloux_prod = piedsjaloux { environment = "prod"; }; + cfg = config.services.myWebsites.PiedsJaloux; in { options.services.myWebsites.PiedsJaloux = { @@ -19,9 +23,14 @@ in { "www.piedsjaloux.fr" = null; }; }; + + services.phpfpm.poolConfigs.piedsjaloux_prod = piedsjaloux_prod.phpFpm.pool; + system.activationScripts.piedsjaloux_prod = piedsjaloux_prod.activationScript; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."piedsjaloux.immae.eu" = null; + services.phpfpm.poolConfigs.piedsjaloux_dev = piedsjaloux_dev.phpFpm.pool; + system.activationScripts.piedsjaloux_dev = piedsjaloux_dev.activationScript; }) ]; } -- 2.41.0 From 42429ef0756d9ee41cf0ff0b38210edb3b1637e5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Thu, 10 Jan 2019 01:59:32 +0100 Subject: [PATCH 05/16] Continue moving websites: apache configuration and modules --- virtual/eldiron.nix | 94 +--------------- virtual/modules/databases.nix | 4 + virtual/modules/websites.nix | 115 ++++++++++++++++++++ virtual/modules/websites/aten.nix | 2 + virtual/modules/websites/chloe.nix | 2 + virtual/modules/websites/connexionswing.nix | 2 + virtual/modules/websites/ludivine.nix | 2 + virtual/modules/websites/piedsjaloux.nix | 2 + 8 files changed, 135 insertions(+), 88 deletions(-) create mode 100644 virtual/modules/websites.nix diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index 7189c39..efaa068 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -21,25 +21,13 @@ ./modules/gitolite.nix ./modules/gitweb.nix ./modules/databases.nix - ./modules/websites/chloe.nix - ./modules/websites/ludivine.nix - ./modules/websites/aten.nix - ./modules/websites/piedsjaloux.nix - ./modules/websites/connexionswing.nix + ./modules/websites.nix ]; services.myGitolite.enable = true; services.myGitweb.enable = true; services.myDatabases.enable = true; - services.myWebsites.Chloe.production.enable = true; - services.myWebsites.Chloe.integration.enable = true; - services.myWebsites.Ludivine.production.enable = true; - services.myWebsites.Ludivine.integration.enable = true; - services.myWebsites.Aten.production.enable = true; - services.myWebsites.Aten.integration.enable = true; - services.myWebsites.PiedsJaloux.production.enable = true; - services.myWebsites.PiedsJaloux.integration.enable = true; - services.myWebsites.Connexionswing.production.enable = true; - services.myWebsites.Connexionswing.integration.enable = true; + services.myWebsites.production.enable = true; + services.myWebsites.integration.enable = true; nixpkgs.config.packageOverrides = oldpkgs: rec { goaccess = oldpkgs.goaccess.overrideAttrs(old: rec { @@ -153,10 +141,6 @@ install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/ttrss install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/davical ''; - redis = '' - mkdir -p /run/redis - chown redis /run/redis - ''; # FIXME: initial sync goaccess = '' mkdir -p /var/lib/goaccess @@ -205,62 +189,7 @@ logFormat = "combinedVhost"; listen = [ { ip = "*"; port = 443; } ]; }; - apacheConfig = { - gzip = { - modules = [ "deflate" "filter" ]; - extraConfig = '' - AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript - ''; - }; - ldap = { - modules = [ "ldap" "authnz_ldap" ]; - extraConfig = assert checkEnv "NIXOPS_HTTP_LDAP_PASSWORD"; '' - - LDAPSharedCacheSize 500000 - LDAPCacheEntries 1024 - LDAPCacheTTL 600 - LDAPOpCacheEntries 1024 - LDAPOpCacheTTL 600 - - - - - AuthLDAPURL ldap://ldap.immae.eu:389/dc=immae,dc=eu - AuthLDAPBindDN cn=httpd,ou=services,dc=immae,dc=eu - AuthLDAPBindPassword "${builtins.getEnv "NIXOPS_HTTP_LDAP_PASSWORD"}" - AuthType Basic - AuthName "Authentification requise (Acces LDAP)" - AuthBasicProvider ldap - - - - - Alias /awstats /var/lib/goaccess/%{domain} - - DirectoryIndex index.html - AllowOverride None - Require all granted - - - Use LDAPConnect - Require ldap-group cn=%{domain},ou=stats,cn=httpd,ou=services,dc=immae,dc=eu - - - ''; - }; - http2 = { - modules = [ "http2" ]; - extraConfig = '' - Protocols h2 http/1.1 - ''; - }; - customLog = { - modules = []; - extraConfig = '' - LogFormat "%v:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedVhost - ''; - }; - }; + apacheConfig = config.services.myWebsites.apacheConfig; in rec { enable = true; logPerVirtualHost = true; @@ -270,25 +199,14 @@ extraModules = pkgs.lib.lists.unique ( mypkgs.adminer.apache.modules ++ mypkgs.nextcloud.apache.modules ++ - mypkgs.connexionswing_dev.apache.modules ++ - mypkgs.connexionswing_prod.apache.modules ++ - mypkgs.ludivinecassal_dev.apache.modules ++ - mypkgs.ludivinecassal_prod.apache.modules ++ - mypkgs.piedsjaloux_dev.apache.modules ++ - mypkgs.piedsjaloux_prod.apache.modules ++ - mypkgs.chloe_dev.apache.modules ++ - mypkgs.chloe_prod.apache.modules ++ - mypkgs.aten_dev.apache.modules ++ - mypkgs.aten_prod.apache.modules ++ mypkgs.ympd.apache.modules ++ mypkgs.git.web.apache.modules ++ mypkgs.mantisbt.apache.modules ++ mypkgs.ttrss.apache.modules ++ mypkgs.roundcubemail.apache.modules ++ - pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules) apacheConfig) ++ - [ "macro" ]); + pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) apacheConfig)); extraConfig = builtins.concatStringsSep "\n" - (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig) apacheConfig); + (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) apacheConfig)); virtualHosts = [ (withConf "eldiron" // { hostName = "eldiron.immae.eu"; diff --git a/virtual/modules/databases.nix b/virtual/modules/databases.nix index 25bd645..9f8e70d 100644 --- a/virtual/modules/databases.nix +++ b/virtual/modules/databases.nix @@ -129,5 +129,9 @@ in { maxclients 1024 ''; }; + system.activationScripts.redis = '' + mkdir -p /run/redis + chown redis /run/redis + ''; }; } diff --git a/virtual/modules/websites.nix b/virtual/modules/websites.nix new file mode 100644 index 0000000..62f45d9 --- /dev/null +++ b/virtual/modules/websites.nix @@ -0,0 +1,115 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myWebsites; +in +{ + imports = [ + ./websites/chloe.nix + ./websites/ludivine.nix + ./websites/aten.nix + ./websites/piedsjaloux.nix + ./websites/connexionswing.nix + ]; + + options.services.myWebsites = { + production = { + enable = lib.mkEnableOption "enable websites in production"; + }; + + integration = { + enable = lib.mkEnableOption "enable websites in integration"; + }; + + 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 = { + 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.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.apacheConfig = { + gzip = { + modules = [ "deflate" "filter" ]; + extraConfig = '' + AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript + ''; + }; + macros = { + modules = [ "macro" ]; + }; + ldap = { + modules = [ "ldap" "authnz_ldap" ]; + # FIXME: starttls + extraConfig = assert mylibs.checkEnv "NIXOPS_HTTP_LDAP_PASSWORD"; '' + + LDAPSharedCacheSize 500000 + LDAPCacheEntries 1024 + LDAPCacheTTL 600 + LDAPOpCacheEntries 1024 + LDAPOpCacheTTL 600 + + + + + AuthLDAPURL ldap://ldap.immae.eu:389/dc=immae,dc=eu STARTTLS + AuthLDAPBindDN cn=httpd,ou=services,dc=immae,dc=eu + AuthLDAPBindPassword "${builtins.getEnv "NIXOPS_HTTP_LDAP_PASSWORD"}" + AuthType Basic + AuthName "Authentification requise (Acces LDAP)" + AuthBasicProvider ldap + + + + + Alias /awstats /var/lib/goaccess/%{domain} + + DirectoryIndex index.html + AllowOverride None + Require all granted + + + Use LDAPConnect + Require ldap-group cn=%{domain},ou=stats,cn=httpd,ou=services,dc=immae,dc=eu + + + ''; + }; + 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 + ''; + }; + }; + }; +} diff --git a/virtual/modules/websites/aten.nix b/virtual/modules/websites/aten.nix index 88a9857..1a65389 100644 --- a/virtual/modules/websites/aten.nix +++ b/virtual/modules/websites/aten.nix @@ -26,11 +26,13 @@ in { services.phpfpm.poolConfigs.aten_prod = aten_prod.phpFpm.pool; system.activationScripts.aten_prod = aten_prod.activationScript; + services.myWebsites.apacheConfig.aten_prod.modules = aten_prod.apache.modules; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."dev.aten.pro" = null; services.phpfpm.poolConfigs.aten_dev = aten_dev.phpFpm.pool; system.activationScripts.aten_dev = aten_dev.activationScript; + services.myWebsites.apacheConfig.aten_dev.modules = aten_dev.apache.modules; }) ]; } diff --git a/virtual/modules/websites/chloe.nix b/virtual/modules/websites/chloe.nix index 9b5c5ca..d54c42d 100644 --- a/virtual/modules/websites/chloe.nix +++ b/virtual/modules/websites/chloe.nix @@ -26,11 +26,13 @@ in { services.phpfpm.poolConfigs.chloe_prod = chloe_prod.phpFpm.pool; system.activationScripts.chloe_prod = chloe_prod.activationScript; + services.myWebsites.apacheConfig.chloe_prod.modules = chloe_prod.apache.modules; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."chloe.immae.eu" = null; services.phpfpm.poolConfigs.chloe_dev = chloe_dev.phpFpm.pool; system.activationScripts.chloe_dev = chloe_dev.activationScript; + services.myWebsites.apacheConfig.chloe_dev.modules = chloe_dev.apache.modules; }) ]; } diff --git a/virtual/modules/websites/connexionswing.nix b/virtual/modules/websites/connexionswing.nix index e4b9c0e..8bf63a8 100644 --- a/virtual/modules/websites/connexionswing.nix +++ b/virtual/modules/websites/connexionswing.nix @@ -28,12 +28,14 @@ in { services.phpfpm.poolConfigs.connexionswing_prod = connexionswing_prod.phpFpm.pool; system.activationScripts.connexionswing_prod = connexionswing_prod.activationScript; + services.myWebsites.apacheConfig.connexionswing_prod.modules = connexionswing_prod.apache.modules; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."sandetludo.immae.eu" = null; security.acme.certs."eldiron".extraDomains."connexionswing.immae.eu" = null; services.phpfpm.poolConfigs.connexionswing_dev = connexionswing_dev.phpFpm.pool; system.activationScripts.connexionswing_dev = connexionswing_dev.activationScript; + services.myWebsites.apacheConfig.connexionswing_dev.modules = connexionswing_dev.apache.modules; }) ]; } diff --git a/virtual/modules/websites/ludivine.nix b/virtual/modules/websites/ludivine.nix index 9d6b693..f06e41a 100644 --- a/virtual/modules/websites/ludivine.nix +++ b/virtual/modules/websites/ludivine.nix @@ -26,12 +26,14 @@ in { services.phpfpm.poolConfigs.ludivinecassal_prod = ludivinecassal_prod.phpFpm.pool; system.activationScripts.ludivinecassal_prod = ludivinecassal_prod.activationScript; + services.myWebsites.apacheConfig.ludivinecassal_prod.modules = ludivinecassal_prod.apache.modules; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."ludivine.immae.eu" = null; services.phpfpm.poolConfigs.ludivinecassal_dev = ludivinecassal_dev.phpFpm.pool; system.activationScripts.ludivinecassal_dev = ludivinecassal_dev.activationScript; + services.myWebsites.apacheConfig.ludivinecassal_dev.modules = ludivinecassal_dev.apache.modules; }) ]; } diff --git a/virtual/modules/websites/piedsjaloux.nix b/virtual/modules/websites/piedsjaloux.nix index f2b17ad..285fd18 100644 --- a/virtual/modules/websites/piedsjaloux.nix +++ b/virtual/modules/websites/piedsjaloux.nix @@ -26,11 +26,13 @@ in { services.phpfpm.poolConfigs.piedsjaloux_prod = piedsjaloux_prod.phpFpm.pool; system.activationScripts.piedsjaloux_prod = piedsjaloux_prod.activationScript; + services.myWebsites.apacheConfig.piedsjaloux_prod.modules = piedsjaloux_prod.apache.modules; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."piedsjaloux.immae.eu" = null; services.phpfpm.poolConfigs.piedsjaloux_dev = piedsjaloux_dev.phpFpm.pool; system.activationScripts.piedsjaloux_dev = piedsjaloux_dev.activationScript; + services.myWebsites.apacheConfig.piedsjaloux_dev.modules = piedsjaloux_dev.apache.modules; }) ]; } -- 2.41.0 From f8bde3d6d31da84b5e81bdfc4f96efdf6bec3df2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Thu, 10 Jan 2019 20:56:44 +0100 Subject: [PATCH 06/16] Add http configuration to modules and separate production from integration --- virtual/eldiron.nix | 57 +- virtual/modules/websites.nix | 81 +- .../modules/websites/apache/httpd_inte.nix | 722 ++++++++++++++++++ .../modules/websites/apache/httpd_prod.nix | 722 ++++++++++++++++++ .../websites/apache/per-server-options.nix | 188 +++++ virtual/modules/websites/aten.nix | 15 +- virtual/modules/websites/chloe.nix | 16 +- virtual/modules/websites/connexionswing.nix | 16 +- virtual/modules/websites/ludivine.nix | 15 +- virtual/modules/websites/piedsjaloux.nix | 16 +- 10 files changed, 1792 insertions(+), 56 deletions(-) create mode 100644 virtual/modules/websites/apache/httpd_inte.nix create mode 100644 virtual/modules/websites/apache/httpd_prod.nix create mode 100644 virtual/modules/websites/apache/per-server-options.nix diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index efaa068..a1e6909 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -4,7 +4,7 @@ enableRollback = true; }; - eldiron = { config, pkgs, mylibs, ... }: + eldiron = { config, pkgs, mylibs, myconfig, ... }: with mylibs; let mypkgs = pkgs.callPackage ./packages.nix { @@ -14,6 +14,13 @@ { _module.args = { mylibs = import ../libs.nix; + myconfig = { + ips = { + main = "176.9.151.89"; + production = "176.9.151.154"; + integration = "176.9.151.155"; + }; + }; }; imports = [ @@ -47,6 +54,11 @@ enable = true; allowedTCPPorts = [ 22 80 443 9418 ]; }; + interfaces."eth0".ipv4.addresses = [ + # 176.9.151.89 declared in nixops -> infra / tools + { address = myconfig.ips.production; prefixLength = 32; } + { address = myconfig.ips.integration; prefixLength = 32; } + ]; }; deployment = { @@ -54,7 +66,7 @@ hetzner = { #robotUser = "defined in HETZNER_ROBOT_USER"; #robotPass = "defined in HETZNER_ROBOT_PASS"; - mainIPv4 = "176.9.151.89"; + mainIPv4 = myconfig.ips.main; partitions = '' clearpart --all --initlabel --drives=sda,sdb @@ -138,7 +150,6 @@ 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/sessions/mantisbt - install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/ttrss install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/davical ''; # FIXME: initial sync @@ -187,7 +198,9 @@ sslServerKey = "/var/lib/acme/${domain}/key.pem"; sslServerChain = "/var/lib/acme/${domain}/fullchain.pem"; logFormat = "combinedVhost"; - listen = [ { ip = "*"; port = 443; } ]; + listen = [ + { ip = "176.9.151.89"; port = 443; } + ]; }; apacheConfig = config.services.myWebsites.apacheConfig; in rec { @@ -240,14 +253,6 @@ mypkgs.davical.apache.vhostConf ]; }) - (withConf "eldiron" // { - hostName = "connexionswing.immae.eu"; - serverAliases = [ "sandetludo.immae.eu" ]; - documentRoot = mypkgs.connexionswing_dev.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.connexionswing_dev.apache.vhostConf - ]; - }) (withConf "connexionswing" // { hostName = "connexionswing.com"; serverAliases = [ "sandetludo.com" "www.connexionswing.com" "www.sandetludo.com" ]; @@ -256,13 +261,6 @@ mypkgs.connexionswing_prod.apache.vhostConf ]; }) - (withConf "eldiron" // { - hostName = "ludivine.immae.eu"; - documentRoot = mypkgs.ludivinecassal_dev.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.ludivinecassal_dev.apache.vhostConf - ]; - }) (withConf "ludivinecassal" // { hostName = "ludivinecassal.com"; serverAliases = [ "www.ludivinecassal.com" ]; @@ -271,13 +269,6 @@ mypkgs.ludivinecassal_prod.apache.vhostConf ]; }) - (withConf "eldiron" // { - hostName = "piedsjaloux.immae.eu"; - documentRoot = mypkgs.piedsjaloux_dev.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.piedsjaloux_dev.apache.vhostConf - ]; - }) (withConf "piedsjaloux" // { hostName = "piedsjaloux.fr"; serverAliases = [ "www.piedsjaloux.fr" ]; @@ -286,13 +277,6 @@ mypkgs.piedsjaloux_prod.apache.vhostConf ]; }) - (withConf "eldiron" // { - hostName = "chloe.immae.eu"; - documentRoot = mypkgs.chloe_dev.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.chloe_dev.apache.vhostConf - ]; - }) (withConf "chloe" // { hostName = "osteopathe-cc.fr"; serverAliases = [ "www.osteopathe-cc.fr" ]; @@ -301,13 +285,6 @@ mypkgs.chloe_prod.apache.vhostConf ]; }) - (withConf "eldiron" // { - hostName = "dev.aten.pro"; - documentRoot = mypkgs.aten_dev.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.aten_dev.apache.vhostConf - ]; - }) (withConf "aten" // { hostName = "aten.pro"; serverAliases = [ "www.aten.pro" ]; diff --git a/virtual/modules/websites.nix b/virtual/modules/websites.nix index 62f45d9..cbd7de0 100644 --- a/virtual/modules/websites.nix +++ b/virtual/modules/websites.nix @@ -1,6 +1,61 @@ -{ lib, pkgs, config, mylibs, ... }: +{ lib, pkgs, config, mylibs, myconfig, ... }: let cfg = config.services.myWebsites; + 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 = [ + { ip = cfg.ip; port = 443; } + ]; + hostName = builtins.head vhostConf.hosts; + serverAliases = builtins.tail vhostConf.hosts or []; + documentRoot = vhostConf.root; + extraConfig = builtins.concatStringsSep "\n" vhostConf.extraConfig; + }; + in rec { + enable = true; + listen = [ + { ip = cfg.ip; port = 443; } + ]; + 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 = pkgs.lib.attrsets.mapAttrsToList (n: v: toVhost v) cfg.vhostConfs; + }; + makeServiceOptions = name: ip: { + enable = lib.mkEnableOption "enable websites in ${name}"; + ip = lib.mkOption { + type = lib.types.string; + default = ip; + description = "${name} ip to listen to"; + }; + modules = lib.mkOption { + type = lib.types.listOf (lib.types.str); + default = []; + }; + extraConfig = lib.mkOption { + type = lib.types.listOf (lib.types.lines); + default = []; + }; + 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 = []; }; + }; + }); + }; + }; in { imports = [ @@ -9,16 +64,16 @@ in ./websites/aten.nix ./websites/piedsjaloux.nix ./websites/connexionswing.nix + # built using: + # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix + # And removed users / groups + ./websites/apache/httpd_prod.nix + ./websites/apache/httpd_inte.nix ]; options.services.myWebsites = { - production = { - enable = lib.mkEnableOption "enable websites in production"; - }; - - integration = { - enable = lib.mkEnableOption "enable websites in integration"; - }; + production = makeServiceOptions "production" myconfig.ips.production; + integration = makeServiceOptions "integration" myconfig.ips.integration; apacheConfig = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule { @@ -111,5 +166,15 @@ in ''; }; }; + + # FIXME: logrotate + # FIXME: ipv6 + services.httpdProd = makeService "production" config.services.myWebsites.production; + services.myWebsites.production.modules = pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig); + services.myWebsites.production.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); + + services.httpdInte = makeService "integration" config.services.myWebsites.integration; + services.myWebsites.integration.modules = pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig); + services.myWebsites.integration.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); }; } diff --git a/virtual/modules/websites/apache/httpd_inte.nix b/virtual/modules/websites/apache/httpd_inte.nix new file mode 100644 index 0000000..83d8ab8 --- /dev/null +++ b/virtual/modules/websites/apache/httpd_inte.nix @@ -0,0 +1,722 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + mainCfg = config.services.httpdInte; + + httpd = mainCfg.package.out; + + version24 = !versionOlder httpd.version "2.4"; + + httpdConf = mainCfg.configFile; + + php = mainCfg.phpPackage.override { apacheHttpd = httpd.dev; /* otherwise it only gets .out */ }; + + phpMajorVersion = head (splitString "." php.version); + + mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = httpd; }; + + defaultListen = cfg: if cfg.enableSSL + then [{ip = "*"; port = 443;}] + else [{ip = "*"; port = 80;}]; + + getListen = cfg: + let list = (lib.optional (cfg.port != 0) {ip = "*"; port = cfg.port;}) ++ cfg.listen; + in if list == [] + then defaultListen cfg + else list; + + listenToString = l: "${l.ip}:${toString l.port}"; + + extraModules = attrByPath ["extraModules"] [] mainCfg; + extraForeignModules = filter isAttrs extraModules; + extraApacheModules = filter isString extraModules; + + + makeServerInfo = cfg: { + # Canonical name must not include a trailing slash. + canonicalNames = + let defaultPort = (head (defaultListen cfg)).port; in + map (port: + (if cfg.enableSSL then "https" else "http") + "://" + + cfg.hostName + + (if port != defaultPort then ":${toString port}" else "") + ) (map (x: x.port) (getListen cfg)); + + # Admin address: inherit from the main server if not specified for + # a virtual host. + adminAddr = if cfg.adminAddr != null then cfg.adminAddr else mainCfg.adminAddr; + + vhostConfig = cfg; + serverConfig = mainCfg; + fullConfig = config; # machine config + }; + + + allHosts = [mainCfg] ++ mainCfg.virtualHosts; + + + callSubservices = serverInfo: defs: + let f = svc: + let + svcFunction = + if svc ? function then svc.function + # instead of using serviceType="mediawiki"; you can copy mediawiki.nix to any location outside nixpkgs, modify it at will, and use serviceExpression=./mediawiki.nix; + else if svc ? serviceExpression then import (toString svc.serviceExpression) + else import (toString "${toString ./.}/${if svc ? serviceType then svc.serviceType else svc.serviceName}.nix"); + config = (evalModules + { modules = [ { options = res.options; config = svc.config or svc; } ]; + check = false; + }).config; + defaults = { + extraConfig = ""; + extraModules = []; + extraModulesPre = []; + extraPath = []; + extraServerPath = []; + globalEnvVars = []; + robotsEntries = ""; + startupScript = ""; + enablePHP = false; + enablePerl = false; + phpOptions = ""; + options = {}; + documentRoot = null; + }; + res = defaults // svcFunction { inherit config lib pkgs serverInfo php; }; + in res; + in map f defs; + + + # !!! callSubservices is expensive + subservicesFor = cfg: callSubservices (makeServerInfo cfg) cfg.extraSubservices; + + mainSubservices = subservicesFor mainCfg; + + allSubservices = mainSubservices ++ concatMap subservicesFor mainCfg.virtualHosts; + + + enableSSL = any (vhost: vhost.enableSSL) allHosts; + + + # Names of modules from ${httpd}/modules that we want to load. + apacheModules = + [ # HTTP authentication mechanisms: basic and digest. + "auth_basic" "auth_digest" + + # Authentication: is the user who he claims to be? + "authn_file" "authn_dbm" "authn_anon" + (if version24 then "authn_core" else "authn_alias") + + # Authorization: is the user allowed access? + "authz_user" "authz_groupfile" "authz_host" + + # Other modules. + "ext_filter" "include" "log_config" "env" "mime_magic" + "cern_meta" "expires" "headers" "usertrack" /* "unique_id" */ "setenvif" + "mime" "dav" "status" "autoindex" "asis" "info" "dav_fs" + "vhost_alias" "negotiation" "dir" "imagemap" "actions" "speling" + "userdir" "alias" "rewrite" "proxy" "proxy_http" + ] + ++ optionals version24 [ + "mpm_${mainCfg.multiProcessingModule}" + "authz_core" + "unixd" + "cache" "cache_disk" + "slotmem_shm" + "socache_shmcb" + # For compatibility with old configurations, the new module mod_access_compat is provided. + "access_compat" + ] + ++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ]) + ++ optional enableSSL "ssl" + ++ extraApacheModules; + + + allDenied = if version24 then '' + Require all denied + '' else '' + Order deny,allow + Deny from all + ''; + + allGranted = if version24 then '' + Require all granted + '' else '' + Order allow,deny + Allow from all + ''; + + + loggingConf = (if mainCfg.logFormat != "none" then '' + ErrorLog ${mainCfg.logDir}/error_log + + LogLevel notice + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + LogFormat "%{Referer}i -> %U" referer + LogFormat "%{User-agent}i" agent + + CustomLog ${mainCfg.logDir}/access_log ${mainCfg.logFormat} + '' else '' + ErrorLog /dev/null + ''); + + + browserHacks = '' + BrowserMatch "Mozilla/2" nokeepalive + BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + BrowserMatch "RealPlayer 4\.0" force-response-1.0 + BrowserMatch "Java/1\.0" force-response-1.0 + BrowserMatch "JDK/1\.0" force-response-1.0 + BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully + BrowserMatch "^WebDrive" redirect-carefully + BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully + BrowserMatch "^gnome-vfs" redirect-carefully + ''; + + + sslConf = '' + SSLSessionCache ${if version24 then "shmcb" else "shm"}:${mainCfg.stateDir}/ssl_scache(512000) + + ${if version24 then "Mutex" else "SSLMutex"} posixsem + + SSLRandomSeed startup builtin + SSLRandomSeed connect builtin + + SSLProtocol All -SSLv2 -SSLv3 + SSLCipherSuite HIGH:!aNULL:!MD5:!EXP + SSLHonorCipherOrder on + ''; + + + mimeConf = '' + TypesConfig ${httpd}/conf/mime.types + + AddType application/x-x509-ca-cert .crt + AddType application/x-pkcs7-crl .crl + AddType application/x-httpd-php .php .phtml + + + MIMEMagicFile ${httpd}/conf/magic + + ''; + + + perServerConf = isMainServer: cfg: let + + serverInfo = makeServerInfo cfg; + + subservices = callSubservices serverInfo cfg.extraSubservices; + + maybeDocumentRoot = fold (svc: acc: + if acc == null then svc.documentRoot else assert svc.documentRoot == null; acc + ) null ([ cfg ] ++ subservices); + + documentRoot = if maybeDocumentRoot != null then maybeDocumentRoot else + pkgs.runCommand "empty" {} "mkdir -p $out"; + + documentRootConf = '' + DocumentRoot "${documentRoot}" + + + Options Indexes FollowSymLinks + AllowOverride None + ${allGranted} + + ''; + + robotsTxt = + concatStringsSep "\n" (filter (x: x != "") ( + # If this is a vhost, the include the entries for the main server as well. + (if isMainServer then [] else [mainCfg.robotsEntries] ++ map (svc: svc.robotsEntries) mainSubservices) + ++ [cfg.robotsEntries] + ++ (map (svc: svc.robotsEntries) subservices))); + + in '' + ${concatStringsSep "\n" (map (n: "ServerName ${n}") serverInfo.canonicalNames)} + + ${concatMapStrings (alias: "ServerAlias ${alias}\n") cfg.serverAliases} + + ${if cfg.sslServerCert != null then '' + SSLCertificateFile ${cfg.sslServerCert} + SSLCertificateKeyFile ${cfg.sslServerKey} + ${if cfg.sslServerChain != null then '' + SSLCertificateChainFile ${cfg.sslServerChain} + '' else ""} + '' else ""} + + ${if cfg.enableSSL then '' + SSLEngine on + '' else if enableSSL then /* i.e., SSL is enabled for some host, but not this one */ + '' + SSLEngine off + '' else ""} + + ${if isMainServer || cfg.adminAddr != null then '' + ServerAdmin ${cfg.adminAddr} + '' else ""} + + ${if !isMainServer && mainCfg.logPerVirtualHost then '' + ErrorLog ${mainCfg.logDir}/error_log-${cfg.hostName} + CustomLog ${mainCfg.logDir}/access_log-${cfg.hostName} ${cfg.logFormat} + '' else ""} + + ${optionalString (robotsTxt != "") '' + Alias /robots.txt ${pkgs.writeText "robots.txt" robotsTxt} + ''} + + ${if isMainServer || maybeDocumentRoot != null then documentRootConf else ""} + + ${if cfg.enableUserDir then '' + + UserDir public_html + UserDir disabled root + + + AllowOverride FileInfo AuthConfig Limit Indexes + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec + + ${allGranted} + + + ${allDenied} + + + + '' else ""} + + ${if cfg.globalRedirect != null && cfg.globalRedirect != "" then '' + RedirectPermanent / ${cfg.globalRedirect} + '' else ""} + + ${ + let makeFileConf = elem: '' + Alias ${elem.urlPath} ${elem.file} + ''; + in concatMapStrings makeFileConf cfg.servedFiles + } + + ${ + let makeDirConf = elem: '' + Alias ${elem.urlPath} ${elem.dir}/ + + Options +Indexes + ${allGranted} + AllowOverride All + + ''; + in concatMapStrings makeDirConf cfg.servedDirs + } + + ${concatMapStrings (svc: svc.extraConfig) subservices} + + ${cfg.extraConfig} + ''; + + + confFile = pkgs.writeText "httpd.conf" '' + + ServerRoot ${httpd} + + ${optionalString version24 '' + DefaultRuntimeDir ${mainCfg.stateDir}/runtime + ''} + + PidFile ${mainCfg.stateDir}/httpd.pid + + ${optionalString (mainCfg.multiProcessingModule != "prefork") '' + # mod_cgid requires this. + ScriptSock ${mainCfg.stateDir}/cgisock + ''} + + + MaxClients ${toString mainCfg.maxClients} + MaxRequestsPerChild ${toString mainCfg.maxRequestsPerChild} + + + ${let + listen = concatMap getListen allHosts; + toStr = listen: "Listen ${listenToString listen}\n"; + uniqueListen = uniqList {inputList = map toStr listen;}; + in concatStrings uniqueListen + } + + User ${mainCfg.user} + Group ${mainCfg.group} + + ${let + load = {name, path}: "LoadModule ${name}_module ${path}\n"; + allModules = + concatMap (svc: svc.extraModulesPre) allSubservices + ++ map (name: {inherit name; path = "${httpd}/modules/mod_${name}.so";}) apacheModules + ++ optional mainCfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; } + ++ optional enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; } + ++ optional enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; } + ++ concatMap (svc: svc.extraModules) allSubservices + ++ extraForeignModules; + in concatMapStrings load allModules + } + + AddHandler type-map var + + + ${allDenied} + + + ${mimeConf} + ${loggingConf} + ${browserHacks} + + Include ${httpd}/conf/extra/httpd-default.conf + Include ${httpd}/conf/extra/httpd-autoindex.conf + Include ${httpd}/conf/extra/httpd-multilang-errordoc.conf + Include ${httpd}/conf/extra/httpd-languages.conf + + ${if enableSSL then sslConf else ""} + + # Fascist default - deny access to everything. + + Options FollowSymLinks + AllowOverride None + ${allDenied} + + + # But do allow access to files in the store so that we don't have + # to generate clauses for every generated file that we + # want to serve. + + ${allGranted} + + + # Generate directives for the main server. + ${perServerConf true mainCfg} + + # Always enable virtual hosts; it doesn't seem to hurt. + ${let + listen = concatMap getListen allHosts; + uniqueListen = uniqList {inputList = listen;}; + directives = concatMapStrings (listen: "NameVirtualHost ${listenToString listen}\n") uniqueListen; + in optionalString (!version24) directives + } + + ${let + makeVirtualHost = vhost: '' + + ${perServerConf false vhost} + + ''; + in concatMapStrings makeVirtualHost mainCfg.virtualHosts + } + ''; + + + enablePHP = mainCfg.enablePHP || any (svc: svc.enablePHP) allSubservices; + + enablePerl = mainCfg.enablePerl || any (svc: svc.enablePerl) allSubservices; + + + # Generate the PHP configuration file. Should probably be factored + # out into a separate module. + phpIni = pkgs.runCommand "php.ini" + { options = concatStringsSep "\n" + ([ mainCfg.phpOptions ] ++ (map (svc: svc.phpOptions) allSubservices)); + } + '' + cat ${php}/etc/php.ini > $out + echo "$options" >> $out + ''; + +in + + +{ + + ###### interface + + options = { + + services.httpdInte = { + + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the Apache HTTP Server."; + }; + + package = mkOption { + type = types.package; + default = pkgs.apacheHttpd; + defaultText = "pkgs.apacheHttpd"; + description = '' + Overridable attribute of the Apache HTTP Server package to use. + ''; + }; + + configFile = mkOption { + type = types.path; + default = confFile; + defaultText = "confFile"; + example = literalExample ''pkgs.writeText "httpd.conf" "# my custom config file ..."''; + description = '' + Override the configuration file used by Apache. By default, + NixOS generates one automatically. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Cnfiguration lines appended to the generated Apache + configuration file. Note that this mechanism may not work + when is overridden. + ''; + }; + + extraModules = mkOption { + type = types.listOf types.unspecified; + default = []; + example = literalExample ''[ "proxy_connect" { name = "php5"; path = "''${pkgs.php}/modules/libphp5.so"; } ]''; + description = '' + Additional Apache modules to be used. These can be + specified as a string in the case of modules distributed + with Apache, or as an attribute set specifying the + name and path of the + module. + ''; + }; + + logPerVirtualHost = mkOption { + type = types.bool; + default = false; + description = '' + If enabled, each virtual host gets its own + access_log and + error_log, namely suffixed by the + of the virtual host. + ''; + }; + + user = mkOption { + type = types.str; + default = "wwwrun"; + description = '' + User account under which httpd runs. The account is created + automatically if it doesn't exist. + ''; + }; + + group = mkOption { + type = types.str; + default = "wwwrun"; + description = '' + Group under which httpd runs. The account is created + automatically if it doesn't exist. + ''; + }; + + logDir = mkOption { + type = types.path; + default = "/var/log/httpd"; + description = '' + Directory for Apache's log files. It is created automatically. + ''; + }; + + stateDir = mkOption { + type = types.path; + default = "/run/httpd"; + description = '' + Directory for Apache's transient runtime state (such as PID + files). It is created automatically. Note that the default, + /run/httpd, is deleted at boot time. + ''; + }; + + virtualHosts = mkOption { + type = types.listOf (types.submodule ( + { options = import ./per-server-options.nix { + inherit lib; + forMainServer = false; + }; + })); + default = []; + example = [ + { hostName = "foo"; + documentRoot = "/data/webroot-foo"; + } + { hostName = "bar"; + documentRoot = "/data/webroot-bar"; + } + ]; + description = '' + Specification of the virtual hosts served by Apache. Each + element should be an attribute set specifying the + configuration of the virtual host. The available options + are the non-global options permissible for the main host. + ''; + }; + + enableMellon = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the mod_auth_mellon module."; + }; + + enablePHP = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the PHP module."; + }; + + phpPackage = mkOption { + type = types.package; + default = pkgs.php; + defaultText = "pkgs.php"; + description = '' + Overridable attribute of the PHP package to use. + ''; + }; + + enablePerl = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the Perl module (mod_perl)."; + }; + + phpOptions = mkOption { + type = types.lines; + default = ""; + example = + '' + date.timezone = "CET" + ''; + description = + "Options appended to the PHP configuration file php.ini."; + }; + + multiProcessingModule = mkOption { + type = types.str; + default = "prefork"; + example = "worker"; + description = + '' + Multi-processing module to be used by Apache. Available + modules are prefork (the default; + handles each request in a separate child process), + worker (hybrid approach that starts a + number of child processes each running a number of + threads) and event (a recent variant of + worker that handles persistent + connections more efficiently). + ''; + }; + + maxClients = mkOption { + type = types.int; + default = 150; + example = 8; + description = "Maximum number of httpd processes (prefork)"; + }; + + maxRequestsPerChild = mkOption { + type = types.int; + default = 0; + example = 500; + description = + "Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited"; + }; + } + + # Include the options shared between the main server and virtual hosts. + // (import ./per-server-options.nix { + inherit lib; + forMainServer = true; + }); + + }; + + + ###### implementation + + config = mkIf config.services.httpdInte.enable { + + assertions = [ { assertion = mainCfg.enableSSL == true + -> mainCfg.sslServerCert != null + && mainCfg.sslServerKey != null; + message = "SSL is enabled for httpd, but sslServerCert and/or sslServerKey haven't been specified."; } + ]; + + warnings = map (cfg: ''apache-httpd's port option is deprecated. Use listen = [{/*ip = "*"; */ port = ${toString cfg.port};}]; instead'' ) (lib.filter (cfg: cfg.port != 0) allHosts); + + environment.systemPackages = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices; + + services.httpdInte.phpOptions = + '' + ; Needed for PHP's mail() function. + sendmail_path = sendmail -t -i + '' + optionalString (!isNull config.time.timeZone) '' + + ; Apparently PHP doesn't use $TZ. + date.timezone = "${config.time.timeZone}" + ''; + + systemd.services.httpdInte = + { description = "Apache HTTPD"; + + wantedBy = [ "multi-user.target" ]; + wants = [ "keys.target" ]; + after = [ "network.target" "fs.target" "postgresql.service" "keys.target" ]; + + path = + [ httpd pkgs.coreutils pkgs.gnugrep ] + ++ # Needed for PHP's mail() function. !!! Probably the + # ssmtp module should export the path to sendmail in + # some way. + optional config.networking.defaultMailServer.directDelivery pkgs.ssmtp + ++ concatMap (svc: svc.extraServerPath) allSubservices; + + environment = + optionalAttrs enablePHP { PHPRC = phpIni; } + // optionalAttrs mainCfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; } + // (listToAttrs (concatMap (svc: svc.globalEnvVars) allSubservices)); + + preStart = + '' + mkdir -m 0750 -p ${mainCfg.stateDir} + [ $(id -u) != 0 ] || chown root.${mainCfg.group} ${mainCfg.stateDir} + ${optionalString version24 '' + mkdir -m 0750 -p "${mainCfg.stateDir}/runtime" + [ $(id -u) != 0 ] || chown root.${mainCfg.group} "${mainCfg.stateDir}/runtime" + ''} + mkdir -m 0700 -p ${mainCfg.logDir} + + # Get rid of old semaphores. These tend to accumulate across + # server restarts, eventually preventing it from restarting + # successfully. + for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${mainCfg.user} ' | cut -f2 -d ' '); do + ${pkgs.utillinux}/bin/ipcrm -s $i + done + + # Run the startup hooks for the subservices. + for i in ${toString (map (svn: svn.startupScript) allSubservices)}; do + echo Running Apache startup hook $i... + $i + done + ''; + + serviceConfig.ExecStart = "@${httpd}/bin/httpd httpd -f ${httpdConf}"; + serviceConfig.ExecStop = "${httpd}/bin/httpd -f ${httpdConf} -k graceful-stop"; + serviceConfig.ExecReload = "${httpd}/bin/httpd -f ${httpdConf} -k graceful"; + serviceConfig.Type = "forking"; + serviceConfig.PIDFile = "${mainCfg.stateDir}/httpd.pid"; + serviceConfig.Restart = "always"; + serviceConfig.RestartSec = "5s"; + }; + + }; +} diff --git a/virtual/modules/websites/apache/httpd_prod.nix b/virtual/modules/websites/apache/httpd_prod.nix new file mode 100644 index 0000000..576a305 --- /dev/null +++ b/virtual/modules/websites/apache/httpd_prod.nix @@ -0,0 +1,722 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + mainCfg = config.services.httpdProd; + + httpd = mainCfg.package.out; + + version24 = !versionOlder httpd.version "2.4"; + + httpdConf = mainCfg.configFile; + + php = mainCfg.phpPackage.override { apacheHttpd = httpd.dev; /* otherwise it only gets .out */ }; + + phpMajorVersion = head (splitString "." php.version); + + mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = httpd; }; + + defaultListen = cfg: if cfg.enableSSL + then [{ip = "*"; port = 443;}] + else [{ip = "*"; port = 80;}]; + + getListen = cfg: + let list = (lib.optional (cfg.port != 0) {ip = "*"; port = cfg.port;}) ++ cfg.listen; + in if list == [] + then defaultListen cfg + else list; + + listenToString = l: "${l.ip}:${toString l.port}"; + + extraModules = attrByPath ["extraModules"] [] mainCfg; + extraForeignModules = filter isAttrs extraModules; + extraApacheModules = filter isString extraModules; + + + makeServerInfo = cfg: { + # Canonical name must not include a trailing slash. + canonicalNames = + let defaultPort = (head (defaultListen cfg)).port; in + map (port: + (if cfg.enableSSL then "https" else "http") + "://" + + cfg.hostName + + (if port != defaultPort then ":${toString port}" else "") + ) (map (x: x.port) (getListen cfg)); + + # Admin address: inherit from the main server if not specified for + # a virtual host. + adminAddr = if cfg.adminAddr != null then cfg.adminAddr else mainCfg.adminAddr; + + vhostConfig = cfg; + serverConfig = mainCfg; + fullConfig = config; # machine config + }; + + + allHosts = [mainCfg] ++ mainCfg.virtualHosts; + + + callSubservices = serverInfo: defs: + let f = svc: + let + svcFunction = + if svc ? function then svc.function + # instead of using serviceType="mediawiki"; you can copy mediawiki.nix to any location outside nixpkgs, modify it at will, and use serviceExpression=./mediawiki.nix; + else if svc ? serviceExpression then import (toString svc.serviceExpression) + else import (toString "${toString ./.}/${if svc ? serviceType then svc.serviceType else svc.serviceName}.nix"); + config = (evalModules + { modules = [ { options = res.options; config = svc.config or svc; } ]; + check = false; + }).config; + defaults = { + extraConfig = ""; + extraModules = []; + extraModulesPre = []; + extraPath = []; + extraServerPath = []; + globalEnvVars = []; + robotsEntries = ""; + startupScript = ""; + enablePHP = false; + enablePerl = false; + phpOptions = ""; + options = {}; + documentRoot = null; + }; + res = defaults // svcFunction { inherit config lib pkgs serverInfo php; }; + in res; + in map f defs; + + + # !!! callSubservices is expensive + subservicesFor = cfg: callSubservices (makeServerInfo cfg) cfg.extraSubservices; + + mainSubservices = subservicesFor mainCfg; + + allSubservices = mainSubservices ++ concatMap subservicesFor mainCfg.virtualHosts; + + + enableSSL = any (vhost: vhost.enableSSL) allHosts; + + + # Names of modules from ${httpd}/modules that we want to load. + apacheModules = + [ # HTTP authentication mechanisms: basic and digest. + "auth_basic" "auth_digest" + + # Authentication: is the user who he claims to be? + "authn_file" "authn_dbm" "authn_anon" + (if version24 then "authn_core" else "authn_alias") + + # Authorization: is the user allowed access? + "authz_user" "authz_groupfile" "authz_host" + + # Other modules. + "ext_filter" "include" "log_config" "env" "mime_magic" + "cern_meta" "expires" "headers" "usertrack" /* "unique_id" */ "setenvif" + "mime" "dav" "status" "autoindex" "asis" "info" "dav_fs" + "vhost_alias" "negotiation" "dir" "imagemap" "actions" "speling" + "userdir" "alias" "rewrite" "proxy" "proxy_http" + ] + ++ optionals version24 [ + "mpm_${mainCfg.multiProcessingModule}" + "authz_core" + "unixd" + "cache" "cache_disk" + "slotmem_shm" + "socache_shmcb" + # For compatibility with old configurations, the new module mod_access_compat is provided. + "access_compat" + ] + ++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ]) + ++ optional enableSSL "ssl" + ++ extraApacheModules; + + + allDenied = if version24 then '' + Require all denied + '' else '' + Order deny,allow + Deny from all + ''; + + allGranted = if version24 then '' + Require all granted + '' else '' + Order allow,deny + Allow from all + ''; + + + loggingConf = (if mainCfg.logFormat != "none" then '' + ErrorLog ${mainCfg.logDir}/error_log + + LogLevel notice + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + LogFormat "%{Referer}i -> %U" referer + LogFormat "%{User-agent}i" agent + + CustomLog ${mainCfg.logDir}/access_log ${mainCfg.logFormat} + '' else '' + ErrorLog /dev/null + ''); + + + browserHacks = '' + BrowserMatch "Mozilla/2" nokeepalive + BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + BrowserMatch "RealPlayer 4\.0" force-response-1.0 + BrowserMatch "Java/1\.0" force-response-1.0 + BrowserMatch "JDK/1\.0" force-response-1.0 + BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully + BrowserMatch "^WebDrive" redirect-carefully + BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully + BrowserMatch "^gnome-vfs" redirect-carefully + ''; + + + sslConf = '' + SSLSessionCache ${if version24 then "shmcb" else "shm"}:${mainCfg.stateDir}/ssl_scache(512000) + + ${if version24 then "Mutex" else "SSLMutex"} posixsem + + SSLRandomSeed startup builtin + SSLRandomSeed connect builtin + + SSLProtocol All -SSLv2 -SSLv3 + SSLCipherSuite HIGH:!aNULL:!MD5:!EXP + SSLHonorCipherOrder on + ''; + + + mimeConf = '' + TypesConfig ${httpd}/conf/mime.types + + AddType application/x-x509-ca-cert .crt + AddType application/x-pkcs7-crl .crl + AddType application/x-httpd-php .php .phtml + + + MIMEMagicFile ${httpd}/conf/magic + + ''; + + + perServerConf = isMainServer: cfg: let + + serverInfo = makeServerInfo cfg; + + subservices = callSubservices serverInfo cfg.extraSubservices; + + maybeDocumentRoot = fold (svc: acc: + if acc == null then svc.documentRoot else assert svc.documentRoot == null; acc + ) null ([ cfg ] ++ subservices); + + documentRoot = if maybeDocumentRoot != null then maybeDocumentRoot else + pkgs.runCommand "empty" {} "mkdir -p $out"; + + documentRootConf = '' + DocumentRoot "${documentRoot}" + + + Options Indexes FollowSymLinks + AllowOverride None + ${allGranted} + + ''; + + robotsTxt = + concatStringsSep "\n" (filter (x: x != "") ( + # If this is a vhost, the include the entries for the main server as well. + (if isMainServer then [] else [mainCfg.robotsEntries] ++ map (svc: svc.robotsEntries) mainSubservices) + ++ [cfg.robotsEntries] + ++ (map (svc: svc.robotsEntries) subservices))); + + in '' + ${concatStringsSep "\n" (map (n: "ServerName ${n}") serverInfo.canonicalNames)} + + ${concatMapStrings (alias: "ServerAlias ${alias}\n") cfg.serverAliases} + + ${if cfg.sslServerCert != null then '' + SSLCertificateFile ${cfg.sslServerCert} + SSLCertificateKeyFile ${cfg.sslServerKey} + ${if cfg.sslServerChain != null then '' + SSLCertificateChainFile ${cfg.sslServerChain} + '' else ""} + '' else ""} + + ${if cfg.enableSSL then '' + SSLEngine on + '' else if enableSSL then /* i.e., SSL is enabled for some host, but not this one */ + '' + SSLEngine off + '' else ""} + + ${if isMainServer || cfg.adminAddr != null then '' + ServerAdmin ${cfg.adminAddr} + '' else ""} + + ${if !isMainServer && mainCfg.logPerVirtualHost then '' + ErrorLog ${mainCfg.logDir}/error_log-${cfg.hostName} + CustomLog ${mainCfg.logDir}/access_log-${cfg.hostName} ${cfg.logFormat} + '' else ""} + + ${optionalString (robotsTxt != "") '' + Alias /robots.txt ${pkgs.writeText "robots.txt" robotsTxt} + ''} + + ${if isMainServer || maybeDocumentRoot != null then documentRootConf else ""} + + ${if cfg.enableUserDir then '' + + UserDir public_html + UserDir disabled root + + + AllowOverride FileInfo AuthConfig Limit Indexes + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec + + ${allGranted} + + + ${allDenied} + + + + '' else ""} + + ${if cfg.globalRedirect != null && cfg.globalRedirect != "" then '' + RedirectPermanent / ${cfg.globalRedirect} + '' else ""} + + ${ + let makeFileConf = elem: '' + Alias ${elem.urlPath} ${elem.file} + ''; + in concatMapStrings makeFileConf cfg.servedFiles + } + + ${ + let makeDirConf = elem: '' + Alias ${elem.urlPath} ${elem.dir}/ + + Options +Indexes + ${allGranted} + AllowOverride All + + ''; + in concatMapStrings makeDirConf cfg.servedDirs + } + + ${concatMapStrings (svc: svc.extraConfig) subservices} + + ${cfg.extraConfig} + ''; + + + confFile = pkgs.writeText "httpd.conf" '' + + ServerRoot ${httpd} + + ${optionalString version24 '' + DefaultRuntimeDir ${mainCfg.stateDir}/runtime + ''} + + PidFile ${mainCfg.stateDir}/httpd.pid + + ${optionalString (mainCfg.multiProcessingModule != "prefork") '' + # mod_cgid requires this. + ScriptSock ${mainCfg.stateDir}/cgisock + ''} + + + MaxClients ${toString mainCfg.maxClients} + MaxRequestsPerChild ${toString mainCfg.maxRequestsPerChild} + + + ${let + listen = concatMap getListen allHosts; + toStr = listen: "Listen ${listenToString listen}\n"; + uniqueListen = uniqList {inputList = map toStr listen;}; + in concatStrings uniqueListen + } + + User ${mainCfg.user} + Group ${mainCfg.group} + + ${let + load = {name, path}: "LoadModule ${name}_module ${path}\n"; + allModules = + concatMap (svc: svc.extraModulesPre) allSubservices + ++ map (name: {inherit name; path = "${httpd}/modules/mod_${name}.so";}) apacheModules + ++ optional mainCfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; } + ++ optional enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; } + ++ optional enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; } + ++ concatMap (svc: svc.extraModules) allSubservices + ++ extraForeignModules; + in concatMapStrings load allModules + } + + AddHandler type-map var + + + ${allDenied} + + + ${mimeConf} + ${loggingConf} + ${browserHacks} + + Include ${httpd}/conf/extra/httpd-default.conf + Include ${httpd}/conf/extra/httpd-autoindex.conf + Include ${httpd}/conf/extra/httpd-multilang-errordoc.conf + Include ${httpd}/conf/extra/httpd-languages.conf + + ${if enableSSL then sslConf else ""} + + # Fascist default - deny access to everything. + + Options FollowSymLinks + AllowOverride None + ${allDenied} + + + # But do allow access to files in the store so that we don't have + # to generate clauses for every generated file that we + # want to serve. + + ${allGranted} + + + # Generate directives for the main server. + ${perServerConf true mainCfg} + + # Always enable virtual hosts; it doesn't seem to hurt. + ${let + listen = concatMap getListen allHosts; + uniqueListen = uniqList {inputList = listen;}; + directives = concatMapStrings (listen: "NameVirtualHost ${listenToString listen}\n") uniqueListen; + in optionalString (!version24) directives + } + + ${let + makeVirtualHost = vhost: '' + + ${perServerConf false vhost} + + ''; + in concatMapStrings makeVirtualHost mainCfg.virtualHosts + } + ''; + + + enablePHP = mainCfg.enablePHP || any (svc: svc.enablePHP) allSubservices; + + enablePerl = mainCfg.enablePerl || any (svc: svc.enablePerl) allSubservices; + + + # Generate the PHP configuration file. Should probably be factored + # out into a separate module. + phpIni = pkgs.runCommand "php.ini" + { options = concatStringsSep "\n" + ([ mainCfg.phpOptions ] ++ (map (svc: svc.phpOptions) allSubservices)); + } + '' + cat ${php}/etc/php.ini > $out + echo "$options" >> $out + ''; + +in + + +{ + + ###### interface + + options = { + + services.httpdProd = { + + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the Apache HTTP Server."; + }; + + package = mkOption { + type = types.package; + default = pkgs.apacheHttpd; + defaultText = "pkgs.apacheHttpd"; + description = '' + Overridable attribute of the Apache HTTP Server package to use. + ''; + }; + + configFile = mkOption { + type = types.path; + default = confFile; + defaultText = "confFile"; + example = literalExample ''pkgs.writeText "httpd.conf" "# my custom config file ..."''; + description = '' + Override the configuration file used by Apache. By default, + NixOS generates one automatically. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Cnfiguration lines appended to the generated Apache + configuration file. Note that this mechanism may not work + when is overridden. + ''; + }; + + extraModules = mkOption { + type = types.listOf types.unspecified; + default = []; + example = literalExample ''[ "proxy_connect" { name = "php5"; path = "''${pkgs.php}/modules/libphp5.so"; } ]''; + description = '' + Additional Apache modules to be used. These can be + specified as a string in the case of modules distributed + with Apache, or as an attribute set specifying the + name and path of the + module. + ''; + }; + + logPerVirtualHost = mkOption { + type = types.bool; + default = false; + description = '' + If enabled, each virtual host gets its own + access_log and + error_log, namely suffixed by the + of the virtual host. + ''; + }; + + user = mkOption { + type = types.str; + default = "wwwrun"; + description = '' + User account under which httpd runs. The account is created + automatically if it doesn't exist. + ''; + }; + + group = mkOption { + type = types.str; + default = "wwwrun"; + description = '' + Group under which httpd runs. The account is created + automatically if it doesn't exist. + ''; + }; + + logDir = mkOption { + type = types.path; + default = "/var/log/httpd"; + description = '' + Directory for Apache's log files. It is created automatically. + ''; + }; + + stateDir = mkOption { + type = types.path; + default = "/run/httpd"; + description = '' + Directory for Apache's transient runtime state (such as PID + files). It is created automatically. Note that the default, + /run/httpd, is deleted at boot time. + ''; + }; + + virtualHosts = mkOption { + type = types.listOf (types.submodule ( + { options = import ./per-server-options.nix { + inherit lib; + forMainServer = false; + }; + })); + default = []; + example = [ + { hostName = "foo"; + documentRoot = "/data/webroot-foo"; + } + { hostName = "bar"; + documentRoot = "/data/webroot-bar"; + } + ]; + description = '' + Specification of the virtual hosts served by Apache. Each + element should be an attribute set specifying the + configuration of the virtual host. The available options + are the non-global options permissible for the main host. + ''; + }; + + enableMellon = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the mod_auth_mellon module."; + }; + + enablePHP = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the PHP module."; + }; + + phpPackage = mkOption { + type = types.package; + default = pkgs.php; + defaultText = "pkgs.php"; + description = '' + Overridable attribute of the PHP package to use. + ''; + }; + + enablePerl = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the Perl module (mod_perl)."; + }; + + phpOptions = mkOption { + type = types.lines; + default = ""; + example = + '' + date.timezone = "CET" + ''; + description = + "Options appended to the PHP configuration file php.ini."; + }; + + multiProcessingModule = mkOption { + type = types.str; + default = "prefork"; + example = "worker"; + description = + '' + Multi-processing module to be used by Apache. Available + modules are prefork (the default; + handles each request in a separate child process), + worker (hybrid approach that starts a + number of child processes each running a number of + threads) and event (a recent variant of + worker that handles persistent + connections more efficiently). + ''; + }; + + maxClients = mkOption { + type = types.int; + default = 150; + example = 8; + description = "Maximum number of httpd processes (prefork)"; + }; + + maxRequestsPerChild = mkOption { + type = types.int; + default = 0; + example = 500; + description = + "Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited"; + }; + } + + # Include the options shared between the main server and virtual hosts. + // (import ./per-server-options.nix { + inherit lib; + forMainServer = true; + }); + + }; + + + ###### implementation + + config = mkIf config.services.httpdProd.enable { + + assertions = [ { assertion = mainCfg.enableSSL == true + -> mainCfg.sslServerCert != null + && mainCfg.sslServerKey != null; + message = "SSL is enabled for httpd, but sslServerCert and/or sslServerKey haven't been specified."; } + ]; + + warnings = map (cfg: ''apache-httpd's port option is deprecated. Use listen = [{/*ip = "*"; */ port = ${toString cfg.port};}]; instead'' ) (lib.filter (cfg: cfg.port != 0) allHosts); + + environment.systemPackages = [httpd] ++ concatMap (svc: svc.extraPath) allSubservices; + + services.httpdProd.phpOptions = + '' + ; Needed for PHP's mail() function. + sendmail_path = sendmail -t -i + '' + optionalString (!isNull config.time.timeZone) '' + + ; Apparently PHP doesn't use $TZ. + date.timezone = "${config.time.timeZone}" + ''; + + systemd.services.httpdProd = + { description = "Apache HTTPD"; + + wantedBy = [ "multi-user.target" ]; + wants = [ "keys.target" ]; + after = [ "network.target" "fs.target" "postgresql.service" "keys.target" ]; + + path = + [ httpd pkgs.coreutils pkgs.gnugrep ] + ++ # Needed for PHP's mail() function. !!! Probably the + # ssmtp module should export the path to sendmail in + # some way. + optional config.networking.defaultMailServer.directDelivery pkgs.ssmtp + ++ concatMap (svc: svc.extraServerPath) allSubservices; + + environment = + optionalAttrs enablePHP { PHPRC = phpIni; } + // optionalAttrs mainCfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; } + // (listToAttrs (concatMap (svc: svc.globalEnvVars) allSubservices)); + + preStart = + '' + mkdir -m 0750 -p ${mainCfg.stateDir} + [ $(id -u) != 0 ] || chown root.${mainCfg.group} ${mainCfg.stateDir} + ${optionalString version24 '' + mkdir -m 0750 -p "${mainCfg.stateDir}/runtime" + [ $(id -u) != 0 ] || chown root.${mainCfg.group} "${mainCfg.stateDir}/runtime" + ''} + mkdir -m 0700 -p ${mainCfg.logDir} + + # Get rid of old semaphores. These tend to accumulate across + # server restarts, eventually preventing it from restarting + # successfully. + for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${mainCfg.user} ' | cut -f2 -d ' '); do + ${pkgs.utillinux}/bin/ipcrm -s $i + done + + # Run the startup hooks for the subservices. + for i in ${toString (map (svn: svn.startupScript) allSubservices)}; do + echo Running Apache startup hook $i... + $i + done + ''; + + serviceConfig.ExecStart = "@${httpd}/bin/httpd httpd -f ${httpdConf}"; + serviceConfig.ExecStop = "${httpd}/bin/httpd -f ${httpdConf} -k graceful-stop"; + serviceConfig.ExecReload = "${httpd}/bin/httpd -f ${httpdConf} -k graceful"; + serviceConfig.Type = "forking"; + serviceConfig.PIDFile = "${mainCfg.stateDir}/httpd.pid"; + serviceConfig.Restart = "always"; + serviceConfig.RestartSec = "5s"; + }; + + }; +} diff --git a/virtual/modules/websites/apache/per-server-options.nix b/virtual/modules/websites/apache/per-server-options.nix new file mode 100644 index 0000000..4bbd041 --- /dev/null +++ b/virtual/modules/websites/apache/per-server-options.nix @@ -0,0 +1,188 @@ +# This file defines the options that can be used both for the Apache +# main server configuration, and for the virtual hosts. (The latter +# has additional options that affect the web server as a whole, like +# the user/group to run under.) + +{ forMainServer, lib }: + +with lib; + +{ + + hostName = mkOption { + type = types.str; + default = "localhost"; + description = "Canonical hostname for the server."; + }; + + serverAliases = mkOption { + type = types.listOf types.str; + default = []; + example = ["www.example.org" "www.example.org:8080" "example.org"]; + description = '' + Additional names of virtual hosts served by this virtual host configuration. + ''; + }; + + port = mkOption { + type = types.int; + default = 0; + description = '' + Port for the server. Option will be removed, use instead. + ''; + }; + + listen = mkOption { + type = types.listOf (types.submodule ( + { + options = { + port = mkOption { + type = types.int; + description = "port to listen on"; + }; + ip = mkOption { + type = types.string; + default = "*"; + description = "Ip to listen on. 0.0.0.0 for ipv4 only, * for all."; + }; + }; + } )); + description = '' + List of { /* ip: "*"; */ port = 80;} to listen on + ''; + + default = []; + }; + + enableSSL = mkOption { + type = types.bool; + default = false; + description = "Whether to enable SSL (https) support."; + }; + + # Note: sslServerCert and sslServerKey can be left empty, but this + # only makes sense for virtual hosts (they will inherit from the + # main server). + + sslServerCert = mkOption { + type = types.nullOr types.path; + default = null; + example = "/var/host.cert"; + description = "Path to server SSL certificate."; + }; + + sslServerKey = mkOption { + type = types.path; + example = "/var/host.key"; + description = "Path to server SSL certificate key."; + }; + + sslServerChain = mkOption { + type = types.nullOr types.path; + default = null; + example = "/var/ca.pem"; + description = "Path to server SSL chain file."; + }; + + adminAddr = mkOption ({ + type = types.nullOr types.str; + example = "admin@example.org"; + description = "E-mail address of the server administrator."; + } // (if forMainServer then {} else {default = null;})); + + documentRoot = mkOption { + type = types.nullOr types.path; + default = null; + example = "/data/webserver/docs"; + description = '' + The path of Apache's document root directory. If left undefined, + an empty directory in the Nix store will be used as root. + ''; + }; + + servedDirs = mkOption { + type = types.listOf types.attrs; + default = []; + example = [ + { urlPath = "/nix"; + dir = "/home/eelco/Dev/nix-homepage"; + } + ]; + description = '' + This option provides a simple way to serve static directories. + ''; + }; + + servedFiles = mkOption { + type = types.listOf types.attrs; + default = []; + example = [ + { urlPath = "/foo/bar.png"; + file = "/home/eelco/some-file.png"; + } + ]; + description = '' + This option provides a simple way to serve individual, static files. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + + Options FollowSymlinks + AllowOverride All + + ''; + description = '' + These lines go to httpd.conf verbatim. They will go after + directories and directory aliases defined by default. + ''; + }; + + extraSubservices = mkOption { + type = types.listOf types.unspecified; + default = []; + description = "Extra subservices to enable in the webserver."; + }; + + enableUserDir = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable serving ~/public_html as + /~username. + ''; + }; + + globalRedirect = mkOption { + type = types.nullOr types.str; + default = null; + example = http://newserver.example.org/; + description = '' + If set, all requests for this host are redirected permanently to + the given URL. + ''; + }; + + logFormat = mkOption { + type = types.str; + default = "common"; + example = "combined"; + description = '' + Log format for Apache's log files. Possible values are: combined, common, referer, agent. + ''; + }; + + robotsEntries = mkOption { + type = types.lines; + default = ""; + example = "Disallow: /foo/"; + description = '' + Specification of pages to be ignored by web crawlers. See for details. + ''; + }; + +} diff --git a/virtual/modules/websites/aten.nix b/virtual/modules/websites/aten.nix index 1a65389..53db03a 100644 --- a/virtual/modules/websites/aten.nix +++ b/virtual/modules/websites/aten.nix @@ -27,12 +27,25 @@ in { services.phpfpm.poolConfigs.aten_prod = aten_prod.phpFpm.pool; system.activationScripts.aten_prod = aten_prod.activationScript; services.myWebsites.apacheConfig.aten_prod.modules = aten_prod.apache.modules; + services.myWebsites.production.modules = aten_prod.apache.modules; + services.myWebsites.production.vhostConfs.aten = { + certName = "aten"; + hosts = [ "aten.pro" "www.aten.pro" ]; + root = aten_prod.webRoot; + extraConfig = [ aten_prod.apache.vhostConf ]; + }; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."dev.aten.pro" = null; services.phpfpm.poolConfigs.aten_dev = aten_dev.phpFpm.pool; system.activationScripts.aten_dev = aten_dev.activationScript; - services.myWebsites.apacheConfig.aten_dev.modules = aten_dev.apache.modules; + services.myWebsites.integration.modules = aten_dev.apache.modules; + services.myWebsites.integration.vhostConfs.aten = { + certName = "eldiron"; + hosts = [ "dev.aten.pro" ]; + root = aten_dev.webRoot; + extraConfig = [ aten_dev.apache.vhostConf ]; + }; }) ]; } diff --git a/virtual/modules/websites/chloe.nix b/virtual/modules/websites/chloe.nix index d54c42d..67e8e1f 100644 --- a/virtual/modules/websites/chloe.nix +++ b/virtual/modules/websites/chloe.nix @@ -26,13 +26,25 @@ in { services.phpfpm.poolConfigs.chloe_prod = chloe_prod.phpFpm.pool; system.activationScripts.chloe_prod = chloe_prod.activationScript; - services.myWebsites.apacheConfig.chloe_prod.modules = chloe_prod.apache.modules; + services.myWebsites.production.modules = chloe_prod.apache.modules; + services.myWebsites.production.vhostConfs.chloe = { + certName = "chloe"; + hosts = ["osteopathe-cc.fr" "www.osteopathe-cc.fr" ]; + root = chloe_prod.webRoot; + extraConfig = [ chloe_prod.apache.vhostConf ]; + }; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."chloe.immae.eu" = null; services.phpfpm.poolConfigs.chloe_dev = chloe_dev.phpFpm.pool; system.activationScripts.chloe_dev = chloe_dev.activationScript; - services.myWebsites.apacheConfig.chloe_dev.modules = chloe_dev.apache.modules; + services.myWebsites.integration.modules = chloe_dev.apache.modules; + services.myWebsites.integration.vhostConfs.chloe = { + certName = "eldiron"; + hosts = ["chloe.immae.eu" ]; + root = chloe_dev.webRoot; + extraConfig = [ chloe_dev.apache.vhostConf ]; + }; }) ]; } diff --git a/virtual/modules/websites/connexionswing.nix b/virtual/modules/websites/connexionswing.nix index 8bf63a8..dcc7264 100644 --- a/virtual/modules/websites/connexionswing.nix +++ b/virtual/modules/websites/connexionswing.nix @@ -28,14 +28,26 @@ in { services.phpfpm.poolConfigs.connexionswing_prod = connexionswing_prod.phpFpm.pool; system.activationScripts.connexionswing_prod = connexionswing_prod.activationScript; - services.myWebsites.apacheConfig.connexionswing_prod.modules = connexionswing_prod.apache.modules; + services.myWebsites.production.modules = connexionswing_prod.apache.modules; + services.myWebsites.production.vhostConfs.connexionswing = { + certName = "connexionswing"; + hosts = ["connexionswing.com" "sandetludo.com" "www.connexionswing.com" "www.sandetludo.com" ]; + root = connexionswing_prod.webRoot; + extraConfig = [ connexionswing_prod.apache.vhostConf ]; + }; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."sandetludo.immae.eu" = null; security.acme.certs."eldiron".extraDomains."connexionswing.immae.eu" = null; services.phpfpm.poolConfigs.connexionswing_dev = connexionswing_dev.phpFpm.pool; system.activationScripts.connexionswing_dev = connexionswing_dev.activationScript; - services.myWebsites.apacheConfig.connexionswing_dev.modules = connexionswing_dev.apache.modules; + services.myWebsites.integration.modules = connexionswing_dev.apache.modules; + services.myWebsites.integration.vhostConfs.connexionswing = { + certName = "eldiron"; + hosts = ["connexionswing.immae.eu" "sandetludo.immae.eu" ]; + root = connexionswing_dev.webRoot; + extraConfig = [ connexionswing_dev.apache.vhostConf ]; + }; }) ]; } diff --git a/virtual/modules/websites/ludivine.nix b/virtual/modules/websites/ludivine.nix index f06e41a..6eb98e7 100644 --- a/virtual/modules/websites/ludivine.nix +++ b/virtual/modules/websites/ludivine.nix @@ -26,7 +26,13 @@ in { services.phpfpm.poolConfigs.ludivinecassal_prod = ludivinecassal_prod.phpFpm.pool; system.activationScripts.ludivinecassal_prod = ludivinecassal_prod.activationScript; - services.myWebsites.apacheConfig.ludivinecassal_prod.modules = ludivinecassal_prod.apache.modules; + services.myWebsites.production.modules = ludivinecassal_prod.apache.modules; + services.myWebsites.production.vhostConfs.ludivine = { + certName = "ludivinecassal"; + hosts = ["ludivinecassal.com" "www.ludivinecassal.com" ]; + root = ludivinecassal_prod.webRoot; + extraConfig = [ ludivinecassal_prod.apache.vhostConf ]; + }; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."ludivine.immae.eu" = null; @@ -34,6 +40,13 @@ in { services.phpfpm.poolConfigs.ludivinecassal_dev = ludivinecassal_dev.phpFpm.pool; system.activationScripts.ludivinecassal_dev = ludivinecassal_dev.activationScript; services.myWebsites.apacheConfig.ludivinecassal_dev.modules = ludivinecassal_dev.apache.modules; + services.myWebsites.integration.modules = ludivinecassal_dev.apache.modules; + services.myWebsites.integration.vhostConfs.ludivine = { + certName = "eldiron"; + hosts = [ "ludivine.immae.eu" ]; + root = ludivinecassal_dev.webRoot; + extraConfig = [ ludivinecassal_dev.apache.vhostConf ]; + }; }) ]; } diff --git a/virtual/modules/websites/piedsjaloux.nix b/virtual/modules/websites/piedsjaloux.nix index 285fd18..46161c7 100644 --- a/virtual/modules/websites/piedsjaloux.nix +++ b/virtual/modules/websites/piedsjaloux.nix @@ -26,13 +26,25 @@ in { services.phpfpm.poolConfigs.piedsjaloux_prod = piedsjaloux_prod.phpFpm.pool; system.activationScripts.piedsjaloux_prod = piedsjaloux_prod.activationScript; - services.myWebsites.apacheConfig.piedsjaloux_prod.modules = piedsjaloux_prod.apache.modules; + services.myWebsites.production.modules = piedsjaloux_prod.apache.modules; + services.myWebsites.production.vhostConfs.piedsjaloux = { + certName = "piedsjaloux"; + hosts = [ "piedsjaloux.fr" "www.piedsjaloux.fr" ]; + root = piedsjaloux_prod.webRoot; + extraConfig = [ piedsjaloux_prod.apache.vhostConf ]; + }; }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."piedsjaloux.immae.eu" = null; services.phpfpm.poolConfigs.piedsjaloux_dev = piedsjaloux_dev.phpFpm.pool; system.activationScripts.piedsjaloux_dev = piedsjaloux_dev.activationScript; - services.myWebsites.apacheConfig.piedsjaloux_dev.modules = piedsjaloux_dev.apache.modules; + services.myWebsites.integration.modules = piedsjaloux_dev.apache.modules; + services.myWebsites.integration.vhostConfs.piedsjaloux = { + certName = "eldiron"; + hosts = [ "piedsjaloux.immae.eu" ]; + root = piedsjaloux_dev.webRoot; + extraConfig = [ piedsjaloux_dev.apache.vhostConf ]; + }; }) ]; } -- 2.41.0 From e4a945cd175fa78ee6373f2a30505c4322befa2b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Thu, 10 Jan 2019 22:40:32 +0100 Subject: [PATCH 07/16] Move goaccess to specific module --- virtual/eldiron.nix | 53 ----------------- virtual/modules/websites/aten.nix | 8 +++ virtual/modules/websites/chloe.nix | 8 +++ virtual/modules/websites/commons/stats.nix | 66 +++++++++++++++++++++ virtual/modules/websites/connexionswing.nix | 8 +++ virtual/modules/websites/ludivine.nix | 8 +++ virtual/modules/websites/piedsjaloux.nix | 12 ++++ 7 files changed, 110 insertions(+), 53 deletions(-) create mode 100644 virtual/modules/websites/commons/stats.nix diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index a1e6909..e1edc01 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -36,19 +36,6 @@ services.myWebsites.production.enable = true; services.myWebsites.integration.enable = true; - nixpkgs.config.packageOverrides = oldpkgs: rec { - goaccess = oldpkgs.goaccess.overrideAttrs(old: rec { - name = "goaccess-${version}"; - version = "1.3"; - src = pkgs.fetchurl { - url = "https://tar.goaccess.io/${name}.tar.gz"; - sha256 = "16vv3pj7pbraq173wlxa89jjsd279004j4kgzlrsk1dz4if5qxwc"; - }; - configureFlags = old.configureFlags ++ [ "--enable-tcb=btree" ]; - buildInputs = old.buildInputs ++ [ pkgs.tokyocabinet pkgs.bzip2 ]; - }); - }; - networking = { firewall = { enable = true; @@ -96,7 +83,6 @@ pkgs.telnet pkgs.htop pkgs.vim - pkgs.goaccess occ ]; @@ -152,15 +138,6 @@ 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 ''; - # FIXME: initial sync - goaccess = '' - mkdir -p /var/lib/goaccess - mkdir -p /var/lib/goaccess/aten.pro - mkdir -p /var/lib/goaccess/ludivinecassal.com - mkdir -p /var/lib/goaccess/piedsjaloux.fr - mkdir -p /var/lib/goaccess/osteopathe-cc.fr - mkdir -p /var/lib/goaccess/connexionswing.com - ''; }; environment.etc."ssh/ldap_authorized_keys" = let @@ -331,36 +308,6 @@ ]; }; - services.cron = { - enable = true; - systemCronJobs = let - stats = domain: conf: let - d = pkgs.writeScriptBin "stats-${domain}" '' - #!${pkgs.stdenv.shell} - set -e - shopt -s nullglob - date_regex=$(LC_ALL=C date -d yesterday +'%d\/%b\/%Y') - TMPFILE=$(mktemp) - trap "rm -f $TMPFILE" EXIT - - cat /var/log/httpd/access_log-${domain} | sed -n "/\\[$date_regex/ p" > $TMPFILE - for i in /var/log/httpd/access_log-${domain}*.gz; do - zcat "$i" | sed -n "/\\[$date_regex/ p" >> $TMPFILE - done - goaccess $TMPFILE --no-progress -o /var/lib/goaccess/${domain}/index.html -p ${conf} - ''; - in "${d}/bin/stats-${domain}"; - # FIXME: running several goaccess simultaneously seems to be - # bugged? - in [ - "5 0 * * * root ${stats "aten.pro" ./packages/aten_goaccess.conf}" - "6 0 * * * root ${stats "ludivinecassal.com" ./packages/ludivinecassal_goaccess.conf}" - "7 0 * * * root ${stats "piedsjaloux.fr" ./packages/piedsjaloux_goaccess.conf}" - "8 0 * * * root ${stats "osteopathe-cc.fr" ./packages/chloe_goaccess.conf}" - "9 0 * * * root ${stats "connexionswing.com" ./packages/connexionswing_goaccess.conf}" - ]; - }; - systemd.services.tt-rss = { description = "Tiny Tiny RSS feeds update daemon"; serviceConfig = { diff --git a/virtual/modules/websites/aten.nix b/virtual/modules/websites/aten.nix index 53db03a..4688db3 100644 --- a/virtual/modules/websites/aten.nix +++ b/virtual/modules/websites/aten.nix @@ -17,6 +17,14 @@ in { config = lib.mkMerge [ (lib.mkIf cfg.production.enable { + services.myWebsites.commons.stats.enable = true; + services.myWebsites.commons.stats.sites = [ + { + name = "aten.pro"; + conf = ../../packages/aten_goaccess.conf; + } + ]; + security.acme.certs."aten" = config.services.myCertificates.certConfig // { domain = "aten.pro"; extraDomains = { diff --git a/virtual/modules/websites/chloe.nix b/virtual/modules/websites/chloe.nix index 67e8e1f..3309dd2 100644 --- a/virtual/modules/websites/chloe.nix +++ b/virtual/modules/websites/chloe.nix @@ -17,6 +17,14 @@ in { config = lib.mkMerge [ (lib.mkIf cfg.production.enable { + services.myWebsites.commons.stats.enable = true; + services.myWebsites.commons.stats.sites = [ + { + name = "osteopathe-cc.fr"; + conf = ../../packages/chloe_goaccess.conf; + } + ]; + security.acme.certs."chloe" = config.services.myCertificates.certConfig // { domain = "osteopathe-cc.fr"; extraDomains = { diff --git a/virtual/modules/websites/commons/stats.nix b/virtual/modules/websites/commons/stats.nix new file mode 100644 index 0000000..a7ade3b --- /dev/null +++ b/virtual/modules/websites/commons/stats.nix @@ -0,0 +1,66 @@ +{ lib, pkgs, config, mylibs, ... }: +let + cfg = config.services.myWebsites.commons.stats; +in { + options = { + services.myWebsites.commons.stats = { + enable = lib.mkEnableOption "enable statistics"; + sites = lib.mkOption { + # FIXME: specify + type = lib.types.listOf (lib.types.unspecified); + default = []; + description = "Sites to generate stats"; + }; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ + pkgs.goaccess + ]; + + nixpkgs.config.packageOverrides = oldpkgs: rec { + goaccess = oldpkgs.goaccess.overrideAttrs(old: rec { + name = "goaccess-${version}"; + version = "1.3"; + src = pkgs.fetchurl { + url = "https://tar.goaccess.io/${name}.tar.gz"; + sha256 = "16vv3pj7pbraq173wlxa89jjsd279004j4kgzlrsk1dz4if5qxwc"; + }; + configureFlags = old.configureFlags ++ [ "--enable-tcb=btree" ]; + buildInputs = old.buildInputs ++ [ pkgs.tokyocabinet pkgs.bzip2 ]; + }); + }; + + services.cron = { + enable = true; + systemCronJobs = let + stats = domain: conf: let + d = pkgs.writeScriptBin "stats-${domain}" '' + #!${pkgs.stdenv.shell} + set -e + shopt -s nullglob + date_regex=$(LC_ALL=C date -d yesterday +'%d\/%b\/%Y') + TMPFILE=$(mktemp) + trap "rm -f $TMPFILE" EXIT + + cat /var/log/httpd/access_log-${domain} | sed -n "/\\[$date_regex/ p" > $TMPFILE + for i in /var/log/httpd/access_log-${domain}*.gz; do + zcat "$i" | sed -n "/\\[$date_regex/ p" >> $TMPFILE + done + goaccess $TMPFILE --no-progress -o /var/lib/goaccess/${domain}/index.html -p ${conf} + ''; + in "${d}/bin/stats-${domain}"; + # FIXME: running several goaccess simultaneously seems to be + # bugged? + in + pkgs.lib.lists.imap0 (i: v: "${toString (i+5)} 0 * * * root ${stats v.name v.conf}") cfg.sites; + }; + + # FIXME: initial sync + system.activationScripts.goaccess = '' + mkdir -p /var/lib/goaccess + '' + + builtins.concatStringsSep "\n" (map (v: "mkdir -p /var/lib/goaccess/${v.name}") cfg.sites); + }; +} diff --git a/virtual/modules/websites/connexionswing.nix b/virtual/modules/websites/connexionswing.nix index dcc7264..9fc0cec 100644 --- a/virtual/modules/websites/connexionswing.nix +++ b/virtual/modules/websites/connexionswing.nix @@ -17,6 +17,14 @@ in { config = lib.mkMerge [ (lib.mkIf cfg.production.enable { + services.myWebsites.commons.stats.enable = true; + services.myWebsites.commons.stats.sites = [ + { + name = "connexionswing.com"; + conf = ../../packages/connexionswing_goaccess.conf; + } + ]; + security.acme.certs."connexionswing" = config.services.myCertificates.certConfig // { domain = "connexionswing.com"; extraDomains = { diff --git a/virtual/modules/websites/ludivine.nix b/virtual/modules/websites/ludivine.nix index 6eb98e7..b3c1c51 100644 --- a/virtual/modules/websites/ludivine.nix +++ b/virtual/modules/websites/ludivine.nix @@ -17,6 +17,14 @@ in { config = lib.mkMerge [ (lib.mkIf cfg.production.enable { + services.myWebsites.commons.stats.enable = true; + services.myWebsites.commons.stats.sites = [ + { + name = "ludivinecassal.com"; + conf = ../../packages/ludivinecassal_goaccess.conf; + } + ]; + security.acme.certs."ludivinecassal" = config.services.myCertificates.certConfig // { domain = "ludivinecassal.com"; extraDomains = { diff --git a/virtual/modules/websites/piedsjaloux.nix b/virtual/modules/websites/piedsjaloux.nix index 46161c7..451ae52 100644 --- a/virtual/modules/websites/piedsjaloux.nix +++ b/virtual/modules/websites/piedsjaloux.nix @@ -15,8 +15,20 @@ in { }; }; + imports = [ + ./commons/stats.nix + ]; + config = lib.mkMerge [ (lib.mkIf cfg.production.enable { + services.myWebsites.commons.stats.enable = true; + services.myWebsites.commons.stats.sites = [ + { + name = "piedsjaloux.fr"; + conf = ../../packages/piedsjaloux_goaccess.conf; + } + ]; + security.acme.certs."piedsjaloux" = config.services.myCertificates.certConfig // { domain = "piedsjaloux.fr"; extraDomains = { -- 2.41.0 From ad915416a6886010139413f4fbc41ed827336aa2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Thu, 10 Jan 2019 22:50:34 +0100 Subject: [PATCH 08/16] Remove production websites from tool httpd --- virtual/eldiron.nix | 42 +----------------------------------------- virtual/packages.nix | 17 +---------------- 2 files changed, 2 insertions(+), 57 deletions(-) diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index e1edc01..ad94fb2 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -8,7 +8,7 @@ with mylibs; let mypkgs = pkgs.callPackage ./packages.nix { - inherit checkEnv fetchedGit fetchedGitPrivate fetchedGithub; + inherit checkEnv fetchedGit fetchedGithub; }; in { @@ -230,46 +230,6 @@ mypkgs.davical.apache.vhostConf ]; }) - (withConf "connexionswing" // { - hostName = "connexionswing.com"; - serverAliases = [ "sandetludo.com" "www.connexionswing.com" "www.sandetludo.com" ]; - documentRoot = mypkgs.connexionswing_prod.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.connexionswing_prod.apache.vhostConf - ]; - }) - (withConf "ludivinecassal" // { - hostName = "ludivinecassal.com"; - serverAliases = [ "www.ludivinecassal.com" ]; - documentRoot = mypkgs.ludivinecassal_prod.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.ludivinecassal_prod.apache.vhostConf - ]; - }) - (withConf "piedsjaloux" // { - hostName = "piedsjaloux.fr"; - serverAliases = [ "www.piedsjaloux.fr" ]; - documentRoot = mypkgs.piedsjaloux_prod.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.piedsjaloux_prod.apache.vhostConf - ]; - }) - (withConf "chloe" // { - hostName = "osteopathe-cc.fr"; - serverAliases = [ "www.osteopathe-cc.fr" ]; - documentRoot = mypkgs.chloe_prod.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.chloe_prod.apache.vhostConf - ]; - }) - (withConf "aten" // { - hostName = "aten.pro"; - serverAliases = [ "www.aten.pro" ]; - documentRoot = mypkgs.aten_prod.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.aten_prod.apache.vhostConf - ]; - }) (withConf "eldiron" // { hostName = "cloud.immae.eu"; documentRoot = mypkgs.nextcloud.webRoot; diff --git a/virtual/packages.nix b/virtual/packages.nix index 80c0957..fa1b666 100644 --- a/virtual/packages.nix +++ b/virtual/packages.nix @@ -1,10 +1,5 @@ -{ callPackage, checkEnv, fetchedGit, fetchedGitPrivate, fetchedGithub }: +{ callPackage, checkEnv, fetchedGit, fetchedGithub }: let - connexionswing = callPackage ./packages/connexionswing.nix { inherit checkEnv fetchedGitPrivate; }; - ludivinecassal = callPackage ./packages/ludivinecassal.nix { inherit checkEnv fetchedGitPrivate; }; - piedsjaloux = callPackage ./packages/piedsjaloux.nix { inherit checkEnv fetchedGitPrivate; }; - aten = callPackage ./packages/aten.nix { inherit checkEnv fetchedGitPrivate; }; - chloe = callPackage ./packages/chloe.nix { inherit checkEnv fetchedGitPrivate; }; nextcloud = callPackage ./packages/nextcloud.nix { inherit checkEnv; }; adminer = callPackage ./packages/adminer.nix {}; ympd = callPackage ./packages/ympd.nix {}; @@ -18,16 +13,6 @@ in { inherit adminer; inherit ympd; - connexionswing_dev = connexionswing { environment = "dev"; }; - connexionswing_prod = connexionswing { environment = "prod"; }; - ludivinecassal_dev = ludivinecassal { environment = "dev"; }; - ludivinecassal_prod = ludivinecassal { environment = "prod"; }; - aten_dev = aten { environment = "dev"; }; - aten_prod = aten { environment = "prod"; }; - piedsjaloux_dev = piedsjaloux { environment = "dev"; }; - piedsjaloux_prod = piedsjaloux { environment = "prod"; }; - chloe_dev = chloe { environment = "dev"; }; - chloe_prod = chloe { environment = "prod"; }; inherit nextcloud; inherit mantisbt; inherit ttrss; -- 2.41.0 From 091ae73429b8853e6ab971bffaccd84bdd59f40d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Thu, 10 Jan 2019 23:02:54 +0100 Subject: [PATCH 09/16] Move packages fils to module --- virtual/modules/websites.nix | 10 +++++----- virtual/{packages => modules/websites/aten}/aten.json | 0 virtual/{packages => modules/websites/aten}/aten.nix | 0 .../modules/websites/{aten.nix => aten/default.nix} | 8 ++++++-- .../websites/aten/goaccess.conf} | 0 .../{packages => modules/websites/chloe}/chloe.json | 0 virtual/{packages => modules/websites/chloe}/chloe.nix | 6 +++--- .../websites/chloe}/chloe_config/chmod.php | 0 .../websites/chloe}/chloe_config/connect.php | 0 .../websites/chloe}/chloe_config/ldap.php | 0 .../modules/websites/{chloe.nix => chloe/default.nix} | 8 ++++++-- .../websites/chloe/goaccess.conf} | 0 .../websites/commons/spip}/spip_ldap_patch.patch | 0 .../websites/commons/spip}/spip_mes_options.php | 0 .../websites/connexionswing/connexionswing.json} | 2 +- .../websites/connexionswing}/connexionswing.nix | 2 +- .../{connexionswing.nix => connexionswing/default.nix} | 8 ++++++-- .../websites/connexionswing/goaccess.conf} | 0 .../websites/{ludivine.nix => ludivine/default.nix} | 4 ++-- .../websites/ludivine/goaccess.conf} | 0 .../websites/ludivine/ludivinecassal.json} | 2 +- .../websites/ludivine}/ludivinecassal.nix | 2 +- .../{piedsjaloux.nix => piedsjaloux/default.nix} | 6 +++--- .../websites/piedsjaloux/goaccess.conf} | 0 .../websites/piedsjaloux}/piedsjaloux.json | 0 .../websites/piedsjaloux}/piedsjaloux.nix | 0 26 files changed, 35 insertions(+), 23 deletions(-) rename virtual/{packages => modules/websites/aten}/aten.json (100%) rename virtual/{packages => modules/websites/aten}/aten.nix (100%) rename virtual/modules/websites/{aten.nix => aten/default.nix} (92%) rename virtual/{packages/aten_goaccess.conf => modules/websites/aten/goaccess.conf} (100%) rename virtual/{packages => modules/websites/chloe}/chloe.json (100%) rename virtual/{packages => modules/websites/chloe}/chloe.nix (94%) rename virtual/{packages => modules/websites/chloe}/chloe_config/chmod.php (100%) rename virtual/{packages => modules/websites/chloe}/chloe_config/connect.php (100%) rename virtual/{packages => modules/websites/chloe}/chloe_config/ldap.php (100%) rename virtual/modules/websites/{chloe.nix => chloe/default.nix} (91%) rename virtual/{packages/chloe_goaccess.conf => modules/websites/chloe/goaccess.conf} (100%) rename virtual/{packages => modules/websites/commons/spip}/spip_ldap_patch.patch (100%) rename virtual/{packages => modules/websites/commons/spip}/spip_mes_options.php (100%) rename virtual/{packages/connexionswing_master.json => modules/websites/connexionswing/connexionswing.json} (91%) rename virtual/{packages => modules/websites/connexionswing}/connexionswing.nix (99%) rename virtual/modules/websites/{connexionswing.nix => connexionswing/default.nix} (92%) rename virtual/{packages/connexionswing_goaccess.conf => modules/websites/connexionswing/goaccess.conf} (100%) rename virtual/modules/websites/{ludivine.nix => ludivine/default.nix} (92%) rename virtual/{packages/ludivinecassal_goaccess.conf => modules/websites/ludivine/goaccess.conf} (100%) rename virtual/{packages/ludivinecassal_master.json => modules/websites/ludivine/ludivinecassal.json} (90%) rename virtual/{packages => modules/websites/ludivine}/ludivinecassal.nix (99%) rename virtual/modules/websites/{piedsjaloux.nix => piedsjaloux/default.nix} (91%) rename virtual/{packages/piedsjaloux_goaccess.conf => modules/websites/piedsjaloux/goaccess.conf} (100%) rename virtual/{packages => modules/websites/piedsjaloux}/piedsjaloux.json (100%) rename virtual/{packages => modules/websites/piedsjaloux}/piedsjaloux.nix (100%) diff --git a/virtual/modules/websites.nix b/virtual/modules/websites.nix index cbd7de0..d794c7a 100644 --- a/virtual/modules/websites.nix +++ b/virtual/modules/websites.nix @@ -59,11 +59,11 @@ let in { imports = [ - ./websites/chloe.nix - ./websites/ludivine.nix - ./websites/aten.nix - ./websites/piedsjaloux.nix - ./websites/connexionswing.nix + ./websites/chloe + ./websites/ludivine + ./websites/aten + ./websites/piedsjaloux + ./websites/connexionswing # built using: # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix # And removed users / groups diff --git a/virtual/packages/aten.json b/virtual/modules/websites/aten/aten.json similarity index 100% rename from virtual/packages/aten.json rename to virtual/modules/websites/aten/aten.json diff --git a/virtual/packages/aten.nix b/virtual/modules/websites/aten/aten.nix similarity index 100% rename from virtual/packages/aten.nix rename to virtual/modules/websites/aten/aten.nix diff --git a/virtual/modules/websites/aten.nix b/virtual/modules/websites/aten/default.nix similarity index 92% rename from virtual/modules/websites/aten.nix rename to virtual/modules/websites/aten/default.nix index 4688db3..d9db75c 100644 --- a/virtual/modules/websites/aten.nix +++ b/virtual/modules/websites/aten/default.nix @@ -1,6 +1,6 @@ { lib, pkgs, config, mylibs, ... }: let - aten = pkgs.callPackage ../../packages/aten.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + aten = pkgs.callPackage ./aten.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; aten_dev = aten { environment = "dev"; }; aten_prod = aten { environment = "prod"; }; @@ -15,13 +15,17 @@ in { }; }; + imports = [ + ../commons/stats.nix + ]; + config = lib.mkMerge [ (lib.mkIf cfg.production.enable { services.myWebsites.commons.stats.enable = true; services.myWebsites.commons.stats.sites = [ { name = "aten.pro"; - conf = ../../packages/aten_goaccess.conf; + conf = ./goaccess.conf; } ]; diff --git a/virtual/packages/aten_goaccess.conf b/virtual/modules/websites/aten/goaccess.conf similarity index 100% rename from virtual/packages/aten_goaccess.conf rename to virtual/modules/websites/aten/goaccess.conf diff --git a/virtual/packages/chloe.json b/virtual/modules/websites/chloe/chloe.json similarity index 100% rename from virtual/packages/chloe.json rename to virtual/modules/websites/chloe/chloe.json diff --git a/virtual/packages/chloe.nix b/virtual/modules/websites/chloe/chloe.nix similarity index 94% rename from virtual/packages/chloe.nix rename to virtual/modules/websites/chloe/chloe.nix index 8633317..126d8e7 100644 --- a/virtual/packages/chloe.nix +++ b/virtual/modules/websites/chloe/chloe.nix @@ -21,7 +21,7 @@ let php_admin_value[upload_max_filesize] = 20M php_admin_value[post_max_size] = 20M ;php_admin_flag[log_errors] = on - php_admin_value[open_basedir] = "${./spip_mes_options.php}:${configDir}:${webRoot}:${varDir}:/tmp" + php_admin_value[open_basedir] = "${../commons/spip/spip_mes_options.php}:${configDir}:${webRoot}:${varDir}:/tmp" php_admin_value[session.save_path] = "${varDir}/phpSessions" env[SPIP_CONFIG_DIR] = "${configDir}" env[SPIP_VAR_DIR] = "${varDir}" @@ -114,10 +114,10 @@ let url = "http://files.spip.org/spip/stable/spip-${version}.zip"; sha256 = "0cacpxs9nv61i3hzd3nbmplq4mp22s886llhacp3n4923jd6snx5"; }; - paches = [ ./spip_ldap_patch.patch ]; + paches = [ ../commons/spip/spip_ldap_patch.patch ]; buildPhase = '' rm -rf IMG local tmp config/remove.txt - ln -sf ${./spip_mes_options.php} config/mes_options.php + ln -sf ${../commons/spip/spip_mes_options.php} config/mes_options.php echo "Require all denied" > "config/.htaccess" ln -sf ../../../../../${varDir}/{IMG,local} . ''; diff --git a/virtual/packages/chloe_config/chmod.php b/virtual/modules/websites/chloe/chloe_config/chmod.php similarity index 100% rename from virtual/packages/chloe_config/chmod.php rename to virtual/modules/websites/chloe/chloe_config/chmod.php diff --git a/virtual/packages/chloe_config/connect.php b/virtual/modules/websites/chloe/chloe_config/connect.php similarity index 100% rename from virtual/packages/chloe_config/connect.php rename to virtual/modules/websites/chloe/chloe_config/connect.php diff --git a/virtual/packages/chloe_config/ldap.php b/virtual/modules/websites/chloe/chloe_config/ldap.php similarity index 100% rename from virtual/packages/chloe_config/ldap.php rename to virtual/modules/websites/chloe/chloe_config/ldap.php diff --git a/virtual/modules/websites/chloe.nix b/virtual/modules/websites/chloe/default.nix similarity index 91% rename from virtual/modules/websites/chloe.nix rename to virtual/modules/websites/chloe/default.nix index 3309dd2..72a9b6f 100644 --- a/virtual/modules/websites/chloe.nix +++ b/virtual/modules/websites/chloe/default.nix @@ -1,6 +1,6 @@ { lib, pkgs, config, mylibs, ... }: let - chloe = pkgs.callPackage ../../packages/chloe.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + chloe = pkgs.callPackage ./chloe.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; chloe_dev = chloe { environment = "dev"; }; chloe_prod = chloe { environment = "prod"; }; @@ -15,13 +15,17 @@ in { }; }; + imports = [ + ../commons/stats.nix + ]; + config = lib.mkMerge [ (lib.mkIf cfg.production.enable { services.myWebsites.commons.stats.enable = true; services.myWebsites.commons.stats.sites = [ { name = "osteopathe-cc.fr"; - conf = ../../packages/chloe_goaccess.conf; + conf = ./goaccess.conf; } ]; diff --git a/virtual/packages/chloe_goaccess.conf b/virtual/modules/websites/chloe/goaccess.conf similarity index 100% rename from virtual/packages/chloe_goaccess.conf rename to virtual/modules/websites/chloe/goaccess.conf diff --git a/virtual/packages/spip_ldap_patch.patch b/virtual/modules/websites/commons/spip/spip_ldap_patch.patch similarity index 100% rename from virtual/packages/spip_ldap_patch.patch rename to virtual/modules/websites/commons/spip/spip_ldap_patch.patch diff --git a/virtual/packages/spip_mes_options.php b/virtual/modules/websites/commons/spip/spip_mes_options.php similarity index 100% rename from virtual/packages/spip_mes_options.php rename to virtual/modules/websites/commons/spip/spip_mes_options.php diff --git a/virtual/packages/connexionswing_master.json b/virtual/modules/websites/connexionswing/connexionswing.json similarity index 91% rename from virtual/packages/connexionswing_master.json rename to virtual/modules/websites/connexionswing/connexionswing.json index 2e1775b..146c5f6 100644 --- a/virtual/packages/connexionswing_master.json +++ b/virtual/modules/websites/connexionswing/connexionswing.json @@ -1,7 +1,7 @@ { "tag": "0330478-master", "meta": { - "name": "connexionswing_master", + "name": "connexionswing", "url": "gitolite@git.immae.eu:perso/Immae/Projets/Connexionswing", "branch": "master" }, diff --git a/virtual/packages/connexionswing.nix b/virtual/modules/websites/connexionswing/connexionswing.nix similarity index 99% rename from virtual/packages/connexionswing.nix rename to virtual/modules/websites/connexionswing/connexionswing.nix index 1f3f2d5..90cca73 100644 --- a/virtual/packages/connexionswing.nix +++ b/virtual/modules/websites/connexionswing/connexionswing.nix @@ -148,7 +148,7 @@ let fi ''; }; - webappDir = stdenv.mkDerivation (fetchedGitPrivate ./connexionswing_master.json // rec { + webappDir = stdenv.mkDerivation (fetchedGitPrivate ./connexionswing.json // rec { # FIXME: can we do better than symlink? # FIXME: imagick optional # FIXME: initial sync diff --git a/virtual/modules/websites/connexionswing.nix b/virtual/modules/websites/connexionswing/default.nix similarity index 92% rename from virtual/modules/websites/connexionswing.nix rename to virtual/modules/websites/connexionswing/default.nix index 9fc0cec..636b16e 100644 --- a/virtual/modules/websites/connexionswing.nix +++ b/virtual/modules/websites/connexionswing/default.nix @@ -1,6 +1,6 @@ { lib, pkgs, config, mylibs, ... }: let - connexionswing = pkgs.callPackage ../../packages/connexionswing.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + connexionswing = pkgs.callPackage ./connexionswing.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; connexionswing_dev = connexionswing { environment = "dev"; }; connexionswing_prod = connexionswing { environment = "prod"; }; @@ -15,13 +15,17 @@ in { }; }; + imports = [ + ../commons/stats.nix + ]; + config = lib.mkMerge [ (lib.mkIf cfg.production.enable { services.myWebsites.commons.stats.enable = true; services.myWebsites.commons.stats.sites = [ { name = "connexionswing.com"; - conf = ../../packages/connexionswing_goaccess.conf; + conf = ./goaccess.conf; } ]; diff --git a/virtual/packages/connexionswing_goaccess.conf b/virtual/modules/websites/connexionswing/goaccess.conf similarity index 100% rename from virtual/packages/connexionswing_goaccess.conf rename to virtual/modules/websites/connexionswing/goaccess.conf diff --git a/virtual/modules/websites/ludivine.nix b/virtual/modules/websites/ludivine/default.nix similarity index 92% rename from virtual/modules/websites/ludivine.nix rename to virtual/modules/websites/ludivine/default.nix index b3c1c51..ed719ba 100644 --- a/virtual/modules/websites/ludivine.nix +++ b/virtual/modules/websites/ludivine/default.nix @@ -1,6 +1,6 @@ { lib, pkgs, config, mylibs, ... }: let - ludivinecassal = pkgs.callPackage ../../packages/ludivinecassal.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + ludivinecassal = pkgs.callPackage ./ludivinecassal.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; ludivinecassal_dev = ludivinecassal { environment = "dev"; }; ludivinecassal_prod = ludivinecassal { environment = "prod"; }; @@ -21,7 +21,7 @@ in { services.myWebsites.commons.stats.sites = [ { name = "ludivinecassal.com"; - conf = ../../packages/ludivinecassal_goaccess.conf; + conf = ./goaccess.conf; } ]; diff --git a/virtual/packages/ludivinecassal_goaccess.conf b/virtual/modules/websites/ludivine/goaccess.conf similarity index 100% rename from virtual/packages/ludivinecassal_goaccess.conf rename to virtual/modules/websites/ludivine/goaccess.conf diff --git a/virtual/packages/ludivinecassal_master.json b/virtual/modules/websites/ludivine/ludivinecassal.json similarity index 90% rename from virtual/packages/ludivinecassal_master.json rename to virtual/modules/websites/ludivine/ludivinecassal.json index 403f9b0..89667c0 100644 --- a/virtual/packages/ludivinecassal_master.json +++ b/virtual/modules/websites/ludivine/ludivinecassal.json @@ -1,7 +1,7 @@ { "tag": "4327b82-master", "meta": { - "name": "ludivinecassal_master", + "name": "ludivinecassal", "url": "gitolite@git.immae.eu:perso/Immae/Sites/Ludivine", "branch": "master" }, diff --git a/virtual/packages/ludivinecassal.nix b/virtual/modules/websites/ludivine/ludivinecassal.nix similarity index 99% rename from virtual/packages/ludivinecassal.nix rename to virtual/modules/websites/ludivine/ludivinecassal.nix index eabb8fa..ac63735 100644 --- a/virtual/packages/ludivinecassal.nix +++ b/virtual/modules/websites/ludivine/ludivinecassal.nix @@ -148,7 +148,7 @@ let fi ''; }; - webappDir = stdenv.mkDerivation (fetchedGitPrivate ./ludivinecassal_master.json // rec { + webappDir = stdenv.mkDerivation (fetchedGitPrivate ./ludivinecassal.json // rec { # FIXME: can we do better than symlink? # FIXME: initial sync # FIXME: backup diff --git a/virtual/modules/websites/piedsjaloux.nix b/virtual/modules/websites/piedsjaloux/default.nix similarity index 91% rename from virtual/modules/websites/piedsjaloux.nix rename to virtual/modules/websites/piedsjaloux/default.nix index 451ae52..bf74173 100644 --- a/virtual/modules/websites/piedsjaloux.nix +++ b/virtual/modules/websites/piedsjaloux/default.nix @@ -1,6 +1,6 @@ { lib, pkgs, config, mylibs, ... }: let - piedsjaloux = pkgs.callPackage ../../packages/piedsjaloux.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; + piedsjaloux = pkgs.callPackage ./piedsjaloux.nix { inherit (mylibs) checkEnv fetchedGitPrivate; }; piedsjaloux_dev = piedsjaloux { environment = "dev"; }; piedsjaloux_prod = piedsjaloux { environment = "prod"; }; @@ -16,7 +16,7 @@ in { }; imports = [ - ./commons/stats.nix + ../commons/stats.nix ]; config = lib.mkMerge [ @@ -25,7 +25,7 @@ in { services.myWebsites.commons.stats.sites = [ { name = "piedsjaloux.fr"; - conf = ../../packages/piedsjaloux_goaccess.conf; + conf = ./goaccess.conf; } ]; diff --git a/virtual/packages/piedsjaloux_goaccess.conf b/virtual/modules/websites/piedsjaloux/goaccess.conf similarity index 100% rename from virtual/packages/piedsjaloux_goaccess.conf rename to virtual/modules/websites/piedsjaloux/goaccess.conf diff --git a/virtual/packages/piedsjaloux.json b/virtual/modules/websites/piedsjaloux/piedsjaloux.json similarity index 100% rename from virtual/packages/piedsjaloux.json rename to virtual/modules/websites/piedsjaloux/piedsjaloux.json diff --git a/virtual/packages/piedsjaloux.nix b/virtual/modules/websites/piedsjaloux/piedsjaloux.nix similarity index 100% rename from virtual/packages/piedsjaloux.nix rename to virtual/modules/websites/piedsjaloux/piedsjaloux.nix -- 2.41.0 From 54307da49e9975ca3cce0d45fd12ade016cf90d9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Thu, 10 Jan 2019 23:29:52 +0100 Subject: [PATCH 10/16] Move some more configuration for websites --- virtual/eldiron.nix | 9 ++----- .../{websites.nix => websites/default.nix} | 26 ++++++++++++++----- 2 files changed, 21 insertions(+), 14 deletions(-) rename virtual/modules/{websites.nix => websites/default.nix} (93%) diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index ad94fb2..fa5cb51 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -28,7 +28,7 @@ ./modules/gitolite.nix ./modules/gitweb.nix ./modules/databases.nix - ./modules/websites.nix + ./modules/websites ]; services.myGitolite.enable = true; services.myGitweb.enable = true; @@ -39,13 +39,8 @@ networking = { firewall = { enable = true; - allowedTCPPorts = [ 22 80 443 9418 ]; + allowedTCPPorts = [ 22 9418 ]; }; - interfaces."eth0".ipv4.addresses = [ - # 176.9.151.89 declared in nixops -> infra / tools - { address = myconfig.ips.production; prefixLength = 32; } - { address = myconfig.ips.integration; prefixLength = 32; } - ]; }; deployment = { diff --git a/virtual/modules/websites.nix b/virtual/modules/websites/default.nix similarity index 93% rename from virtual/modules/websites.nix rename to virtual/modules/websites/default.nix index d794c7a..14b9998 100644 --- a/virtual/modules/websites.nix +++ b/virtual/modules/websites/default.nix @@ -59,16 +59,16 @@ let in { imports = [ - ./websites/chloe - ./websites/ludivine - ./websites/aten - ./websites/piedsjaloux - ./websites/connexionswing + ./chloe + ./ludivine + ./aten + ./piedsjaloux + ./connexionswing # built using: # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix # And removed users / groups - ./websites/apache/httpd_prod.nix - ./websites/apache/httpd_inte.nix + ./apache/httpd_prod.nix + ./apache/httpd_inte.nix ]; options.services.myWebsites = { @@ -95,6 +95,18 @@ in }; config = { + networking = { + firewall = { + enable = true; + allowedTCPPorts = [ 80 443 ]; + }; + interfaces."eth0".ipv4.addresses = [ + # 176.9.151.89 declared in nixops -> infra / tools + { address = myconfig.ips.production; prefixLength = 32; } + { address = myconfig.ips.integration; prefixLength = 32; } + ]; + }; + services.myWebsites.Chloe.production.enable = cfg.production.enable; services.myWebsites.Ludivine.production.enable = cfg.production.enable; services.myWebsites.Aten.production.enable = cfg.production.enable; -- 2.41.0 From f3d9c61e9becccc9ef25f64e5e639d45ea25650a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Fri, 11 Jan 2019 15:46:45 +0100 Subject: [PATCH 11/16] Improve postgresql: allow replication from backup-1, change root to /run/postgres --- virtual/eldiron.nix | 3 + virtual/modules/certificates.nix | 1 - virtual/modules/databases.nix | 61 ++++++++++++++++--- .../modules/postgresql_run_socket_path.patch | 12 ++++ virtual/packages/nextcloud.nix | 2 +- 5 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 virtual/modules/postgresql_run_socket_path.patch diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index fa5cb51..2e4ae12 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -4,6 +4,9 @@ enableRollback = true; }; + # Full backup: + # The star after /var/lib/* avoids deleting all folders in case of problem + # rsync -e "ssh -i /root/.ssh/id_charon_vpn" -aAXvz --delete --numeric-ids --super --rsync-path="sudo rsync" /var/lib/* immae@immae.eu: eldiron = { config, pkgs, mylibs, myconfig, ... }: with mylibs; let diff --git a/virtual/modules/certificates.nix b/virtual/modules/certificates.nix index a9d6d99..1a63035 100644 --- a/virtual/modules/certificates.nix +++ b/virtual/modules/certificates.nix @@ -23,7 +23,6 @@ # it in httpd "eldiron" = config.services.myCertificates.certConfig // { domain = "eldiron.immae.eu"; - allowKeysForGroup = true; }; }; }; diff --git a/virtual/modules/databases.nix b/virtual/modules/databases.nix index 9f8e70d..de4ace6 100644 --- a/virtual/modules/databases.nix +++ b/virtual/modules/databases.nix @@ -42,6 +42,11 @@ in { url = "mirror://postgresql/source/v11.1/${name}.tar.bz2"; sha256 = "026v0sicsh7avzi45waf8shcbhivyxmi7qgn9fd1x0vl520mx0ch"; }; + configureFlags = old.configureFlags ++ [ "--with-pam" ]; + buildInputs = (old.buildInputs or []) ++ [ pkgs.pam ]; + patches = old.patches ++ [ + ./postgresql_run_socket_path.patch + ]; }); mariadb = mariadbPAM; mariadbPAM = oldpkgs.mariadb.overrideAttrs(old: rec { @@ -62,9 +67,23 @@ in { package = pkgs.mariadb; }; + # Cannot use eldiron: psql complains too much rights on the key, and + # setfacl cannot work properly because of acme prestart script + security.acme.certs."postgresql" = config.services.myCertificates.certConfig // { + user = "postgres"; + group = "postgres"; + plugins = [ "fullchain.pem" "key.pem" "account_key.json" ]; + domain = "db-1.immae.eu"; + postRun = '' + systemctl reload postgresql.service + ''; + }; + + system.activationScripts.postgresql = '' + install -m 0755 -o postgres -g postgres -d /run/postgresql + ''; + # FIXME: initial sync - # FIXME: backup - # FIXME: ssl services.postgresql = rec { enable = cfg.postgresql.enable; package = pkgs.postgresql; @@ -83,17 +102,19 @@ in { lc_numeric = 'en_US.UTF-8' lc_time = 'en_US.UTF-8' default_text_search_config = 'pg_catalog.english' - # ssl = on - # ssl_cert_file = '/var/lib/acme/eldiron/fullchain.pem' - # ssl_key_file = '/var/lib/acme/eldiron/key.pem' + ssl = on + ssl_cert_file = '/var/lib/acme/postgresql/fullchain.pem' + ssl_key_file = '/var/lib/acme/postgresql/key.pem' ''; authentication = '' local all postgres ident local all all md5 - host all all samehost md5 - host all all 178.33.252.96/32 md5 - host all all 188.165.209.148/32 md5 - #host all all all pam + hostssl all all samehost md5 + hostssl all all 178.33.252.96/32 md5 + hostssl all all 188.165.209.148/32 md5 + hostssl all all all pam + hostssl replication backup-1 2001:41d0:302:1100::9:e5a9/128 pam pamservice=postgresql_replication + hostssl replication backup-1 54.37.151.137/32 pam pamservice=postgresql_replication ''; }; @@ -107,6 +128,14 @@ in { bindpw ${builtins.getEnv "NIXOPS_MYSQL_PAM_PASSWORD"} pam_filter memberOf=cn=users,cn=mysql,cn=pam,ou=services,dc=immae,dc=eu ''; + pam_ldap_postgresql_replication = assert mylibs.checkEnv "NIXOPS_ELDIRON_LDAP_PASSWORD"; + pkgs.writeText "postgresql.conf" '' + host ldap.immae.eu + base dc=immae,dc=eu + binddn cn=eldiron,ou=hosts,dc=immae,dc=eu + bindpw ${builtins.getEnv "NIXOPS_ELDIRON_LDAP_PASSWORD"} + pam_login_attribute cn + ''; in [ { name = "mysql"; @@ -116,6 +145,20 @@ in { account required ${pam_ldap}/lib/security/pam_ldap.so config=${pam_ldap_mysql} ''; } + { + name = "postgresql"; + text = '' + auth required ${pam_ldap}/lib/security/pam_ldap.so config=${pam_ldap_postgresql_replication} + account required ${pam_ldap}/lib/security/pam_ldap.so config=${pam_ldap_postgresql_replication} + ''; + } + { + name = "postgresql_replication"; + text = '' + auth required ${pam_ldap}/lib/security/pam_ldap.so config=${pam_ldap_postgresql_replication} + account required ${pam_ldap}/lib/security/pam_ldap.so config=${pam_ldap_postgresql_replication} + ''; + } ]; # FIXME: backup diff --git a/virtual/modules/postgresql_run_socket_path.patch b/virtual/modules/postgresql_run_socket_path.patch new file mode 100644 index 0000000..b558c7b --- /dev/null +++ b/virtual/modules/postgresql_run_socket_path.patch @@ -0,0 +1,12 @@ +diff -Naur postgresql-9.2.0.sockets/src/include/pg_config_manual.h postgresql-9.2.0/src/include/pg_config_manual.h +--- postgresql-9.2.0.sockets/src/include/pg_config_manual.h 2012-09-06 17:26:17.000000000 -0400 ++++ postgresql-9.2.0/src/include/pg_config_manual.h 2012-09-06 18:13:18.183092471 -0400 +@@ -144,7 +144,7 @@ + * here's where to twiddle it. You can also override this at runtime + * with the postmaster's -k switch. + */ +-#define DEFAULT_PGSOCKET_DIR "/tmp" ++#define DEFAULT_PGSOCKET_DIR "/run/postgresql" + + /* + * The random() function is expected to yield values between 0 and diff --git a/virtual/packages/nextcloud.nix b/virtual/packages/nextcloud.nix index 5e9a927..3ac71e0 100644 --- a/virtual/packages/nextcloud.nix +++ b/virtual/packages/nextcloud.nix @@ -115,7 +115,7 @@ let 'dbtype' => 'pgsql', 'version' => '15.0.0.10', 'dbname' => 'webapps', - 'dbhost' => '/tmp', + 'dbhost' => '/run/postgresql', 'dbtableprefix' => 'oc_', 'dbuser' => '${builtins.getEnv "NIXOPS_NEXTCLOUD_DB_USER"}', 'dbpassword' => '${builtins.getEnv "NIXOPS_NEXTCLOUD_DB_PASSWORD"}', -- 2.41.0 From 985845405f0ddd6531e4392e899a31179cde70d6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Sat, 12 Jan 2019 01:15:55 +0100 Subject: [PATCH 12/16] Refactor a bit the php-fpm module This commit adds a new phpfpm service with a new option that permits to specify pool-specific php configuration (caveat: now each pool has distinct php ini file, even if they have the same content) Make sure that the same php package is used everywhere Build pdo_mysql using mysql c-connector. Would be good to have the same with mysqli but it seems not to work --- virtual/eldiron.nix | 19 +- virtual/modules/websites/aten/default.nix | 4 +- virtual/modules/websites/chloe/default.nix | 4 +- .../websites/connexionswing/default.nix | 4 +- virtual/modules/websites/default.nix | 20 ++ virtual/modules/websites/ludivine/default.nix | 4 +- virtual/modules/websites/phpfpm/default.nix | 178 ++++++++++++++++++ .../modules/websites/phpfpm/pool-options.nix | 35 ++++ .../modules/websites/piedsjaloux/default.nix | 4 +- virtual/packages/nextcloud.nix | 7 +- 10 files changed, 257 insertions(+), 22 deletions(-) create mode 100644 virtual/modules/websites/phpfpm/default.nix create mode 100644 virtual/modules/websites/phpfpm/pool-options.nix diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index 2e4ae12..c9075cf 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -32,6 +32,7 @@ ./modules/gitweb.nix ./modules/databases.nix ./modules/websites + ./modules/websites/phpfpm ]; services.myGitolite.enable = true; services.myGitweb.enable = true; @@ -73,8 +74,8 @@ cd ${mypkgs.nextcloud.webRoot} NEXTCLOUD_CONFIG_DIR="${mypkgs.nextcloud.webRoot}/config" \ exec \ - ${config.services.phpfpm.phpPackage}/bin/php \ - -c ${config.services.phpfpm.phpPackage}/etc/php.ini \ + ${pkgs.php}/bin/php \ + -c ${pkgs.php}/etc/php.ini \ occ $* ''; in [ @@ -98,23 +99,19 @@ services.ympd = mypkgs.ympd.config // { enable = false; }; - services.phpfpm = { - # FIXME: move session files to separate dirs - # /!\ phppackage is used in nextcloud configuation + services.myPhpfpm = { + phpPackage = pkgs.php; phpOptions = '' session.save_path = "/var/lib/php/sessions" session.gc_maxlifetime = 60*60*24*15 session.cache_expire = 60*24*30 - ; For nextcloud - extension=${pkgs.phpPackages.redis}/lib/php/extensions/redis.so - ; For nextcloud - extension=${pkgs.phpPackages.apcu}/lib/php/extensions/apcu.so - ; For nextcloud - zend_extension=${pkgs.php}/lib/php/extensions/opcache.so ''; extraConfig = '' log_level = notice ''; + poolPhpConfigs = { + nextcloud = mypkgs.nextcloud.phpFpm.phpConfig; + }; poolConfigs = { adminer = mypkgs.adminer.phpFpm.pool; nextcloud = mypkgs.nextcloud.phpFpm.pool; diff --git a/virtual/modules/websites/aten/default.nix b/virtual/modules/websites/aten/default.nix index d9db75c..2f319bb 100644 --- a/virtual/modules/websites/aten/default.nix +++ b/virtual/modules/websites/aten/default.nix @@ -36,7 +36,7 @@ in { }; }; - services.phpfpm.poolConfigs.aten_prod = aten_prod.phpFpm.pool; + services.myPhpfpm.poolConfigs.aten_prod = aten_prod.phpFpm.pool; system.activationScripts.aten_prod = aten_prod.activationScript; services.myWebsites.apacheConfig.aten_prod.modules = aten_prod.apache.modules; services.myWebsites.production.modules = aten_prod.apache.modules; @@ -49,7 +49,7 @@ in { }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."dev.aten.pro" = null; - services.phpfpm.poolConfigs.aten_dev = aten_dev.phpFpm.pool; + services.myPhpfpm.poolConfigs.aten_dev = aten_dev.phpFpm.pool; system.activationScripts.aten_dev = aten_dev.activationScript; services.myWebsites.integration.modules = aten_dev.apache.modules; services.myWebsites.integration.vhostConfs.aten = { diff --git a/virtual/modules/websites/chloe/default.nix b/virtual/modules/websites/chloe/default.nix index 72a9b6f..e5c3db7 100644 --- a/virtual/modules/websites/chloe/default.nix +++ b/virtual/modules/websites/chloe/default.nix @@ -36,7 +36,7 @@ in { }; }; - services.phpfpm.poolConfigs.chloe_prod = chloe_prod.phpFpm.pool; + services.myPhpfpm.poolConfigs.chloe_prod = chloe_prod.phpFpm.pool; system.activationScripts.chloe_prod = chloe_prod.activationScript; services.myWebsites.production.modules = chloe_prod.apache.modules; services.myWebsites.production.vhostConfs.chloe = { @@ -48,7 +48,7 @@ in { }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."chloe.immae.eu" = null; - services.phpfpm.poolConfigs.chloe_dev = chloe_dev.phpFpm.pool; + services.myPhpfpm.poolConfigs.chloe_dev = chloe_dev.phpFpm.pool; system.activationScripts.chloe_dev = chloe_dev.activationScript; services.myWebsites.integration.modules = chloe_dev.apache.modules; services.myWebsites.integration.vhostConfs.chloe = { diff --git a/virtual/modules/websites/connexionswing/default.nix b/virtual/modules/websites/connexionswing/default.nix index 636b16e..5667c91 100644 --- a/virtual/modules/websites/connexionswing/default.nix +++ b/virtual/modules/websites/connexionswing/default.nix @@ -38,7 +38,7 @@ in { }; }; - services.phpfpm.poolConfigs.connexionswing_prod = connexionswing_prod.phpFpm.pool; + services.myPhpfpm.poolConfigs.connexionswing_prod = connexionswing_prod.phpFpm.pool; system.activationScripts.connexionswing_prod = connexionswing_prod.activationScript; services.myWebsites.production.modules = connexionswing_prod.apache.modules; services.myWebsites.production.vhostConfs.connexionswing = { @@ -51,7 +51,7 @@ in { (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."sandetludo.immae.eu" = null; security.acme.certs."eldiron".extraDomains."connexionswing.immae.eu" = null; - services.phpfpm.poolConfigs.connexionswing_dev = connexionswing_dev.phpFpm.pool; + services.myPhpfpm.poolConfigs.connexionswing_dev = connexionswing_dev.phpFpm.pool; system.activationScripts.connexionswing_dev = connexionswing_dev.activationScript; services.myWebsites.integration.modules = connexionswing_dev.apache.modules; services.myWebsites.integration.vhostConfs.connexionswing = { diff --git a/virtual/modules/websites/default.nix b/virtual/modules/websites/default.nix index 14b9998..54284e8 100644 --- a/virtual/modules/websites/default.nix +++ b/virtual/modules/websites/default.nix @@ -107,6 +107,26 @@ in ]; }; + nixpkgs.config.packageOverrides = oldpkgs: rec { + php = php72; + php72 = (oldpkgs.php72.override { + mysql.connector-c = pkgs.mariadb; + config.php.mysqlnd = false; + config.php.mysqli = false; + }).overrideAttrs(old: rec { + # Didn't manage to build with mysqli + mysql_config connector + configureFlags = old.configureFlags ++ [ + "--with-mysqli=mysqlnd" + ]; + # preConfigure = (old.preConfigure or "") + '' + # export CPPFLAGS="$CPPFLAGS -I${pkgs.mariadb}/include/mysql/server"; + # sed -i -e 's/#include "mysqli_priv.h"/#include "mysqli_priv.h"\n#include /' \ + # ext/mysqli/mysqli.c ext/mysqli/mysqli_prop.c + # ''; + }); + phpPackages = oldpkgs.php72Packages.override { inherit php; }; + }; + services.myWebsites.Chloe.production.enable = cfg.production.enable; services.myWebsites.Ludivine.production.enable = cfg.production.enable; services.myWebsites.Aten.production.enable = cfg.production.enable; diff --git a/virtual/modules/websites/ludivine/default.nix b/virtual/modules/websites/ludivine/default.nix index ed719ba..6aa1862 100644 --- a/virtual/modules/websites/ludivine/default.nix +++ b/virtual/modules/websites/ludivine/default.nix @@ -32,7 +32,7 @@ in { }; }; - services.phpfpm.poolConfigs.ludivinecassal_prod = ludivinecassal_prod.phpFpm.pool; + services.myPhpfpm.poolConfigs.ludivinecassal_prod = ludivinecassal_prod.phpFpm.pool; system.activationScripts.ludivinecassal_prod = ludivinecassal_prod.activationScript; services.myWebsites.production.modules = ludivinecassal_prod.apache.modules; services.myWebsites.production.vhostConfs.ludivine = { @@ -45,7 +45,7 @@ in { (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."ludivine.immae.eu" = null; - services.phpfpm.poolConfigs.ludivinecassal_dev = ludivinecassal_dev.phpFpm.pool; + services.myPhpfpm.poolConfigs.ludivinecassal_dev = ludivinecassal_dev.phpFpm.pool; system.activationScripts.ludivinecassal_dev = ludivinecassal_dev.activationScript; services.myWebsites.apacheConfig.ludivinecassal_dev.modules = ludivinecassal_dev.apache.modules; services.myWebsites.integration.modules = ludivinecassal_dev.apache.modules; diff --git a/virtual/modules/websites/phpfpm/default.nix b/virtual/modules/websites/phpfpm/default.nix new file mode 100644 index 0000000..3c6f027 --- /dev/null +++ b/virtual/modules/websites/phpfpm/default.nix @@ -0,0 +1,178 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.myPhpfpm; + enabled = cfg.poolConfigs != {} || cfg.pools != {}; + + stateDir = "/run/phpfpm"; + + poolConfigs = cfg.poolConfigs // mapAttrs mkPool cfg.pools; + + mkPool = n: p: '' + listen = ${p.listen} + ${p.extraConfig} + ''; + + fpmCfgFile = pool: poolConfig: pkgs.writeText "phpfpm-${pool}.conf" '' + [global] + error_log = syslog + daemonize = no + ${cfg.extraConfig} + + [${pool}] + ${poolConfig} + ''; + + phpIni = poolPhpOptions: (pkgs.runCommand "php.ini" { + inherit (cfg) phpPackage phpOptions; + inherit poolPhpOptions; + nixDefaults = '' + sendmail_path = "/run/wrappers/bin/sendmail -t -i" + ''; + passAsFile = [ "nixDefaults" "phpOptions" "poolPhpOptions" ]; + } '' + cat $phpPackage/etc/php.ini $nixDefaultsPath $phpOptionsPath $poolPhpOptionsPath > $out + ''); + +in { + + options = { + services.myPhpfpm = { + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration that should be put in the global section of + the PHP-FPM configuration file. Do not specify the options + error_log or + daemonize here, since they are generated by + NixOS. + ''; + }; + + phpPackage = mkOption { + type = types.package; + default = pkgs.php; + defaultText = "pkgs.php"; + description = '' + The PHP package to use for running the PHP-FPM service. + ''; + }; + + phpOptions = mkOption { + type = types.lines; + default = ""; + example = + '' + date.timezone = "CET" + ''; + description = + "Options appended to the PHP configuration file php.ini."; + }; + + poolPhpConfigs = mkOption { + default = {}; + type = types.attrsOf types.lines; + example = literalExample '' + { mypool = ''' + extension = some_extension.so + '''; + } + ''; + description = '' + Extra lines that go into the php configuration specific to pool. + ''; + }; + + poolConfigs = mkOption { + default = {}; + type = types.attrsOf types.lines; + example = literalExample '' + { mypool = ''' + listen = /run/phpfpm/mypool + user = nobody + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + '''; + } + ''; + description = '' + A mapping between PHP-FPM pool names and their configurations. + See the documentation on php-fpm.conf for + details on configuration directives. If no pools are defined, + the phpfpm service is disabled. + ''; + }; + + pools = mkOption { + type = types.attrsOf (types.submodule (import ./pool-options.nix { + inherit lib; + })); + default = {}; + example = literalExample '' + { + mypool = { + listen = "/path/to/unix/socket"; + extraConfig = ''' + user = nobody + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + '''; + } + }''; + description = '' + PHP-FPM pools. If no pools or poolConfigs are defined, the PHP-FPM + service is disabled. + ''; + }; + }; + }; + + config = mkIf enabled { + + systemd.slices.phpfpm = { + description = "PHP FastCGI Process manager pools slice"; + }; + + systemd.targets.phpfpm = { + description = "PHP FastCGI Process manager pools target"; + wantedBy = [ "multi-user.target" ]; + }; + + systemd.services = flip mapAttrs' poolConfigs (pool: poolConfig: + nameValuePair "phpfpm-${pool}" { + description = "PHP FastCGI Process Manager service for pool ${pool}"; + after = [ "network.target" ]; + wantedBy = [ "phpfpm.target" ]; + partOf = [ "phpfpm.target" ]; + preStart = '' + mkdir -p ${stateDir} + ''; + serviceConfig = let + cfgFile = fpmCfgFile pool poolConfig; + poolPhpIni = cfg.poolPhpConfigs.${pool} or ""; + in { + Slice = "phpfpm.slice"; + PrivateDevices = true; + ProtectSystem = "full"; + ProtectHome = true; + # XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; + Type = "notify"; + ExecStart = "${cfg.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${phpIni poolPhpIni}"; + ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; + }; + } + ); + }; +} diff --git a/virtual/modules/websites/phpfpm/pool-options.nix b/virtual/modules/websites/phpfpm/pool-options.nix new file mode 100644 index 0000000..cc688c2 --- /dev/null +++ b/virtual/modules/websites/phpfpm/pool-options.nix @@ -0,0 +1,35 @@ +{ lib }: + +with lib; { + + options = { + + listen = mkOption { + type = types.str; + example = "/path/to/unix/socket"; + description = '' + The address on which to accept FastCGI requests. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + example = '' + user = nobody + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + ''; + + description = '' + Extra lines that go into the pool configuration. + See the documentation on php-fpm.conf for + details on configuration directives. + ''; + }; + }; +} + diff --git a/virtual/modules/websites/piedsjaloux/default.nix b/virtual/modules/websites/piedsjaloux/default.nix index bf74173..80261a3 100644 --- a/virtual/modules/websites/piedsjaloux/default.nix +++ b/virtual/modules/websites/piedsjaloux/default.nix @@ -36,7 +36,7 @@ in { }; }; - services.phpfpm.poolConfigs.piedsjaloux_prod = piedsjaloux_prod.phpFpm.pool; + services.myPhpfpm.poolConfigs.piedsjaloux_prod = piedsjaloux_prod.phpFpm.pool; system.activationScripts.piedsjaloux_prod = piedsjaloux_prod.activationScript; services.myWebsites.production.modules = piedsjaloux_prod.apache.modules; services.myWebsites.production.vhostConfs.piedsjaloux = { @@ -48,7 +48,7 @@ in { }) (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."piedsjaloux.immae.eu" = null; - services.phpfpm.poolConfigs.piedsjaloux_dev = piedsjaloux_dev.phpFpm.pool; + services.myPhpfpm.poolConfigs.piedsjaloux_dev = piedsjaloux_dev.phpFpm.pool; system.activationScripts.piedsjaloux_dev = piedsjaloux_dev.activationScript; services.myWebsites.integration.modules = piedsjaloux_dev.apache.modules; services.myWebsites.integration.vhostConfs.piedsjaloux = { diff --git a/virtual/packages/nextcloud.nix b/virtual/packages/nextcloud.nix index 3ac71e0..b8d8e59 100644 --- a/virtual/packages/nextcloud.nix +++ b/virtual/packages/nextcloud.nix @@ -1,4 +1,4 @@ -{ stdenv, fetchurl, checkEnv, writeText, lib }: +{ stdenv, fetchurl, checkEnv, writeText, lib, phpPackages, php }: let nextcloud = let # FIXME: initial sync @@ -231,6 +231,11 @@ let [ webRoot varDir config ] ++ lib.attrsets.mapAttrsToList (name: value: value) apps); socket = "/var/run/phpfpm/nextcloud.sock"; + phpConfig = '' + extension=${phpPackages.redis}/lib/php/extensions/redis.so + extension=${phpPackages.apcu}/lib/php/extensions/apcu.so + zend_extension=${php}/lib/php/extensions/opcache.so + ''; pool = '' listen = ${socket} user = ${apache.user} -- 2.41.0 From 912921a74c8c67663048de66c6d11e1ae63dc10e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Sat, 12 Jan 2019 01:45:52 +0100 Subject: [PATCH 13/16] Make mysqli a shared extension, and load it where necessary --- virtual/modules/websites/chloe/default.nix | 6 ++++++ virtual/modules/websites/default.nix | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/virtual/modules/websites/chloe/default.nix b/virtual/modules/websites/chloe/default.nix index e5c3db7..fb1f602 100644 --- a/virtual/modules/websites/chloe/default.nix +++ b/virtual/modules/websites/chloe/default.nix @@ -37,6 +37,9 @@ in { }; services.myPhpfpm.poolConfigs.chloe_prod = chloe_prod.phpFpm.pool; + services.myPhpfpm.poolPhpConfigs.chloe_prod = '' + extension=${pkgs.php}/lib/php/extensions/mysqli.so + ''; system.activationScripts.chloe_prod = chloe_prod.activationScript; services.myWebsites.production.modules = chloe_prod.apache.modules; services.myWebsites.production.vhostConfs.chloe = { @@ -49,6 +52,9 @@ in { (lib.mkIf cfg.integration.enable { security.acme.certs."eldiron".extraDomains."chloe.immae.eu" = null; services.myPhpfpm.poolConfigs.chloe_dev = chloe_dev.phpFpm.pool; + services.myPhpfpm.poolPhpConfigs.chloe_prod = '' + extension=${pkgs.php}/lib/php/extensions/mysqli.so + ''; system.activationScripts.chloe_dev = chloe_dev.activationScript; services.myWebsites.integration.modules = chloe_dev.apache.modules; services.myWebsites.integration.vhostConfs.chloe = { diff --git a/virtual/modules/websites/default.nix b/virtual/modules/websites/default.nix index 54284e8..a9e62a5 100644 --- a/virtual/modules/websites/default.nix +++ b/virtual/modules/websites/default.nix @@ -116,7 +116,7 @@ in }).overrideAttrs(old: rec { # Didn't manage to build with mysqli + mysql_config connector configureFlags = old.configureFlags ++ [ - "--with-mysqli=mysqlnd" + "--with-mysqli=shared,mysqlnd" ]; # preConfigure = (old.preConfigure or "") + '' # export CPPFLAGS="$CPPFLAGS -I${pkgs.mariadb}/include/mysql/server"; -- 2.41.0 From 950ca5ee979ae2467f3471216140de2c1d572f4b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Sat, 12 Jan 2019 10:24:15 +0100 Subject: [PATCH 14/16] Move httpd service to module --- virtual/eldiron.nix | 110 +----------------- virtual/modules/gitolite.nix | 21 +++- .../{gitweb.nix => gitweb/default.nix} | 11 +- .../{packages => modules/gitweb}/gitweb.nix | 4 +- virtual/modules/websites/default.nix | 90 +++++++++++++- virtual/packages.nix | 3 - virtual/packages/adminer.nix | 2 +- virtual/packages/gitweb.conf | 24 ---- 8 files changed, 119 insertions(+), 146 deletions(-) rename virtual/modules/{gitweb.nix => gitweb/default.nix} (50%) rename virtual/{packages => modules/gitweb}/gitweb.nix (96%) delete mode 100644 virtual/packages/gitweb.conf diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index c9075cf..cefef70 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -29,7 +29,7 @@ imports = [ ./modules/certificates.nix ./modules/gitolite.nix - ./modules/gitweb.nix + ./modules/gitweb ./modules/databases.nix ./modules/websites ./modules/websites/phpfpm @@ -155,114 +155,6 @@ source = ldap_authorized_keys; }; - services.gitDaemon = { - enable = true; - user = "gitolite"; - group = "gitolite"; - basePath = "${mypkgs.git.web.varDir}/repositories"; - }; - - # FIXME: logrotate - services.httpd = let - withConf = domain: { - enableSSL = true; - sslServerCert = "/var/lib/acme/${domain}/cert.pem"; - sslServerKey = "/var/lib/acme/${domain}/key.pem"; - sslServerChain = "/var/lib/acme/${domain}/fullchain.pem"; - logFormat = "combinedVhost"; - listen = [ - { ip = "176.9.151.89"; port = 443; } - ]; - }; - apacheConfig = config.services.myWebsites.apacheConfig; - in rec { - enable = true; - logPerVirtualHost = true; - multiProcessingModule = "worker"; - adminAddr = "httpd@immae.eu"; - logFormat = "combinedVhost"; - extraModules = pkgs.lib.lists.unique ( - mypkgs.adminer.apache.modules ++ - mypkgs.nextcloud.apache.modules ++ - mypkgs.ympd.apache.modules ++ - mypkgs.git.web.apache.modules ++ - mypkgs.mantisbt.apache.modules ++ - mypkgs.ttrss.apache.modules ++ - mypkgs.roundcubemail.apache.modules ++ - pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) apacheConfig)); - extraConfig = builtins.concatStringsSep "\n" - (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) apacheConfig)); - virtualHosts = [ - (withConf "eldiron" // { - hostName = "eldiron.immae.eu"; - documentRoot = ./www; - extraConfig = '' - DirectoryIndex index.htm - ''; - }) - (withConf "eldiron" // { - hostName = "db-1.immae.eu"; - documentRoot = null; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.adminer.apache.vhostConf - ]; - }) - (withConf "eldiron" // { - hostName = "tools.immae.eu"; - documentRoot = null; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.adminer.apache.vhostConf - mypkgs.ympd.apache.vhostConf - mypkgs.ttrss.apache.vhostConf - mypkgs.roundcubemail.apache.vhostConf - ]; - }) - (withConf "eldiron" // { - hostName = "dav.immae.eu"; - documentRoot = null; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.infcloud.apache.vhostConf - mypkgs.davical.apache.vhostConf - ]; - }) - (withConf "eldiron" // { - hostName = "cloud.immae.eu"; - documentRoot = mypkgs.nextcloud.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.nextcloud.apache.vhostConf - ]; - }) - (withConf "eldiron" // { - hostName = "git.immae.eu"; - documentRoot = mypkgs.git.web.webRoot; - extraConfig = builtins.concatStringsSep "\n" [ - mypkgs.git.web.apache.vhostConf - mypkgs.mantisbt.apache.vhostConf - ] + '' - RewriteEngine on - RewriteCond %{REQUEST_URI} ^/releases - RewriteRule /releases(.*) https://release.immae.eu$1 [P,L] - ''; - }) - { # Should go last, default fallback - listen = [ { ip = "*"; port = 80; } ]; - hostName = "redirectSSL"; - serverAliases = [ "*" ]; - enableSSL = false; - logFormat = "combinedVhost"; - documentRoot = "/var/lib/acme/acme-challenge"; - 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 - ''; - } - ]; - }; - systemd.services.tt-rss = { description = "Tiny Tiny RSS feeds update daemon"; serviceConfig = { diff --git a/virtual/modules/gitolite.nix b/virtual/modules/gitolite.nix index 85c7be1..d6b9c79 100644 --- a/virtual/modules/gitolite.nix +++ b/virtual/modules/gitolite.nix @@ -4,6 +4,10 @@ let in { options.services.myGitolite = { enable = lib.mkEnableOption "my gitolite service"; + gitoliteDir = lib.mkOption { + type = lib.types.string; + default = "/var/lib/gitolite"; + }; }; config = lib.mkIf cfg.enable { @@ -20,6 +24,13 @@ in { }); }; + services.gitDaemon = { + enable = true; + user = "gitolite"; + group = "gitolite"; + basePath = "${cfg.gitoliteDir}/repositories"; + }; + system.activationScripts.gitolite = assert mylibs.checkEnv "NIXOPS_GITOLITE_LDAP_PASSWORD"; let @@ -34,12 +45,12 @@ in { in { deps = [ "users" ]; text = '' - if [ -d /var/lib/gitolite ]; then - ln -sf ${gitolite_ldap_groups} /var/lib/gitolite/gitolite_ldap_groups.sh - chmod g+rx /var/lib/gitolite + if [ -d ${cfg.gitoliteDir} ]; then + ln -sf ${gitolite_ldap_groups} ${cfg.gitoliteDir}/gitolite_ldap_groups.sh + chmod g+rx ${cfg.gitoliteDir} fi - if [ -f /var/lib/gitolite/projects.list ]; then - chmod g+r /var/lib/gitolite/projects.list + if [ -f ${cfg.gitoliteDir}/projects.list ]; then + chmod g+r ${cfg.gitoliteDir}/projects.list fi ''; }; diff --git a/virtual/modules/gitweb.nix b/virtual/modules/gitweb/default.nix similarity index 50% rename from virtual/modules/gitweb.nix rename to virtual/modules/gitweb/default.nix index f3ef1bd..2a860ba 100644 --- a/virtual/modules/gitweb.nix +++ b/virtual/modules/gitweb/default.nix @@ -1,5 +1,7 @@ { lib, pkgs, config, mylibs, ... }: let + # FIXME: add buildbot + gitweb = pkgs.callPackage ./gitweb.nix { gitoliteDir = config.services.myGitolite.gitoliteDir; }; cfg = config.services.myGitweb; in { options.services.myGitweb = { @@ -12,10 +14,17 @@ in { nixpkgs.config.packageOverrides = oldpkgs: rec { gitweb = oldpkgs.gitweb.overrideAttrs(old: { installPhase = old.installPhase + '' - cp -r ${./gitweb/theme} $out/gitweb-theme; + cp -r ${./theme} $out/gitweb-theme; ''; }); }; + services.myWebsites.tools.modules = gitweb.apache.modules; + services.myWebsites.tools.vhostConfs.git = { + certName = "eldiron"; + hosts = ["git.immae.eu" ]; + root = gitweb.webRoot; + extraConfig = [ gitweb.apache.vhostConf ]; + }; }; } diff --git a/virtual/packages/gitweb.nix b/virtual/modules/gitweb/gitweb.nix similarity index 96% rename from virtual/packages/gitweb.nix rename to virtual/modules/gitweb/gitweb.nix index 1c2430a..7b4dcac 100644 --- a/virtual/packages/gitweb.nix +++ b/virtual/modules/gitweb/gitweb.nix @@ -1,6 +1,6 @@ -{ gitweb, writeText, gitolite, git }: +{ gitweb, writeText, gitolite, git, gitoliteDir }: rec { - varDir = "/var/lib/gitolite"; + varDir = gitoliteDir; webRoot = gitweb; config = writeText "gitweb.conf" '' $git_temp = "/tmp"; diff --git a/virtual/modules/websites/default.nix b/virtual/modules/websites/default.nix index a9e62a5..b027b81 100644 --- a/virtual/modules/websites/default.nix +++ b/virtual/modules/websites/default.nix @@ -1,5 +1,8 @@ { lib, pkgs, config, mylibs, myconfig, ... }: let + mypkgs = pkgs.callPackage ../../packages.nix { + inherit (mylibs) checkEnv fetchedGit fetchedGithub; + }; cfg = config.services.myWebsites; makeService = name: cfg: let toVhost = vhostConf: { @@ -16,6 +19,28 @@ let documentRoot = vhostConf.root; extraConfig = builtins.concatStringsSep "\n" vhostConf.extraConfig; }; + redirectVhost = { # Should go last, catchall http -> https redirect + listen = [ { ip = cfg.ip; port = 80; } ]; + hostName = "redirectSSL"; + serverAliases = [ "*" ]; + enableSSL = false; + logFormat = "combinedVhost"; + documentRoot = "/var/lib/acme/acme-challenge"; + 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 + ''; + }; + fallbackVhost = toVhost { # Should go first, default choice + certName = "eldiron"; + hosts = ["eldiron.immae.eu" ]; + root = ../../www; + extraConfig = [ "DirectoryIndex index.htm" ]; + }; in rec { enable = true; listen = [ @@ -28,7 +53,9 @@ let logFormat = "combinedVhost"; extraModules = pkgs.lib.lists.unique (pkgs.lib.lists.flatten cfg.modules); extraConfig = builtins.concatStringsSep "\n" cfg.extraConfig; - virtualHosts = pkgs.lib.attrsets.mapAttrsToList (n: v: toVhost v) cfg.vhostConfs; + virtualHosts = [ fallbackVhost ] + ++ (pkgs.lib.attrsets.mapAttrsToList (n: v: toVhost v) cfg.vhostConfs) + ++ [ redirectVhost ]; }; makeServiceOptions = name: ip: { enable = lib.mkEnableOption "enable websites in ${name}"; @@ -74,6 +101,7 @@ in options.services.myWebsites = { production = makeServiceOptions "production" myconfig.ips.production; integration = makeServiceOptions "integration" myconfig.ips.integration; + tools = makeServiceOptions "tools" myconfig.ips.main; apacheConfig = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule { @@ -208,5 +236,65 @@ in services.httpdInte = makeService "integration" config.services.myWebsites.integration; services.myWebsites.integration.modules = pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig); services.myWebsites.integration.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); + + services.httpd = makeService "tools" config.services.myWebsites.tools; + services.myWebsites.tools.modules = + mypkgs.adminer.apache.modules ++ + mypkgs.nextcloud.apache.modules ++ + mypkgs.ympd.apache.modules ++ + mypkgs.mantisbt.apache.modules ++ + mypkgs.ttrss.apache.modules ++ + mypkgs.roundcubemail.apache.modules ++ + pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig); + services.myWebsites.tools.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); + # FIXME: move them all to separate modules + services.myWebsites.tools.vhostConfs.eldiron = { + certName = "eldiron"; + hosts = ["eldiron.immae.eu" ]; + root = ../../www; + extraConfig = [ "DirectoryIndex index.htm" ]; + }; + services.myWebsites.tools.vhostConfs.db-1 = { + certName = "eldiron"; + hosts = ["db-1.immae.eu" ]; + root = null; + extraConfig = [ mypkgs.adminer.apache.vhostConf ]; + }; + services.myWebsites.tools.vhostConfs.tools = { + certName = "eldiron"; + hosts = ["tools.immae.eu" ]; + root = null; + extraConfig = [ + mypkgs.adminer.apache.vhostConf + mypkgs.ympd.apache.vhostConf + mypkgs.ttrss.apache.vhostConf + mypkgs.roundcubemail.apache.vhostConf + ]; + }; + services.myWebsites.tools.vhostConfs.dav = { + certName = "eldiron"; + hosts = ["dav.immae.eu" ]; + root = null; + extraConfig = [ + mypkgs.infcloud.apache.vhostConf + mypkgs.davical.apache.vhostConf + ]; + }; + services.myWebsites.tools.vhostConfs.cloud = { + certName = "eldiron"; + hosts = ["cloud.immae.eu" ]; + root = mypkgs.nextcloud.webRoot; + extraConfig = [ + mypkgs.nextcloud.apache.vhostConf + ]; + }; + services.myWebsites.tools.vhostConfs.git.extraConfig = [ + mypkgs.mantisbt.apache.vhostConf + '' + RewriteEngine on + RewriteCond %{REQUEST_URI} ^/releases + RewriteRule /releases(.*) https://release.immae.eu$1 [P,L] + '' + ]; }; } diff --git a/virtual/packages.nix b/virtual/packages.nix index fa1b666..1f01ba7 100644 --- a/virtual/packages.nix +++ b/virtual/packages.nix @@ -3,7 +3,6 @@ let nextcloud = callPackage ./packages/nextcloud.nix { inherit checkEnv; }; adminer = callPackage ./packages/adminer.nix {}; ympd = callPackage ./packages/ympd.nix {}; - gitweb = callPackage ./packages/gitweb.nix {}; mantisbt = callPackage ./packages/mantisbt.nix { inherit checkEnv fetchedGithub; }; ttrss = callPackage ./packages/ttrss.nix { inherit checkEnv fetchedGithub fetchedGit; }; roundcubemail = callPackage ./packages/roundcubemail.nix { inherit checkEnv; }; @@ -19,6 +18,4 @@ in inherit roundcubemail; inherit infcloud; inherit davical; - # FIXME: add buildbot - git = { web = gitweb; }; } diff --git a/virtual/packages/adminer.nix b/virtual/packages/adminer.nix index d2800aa..7094e45 100644 --- a/virtual/packages/adminer.nix +++ b/virtual/packages/adminer.nix @@ -39,7 +39,7 @@ let vhostConf = '' Alias /adminer ${webRoot} - DirectoryIndex = index.php + DirectoryIndex index.php SetHandler "proxy:unix:${phpFpm.socket}|fcgi://localhost" diff --git a/virtual/packages/gitweb.conf b/virtual/packages/gitweb.conf deleted file mode 100644 index 0d5f50d..0000000 --- a/virtual/packages/gitweb.conf +++ /dev/null @@ -1,24 +0,0 @@ -$git_temp = "/tmp"; - -# The directories where your projects are. Must not end with a slash. -$projectroot = "/srv/git/repositories"; - -$projects_list = "/srv/git/projects.list"; -$strict_export = "true"; - -# Base URLs for links displayed in the web interface. -our @git_base_url_list = qw(ssh://gitolite@git.immae.eu https://git.immae.eu); - -$feature{'blame'}{'default'} = [1]; -$feature{'avatar'}{'default'} = ['gravatar']; -$feature{'highlight'}{'default'} = [1]; - -@stylesheets = ("gitweb-theme/gitweb.css"); -$logo = "gitweb-theme/git-logo.png"; -$favicon = "gitweb-theme/git-favicon.png"; - -$javascript = "gitweb-theme/gitweb.js"; -$logo_url = "https://git.immae.eu/"; -$projects_list_group_categories = "true"; -$projects_list_description_width = 60; -$project_list_default_category = "__Others__"; -- 2.41.0 From 108891744eaa7410e305871212d5b81c1b67a095 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Sat, 12 Jan 2019 12:41:23 +0100 Subject: [PATCH 15/16] Refactor websites. This commit refactors websites into module per "vhost". --- virtual/eldiron.nix | 88 +--------------- .../{databases.nix => databases/default.nix} | 0 .../postgresql_run_socket_path.patch | 0 .../{gitolite.nix => gitolite/default.nix} | 4 +- virtual/modules/gitweb/default.nix | 30 ------ .../websites/commons}/adminer.nix | 0 virtual/modules/websites/default.nix | 93 +++++++--------- .../modules/websites/tools/cloud/default.nix | 45 ++++++++ .../nextcloud-config/mimetypealiases.json | 0 .../nextcloud-config/mimetypemapping.json | 0 .../websites/tools/cloud}/nextcloud.nix | 0 .../websites/tools/dav}/davical.nix | 1 + ...79ebf9250e5f339675319902458c40ed1755.patch | 0 .../modules/websites/tools/dav/default.nix | 33 ++++++ .../websites/tools/dav}/infcloud.nix | 0 .../websites/tools/dav}/infcloud_config.js | 0 virtual/modules/websites/tools/db/default.nix | 23 ++++ .../modules/websites/tools/git/default.nix | 46 ++++++++ .../tools/git}/gitweb/gitweb.nix | 0 .../tools/git}/gitweb/theme/git-favicon.png | Bin .../tools/git}/gitweb/theme/git-logo.png | Bin .../tools/git}/gitweb/theme/gitweb.css | 0 .../tools/git}/gitweb/theme/gitweb.js | 0 .../git/mantisbt}/mantisbt-plugin-slack.json | 0 .../mantisbt-plugin-source-integration.json | 0 ...gin-source-integration_Source.API.php.diff | 0 .../websites/tools/git/mantisbt}/mantisbt.nix | 8 +- .../git/mantisbt/patches}/bug_report.php.diff | 0 .../patches}/bug_report_page.php.diff | 0 .../mantisbt/patches}/bugnote_add.php.diff | 0 .../patches}/bugnote_add_inc.php.diff | 0 .../modules/websites/tools/tools/default.nix | 65 ++++++++++++ .../websites/tools/tools}/roundcubemail.nix | 0 .../websites/tools/tools}/tt-rss.json | 0 .../ttrss-af-feedmod_type_replace.patch | 0 .../tools/tools}/ttrss-af_feedmod.json | 0 .../tools/tools}/ttrss-auth-ldap.json | 0 .../websites/tools/tools}/ttrss-feediron.json | 0 .../tools}/ttrss-feediron_json_reformat.patch | 0 .../tools/tools}/ttrss-ff_instagram.json | 0 .../tools/tools}/ttrss-tumblr_gdpr_ua.json | 0 .../websites/tools/tools}/ttrss.nix | 0 .../websites/tools/tools}/ympd.nix | 0 virtual/packages.nix | 21 ---- virtual/packages/test_goaccess.conf | 99 ------------------ 45 files changed, 261 insertions(+), 295 deletions(-) rename virtual/modules/{databases.nix => databases/default.nix} (100%) rename virtual/modules/{ => databases}/postgresql_run_socket_path.patch (100%) rename virtual/modules/{gitolite.nix => gitolite/default.nix} (96%) delete mode 100644 virtual/modules/gitweb/default.nix rename virtual/{packages => modules/websites/commons}/adminer.nix (100%) create mode 100644 virtual/modules/websites/tools/cloud/default.nix rename virtual/{packages => modules/websites/tools/cloud}/nextcloud-config/mimetypealiases.json (100%) rename virtual/{packages => modules/websites/tools/cloud}/nextcloud-config/mimetypemapping.json (100%) rename virtual/{packages => modules/websites/tools/cloud}/nextcloud.nix (100%) rename virtual/{packages => modules/websites/tools/dav}/davical.nix (99%) rename virtual/{packages => modules/websites/tools/dav}/davical_19eb79ebf9250e5f339675319902458c40ed1755.patch (100%) create mode 100644 virtual/modules/websites/tools/dav/default.nix rename virtual/{packages => modules/websites/tools/dav}/infcloud.nix (100%) rename virtual/{packages => modules/websites/tools/dav}/infcloud_config.js (100%) create mode 100644 virtual/modules/websites/tools/db/default.nix create mode 100644 virtual/modules/websites/tools/git/default.nix rename virtual/modules/{ => websites/tools/git}/gitweb/gitweb.nix (100%) rename virtual/modules/{ => websites/tools/git}/gitweb/theme/git-favicon.png (100%) rename virtual/modules/{ => websites/tools/git}/gitweb/theme/git-logo.png (100%) rename virtual/modules/{ => websites/tools/git}/gitweb/theme/gitweb.css (100%) rename virtual/modules/{ => websites/tools/git}/gitweb/theme/gitweb.js (100%) rename virtual/{packages => modules/websites/tools/git/mantisbt}/mantisbt-plugin-slack.json (100%) rename virtual/{packages => modules/websites/tools/git/mantisbt}/mantisbt-plugin-source-integration.json (100%) rename virtual/{packages => modules/websites/tools/git/mantisbt}/mantisbt-plugin-source-integration_Source.API.php.diff (100%) rename virtual/{packages => modules/websites/tools/git/mantisbt}/mantisbt.nix (95%) rename virtual/{packages/mantisbt-patches => modules/websites/tools/git/mantisbt/patches}/bug_report.php.diff (100%) rename virtual/{packages/mantisbt-patches => modules/websites/tools/git/mantisbt/patches}/bug_report_page.php.diff (100%) rename virtual/{packages/mantisbt-patches => modules/websites/tools/git/mantisbt/patches}/bugnote_add.php.diff (100%) rename virtual/{packages/mantisbt-patches => modules/websites/tools/git/mantisbt/patches}/bugnote_add_inc.php.diff (100%) create mode 100644 virtual/modules/websites/tools/tools/default.nix rename virtual/{packages => modules/websites/tools/tools}/roundcubemail.nix (100%) rename virtual/{packages => modules/websites/tools/tools}/tt-rss.json (100%) rename virtual/{packages => modules/websites/tools/tools}/ttrss-af-feedmod_type_replace.patch (100%) rename virtual/{packages => modules/websites/tools/tools}/ttrss-af_feedmod.json (100%) rename virtual/{packages => modules/websites/tools/tools}/ttrss-auth-ldap.json (100%) rename virtual/{packages => modules/websites/tools/tools}/ttrss-feediron.json (100%) rename virtual/{packages => modules/websites/tools/tools}/ttrss-feediron_json_reformat.patch (100%) rename virtual/{packages => modules/websites/tools/tools}/ttrss-ff_instagram.json (100%) rename virtual/{packages => modules/websites/tools/tools}/ttrss-tumblr_gdpr_ua.json (100%) rename virtual/{packages => modules/websites/tools/tools}/ttrss.nix (100%) rename virtual/{packages => modules/websites/tools/tools}/ympd.nix (100%) delete mode 100644 virtual/packages.nix delete mode 100644 virtual/packages/test_goaccess.conf diff --git a/virtual/eldiron.nix b/virtual/eldiron.nix index cefef70..0970521 100644 --- a/virtual/eldiron.nix +++ b/virtual/eldiron.nix @@ -9,11 +9,6 @@ # rsync -e "ssh -i /root/.ssh/id_charon_vpn" -aAXvz --delete --numeric-ids --super --rsync-path="sudo rsync" /var/lib/* immae@immae.eu: eldiron = { config, pkgs, mylibs, myconfig, ... }: with mylibs; - let - mypkgs = pkgs.callPackage ./packages.nix { - inherit checkEnv fetchedGit fetchedGithub; - }; - in { _module.args = { mylibs = import ../libs.nix; @@ -28,22 +23,20 @@ imports = [ ./modules/certificates.nix - ./modules/gitolite.nix - ./modules/gitweb - ./modules/databases.nix + ./modules/gitolite + ./modules/databases ./modules/websites - ./modules/websites/phpfpm ]; services.myGitolite.enable = true; - services.myGitweb.enable = true; services.myDatabases.enable = true; services.myWebsites.production.enable = true; services.myWebsites.integration.enable = true; + services.myWebsites.tools.enable = true; networking = { firewall = { enable = true; - allowedTCPPorts = [ 22 9418 ]; + allowedTCPPorts = [ 22 ]; }; }; @@ -67,74 +60,17 @@ }; }; - environment.systemPackages = let - # FIXME: move it to nextcloud - occ = pkgs.writeScriptBin "nextcloud-occ" '' - #! ${pkgs.stdenv.shell} - cd ${mypkgs.nextcloud.webRoot} - NEXTCLOUD_CONFIG_DIR="${mypkgs.nextcloud.webRoot}/config" \ - exec \ - ${pkgs.php}/bin/php \ - -c ${pkgs.php}/etc/php.ini \ - occ $* - ''; - in [ + environment.systemPackages = [ pkgs.telnet pkgs.htop pkgs.vim - occ ]; - security.acme.certs."eldiron".extraDomains = { - "db-1.immae.eu" = null; - "tools.immae.eu" = null; - "cloud.immae.eu" = null; - "dav.immae.eu" = null; - }; - services.openssh.extraConfig = '' AuthorizedKeysCommand /etc/ssh/ldap_authorized_keys AuthorizedKeysCommandUser nobody ''; - services.ympd = mypkgs.ympd.config // { enable = false; }; - - services.myPhpfpm = { - phpPackage = pkgs.php; - phpOptions = '' - session.save_path = "/var/lib/php/sessions" - session.gc_maxlifetime = 60*60*24*15 - session.cache_expire = 60*24*30 - ''; - extraConfig = '' - log_level = notice - ''; - poolPhpConfigs = { - nextcloud = mypkgs.nextcloud.phpFpm.phpConfig; - }; - poolConfigs = { - adminer = mypkgs.adminer.phpFpm.pool; - nextcloud = mypkgs.nextcloud.phpFpm.pool; - mantisbt = mypkgs.mantisbt.phpFpm.pool; - ttrss = mypkgs.ttrss.phpFpm.pool; - roundcubemail = mypkgs.roundcubemail.phpFpm.pool; - davical = mypkgs.davical.phpFpm.pool; - }; - }; - - system.activationScripts = { - nextcloud = mypkgs.nextcloud.activationScript; - ttrss = mypkgs.ttrss.activationScript; - roundcubemail = mypkgs.roundcubemail.activationScript; - httpd = '' - install -d -m 0755 /var/lib/acme/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/sessions/mantisbt - install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/davical - ''; - }; - environment.etc."ssh/ldap_authorized_keys" = let ldap_authorized_keys = assert checkEnv "NIXOPS_SSHD_LDAP_PASSWORD"; @@ -155,19 +91,5 @@ source = ldap_authorized_keys; }; - systemd.services.tt-rss = { - description = "Tiny Tiny RSS feeds update daemon"; - serviceConfig = { - User = "wwwrun"; - ExecStart = "${pkgs.php}/bin/php ${mypkgs.ttrss.webRoot}/update.php --daemon"; - StandardOutput = "syslog"; - StandardError = "syslog"; - PermissionsStartOnly = true; - }; - - wantedBy = [ "multi-user.target" ]; - requires = ["postgresql.service"]; - after = ["network.target" "postgresql.service"]; - }; }; } diff --git a/virtual/modules/databases.nix b/virtual/modules/databases/default.nix similarity index 100% rename from virtual/modules/databases.nix rename to virtual/modules/databases/default.nix diff --git a/virtual/modules/postgresql_run_socket_path.patch b/virtual/modules/databases/postgresql_run_socket_path.patch similarity index 100% rename from virtual/modules/postgresql_run_socket_path.patch rename to virtual/modules/databases/postgresql_run_socket_path.patch diff --git a/virtual/modules/gitolite.nix b/virtual/modules/gitolite/default.nix similarity index 96% rename from virtual/modules/gitolite.nix rename to virtual/modules/gitolite/default.nix index d6b9c79..78691fa 100644 --- a/virtual/modules/gitolite.nix +++ b/virtual/modules/gitolite/default.nix @@ -24,6 +24,8 @@ in { }); }; + networking.firewall.allowedTCPPorts = [ 9418 ]; + services.gitDaemon = { enable = true; user = "gitolite"; @@ -36,7 +38,7 @@ in { let gitolite_ldap_groups = mylibs.wrap { name = "gitolite_ldap_groups.sh"; - file = ./gitolite/gitolite_ldap_groups.sh; + file = ./gitolite_ldap_groups.sh; vars = { LDAP_PASS = builtins.getEnv "NIXOPS_GITOLITE_LDAP_PASSWORD"; }; diff --git a/virtual/modules/gitweb/default.nix b/virtual/modules/gitweb/default.nix deleted file mode 100644 index 2a860ba..0000000 --- a/virtual/modules/gitweb/default.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ lib, pkgs, config, mylibs, ... }: -let - # FIXME: add buildbot - gitweb = pkgs.callPackage ./gitweb.nix { gitoliteDir = config.services.myGitolite.gitoliteDir; }; - cfg = config.services.myGitweb; -in { - options.services.myGitweb = { - enable = lib.mkEnableOption "my gitweb service"; - }; - - config = lib.mkIf cfg.enable { - security.acme.certs."eldiron".extraDomains."git.immae.eu" = null; - - nixpkgs.config.packageOverrides = oldpkgs: rec { - gitweb = oldpkgs.gitweb.overrideAttrs(old: { - installPhase = old.installPhase + '' - cp -r ${./theme} $out/gitweb-theme; - ''; - }); - }; - - services.myWebsites.tools.modules = gitweb.apache.modules; - services.myWebsites.tools.vhostConfs.git = { - certName = "eldiron"; - hosts = ["git.immae.eu" ]; - root = gitweb.webRoot; - extraConfig = [ gitweb.apache.vhostConf ]; - }; - }; -} diff --git a/virtual/packages/adminer.nix b/virtual/modules/websites/commons/adminer.nix similarity index 100% rename from virtual/packages/adminer.nix rename to virtual/modules/websites/commons/adminer.nix diff --git a/virtual/modules/websites/default.nix b/virtual/modules/websites/default.nix index b027b81..6b31381 100644 --- a/virtual/modules/websites/default.nix +++ b/virtual/modules/websites/default.nix @@ -91,11 +91,18 @@ in ./aten ./piedsjaloux ./connexionswing + ./tools/db + ./tools/tools + ./tools/dav + ./tools/cloud + ./tools/git # built using: # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix # And removed users / groups ./apache/httpd_prod.nix ./apache/httpd_inte.nix + # Adapted from base phpfpm + ./phpfpm ]; options.services.myWebsites = { @@ -155,6 +162,12 @@ in phpPackages = oldpkgs.php72Packages.override { inherit php; }; }; + services.myWebsites.tools.databases.enable = true; + services.myWebsites.tools.tools.enable = true; + services.myWebsites.tools.dav.enable = true; + services.myWebsites.tools.cloud.enable = true; + services.myWebsites.tools.git.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; @@ -227,6 +240,28 @@ in }; }; + system.activationScripts = { + httpd = '' + install -d -m 0755 /var/lib/acme/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/sessions/mantisbt + install -d -m 0750 -o wwwrun -g wwwrun /var/lib/php/sessions/davical + ''; + }; + + services.myPhpfpm = { + phpPackage = pkgs.php; + phpOptions = '' + session.save_path = "/var/lib/php/sessions" + session.gc_maxlifetime = 60*60*24*15 + session.cache_expire = 60*24*30 + ''; + extraConfig = '' + log_level = notice + ''; + }; + # FIXME: logrotate # FIXME: ipv6 services.httpdProd = makeService "production" config.services.myWebsites.production; @@ -238,63 +273,7 @@ in services.myWebsites.integration.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); services.httpd = makeService "tools" config.services.myWebsites.tools; - services.myWebsites.tools.modules = - mypkgs.adminer.apache.modules ++ - mypkgs.nextcloud.apache.modules ++ - mypkgs.ympd.apache.modules ++ - mypkgs.mantisbt.apache.modules ++ - mypkgs.ttrss.apache.modules ++ - mypkgs.roundcubemail.apache.modules ++ - pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig); + services.myWebsites.tools.modules = pkgs.lib.lists.flatten (pkgs.lib.attrsets.mapAttrsToList (n: v: v.modules or []) cfg.apacheConfig); services.myWebsites.tools.extraConfig = (builtins.filter (x: x != null) (pkgs.lib.attrsets.mapAttrsToList (n: v: v.extraConfig or null) cfg.apacheConfig)); - # FIXME: move them all to separate modules - services.myWebsites.tools.vhostConfs.eldiron = { - certName = "eldiron"; - hosts = ["eldiron.immae.eu" ]; - root = ../../www; - extraConfig = [ "DirectoryIndex index.htm" ]; - }; - services.myWebsites.tools.vhostConfs.db-1 = { - certName = "eldiron"; - hosts = ["db-1.immae.eu" ]; - root = null; - extraConfig = [ mypkgs.adminer.apache.vhostConf ]; - }; - services.myWebsites.tools.vhostConfs.tools = { - certName = "eldiron"; - hosts = ["tools.immae.eu" ]; - root = null; - extraConfig = [ - mypkgs.adminer.apache.vhostConf - mypkgs.ympd.apache.vhostConf - mypkgs.ttrss.apache.vhostConf - mypkgs.roundcubemail.apache.vhostConf - ]; - }; - services.myWebsites.tools.vhostConfs.dav = { - certName = "eldiron"; - hosts = ["dav.immae.eu" ]; - root = null; - extraConfig = [ - mypkgs.infcloud.apache.vhostConf - mypkgs.davical.apache.vhostConf - ]; - }; - services.myWebsites.tools.vhostConfs.cloud = { - certName = "eldiron"; - hosts = ["cloud.immae.eu" ]; - root = mypkgs.nextcloud.webRoot; - extraConfig = [ - mypkgs.nextcloud.apache.vhostConf - ]; - }; - services.myWebsites.tools.vhostConfs.git.extraConfig = [ - mypkgs.mantisbt.apache.vhostConf - '' - RewriteEngine on - RewriteCond %{REQUEST_URI} ^/releases - RewriteRule /releases(.*) https://release.immae.eu$1 [P,L] - '' - ]; }; } diff --git a/virtual/modules/websites/tools/cloud/default.nix b/virtual/modules/websites/tools/cloud/default.nix new file mode 100644 index 0000000..7dd5c6e --- /dev/null +++ b/virtual/modules/websites/tools/cloud/default.nix @@ -0,0 +1,45 @@ +{ lib, pkgs, config, mylibs, ... }: +let + nextcloud = pkgs.callPackage ./nextcloud.nix { inherit (mylibs) checkEnv; }; + + cfg = config.services.myWebsites.tools.cloud; +in { + options.services.myWebsites.tools.cloud = { + enable = lib.mkEnableOption "enable cloud website"; + }; + + config = lib.mkIf cfg.enable { + security.acme.certs."eldiron".extraDomains."cloud.immae.eu" = null; + + services.myWebsites.tools.modules = nextcloud.apache.modules; + + services.myWebsites.tools.vhostConfs.cloud = { + certName = "eldiron"; + hosts = ["cloud.immae.eu" ]; + root = nextcloud.webRoot; + extraConfig = [ + nextcloud.apache.vhostConf + ]; + }; + + environment.systemPackages = let + occ = pkgs.writeScriptBin "nextcloud-occ" '' + #! ${pkgs.stdenv.shell} + cd ${nextcloud.webRoot} + NEXTCLOUD_CONFIG_DIR="${nextcloud.webRoot}/config" \ + exec \ + ${pkgs.php}/bin/php \ + -c ${pkgs.php}/etc/php.ini \ + occ $* + ''; + in [ occ ]; + + system.activationScripts.nextcloud = nextcloud.activationScript; + + services.myPhpfpm = { + poolPhpConfigs.nextcloud = nextcloud.phpFpm.phpConfig; + poolConfigs.nextcloud = nextcloud.phpFpm.pool; + }; + + }; +} diff --git a/virtual/packages/nextcloud-config/mimetypealiases.json b/virtual/modules/websites/tools/cloud/nextcloud-config/mimetypealiases.json similarity index 100% rename from virtual/packages/nextcloud-config/mimetypealiases.json rename to virtual/modules/websites/tools/cloud/nextcloud-config/mimetypealiases.json diff --git a/virtual/packages/nextcloud-config/mimetypemapping.json b/virtual/modules/websites/tools/cloud/nextcloud-config/mimetypemapping.json similarity index 100% rename from virtual/packages/nextcloud-config/mimetypemapping.json rename to virtual/modules/websites/tools/cloud/nextcloud-config/mimetypemapping.json diff --git a/virtual/packages/nextcloud.nix b/virtual/modules/websites/tools/cloud/nextcloud.nix similarity index 100% rename from virtual/packages/nextcloud.nix rename to virtual/modules/websites/tools/cloud/nextcloud.nix diff --git a/virtual/packages/davical.nix b/virtual/modules/websites/tools/dav/davical.nix similarity index 99% rename from virtual/packages/davical.nix rename to virtual/modules/websites/tools/dav/davical.nix index f539ba6..697bd60 100644 --- a/virtual/packages/davical.nix +++ b/virtual/modules/websites/tools/dav/davical.nix @@ -96,6 +96,7 @@ let apache = { user = "wwwrun"; group = "wwwrun"; + modules = [ "proxy_fcgi" ]; vhostConf = '' Alias /davical "${webRoot}" Alias /caldav.php "${webRoot}/caldav.php" diff --git a/virtual/packages/davical_19eb79ebf9250e5f339675319902458c40ed1755.patch b/virtual/modules/websites/tools/dav/davical_19eb79ebf9250e5f339675319902458c40ed1755.patch similarity index 100% rename from virtual/packages/davical_19eb79ebf9250e5f339675319902458c40ed1755.patch rename to virtual/modules/websites/tools/dav/davical_19eb79ebf9250e5f339675319902458c40ed1755.patch diff --git a/virtual/modules/websites/tools/dav/default.nix b/virtual/modules/websites/tools/dav/default.nix new file mode 100644 index 0000000..201da38 --- /dev/null +++ b/virtual/modules/websites/tools/dav/default.nix @@ -0,0 +1,33 @@ +{ lib, pkgs, config, mylibs, ... }: +let + infcloud = pkgs.callPackage ./infcloud.nix {}; + davical = pkgs.callPackage ./davical.nix { inherit (mylibs) checkEnv; }; + + cfg = config.services.myWebsites.tools.dav; +in { + options.services.myWebsites.tools.dav = { + enable = lib.mkEnableOption "enable dav website"; + }; + + config = lib.mkIf cfg.enable { + security.acme.certs."eldiron".extraDomains."dav.immae.eu" = null; + + services.myWebsites.tools.modules = davical.apache.modules; + + services.myWebsites.tools.vhostConfs.dav = { + certName = "eldiron"; + hosts = ["dav.immae.eu" ]; + root = null; + extraConfig = [ + infcloud.apache.vhostConf + davical.apache.vhostConf + ]; + }; + + services.myPhpfpm.poolConfigs = { + davical = davical.phpFpm.pool; + }; + + }; +} + diff --git a/virtual/packages/infcloud.nix b/virtual/modules/websites/tools/dav/infcloud.nix similarity index 100% rename from virtual/packages/infcloud.nix rename to virtual/modules/websites/tools/dav/infcloud.nix diff --git a/virtual/packages/infcloud_config.js b/virtual/modules/websites/tools/dav/infcloud_config.js similarity index 100% rename from virtual/packages/infcloud_config.js rename to virtual/modules/websites/tools/dav/infcloud_config.js diff --git a/virtual/modules/websites/tools/db/default.nix b/virtual/modules/websites/tools/db/default.nix new file mode 100644 index 0000000..20f77c7 --- /dev/null +++ b/virtual/modules/websites/tools/db/default.nix @@ -0,0 +1,23 @@ +{ lib, pkgs, config, mylibs, ... }: +let + adminer = pkgs.callPackage ../../commons/adminer.nix {}; + + cfg = config.services.myWebsites.tools.databases; +in { + options.services.myWebsites.tools.databases = { + enable = lib.mkEnableOption "enable database's website"; + }; + + config = lib.mkIf cfg.enable { + # FIXME: include it in vhostConf ? + security.acme.certs."eldiron".extraDomains."db-1.immae.eu" = null; + + services.myWebsites.tools.modules = adminer.apache.modules; + services.myWebsites.tools.vhostConfs.db-1 = { + certName = "eldiron"; + hosts = ["db-1.immae.eu" ]; + root = null; + extraConfig = [ adminer.apache.vhostConf ]; + }; + }; +} diff --git a/virtual/modules/websites/tools/git/default.nix b/virtual/modules/websites/tools/git/default.nix new file mode 100644 index 0000000..0a63013 --- /dev/null +++ b/virtual/modules/websites/tools/git/default.nix @@ -0,0 +1,46 @@ +{ lib, pkgs, config, mylibs, ... }: +let + mantisbt = pkgs.callPackage ./mantisbt/mantisbt.nix { inherit (mylibs) checkEnv fetchedGithub; }; + gitweb = pkgs.callPackage ./gitweb/gitweb.nix { gitoliteDir = config.services.myGitolite.gitoliteDir; }; + + cfg = config.services.myWebsites.tools.git; +in { + options.services.myWebsites.tools.git = { + enable = lib.mkEnableOption "enable git's website"; + }; + + config = lib.mkIf cfg.enable { + # FIXME: include it in vhostConf ? + security.acme.certs."eldiron".extraDomains."git.immae.eu" = null; + + nixpkgs.config.packageOverrides = oldpkgs: rec { + gitweb = oldpkgs.gitweb.overrideAttrs(old: { + installPhase = old.installPhase + '' + cp -r ${./gitweb/theme} $out/gitweb-theme; + ''; + }); + }; + + services.myWebsites.tools.modules = + gitweb.apache.modules ++ + mantisbt.apache.modules; + + services.myWebsites.tools.vhostConfs.git = { + certName = "eldiron"; + hosts = ["git.immae.eu" ]; + root = gitweb.webRoot; + extraConfig = [ + gitweb.apache.vhostConf + mantisbt.apache.vhostConf + '' + RewriteEngine on + RewriteCond %{REQUEST_URI} ^/releases + RewriteRule /releases(.*) https://release.immae.eu$1 [P,L] + '' + ]; + }; + services.myPhpfpm.poolConfigs = { + mantisbt = mantisbt.phpFpm.pool; + }; + }; +} diff --git a/virtual/modules/gitweb/gitweb.nix b/virtual/modules/websites/tools/git/gitweb/gitweb.nix similarity index 100% rename from virtual/modules/gitweb/gitweb.nix rename to virtual/modules/websites/tools/git/gitweb/gitweb.nix diff --git a/virtual/modules/gitweb/theme/git-favicon.png b/virtual/modules/websites/tools/git/gitweb/theme/git-favicon.png similarity index 100% rename from virtual/modules/gitweb/theme/git-favicon.png rename to virtual/modules/websites/tools/git/gitweb/theme/git-favicon.png diff --git a/virtual/modules/gitweb/theme/git-logo.png b/virtual/modules/websites/tools/git/gitweb/theme/git-logo.png similarity index 100% rename from virtual/modules/gitweb/theme/git-logo.png rename to virtual/modules/websites/tools/git/gitweb/theme/git-logo.png diff --git a/virtual/modules/gitweb/theme/gitweb.css b/virtual/modules/websites/tools/git/gitweb/theme/gitweb.css similarity index 100% rename from virtual/modules/gitweb/theme/gitweb.css rename to virtual/modules/websites/tools/git/gitweb/theme/gitweb.css diff --git a/virtual/modules/gitweb/theme/gitweb.js b/virtual/modules/websites/tools/git/gitweb/theme/gitweb.js similarity index 100% rename from virtual/modules/gitweb/theme/gitweb.js rename to virtual/modules/websites/tools/git/gitweb/theme/gitweb.js diff --git a/virtual/packages/mantisbt-plugin-slack.json b/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-slack.json similarity index 100% rename from virtual/packages/mantisbt-plugin-slack.json rename to virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-slack.json diff --git a/virtual/packages/mantisbt-plugin-source-integration.json b/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration.json similarity index 100% rename from virtual/packages/mantisbt-plugin-source-integration.json rename to virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration.json diff --git a/virtual/packages/mantisbt-plugin-source-integration_Source.API.php.diff b/virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration_Source.API.php.diff similarity index 100% rename from virtual/packages/mantisbt-plugin-source-integration_Source.API.php.diff rename to virtual/modules/websites/tools/git/mantisbt/mantisbt-plugin-source-integration_Source.API.php.diff diff --git a/virtual/packages/mantisbt.nix b/virtual/modules/websites/tools/git/mantisbt/mantisbt.nix similarity index 95% rename from virtual/packages/mantisbt.nix rename to virtual/modules/websites/tools/git/mantisbt/mantisbt.nix index 335cb7d..009c902 100644 --- a/virtual/packages/mantisbt.nix +++ b/virtual/modules/websites/tools/git/mantisbt/mantisbt.nix @@ -64,10 +64,10 @@ let sha256 = "0jnrqz6r2hf53v0k1lh3il7hlfiphn61r9wgg6mzyywkjxwq07md"; }; patches = [ - ./mantisbt-patches/bug_report.php.diff - ./mantisbt-patches/bug_report_page.php.diff - ./mantisbt-patches/bugnote_add.php.diff - ./mantisbt-patches/bugnote_add_inc.php.diff + ./patches/bug_report.php.diff + ./patches/bug_report_page.php.diff + ./patches/bugnote_add.php.diff + ./patches/bugnote_add_inc.php.diff ]; installPhase = '' cp -a . $out diff --git a/virtual/packages/mantisbt-patches/bug_report.php.diff b/virtual/modules/websites/tools/git/mantisbt/patches/bug_report.php.diff similarity index 100% rename from virtual/packages/mantisbt-patches/bug_report.php.diff rename to virtual/modules/websites/tools/git/mantisbt/patches/bug_report.php.diff diff --git a/virtual/packages/mantisbt-patches/bug_report_page.php.diff b/virtual/modules/websites/tools/git/mantisbt/patches/bug_report_page.php.diff similarity index 100% rename from virtual/packages/mantisbt-patches/bug_report_page.php.diff rename to virtual/modules/websites/tools/git/mantisbt/patches/bug_report_page.php.diff diff --git a/virtual/packages/mantisbt-patches/bugnote_add.php.diff b/virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add.php.diff similarity index 100% rename from virtual/packages/mantisbt-patches/bugnote_add.php.diff rename to virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add.php.diff diff --git a/virtual/packages/mantisbt-patches/bugnote_add_inc.php.diff b/virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add_inc.php.diff similarity index 100% rename from virtual/packages/mantisbt-patches/bugnote_add_inc.php.diff rename to virtual/modules/websites/tools/git/mantisbt/patches/bugnote_add_inc.php.diff diff --git a/virtual/modules/websites/tools/tools/default.nix b/virtual/modules/websites/tools/tools/default.nix new file mode 100644 index 0000000..f29ac11 --- /dev/null +++ b/virtual/modules/websites/tools/tools/default.nix @@ -0,0 +1,65 @@ +{ lib, pkgs, config, mylibs, ... }: +let + adminer = pkgs.callPackage ../../commons/adminer.nix {}; + ympd = pkgs.callPackage ./ympd.nix {}; + ttrss = pkgs.callPackage ./ttrss.nix { inherit (mylibs) checkEnv fetchedGithub fetchedGit; }; + roundcubemail = pkgs.callPackage ./roundcubemail.nix { inherit (mylibs) checkEnv; }; + + cfg = config.services.myWebsites.tools.tools; +in { + options.services.myWebsites.tools.tools = { + enable = lib.mkEnableOption "enable tools website"; + }; + + config = lib.mkIf cfg.enable { + security.acme.certs."eldiron".extraDomains."tools.immae.eu" = null; + + services.myWebsites.tools.modules = + adminer.apache.modules + ++ ympd.apache.modules + ++ ttrss.apache.modules + ++ roundcubemail.apache.modules; + + services.ympd = ympd.config // { enable = false; }; + + services.myWebsites.tools.vhostConfs.tools = { + certName = "eldiron"; + hosts = ["tools.immae.eu" ]; + root = null; + extraConfig = [ + adminer.apache.vhostConf + ympd.apache.vhostConf + ttrss.apache.vhostConf + roundcubemail.apache.vhostConf + ]; + }; + + services.myPhpfpm.poolConfigs = { + adminer = adminer.phpFpm.pool; + ttrss = ttrss.phpFpm.pool; + roundcubemail = roundcubemail.phpFpm.pool; + }; + + system.activationScripts = { + ttrss = ttrss.activationScript; + roundcubemail = roundcubemail.activationScript; + }; + + systemd.services.tt-rss = { + description = "Tiny Tiny RSS feeds update daemon"; + serviceConfig = { + User = "wwwrun"; + ExecStart = "${pkgs.php}/bin/php ${ttrss.webRoot}/update.php --daemon"; + StandardOutput = "syslog"; + StandardError = "syslog"; + PermissionsStartOnly = true; + }; + + wantedBy = [ "multi-user.target" ]; + requires = ["postgresql.service"]; + after = ["network.target" "postgresql.service"]; + }; + + }; +} + diff --git a/virtual/packages/roundcubemail.nix b/virtual/modules/websites/tools/tools/roundcubemail.nix similarity index 100% rename from virtual/packages/roundcubemail.nix rename to virtual/modules/websites/tools/tools/roundcubemail.nix diff --git a/virtual/packages/tt-rss.json b/virtual/modules/websites/tools/tools/tt-rss.json similarity index 100% rename from virtual/packages/tt-rss.json rename to virtual/modules/websites/tools/tools/tt-rss.json diff --git a/virtual/packages/ttrss-af-feedmod_type_replace.patch b/virtual/modules/websites/tools/tools/ttrss-af-feedmod_type_replace.patch similarity index 100% rename from virtual/packages/ttrss-af-feedmod_type_replace.patch rename to virtual/modules/websites/tools/tools/ttrss-af-feedmod_type_replace.patch diff --git a/virtual/packages/ttrss-af_feedmod.json b/virtual/modules/websites/tools/tools/ttrss-af_feedmod.json similarity index 100% rename from virtual/packages/ttrss-af_feedmod.json rename to virtual/modules/websites/tools/tools/ttrss-af_feedmod.json diff --git a/virtual/packages/ttrss-auth-ldap.json b/virtual/modules/websites/tools/tools/ttrss-auth-ldap.json similarity index 100% rename from virtual/packages/ttrss-auth-ldap.json rename to virtual/modules/websites/tools/tools/ttrss-auth-ldap.json diff --git a/virtual/packages/ttrss-feediron.json b/virtual/modules/websites/tools/tools/ttrss-feediron.json similarity index 100% rename from virtual/packages/ttrss-feediron.json rename to virtual/modules/websites/tools/tools/ttrss-feediron.json diff --git a/virtual/packages/ttrss-feediron_json_reformat.patch b/virtual/modules/websites/tools/tools/ttrss-feediron_json_reformat.patch similarity index 100% rename from virtual/packages/ttrss-feediron_json_reformat.patch rename to virtual/modules/websites/tools/tools/ttrss-feediron_json_reformat.patch diff --git a/virtual/packages/ttrss-ff_instagram.json b/virtual/modules/websites/tools/tools/ttrss-ff_instagram.json similarity index 100% rename from virtual/packages/ttrss-ff_instagram.json rename to virtual/modules/websites/tools/tools/ttrss-ff_instagram.json diff --git a/virtual/packages/ttrss-tumblr_gdpr_ua.json b/virtual/modules/websites/tools/tools/ttrss-tumblr_gdpr_ua.json similarity index 100% rename from virtual/packages/ttrss-tumblr_gdpr_ua.json rename to virtual/modules/websites/tools/tools/ttrss-tumblr_gdpr_ua.json diff --git a/virtual/packages/ttrss.nix b/virtual/modules/websites/tools/tools/ttrss.nix similarity index 100% rename from virtual/packages/ttrss.nix rename to virtual/modules/websites/tools/tools/ttrss.nix diff --git a/virtual/packages/ympd.nix b/virtual/modules/websites/tools/tools/ympd.nix similarity index 100% rename from virtual/packages/ympd.nix rename to virtual/modules/websites/tools/tools/ympd.nix diff --git a/virtual/packages.nix b/virtual/packages.nix deleted file mode 100644 index 1f01ba7..0000000 --- a/virtual/packages.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ callPackage, checkEnv, fetchedGit, fetchedGithub }: -let - nextcloud = callPackage ./packages/nextcloud.nix { inherit checkEnv; }; - adminer = callPackage ./packages/adminer.nix {}; - ympd = callPackage ./packages/ympd.nix {}; - mantisbt = callPackage ./packages/mantisbt.nix { inherit checkEnv fetchedGithub; }; - ttrss = callPackage ./packages/ttrss.nix { inherit checkEnv fetchedGithub fetchedGit; }; - roundcubemail = callPackage ./packages/roundcubemail.nix { inherit checkEnv; }; - infcloud = callPackage ./packages/infcloud.nix {}; - davical = callPackage ./packages/davical.nix { inherit checkEnv; }; -in - { - inherit adminer; - inherit ympd; - inherit nextcloud; - inherit mantisbt; - inherit ttrss; - inherit roundcubemail; - inherit infcloud; - inherit davical; - } diff --git a/virtual/packages/test_goaccess.conf b/virtual/packages/test_goaccess.conf deleted file mode 100644 index d4f243a..0000000 --- a/virtual/packages/test_goaccess.conf +++ /dev/null @@ -1,99 +0,0 @@ -time-format %H:%M:%S -date-format %d/%b/%Y - -#sur immae.eu -#log-format %v %h %^[%d:%t %^] "%r" %s %b "%R" "%u" $^ - -log-format VCOMBINED -#= %v:%^ %h %^[%d:%t %^] "%r" %s %b "%R" "%u" - -html-prefs {"theme":"bright","layout":"vertical"} - -exclude-ip 188.165.209.148 -exclude-ip 178.33.252.96 -exclude-ip 2001:41d0:2:9c94::1 -exclude-ip 2001:41d0:2:9c94:: -exclude-ip 176.9.151.89 -exclude-ip 2a01:4f8:160:3445:: -exclude-ip 82.255.56.72 - -no-query-string true - -keep-db-files true -load-from-disk true -db-path /var/lib/goaccess/cloud.immae.eu - -ignore-panel REFERRERS -ignore-panel KEYPHRASES - -static-file .css -static-file .js -static-file .jpg -static-file .png -static-file .gif -static-file .ico -static-file .jpeg -static-file .pdf -static-file .csv -static-file .mpeg -static-file .mpg -static-file .swf -static-file .woff -static-file .woff2 -static-file .xls -static-file .xlsx -static-file .doc -static-file .docx -static-file .ppt -static-file .pptx -static-file .txt -static-file .zip -static-file .ogg -static-file .mp3 -static-file .mp4 -static-file .exe -static-file .iso -static-file .gz -static-file .rar -static-file .svg -static-file .bmp -static-file .tar -static-file .tgz -static-file .tiff -static-file .tif -static-file .ttf -static-file .flv -#static-file .less -#static-file .ac3 -#static-file .avi -#static-file .bz2 -#static-file .class -#static-file .cue -#static-file .dae -#static-file .dat -#static-file .dts -#static-file .ejs -#static-file .eot -#static-file .eps -#static-file .img -#static-file .jar -#static-file .map -#static-file .mid -#static-file .midi -#static-file .ogv -#static-file .webm -#static-file .mkv -#static-file .odp -#static-file .ods -#static-file .odt -#static-file .otf -#static-file .pict -#static-file .pls -#static-file .ps -#static-file .qt -#static-file .rm -#static-file .svgz -#static-file .wav -#static-file .webp - - -- 2.41.0 From 35a397cd22e6c8dd7dec471f09416441b64deee4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Sun, 13 Jan 2019 13:57:55 +0100 Subject: [PATCH 16/16] Add mastodon service --- default.nix | 20 -- virtual/modules/databases/default.nix | 1 + virtual/modules/websites/default.nix | 2 + .../websites/tools/mastodon/default.nix | 207 ++++++++++++++++++ .../websites/tools/mastodon}/mastodon.json | 0 .../websites/tools/mastodon/mastodon.nix | 100 +++++++++ 6 files changed, 310 insertions(+), 20 deletions(-) create mode 100644 virtual/modules/websites/tools/mastodon/default.nix rename {fetched => virtual/modules/websites/tools/mastodon}/mastodon.json (100%) create mode 100644 virtual/modules/websites/tools/mastodon/mastodon.nix diff --git a/default.nix b/default.nix index c277602..9e79550 100644 --- a/default.nix +++ b/default.nix @@ -252,25 +252,6 @@ let buildInputs = old.buildInputs ++ [ tokyocabinet bzip2 ]; }); - mastodon = stdenv.mkDerivation (fetchedGithub ./fetched/mastodon.json // rec { - buildPhase = '' - export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt - export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt - - bundle install --deployment --without development test - yarn install --pure-lockfile - ''; - installPhase = '' - cp -a . $out - ''; - propagatedBuildInputs = [ - zlib icu libchardet git bundler yarn - protobuf protobufc libidn libpqxx nodejs - imagemagick ffmpeg libxml2 libxslt pkgconfig - autoconf bison libyaml readline ncurses libffi gdbm - jemalloc which postgresql python3 cacert - ]; - }); # https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/setup.sh # https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks in @@ -311,7 +292,6 @@ in inherit mtr; inherit nixops; stgit = gitAndTools.stgit; - #inherit mastodon; # todo: lx* ?, unrar, unzip, zeromq? #inherit nextcloud-client; #inherit nixos; diff --git a/virtual/modules/databases/default.nix b/virtual/modules/databases/default.nix index de4ace6..db85f3c 100644 --- a/virtual/modules/databases/default.nix +++ b/virtual/modules/databases/default.nix @@ -163,6 +163,7 @@ in { # FIXME: backup # Nextcloud: 14 + # Mastodon: 13 services.redis = rec { enable = config.services.myDatabases.redis.enable; bind = "127.0.0.1"; diff --git a/virtual/modules/websites/default.nix b/virtual/modules/websites/default.nix index 6b31381..d88f571 100644 --- a/virtual/modules/websites/default.nix +++ b/virtual/modules/websites/default.nix @@ -96,6 +96,7 @@ in ./tools/dav ./tools/cloud ./tools/git + ./tools/mastodon # built using: # sed -e "s/services\.httpd/services\.httpdProd/g" .nix-defexpr/channels/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix # And removed users / groups @@ -167,6 +168,7 @@ in services.myWebsites.tools.dav.enable = true; services.myWebsites.tools.cloud.enable = true; services.myWebsites.tools.git.enable = true; + services.myWebsites.tools.mastodon.enable = true; services.myWebsites.Chloe.production.enable = cfg.production.enable; services.myWebsites.Ludivine.production.enable = cfg.production.enable; diff --git a/virtual/modules/websites/tools/mastodon/default.nix b/virtual/modules/websites/tools/mastodon/default.nix new file mode 100644 index 0000000..1549ca9 --- /dev/null +++ b/virtual/modules/websites/tools/mastodon/default.nix @@ -0,0 +1,207 @@ +{ lib, pkgs, config, mylibs, ... }: +let + mastodon = pkgs.callPackage ./mastodon.nix { + inherit (mylibs) fetchedGithub checkEnv; + }; + + cfg = config.services.myWebsites.tools.mastodon; +in { + options.services.myWebsites.tools.mastodon = { + enable = lib.mkEnableOption "enable mastodon's website"; + }; + + config = lib.mkIf cfg.enable { + # FIXME: Can we use dynamic users from systemd? + # nixos/modules/misc/ids.nix + ids.uids.mastodon = 399; + ids.gids.mastodon = 399; + + users.users.mastodon = { + name = "mastodon"; + uid = config.ids.uids.mastodon; + group = "mastodon"; + description = "Mastodon user"; + home = "${mastodon.railsRoot}"; + useDefaultShell = true; + }; + + users.groups.mastodon.gid = config.ids.gids.mastodon; + + systemd.services.mastodon-streaming = { + description = "Mastodon Streaming"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "mastodon-web.service" ]; + + environment.NODE_ENV = "production"; + environment.SOCKET = mastodon.nodeSocket; + + path = [ pkgs.nodejs pkgs.bashInteractive ]; + + script = '' + exec npm run start + ''; + + postStart = '' + while [ ! -S $SOCKET ]; do + sleep 0.5 + done + chmod a+w $SOCKET + ''; + + postStop = '' + rm $SOCKET + ''; + + serviceConfig = { + User = "mastodon"; + EnvironmentFile = mastodon.config; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 15; + Type = "simple"; + WorkingDirectory = mastodon.railsRoot; + }; + + unitConfig.RequiresMountsFor = mastodon.varDir; + }; + + systemd.services.mastodon-web = { + description = "Mastodon Web app"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + environment.RAILS_ENV = "production"; + environment.SOCKET = mastodon.railsSocket; + + path = [ pkgs.bundler ]; + + preStart = '' + bundle exec rails db:migrate + ''; + + script = '' + exec bundle exec puma -C config/puma.rb + ''; + + serviceConfig = { + User = "mastodon"; + EnvironmentFile = mastodon.config; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 15; + Type = "simple"; + WorkingDirectory = mastodon.railsRoot; + }; + + unitConfig.RequiresMountsFor = mastodon.varDir; + }; + + systemd.services.mastodon-sidekiq = { + description = "Mastodon Sidekiq"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "mastodon-web.service" ]; + + environment.RAILS_ENV="production"; + environment.DB_POOL="5"; + + path = [ pkgs.bundler ]; + + script = '' + exec bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push + ''; + + serviceConfig = { + User = "mastodon"; + EnvironmentFile = mastodon.config; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 15; + Type = "simple"; + WorkingDirectory = mastodon.railsRoot; + }; + + unitConfig.RequiresMountsFor = mastodon.varDir; + }; + + # FIXME: initial sync + system.activationScripts.mastodon = { + deps = [ "users" ]; + text = '' + install -m 0755 -o mastodon -g mastodon -d ${mastodon.socketsDir} + install -m 0755 -o mastodon -g mastodon -d ${mastodon.varDir} + ''; + }; + + services.myWebsites.tools.modules = [ + "headers" "proxy" "proxy_wstunnel" "proxy_http" "proxy_balancer" + # FIXME: probably only one balancer method is needed: + "lbmethod_byrequests" "lbmethod_bytraffic" "lbmethod_bybusyness" "lbmethod_heartbeat" + ]; + security.acme.certs."eldiron".extraDomains."mastodon.immae.eu" = null; + services.myWebsites.tools.vhostConfs.mastodon = { + certName = "eldiron"; + hosts = ["mastodon.immae.eu" ]; + root = "${mastodon.railsRoot}/public/"; + extraConfig = [ '' + Header always set Referrer-Policy "strict-origin-when-cross-origin" + Header always set Strict-Transport-Security "max-age=31536000" + + + Header always set Cache-Control "public, max-age=31536000, immutable" + Require all granted + + + ProxyPreserveHost On + RequestHeader set X-Forwarded-Proto "https" + + RewriteEngine On + + ProxyPass /500.html ! + ProxyPass /sw.js ! + ProxyPass /embed.js ! + ProxyPass /robots.txt ! + ProxyPass /manifest.json ! + ProxyPass /browserconfig.xml ! + ProxyPass /mask-icon.svg ! + ProxyPassMatch ^(/.*\.(png|ico|gif)$) ! + ProxyPassMatch ^/(assets|avatars|emoji|headers|packs|sounds|system|.well-known/acme-challenge) ! + + ProxyPassMatch /api/v1/streaming/(.+)$ balancer://node_servers_http/api/v1/streaming/$1 + ProxyPass /api/v1/streaming/ balancer://node_servers/ + ProxyPassReverse /api/v1/streaming/ balancer://node_servers/ + ProxyPass / balancer://puma_servers/ + ProxyPassReverse / balancer://puma_servers/ + + + BalancerMember unix://${mastodon.railsSocket}|http:// + + + + BalancerMember unix://${mastodon.nodeSocket}|ws://localhost + + + + BalancerMember unix://${mastodon.nodeSocket}|http://localhost + + + Alias /system ${mastodon.varDir} + + + Require all granted + Options -MultiViews + + + + Require all granted + Options -MultiViews +FollowSymlinks + + + ErrorDocument 500 /500.html + ErrorDocument 501 /500.html + ErrorDocument 502 /500.html + ErrorDocument 503 /500.html + ErrorDocument 504 /500.html + '' ]; + }; + }; +} diff --git a/fetched/mastodon.json b/virtual/modules/websites/tools/mastodon/mastodon.json similarity index 100% rename from fetched/mastodon.json rename to virtual/modules/websites/tools/mastodon/mastodon.json diff --git a/virtual/modules/websites/tools/mastodon/mastodon.nix b/virtual/modules/websites/tools/mastodon/mastodon.nix new file mode 100644 index 0000000..e948852 --- /dev/null +++ b/virtual/modules/websites/tools/mastodon/mastodon.nix @@ -0,0 +1,100 @@ +{ checkEnv, fetchedGithub, stdenv, writeText, pkgs, cacert }: +let + varDir = "/var/lib/mastodon_immae"; + socketsDir = "/run/mastodon"; + mastodon = stdenv.mkDerivation (fetchedGithub ./mastodon.json // rec { + buildPhase = '' + export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt + export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt + + bundle install --deployment --without development test + yarn install --pure-lockfile + ''; + installPhase = '' + cp -a . $out + ''; + propagatedBuildInputs = with pkgs; [ + zlib icu libchardet git bundler yarn + protobuf protobufc libidn libpqxx nodejs + imagemagick ffmpeg libxml2 libxslt pkgconfig + autoconf bison libyaml readline ncurses libffi gdbm + jemalloc which postgresql python3 cacert + ]; + }); + config = + assert checkEnv "NIXOPS_MASTODON_DB_PASS"; + assert checkEnv "NIXOPS_MASTODON_PAPERCLIP_SECRET"; + assert checkEnv "NIXOPS_MASTODON_SECRET_KEY_BASE"; + assert checkEnv "NIXOPS_MASTODON_OTP_SECRET"; + assert checkEnv "NIXOPS_MASTODON_VAPID_PRIVATE_KEY"; + assert checkEnv "NIXOPS_MASTODON_VAPID_PUBLIC_KEY"; + assert checkEnv "NIXOPS_MASTODON_OTP_SECRET"; + assert checkEnv "NIXOPS_MASTODON_LDAP_PASSWORD"; + writeText "mastodon_environment" '' + REDIS_HOST=localhost + REDIS_PORT=6379 + REDIS_DB=13 + DB_HOST=/run/postgresql + DB_USER=mastodon + DB_NAME=mastodon + DB_PASS=${builtins.getEnv "NIXOPS_MASTODON_DB_PASS"} + DB_PORT=5432 + + LOCAL_DOMAIN=mastodon.immae.eu + LOCAL_HTTPS=true + ALTERNATE_DOMAINS=immae.eu + + PAPERCLIP_SECRET=${builtins.getEnv "NIXOPS_MASTODON_PAPERCLIP_SECRET"} + SECRET_KEY_BASE=${builtins.getEnv "NIXOPS_MASTODON_SECRET_KEY_BASE"} + OTP_SECRET=${builtins.getEnv "NIXOPS_MASTODON_OTP_SECRET"} + + VAPID_PRIVATE_KEY=${builtins.getEnv "NIXOPS_MASTODON_VAPID_PRIVATE_KEY"} + VAPID_PUBLIC_KEY=${builtins.getEnv "NIXOPS_MASTODON_VAPID_PUBLIC_KEY"} + + SMTP_SERVER=mail.immae.eu + SMTP_PORT=587 + SMTP_FROM_ADDRESS=notifications@mastodon.immae.eu + SMTP_DELIVERY_METHOD=smtp + PAPERCLIP_ROOT_PATH=${varDir} + + STREAMING_CLUSTER_NUM=1 + + # LDAP authentication (optional) + LDAP_ENABLED=true + LDAP_HOST=ldap.immae.eu + LDAP_PORT=636 + LDAP_METHOD=simple_tls + LDAP_BASE="dc=immae,dc=eu" + LDAP_BIND_DN="cn=mastodon,ou=services,dc=immae,dc=eu" + LDAP_PASSWORD="${builtins.getEnv "NIXOPS_MASTODON_LDAP_PASSWORD"}" + LDAP_UID="uid" + LDAP_SEARCH_FILTER="(&(%{uid}=%{email})(memberOf=cn=users,cn=mastodon,ou=services,dc=immae,dc=eu))" + ''; + + railsRoot = stdenv.mkDerivation { + name = "mastodon_immae"; + inherit config mastodon; + builder = writeText "build_mastodon_immae" '' + source $stdenv/setup + set -a + source $config + set +a + cp -a $mastodon $out + cd $out + chmod u+rwX . node_modules public + RAILS_ENV=production bundle exec rails assets:precompile + ''; + propagatedBuildInputs = with pkgs; [ + zlib icu libchardet git bundler yarn + protobuf protobufc libidn libpqxx nodejs + imagemagick ffmpeg libxml2 libxslt pkgconfig + autoconf bison libyaml readline ncurses libffi gdbm + jemalloc which postgresql python3 cacert + ]; + }; +in + { + inherit railsRoot config varDir socketsDir; + nodeSocket = "${socketsDir}/live_immae_node.sock"; + railsSocket = "${socketsDir}/live_immae_puma.sock"; + } -- 2.41.0