diff --git a/hosts/vm/livre/stirling.nix b/hosts/vm/livre/stirling.nix index f5fadfc..1abe54d 100644 --- a/hosts/vm/livre/stirling.nix +++ b/hosts/vm/livre/stirling.nix @@ -4,6 +4,7 @@ environment.systemPackages = with pkgs; [ imagemagick # Pour la compression des PDFs ]; + services.stirling-pdf = { enable = true; environment = { @@ -17,6 +18,11 @@ }; }; + systemd.services.stirling-pdf.serviceConfig = { + Restart = "always"; + RestartSec = "5s"; + }; + services.nginx = { enable = true; diff --git a/hosts/vm/nextcloud/default.nix b/hosts/vm/nextcloud/default.nix index 99c1ae6..5f9a1fa 100644 --- a/hosts/vm/nextcloud/default.nix +++ b/hosts/vm/nextcloud/default.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ pkgs, config, ... }: { imports = [ @@ -28,13 +28,80 @@ resticClient.enable = false; }; - services.autofs = { - enable = true; + services.autofs = + let + autoMaster = pkgs.writeScript "home-nextcloud" '' + #!/usr/bin/env bash + USER=$(echo $1 | sed "s/_[1-9]*$//") - autoMaster = '' - /home-nextcloud /etc/auto.master.d/home-nextcloud.sh -t60 - ''; - }; + UHOME=/home-adh/$USER + + USERID=$(ldapsearch -LLL -b "dc=crans,dc=org" -H ldap://172.16.10.157 -D "cn=admin,dc=crans,dc=org" -y ${config.age.secrets.nextcloud_ldap_pass.path} "uid=$USER" uidNumber | grep uidNumber | awk '{print $2}') + UGROUP=$(ldapsearch -LLL -b "dc=crans,dc=org" -H ldap://172.16.10.157 -D "cn=admin,dc=crans,dc=org" -y ${config.age.secrets.nextcloud_ldap_pass.path} "uid=$USER" gidNumber | grep gidNumber | awk '{print $2}') + + # On quitte si l'utilisateur $USER n'existe pas + if [ -z "$USERID" ]; then + logger -p local0.error -t autofs "user $USER n'existe pas" + exit 1 + fi + + # Rafraîchi les stats du dossier + ls ''\${UHOME}/NextCloud/ &>/dev/null || /bin/ls ''\${UHOME} &>/dev/null + + # Création du lien symbolique Nextcloud s'il n'existe pas + if [ ! -e "''\${UHOME}/NextCloud" ] || ! ( + find ''\${UHOME}/NextCloud/ -maxdepth 0 -user $USERID -group ''\${UGROUP} | + grep -q ''\${UHOME}/NextCloud/ + ); then + if [ ! -e "''\${UHOME}/NextCloud" ]; then + ln -fs OwnCloud ''\${UHOME}/NextCloud + fi + + if [ ! -e "''\${UHOME}/NextCloud" ] || ! ( + find ''\${UHOME}/NextCloud/ -maxdepth 0 -user $USERID -group ''\${UGROUP} | + grep -q ''\${UHOME}/NextCloud/ + ); then + logger -p local0.error -t autofs "impossible de créer le lien symbolique ''\${UHOME}/NextCloud" + exit 1 + fi + + logger -p local0.info -t autofs "Lien symbolique ''\${UHOME}/NextCloud -> ''\${UHOME}/OwnCloud créé" + fi + + # Création du dossier OwnCloud s'il n'existe pas ou n'appartient pas a l'utilisateur + if [ ! -d "''\${UHOME}/OwnCloud" ] || ! ( + find ''\${UHOME}/OwnCloud/ -maxdepth 0 -user $USERID -group ''\${UGROUP} | + grep -q ''\${UHOME}/OwnCloud/ + ); then + if [ ! -d "''\${UHOME}/OwnCloud" ]; then + mkdir ''\${UHOME}/OwnCloud + fi + chmod 700 ''\${UHOME}/OwnCloud && + chown $USERID:''\${UGROUP} ''\${UHOME}/OwnCloud + + if [ ! -d "''\${UHOME}/OwnCloud" ] || ! ( + find ''\${UHOME}/OwnCloud/ -maxdepth 0 -user $USERID -group ''\${UGROUP} | + grep -q ''\${UHOME}/OwnCloud/ + ); then + logger -p local0.error -t autofs "impossible de créer le dossier ''\${UHOME}/OwnCloud" + exit 1 + fi + + logger -p local0.info -t autofs "Dossier ''\${UHOME}/OwnCloud créé" + fi + + chmod 750 /home-nextcloud && + chown nextcloud:nextcloud /home-nextcloud && + echo "-fstype=fuse.bindfs,map=$USERID/nextcloud:@$UGROUP/@nextcloud,resolve-symlinks,allow_other :''\${UHOME}/NextCloud" + ''; + in + { + enable = true; + + autoMaster = '' + /home-nextcloud ${autoMaster} -t60 + ''; + }; programs.fuse.userAllowOther = true; systemd.services.autofs = { diff --git a/hosts/vm/nextcloud/nextcloud.nix b/hosts/vm/nextcloud/nextcloud.nix index 0636726..b006469 100644 --- a/hosts/vm/nextcloud/nextcloud.nix +++ b/hosts/vm/nextcloud/nextcloud.nix @@ -12,6 +12,10 @@ owner = "nextcloud"; group = "nextcloud"; }; + # Attention : sensible au retour à la ligne final (il n’en faut pas) ! + nextcloud_ldap_pass = { + file = ../../../secrets/nextcloud/nextcloud_ldap_pass.age; + }; }; services.nextcloud = { @@ -20,7 +24,7 @@ configureRedis = true; hostName = "nextcloud.crans.org"; - https = false; + https = true; maxUploadSize = "4G"; @@ -41,11 +45,26 @@ trusted_proxies = [ # hodaur "172.16.10.145" + # reverseproxy + "172.16.10.151" ]; - }; + mail_domain = "crans.org"; + mail_from_address = "root"; + mail_smtphost = "smtp.crans.org"; + mail_smtpport = 25; + }; appstoreEnable = true; extraAppsEnable = true; }; + + # Activation CORS pour récuppérer les agendas depuis le wiki + # TODO: à mettre que sur /remote.php/dav/public-calendars/ pour éviter des requêtes malveillantes depuis le wiki. + services.nginx.virtualHosts.${config.services.nextcloud.hostName}.extraConfig = '' + add_header 'Access-Control-Allow-Origin' 'https://mediawiki.crans.org' always; + add_header 'Access-Control-Allow-Methods' 'GET' always; + add_header 'Access-Control-Allow-Credentials' 'false' always; + add_header 'Vary' 'Origin' always; + ''; } diff --git a/hosts/vm/reverseproxy/reverseproxy.nix b/hosts/vm/reverseproxy/reverseproxy.nix index 485ba25..c262998 100644 --- a/hosts/vm/reverseproxy/reverseproxy.nix +++ b/hosts/vm/reverseproxy/reverseproxy.nix @@ -1,5 +1,6 @@ { pkgs, + lib, ... }: @@ -175,8 +176,8 @@ let src = fetchFromCrans { repo = "site-install-party"; - rev = "master"; - hash = "sha256-KVB4m/ms0WuArrkLn05INVLqhaGxzCg30GMICI6tM5E="; + rev = "ac44f6e4387e0182f2c7dbda3eeccba0be87c9b6"; + hash = "sha256-xFwDXMmzjeIfhV5Ez1EmNfJcOSMljUZ4aycPppoLtqY="; }; build-system = with pkgs.python3Packages; [ @@ -193,8 +194,8 @@ let src = fetchFromCrans { repo = "homepage"; - rev = "master"; - hash = "sha256-e9tttzKEWcBhogQY2ITDqqTbix/zcnBAylj1eKY791E="; + rev = "a71446ad7c125241835190a4035159bc7be751bc"; + hash = "sha256-dAKJpBnGeDtv0UM8gXsdqUCzbliskRMYUEQ1KGCW1Cw="; }; nativeBuildInputs = with pkgs; [ @@ -292,8 +293,8 @@ in "re2o-dev".proxyPass = "172.16.10.166"; "services".serveLocalFiles = fetchFromCrans { repo = "services-page"; - rev = "master"; - hash = "sha256-ov4r6Oeta+vRcEv8bp7lFQg+2n4JTG4buetram5kN08="; + rev = "e32ac21513d88e5123eb4138835453df64aa21d0"; + hash = "sha256-nc4IjA/wtj7WXnt0wZqGymGz/NR45STlMLbsTdnSzJ0="; }; "snl".globalRedirect = "perso.crans.org/sonetlumens"; "test-melon".proxyPass = "172.16.10.150:8080"; @@ -312,9 +313,9 @@ in proxyPass = "172.16.10.161"; serverAliases = [ "wikipedia" ]; }; - "www" = { + "_crans-org" = { serveLocalFiles = homepagePkg; - serverAliases = [ "." ]; + serverAliases = [ "www" ]; }; "zero".proxyPass = "172.16.10.130"; }; @@ -324,5 +325,14 @@ in acme.enable = true; }; }; - services.nginx.virtualHosts."www-alias-crans.org".default = true; + + # Règle particulières + services.nginx.virtualHosts = { + "www-alias-crans.org".default = true; + + "_crans-org".locations = { + "/_matrix/".proxyPass = "https://matrix.crans.org/_matrix/"; + "/_synapse/".proxyPass = "https://matrix.crans.org/_synapse/"; + }; + }; } diff --git a/modules/crans/users.nix b/modules/crans/users.nix index c229bf4..9c14880 100644 --- a/modules/crans/users.nix +++ b/modules/crans/users.nix @@ -1,4 +1,9 @@ -{ config, lib, ... }: +{ + config, + lib, + self, + ... +}: let cfg = config.crans.users; @@ -34,6 +39,20 @@ in users = { mutableUsers = false; + motd = + let + shortRev = self.shortRev or self.dirtyShortRev or "inconnue"; + rev = self.rev or (lib.strings.removeSuffix "-dirty" (self.dirtyRev or "inconnue")); + isDirty = !(self ? rev); + in + '' + ${ + if isDirty then "!! DIRTY !! " else "" + }Version déployée ${shortRev}, modifiée le ${self.lastModifiedDate or "??"}. + + https://gitlab.crans.org/nounous/nixos/-/commit/${rev} + ''; + users.root = { hashedPasswordFile = config.age.secrets.root-passwd-hash.path; }; diff --git a/modules/default.nix b/modules/default.nix index be2ac91..9685e31 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1,4 +1,4 @@ -{ lib, ... }: +{ lib, self, ... }: { imports = [ @@ -25,6 +25,9 @@ cleanOnBoot = true; }; + # Version de la flake pour nixos-version --configuration-revision + system.configurationRevision = self.rev or self.dirtyRev or "inconnue"; + # Recommandé depuis le passage à 26.05 boot.zfs.forceImportAll = lib.mkDefault false; boot.zfs.forceImportRoot = lib.mkDefault false; diff --git a/modules/services/nginx.nix b/modules/services/nginx.nix index b15423d..ec78fdd 100644 --- a/modules/services/nginx.nix +++ b/modules/services/nginx.nix @@ -6,5 +6,13 @@ recommendedOptimisation = true; clientMaxBodySize = "512M"; + + # On trust nos ip internes pour bien indiquer le client au bout + # i.e. on considère pas le reverseproxy comme notre client + appendHttpConfig = '' + set_real_ip_from 172.16.0.0/16; + set_real_ip_from fd00::/56; + real_ip_header X-Real-Ip; + ''; }; } diff --git a/modules/services/reverseproxy.nix b/modules/services/reverseproxy.nix index 874635e..23146c3 100644 --- a/modules/services/reverseproxy.nix +++ b/modules/services/reverseproxy.nix @@ -20,6 +20,8 @@ let mkOption types ; + + mkHostName = als: tld: if als == "_crans-org" then "crans.${tld}" else "${als}.crans.${tld}"; in { @@ -158,11 +160,19 @@ in }; }; + age.secrets.anubis-secret = { + file = ../../secrets/reverseproxy/anubis-secret.age; + owner = "anubis"; + }; + services = mkIf cfg.enable { anubis = { defaultOptions.group = "nginx"; instances = lib.mapAttrs ( vhostName: vhostConfig: + let + hostname = mkHostName vhostName mainTld; + in mkIf (vhostConfig.anubisConfig != null) { enable = true; settings = { @@ -170,9 +180,14 @@ in BIND_NETWORK = "unix"; METRICS_BIND = "/run/anubis/anubis-${vhostName}/anubis-${vhostName}-metrics.sock"; TARGET = "unix:///run/nginx/nginx-${vhostName}.sock"; - COOKIE_DOMAIN = "crans.${mainTld}"; - REDIRECT_DOMAINS = "${vhostName}.crans.${mainTld}"; + COOKIE_DOMAIN = hostname; + # TODO: db pour mettre en commun les token. + # Transitoirement on les sépare + COOKIE_PREFIX = "anubis-${vhostName}"; + REDIRECT_DOMAINS = hostname; SOCKET_MODE = "0660"; + # Secret partagé entre les instances + ED25519_PRIVATE_KEY_HEX_FILE = config.age.secrets.anubis-secret.path; # OpenGraph config OG_PASSTHROUGH = vhostConfig.anubisOpenGraph; OG_EXPIRY_TIME = "24h"; @@ -215,6 +230,8 @@ in configVhost = vhostName: vhostConfig: let + hostname = mkHostName vhostName mainTld; + sslConf = { forceSSL = !vhostConfig.httpOnly; rejectSSL = vhostConfig.httpOnly; @@ -254,7 +271,6 @@ in ''; # Les alias : vhostName × otherTld U serverAliases × allTld - mkHostName = als: tld: if als == "." then "crans.${tld}" else "${als}.crans.${tld}"; aliases = lib.foldr ( @@ -270,7 +286,7 @@ in { # Configuration du service à proxy. "${vhostName}" = vhostExtraConf // { - serverName = mkHostName vhostName mainTld; + serverName = hostname; locations."/" = mkIf (vhostConfig.proxyPass != null) { proxyPass = "http://${vhostConfig.proxyPass}"; proxyWebsockets = vhostConfig.proxyWebsockets; @@ -283,12 +299,17 @@ in # Entrée d’Anubis "${vhostName}-anubis" = mkIf (vhostConfig.anubisConfig != null) ( entryExtraConf - // { - serverName = mkHostName vhostName mainTld; + // rec { + serverName = hostname; locations."/" = { proxyPass = "http://unix:/run/anubis/anubis-${vhostName}/socket.sock"; proxyWebsockets = vhostConfig.proxyWebsockets; }; + locations."/.within.website/x/cmd/anubis/api/honeypot/" = locations."/" // { + extraConfig = '' + add_header 'X-Robots-Tag' 'noindex,nofollow' always; + ''; + }; extraConfig = entryExtraConf.extraConfig + '' access_log /var/log/nginx/anubis/access.log; error_log /var/log/nginx/anubis/error.log; @@ -301,7 +322,7 @@ in lib.map (alias: { "${vhostName}-alias-${alias}" = sslConf // { serverName = alias; - globalRedirect = lib.defaultTo "${vhostName}.crans.${mainTld}" vhostConfig.globalRedirect; + globalRedirect = lib.defaultTo hostname vhostConfig.globalRedirect; extraConfig = logHostConf; }; }) aliases diff --git a/secrets/nextcloud/nextcloud_ldap_pass.age b/secrets/nextcloud/nextcloud_ldap_pass.age new file mode 100644 index 0000000..57f58dc --- /dev/null +++ b/secrets/nextcloud/nextcloud_ldap_pass.age @@ -0,0 +1,33 @@ +age-encryption.org/v1 +-> ssh-ed25519 APVFfA Z+0daNofon4xgikMa0TUQjUgp9jPPrQkOZJuEJDUmzM +l/QeEQvggQtfgyrDcs9lRpvuFMEgn9i/wQFpuaVoAZ0 +-> piv-p256 ewCc3w AzbC2uqqhtetX1z1XlyVxexejzk8tvPNi/3rcGgOyMSZ +cpl1dYYvqgkXbpvy0JcVabP7Ftb7cGY+IahV/yyDbhs +-> piv-p256 6CL/Pw AixE5HedgCUVyin52g5YHUQFKaSr7hlF9LfsmbQPMf1l +loUpO6pz/Qv+F0mSefpCP3IeDeJ/pq5hYlzacdAtlo4 +-> ssh-ed25519 eOAUSg b49cZWhT7+NLJlrH9EyWu6GPLkST9/T5BGU1azdQoBI +dhzYN+L3k8CZRMbVgff1ofqlImyuD19PUGhhsxTHaMY +-> ssh-rsa REaZBA +CWiPTj/40DTjN2GWUsR92frMYiBP7tfSVADQ/+GCapOMNJD91MGxaiK0IocbJr0P +KpOjfdjRDG8KIYszNgaS8XkHn/CUj2KsnRV2WBg3HWSrMdD4quoOxKWbFaU3b38C +4mUK8gIkjbJFWFMSTOhAexHGYSRLl7fG/0VmRvc2ibs5CahbPsMbFDKuto7ApYhY +e/t5SsYgIkbrNpeTLolO943YCIlU/JVP5XOuEDk1ZlKPRc+igpgqFjsD3LsV56Rr +LFrjp4i5wJeA72HeH/S7nP96sAwxyLDHQrWhw3ntM0n2SRRVCVmLqNNOebUL59gy +HRHHoZosepmHzMEOHQ+CrIxuYMiUQ/AyMkZmMTjxQsLniakJWI06G54f1+aaA0F9 +BhwFateWkLBNdkSdwqJpBAzh427yetzp/bac8dcTv45ylgsvCVSDpoew5NLoIuh5 +I/54NC6Pr5BF0LOW7b2fR9pzk7Rv6hnSxTbeyATeMhh7nTjdcFalUI3Bd1P3RL+i + +-> ssh-ed25519 J/iReg wbkKYkdu/cxnZNEGXH0a5R5jV6cQlMpWFMdQiUpWTiQ +cW3rZQMYrzhx93lsxoPhA8AVQLygKytSue3eEF/yxcc +-> ssh-ed25519 GNhSGw Hd4AOis8kPKDKrOgRZNj9pG0bHFHgLfJwo6sd1/dSFg +07UA5cZbEpf3pA7i04CDX6m9FZF5ahAorfp5GzXJSS4 +-> ssh-ed25519 eXMAtA hZ278rlg0u1Bp8rkEQGFagLYg3lkXK3uSolnUbIy0Bo +k2sPaUhiCCaBUogPxrUk3Fm386DKuR7UBrGMAteykps +-> ssh-ed25519 5hXocQ sYQmrGm4eQlgE4Lkn+ZFE4uI6czxM46SMpQHFRedtQU +cIFA9Vk091Q5hFUUrjf6PRr/WS7XN1BfgpSOZN1m0xI +-> ssh-ed25519 bRHVVA 2n976nXhvJzoFjP+JFe6L1rmCEmTr4YwhTR1rqyA1y4 +/X27rYKrHUB0Jltxc190yPXCiHlOXX3QEXM52BnON60 +-> ssh-ed25519 HgW9eA nNf/0O1vh6+uv5i1+HEy6MgF3VUImMru8BFCcJY7R1s +fPSK5LcFR6WP25nFvJRs9RatiJ4t/LvIFYqdoOYxu/k +--- QKKNQqbCPvtps4QlI3ric0JdAcdJ9g3QkTPj+RUGAis +[xqZ†ÿ¥ªSD’ˆcO ÌfkŠÖý ”N¹±›;�H]IòÉ£ÖùÎA‘€A \ No newline at end of file diff --git a/secrets/reverseproxy/anubis-secret.age b/secrets/reverseproxy/anubis-secret.age new file mode 100644 index 0000000..578c302 --- /dev/null +++ b/secrets/reverseproxy/anubis-secret.age @@ -0,0 +1,33 @@ +age-encryption.org/v1 +-> ssh-ed25519 GCcVXA qD1f4YdP88JvuPLS6H416O0LF+rKN/gJ+gPf0lFWIRs +B0LuHjXX0UiHHTwY7v1HqP4VF5/5yn0d/gNW4zUOC5w +-> piv-p256 ewCc3w A8Wnjz7tLNpV/m5bUzuq/MBTHn+jQiaCSUb4vFvGDH7N +gNBEsgdHogaz3OSJBelB39bGrOBt8+hkNXpAYcFcy28 +-> piv-p256 6CL/Pw AoJBcpyhK+hpZOfHOBUHh0Kivvn6YJ4xepo7IWppbMuJ +f1fwsu8okH7F+6nSHowxHpTdtjU72lvd6FmwFIMmV8E +-> ssh-ed25519 eOAUSg 0bH2dDdNzKapr54HKndKJpKO5iTQtbhY957NIJQcvBo +LYVsTuKNsE4JlBxbf2e+Qo9ZjRxnz6saEHEjyfCcAjc +-> ssh-rsa REaZBA +Pho7O15lWd5/2Uy1OQmA/JzE0wmOji6IPKGj03nK9aYSQjsTTc30YhNCrkddglGX +MCClDyGDlQ0mCwHKVfpFeeSC9VQWQDDYk90dM4MF//6hHPqU/zn8dR25NyxDgyyi +DVrCFB+S09LsKI4isbDoCru6fWXfdN4Fj8I44c64dBpIVh4XhSzUtmlzmge//35C +y6EvAjVIhVTbbgnQ5CJFgnRlSPaN5BHDq76aJ3c+8Ajkjowa2YcYu7w8asi7PsIs +WH6J2qMIPvPdxOEKczGc401ysUfz9fNFKs0Xx4spduwv8I3Sv4ImURDkYmCl/k7J +rwRXbUGr8JzZu093cmkjVxDrSfb9VhqlZVJD7uc2VSTk8ntwStLWafSuE03bIN2L +on0t/4/wXtvFtwlGoDe9QGYAJpPYWM0ZUPMZfpddOz9vYvL1+6nUcDroLMvCIItI +blwJZ0970K/Je99SmI3+6mUEAw8nJ/pBFaF/LmTJecypLEalLNsu2IALyCMIdTa0 + +-> ssh-ed25519 J/iReg fpgi4t31rVl+KvOYd0Ph0Nd2gInJAZXNhQC5ekpv0kI +lznh3YwmqVr05vjWxf1HKRWAFZGXbypAYygjUe+ELlk +-> ssh-ed25519 GNhSGw 2cVptD/h5NWcYsjPPwQcP/b9tjJPDbhjDKh2hKhA5GM +JZvQvXkb1RRw+NHnJ+HMV5tlwiBnLf4+cwm6J2hZD9Y +-> ssh-ed25519 eXMAtA axP3hHgfgWJScGLIGpYgu0iYW1qZRQzMK9XjIeszrnc +rBzAqSVoRqj/drZSOlxSIZLgZZU/wqGML1gKCEHtcy4 +-> ssh-ed25519 5hXocQ b3kjoM+FfQ434V7X8FdpIHVFjTn4sc+psj+9jyRljxU +l5rna7ap0ydVXPCSr4qrPnu2MV2n7XwoSh/T87OkuMU +-> ssh-ed25519 bRHVVA 92Rj1gMmueSHWzxsKWVs+7nF4JzuekhfaB2u5AWnazk +yg4qa9lyHsGCOXWOTm7/XH9F8JzvRLjzsxyXe88oXnE +-> ssh-ed25519 HgW9eA mpIFRqMXj08JuyYLf6Hx4p9fOLbxXZquSMAjh0e/lSU +h1kvwnu+mLOeRfVFUXgE9IDo/MQ+4gtkYwrF3JWQfwY +--- MCDm2NH5NWgwnFYQ+zJ4obfdxWpiv3BGohnIJ1bRkco +_Ö¹`ðãFËÉÑvF3[;œç197%»4¼90MÞ[ï¼Ip¢:Ÿs|ÈñC�RÃ6,CÔè÷;á[³;<§Éû¤b(´fqÀg8îp÷p÷ ÷Dk p/ÐwîÒ¿$9Ý\ \ No newline at end of file