From 79d2de8b83d765721b2cb720b2bc59673df54a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isma=C3=ABl=20Bouya?= Date: Tue, 7 May 2019 15:07:00 +0200 Subject: Move directories with only default.nix to standalone file --- nixops/eldiron.nix | 12 +- nixops/modules/dns.nix | 132 +++++++++++ nixops/modules/dns/default.nix | 132 ----------- nixops/modules/ftp.nix | 118 ++++++++++ nixops/modules/ftp/default.nix | 118 ---------- nixops/modules/irc.nix | 48 ++++ nixops/modules/irc/default.nix | 48 ---- nixops/modules/mail.nix | 15 ++ nixops/modules/mail/default.nix | 15 -- nixops/modules/mpd.nix | 58 +++++ nixops/modules/mpd/default.nix | 58 ----- nixops/modules/secrets.nix | 55 +++++ nixops/modules/secrets/default.nix | 55 ----- nixops/modules/websites/default.nix | 10 +- nixops/modules/websites/tools/cloud.nix | 189 ++++++++++++++++ nixops/modules/websites/tools/cloud/default.nix | 189 ---------------- nixops/modules/websites/tools/db.nix | 22 ++ nixops/modules/websites/tools/db/default.nix | 22 -- nixops/modules/websites/tools/diaspora.nix | 249 ++++++++++++++++++++ nixops/modules/websites/tools/diaspora/default.nix | 249 -------------------- nixops/modules/websites/tools/mastodon.nix | 249 ++++++++++++++++++++ nixops/modules/websites/tools/mastodon/default.nix | 249 -------------------- nixops/modules/websites/tools/mediagoblin.nix | 251 +++++++++++++++++++++ .../modules/websites/tools/mediagoblin/default.nix | 251 --------------------- 24 files changed, 1397 insertions(+), 1397 deletions(-) create mode 100644 nixops/modules/dns.nix delete mode 100644 nixops/modules/dns/default.nix create mode 100644 nixops/modules/ftp.nix delete mode 100644 nixops/modules/ftp/default.nix create mode 100644 nixops/modules/irc.nix delete mode 100644 nixops/modules/irc/default.nix create mode 100644 nixops/modules/mail.nix delete mode 100644 nixops/modules/mail/default.nix create mode 100644 nixops/modules/mpd.nix delete mode 100644 nixops/modules/mpd/default.nix create mode 100644 nixops/modules/secrets.nix delete mode 100644 nixops/modules/secrets/default.nix create mode 100644 nixops/modules/websites/tools/cloud.nix delete mode 100644 nixops/modules/websites/tools/cloud/default.nix create mode 100644 nixops/modules/websites/tools/db.nix delete mode 100644 nixops/modules/websites/tools/db/default.nix create mode 100644 nixops/modules/websites/tools/diaspora.nix delete mode 100644 nixops/modules/websites/tools/diaspora/default.nix create mode 100644 nixops/modules/websites/tools/mastodon.nix delete mode 100644 nixops/modules/websites/tools/mastodon/default.nix create mode 100644 nixops/modules/websites/tools/mediagoblin.nix delete mode 100644 nixops/modules/websites/tools/mediagoblin/default.nix (limited to 'nixops') diff --git a/nixops/eldiron.nix b/nixops/eldiron.nix index d62f022..239e065 100644 --- a/nixops/eldiron.nix +++ b/nixops/eldiron.nix @@ -36,16 +36,16 @@ ./modules/certificates.nix ./modules/gitolite ./modules/databases - ./modules/mpd + ./modules/mpd.nix ./modules/websites - ./modules/mail - ./modules/ftp + ./modules/mail.nix + ./modules/ftp.nix ./modules/pub ./modules/task - ./modules/irc + ./modules/irc.nix ./modules/buildbot - ./modules/dns - ./modules/secrets + ./modules/dns.nix + ./modules/secrets.nix ]; services.myGitolite.enable = true; services.myDatabases.enable = true; diff --git a/nixops/modules/dns.nix b/nixops/modules/dns.nix new file mode 100644 index 0000000..0096f55 --- /dev/null +++ b/nixops/modules/dns.nix @@ -0,0 +1,132 @@ +{ lib, pkgs, config, myconfig, mylibs, ... }: +{ + config = let + cfg = config.services.bind; + configFile = pkgs.writeText "named.conf" '' + include "/etc/bind/rndc.key"; + controls { + inet 127.0.0.1 allow {localhost;} keys {"rndc-key";}; + }; + + acl cachenetworks { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.cacheNetworks} }; + acl badnetworks { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.blockedNetworks} }; + + options { + listen-on { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.listenOn} }; + listen-on-v6 { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.listenOnIpv6} }; + allow-query { cachenetworks; }; + blackhole { badnetworks; }; + forward first; + forwarders { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.forwarders} }; + directory "/var/run/named"; + pid-file "/var/run/named/named.pid"; + ${cfg.extraOptions} + }; + + ${cfg.extraConfig} + + ${ lib.concatMapStrings + ({ name, file, master ? true, extra ? "", slaves ? [], masters ? [] }: + '' + zone "${name}" { + type ${if master then "master" else "slave"}; + file "${file}"; + ${ if lib.lists.length slaves > 0 then + '' + allow-transfer { + ${lib.concatMapStrings (ip: "${ip};\n") slaves} + }; + '' else ""} + ${ if lib.lists.length masters > 0 then + '' + masters { + ${lib.concatMapStrings (ip: "${ip};\n") masters} + }; + '' else ""} + allow-query { any; }; + ${extra} + }; + '') + cfg.zones } + ''; + in + { + networking.firewall.allowedUDPPorts = [ 53 ]; + networking.firewall.allowedTCPPorts = [ 53 ]; + services.bind = { + enable = true; + cacheNetworks = ["any"]; + configFile = configFile; + extraOptions = '' + allow-recursion { 127.0.0.1; }; + allow-transfer { none; }; + + notify-source ${myconfig.env.servers.eldiron.ips.main.ip4}; + notify-source-v6 ${lib.head myconfig.env.servers.eldiron.ips.main.ip6}; + version none; + hostname none; + server-id none; + ''; + zones = with myconfig.env.dns; + assert (builtins.substring ((builtins.stringLength soa.email)-1) 1 soa.email) != "."; + assert (builtins.substring ((builtins.stringLength soa.primary)-1) 1 soa.primary) != "."; + (map (conf: { + name = conf.name; + master = false; + file = "/var/run/named/${conf.name}.zone"; + masters = if lib.attrsets.hasAttr "masters" conf + then lib.lists.flatten (map (n: lib.attrsets.attrValues ns.${n}) conf.masters) + else []; + }) slaveZones) + ++ (map (conf: { + name = conf.name; + master = true; + extra = if lib.attrsets.hasAttr "extra" conf then conf.extra else ""; + slaves = if lib.attrsets.hasAttr "slaves" conf + then lib.lists.flatten (map (n: lib.attrsets.attrValues ns.${n}) conf.slaves) + else []; + file = pkgs.writeText "${conf.name}.zone" '' + $TTL 10800 + @ IN SOA ${soa.primary}. ${builtins.replaceStrings ["@"] ["."] soa.email}. ${soa.serial} ${soa.refresh} ${soa.retry} ${soa.expire} ${soa.ttl} + + ${lib.concatStringsSep "\n" (map (x: "@ IN NS ${x}.") (lib.concatMap (n: lib.attrsets.mapAttrsToList (k: v: k) ns.${n}) conf.ns))} + + ${conf.entries} + + ${if lib.attrsets.hasAttr "withEmail" conf && lib.lists.length conf.withEmail > 0 then '' + mail IN A ${myconfig.env.servers.immaeEu.ips.main.ip4} + mx-1 IN A ${myconfig.env.servers.eldiron.ips.main.ip4} + ${builtins.concatStringsSep "\n" (map (i: "mail IN AAAA ${i}") myconfig.env.servers.immaeEu.ips.main.ip6)} + ${builtins.concatStringsSep "\n" (map (i: "mx-1 IN AAAA ${i}") myconfig.env.servers.eldiron.ips.main.ip6)} + ${lib.concatStringsSep "\n\n" (map (e: + let + n = if e.domain == "" then "@" else "${e.domain} "; + suffix = if e.domain == "" then "" else ".${e.domain}"; + in + '' + ; ------------------ mail: ${n} --------------------------- + ${if e.receive then "${n} IN MX 10 mail.${conf.name}." else ""} + ;${if e.receive then "${n} IN MX 50 mx-1.${conf.name}." else ""} + + ; Mail sender authentications + ${n} IN TXT "v=spf1 mx ~all" + _dmarc${suffix} IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; fo=1; rua=mailto:postmaster+rua@immae.eu; ruf=mailto:postmaster+ruf@immae.eu;" + ${if e.send then '' + immae_eu._domainkey${suffix} IN TXT ( "v=DKIM1; k=rsa; s=email; " + "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzl3vLd8W5YAuumC5+ZT9OV7/14Pmh5JYtwyqKI3cfe9NnAqInt3xO4bZ7oqIxRKWN4SD39vm7O/QOvFdBt00ENOOzdP90s5gKw6eIP/4+vPTh0IWltAsmu9B2agzdtWUE7t2xFKIzEn8l9niRE2QYbVaqZv4sub98vY55fIgFoHtjkmNC7325S8fjDJGp6OPbyhAs6Xl5/adjF" + "0ko4Y2p6RaxLQfjlS0bxmK4Qg6C14pIXHtzVeqOuWrwApqt5+AULSn97iUtqV/IJlEEjC6DUR44t3C/G0G/k46iFclCqRRi0hdPrOHCtZDbtMubnTN9eaUiNpkXh1WnCflHwtjQwIDAQAB" ) + '' else ""} + '') conf.withEmail)} + '' + (if conf.name == "immae.eu" then '' + ; ----------------- Accept DMARC reports ------------------- + ${lib.concatStringsSep "\n" ( + lib.flatten ( + map (z: map (e: "${e.domain}${if builtins.stringLength e.domain > 0 then "." else ""}${z.name}._report._dmarc IN TXT \"v=DMARC1;\"") (z.withEmail or [])) masterZones + ) + )} + '' else "") else ""} + ''; + }) masterZones); + }; + }; +} diff --git a/nixops/modules/dns/default.nix b/nixops/modules/dns/default.nix deleted file mode 100644 index 0096f55..0000000 --- a/nixops/modules/dns/default.nix +++ /dev/null @@ -1,132 +0,0 @@ -{ lib, pkgs, config, myconfig, mylibs, ... }: -{ - config = let - cfg = config.services.bind; - configFile = pkgs.writeText "named.conf" '' - include "/etc/bind/rndc.key"; - controls { - inet 127.0.0.1 allow {localhost;} keys {"rndc-key";}; - }; - - acl cachenetworks { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.cacheNetworks} }; - acl badnetworks { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.blockedNetworks} }; - - options { - listen-on { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.listenOn} }; - listen-on-v6 { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.listenOnIpv6} }; - allow-query { cachenetworks; }; - blackhole { badnetworks; }; - forward first; - forwarders { ${lib.concatMapStrings (entry: " ${entry}; ") cfg.forwarders} }; - directory "/var/run/named"; - pid-file "/var/run/named/named.pid"; - ${cfg.extraOptions} - }; - - ${cfg.extraConfig} - - ${ lib.concatMapStrings - ({ name, file, master ? true, extra ? "", slaves ? [], masters ? [] }: - '' - zone "${name}" { - type ${if master then "master" else "slave"}; - file "${file}"; - ${ if lib.lists.length slaves > 0 then - '' - allow-transfer { - ${lib.concatMapStrings (ip: "${ip};\n") slaves} - }; - '' else ""} - ${ if lib.lists.length masters > 0 then - '' - masters { - ${lib.concatMapStrings (ip: "${ip};\n") masters} - }; - '' else ""} - allow-query { any; }; - ${extra} - }; - '') - cfg.zones } - ''; - in - { - networking.firewall.allowedUDPPorts = [ 53 ]; - networking.firewall.allowedTCPPorts = [ 53 ]; - services.bind = { - enable = true; - cacheNetworks = ["any"]; - configFile = configFile; - extraOptions = '' - allow-recursion { 127.0.0.1; }; - allow-transfer { none; }; - - notify-source ${myconfig.env.servers.eldiron.ips.main.ip4}; - notify-source-v6 ${lib.head myconfig.env.servers.eldiron.ips.main.ip6}; - version none; - hostname none; - server-id none; - ''; - zones = with myconfig.env.dns; - assert (builtins.substring ((builtins.stringLength soa.email)-1) 1 soa.email) != "."; - assert (builtins.substring ((builtins.stringLength soa.primary)-1) 1 soa.primary) != "."; - (map (conf: { - name = conf.name; - master = false; - file = "/var/run/named/${conf.name}.zone"; - masters = if lib.attrsets.hasAttr "masters" conf - then lib.lists.flatten (map (n: lib.attrsets.attrValues ns.${n}) conf.masters) - else []; - }) slaveZones) - ++ (map (conf: { - name = conf.name; - master = true; - extra = if lib.attrsets.hasAttr "extra" conf then conf.extra else ""; - slaves = if lib.attrsets.hasAttr "slaves" conf - then lib.lists.flatten (map (n: lib.attrsets.attrValues ns.${n}) conf.slaves) - else []; - file = pkgs.writeText "${conf.name}.zone" '' - $TTL 10800 - @ IN SOA ${soa.primary}. ${builtins.replaceStrings ["@"] ["."] soa.email}. ${soa.serial} ${soa.refresh} ${soa.retry} ${soa.expire} ${soa.ttl} - - ${lib.concatStringsSep "\n" (map (x: "@ IN NS ${x}.") (lib.concatMap (n: lib.attrsets.mapAttrsToList (k: v: k) ns.${n}) conf.ns))} - - ${conf.entries} - - ${if lib.attrsets.hasAttr "withEmail" conf && lib.lists.length conf.withEmail > 0 then '' - mail IN A ${myconfig.env.servers.immaeEu.ips.main.ip4} - mx-1 IN A ${myconfig.env.servers.eldiron.ips.main.ip4} - ${builtins.concatStringsSep "\n" (map (i: "mail IN AAAA ${i}") myconfig.env.servers.immaeEu.ips.main.ip6)} - ${builtins.concatStringsSep "\n" (map (i: "mx-1 IN AAAA ${i}") myconfig.env.servers.eldiron.ips.main.ip6)} - ${lib.concatStringsSep "\n\n" (map (e: - let - n = if e.domain == "" then "@" else "${e.domain} "; - suffix = if e.domain == "" then "" else ".${e.domain}"; - in - '' - ; ------------------ mail: ${n} --------------------------- - ${if e.receive then "${n} IN MX 10 mail.${conf.name}." else ""} - ;${if e.receive then "${n} IN MX 50 mx-1.${conf.name}." else ""} - - ; Mail sender authentications - ${n} IN TXT "v=spf1 mx ~all" - _dmarc${suffix} IN TXT "v=DMARC1; p=none; adkim=r; aspf=r; fo=1; rua=mailto:postmaster+rua@immae.eu; ruf=mailto:postmaster+ruf@immae.eu;" - ${if e.send then '' - immae_eu._domainkey${suffix} IN TXT ( "v=DKIM1; k=rsa; s=email; " - "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzl3vLd8W5YAuumC5+ZT9OV7/14Pmh5JYtwyqKI3cfe9NnAqInt3xO4bZ7oqIxRKWN4SD39vm7O/QOvFdBt00ENOOzdP90s5gKw6eIP/4+vPTh0IWltAsmu9B2agzdtWUE7t2xFKIzEn8l9niRE2QYbVaqZv4sub98vY55fIgFoHtjkmNC7325S8fjDJGp6OPbyhAs6Xl5/adjF" - "0ko4Y2p6RaxLQfjlS0bxmK4Qg6C14pIXHtzVeqOuWrwApqt5+AULSn97iUtqV/IJlEEjC6DUR44t3C/G0G/k46iFclCqRRi0hdPrOHCtZDbtMubnTN9eaUiNpkXh1WnCflHwtjQwIDAQAB" ) - '' else ""} - '') conf.withEmail)} - '' + (if conf.name == "immae.eu" then '' - ; ----------------- Accept DMARC reports ------------------- - ${lib.concatStringsSep "\n" ( - lib.flatten ( - map (z: map (e: "${e.domain}${if builtins.stringLength e.domain > 0 then "." else ""}${z.name}._report._dmarc IN TXT \"v=DMARC1;\"") (z.withEmail or [])) masterZones - ) - )} - '' else "") else ""} - ''; - }) masterZones); - }; - }; -} diff --git a/nixops/modules/ftp.nix b/nixops/modules/ftp.nix new file mode 100644 index 0000000..541e119 --- /dev/null +++ b/nixops/modules/ftp.nix @@ -0,0 +1,118 @@ +{ lib, pkgs, config, myconfig, ... }: +{ + options = { + services.pure-ftpd.enable = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether to enable pure-ftpd. + ''; + }; + }; + + config = lib.mkIf config.services.pure-ftpd.enable { + security.acme.certs."ftp" = config.services.myCertificates.certConfig // { + domain = "eldiron.immae.eu"; + postRun = '' + systemctl restart pure-ftpd.service + ''; + extraDomains = { "ftp.immae.eu" = null; }; + }; + + networking = { + firewall = { + allowedTCPPorts = [ 21 ]; + allowedTCPPortRanges = [ { from = 40000; to = 50000; } ]; + }; + }; + + users.users = [ + { + name = "ftp"; + uid = config.ids.uids.ftp; # 8 + group = "ftp"; + description = "Anonymous FTP user"; + home = "/homeless-shelter"; + extraGroups = [ "keys" ]; + } + ]; + + users.groups.ftp.gid = config.ids.gids.ftp; + + system.activationScripts.pure-ftpd = '' + install -m 0755 -o ftp -g ftp -d /var/lib/ftp + ''; + + mySecrets.keys = [{ + dest = "pure-ftpd-ldap"; + permissions = "0400"; + user = "ftp"; + group = "ftp"; + text = '' + LDAPServer ${myconfig.env.ftp.ldap.host} + LDAPPort 389 + LDAPUseTLS True + LDAPBaseDN ${myconfig.env.ftp.ldap.base} + LDAPBindDN ${myconfig.env.ftp.ldap.dn} + LDAPBindPW ${myconfig.env.ftp.ldap.password} + LDAPDefaultUID 500 + LDAPForceDefaultUID False + LDAPDefaultGID 100 + LDAPForceDefaultGID False + LDAPFilter ${myconfig.env.ftp.ldap.filter} + + LDAPAuthMethod BIND + + # Pas de possibilite de donner l'Uid/Gid ! + # Compile dans pure-ftpd directement avec immaeFtpUid / immaeFtpGid + LDAPHomeDir immaeFtpDirectory + ''; + }]; + + systemd.services.pure-ftpd = let + configFile = pkgs.writeText "pure-ftpd.conf" '' + PassivePortRange 40000 50000 + ChrootEveryone yes + CreateHomeDir yes + BrokenClientsCompatibility yes + MaxClientsNumber 50 + Daemonize yes + MaxClientsPerIP 8 + VerboseLog no + DisplayDotFiles yes + AnonymousOnly no + NoAnonymous no + SyslogFacility ftp + DontResolve yes + MaxIdleTime 15 + LDAPConfigFile /var/secrets/pure-ftpd-ldap + LimitRecursion 10000 8 + AnonymousCanCreateDirs no + MaxLoad 4 + AntiWarez yes + Umask 133:022 + # ftp + MinUID 8 + AllowUserFXP no + AllowAnonymousFXP no + ProhibitDotFilesWrite no + ProhibitDotFilesRead no + AutoRename no + AnonymousCantUpload no + MaxDiskUsage 99 + CustomerProof yes + TLS 1 + CertFile /var/lib/acme/ftp/full.pem + ''; + in { + description = "Pure-FTPd server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig.ExecStart = "${pkgs.pure-ftpd}/bin/pure-ftpd ${configFile}"; + serviceConfig.Type = "forking"; + serviceConfig.PIDFile = "/run/pure-ftpd.pid"; + }; + }; + +} diff --git a/nixops/modules/ftp/default.nix b/nixops/modules/ftp/default.nix deleted file mode 100644 index 541e119..0000000 --- a/nixops/modules/ftp/default.nix +++ /dev/null @@ -1,118 +0,0 @@ -{ lib, pkgs, config, myconfig, ... }: -{ - options = { - services.pure-ftpd.enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Whether to enable pure-ftpd. - ''; - }; - }; - - config = lib.mkIf config.services.pure-ftpd.enable { - security.acme.certs."ftp" = config.services.myCertificates.certConfig // { - domain = "eldiron.immae.eu"; - postRun = '' - systemctl restart pure-ftpd.service - ''; - extraDomains = { "ftp.immae.eu" = null; }; - }; - - networking = { - firewall = { - allowedTCPPorts = [ 21 ]; - allowedTCPPortRanges = [ { from = 40000; to = 50000; } ]; - }; - }; - - users.users = [ - { - name = "ftp"; - uid = config.ids.uids.ftp; # 8 - group = "ftp"; - description = "Anonymous FTP user"; - home = "/homeless-shelter"; - extraGroups = [ "keys" ]; - } - ]; - - users.groups.ftp.gid = config.ids.gids.ftp; - - system.activationScripts.pure-ftpd = '' - install -m 0755 -o ftp -g ftp -d /var/lib/ftp - ''; - - mySecrets.keys = [{ - dest = "pure-ftpd-ldap"; - permissions = "0400"; - user = "ftp"; - group = "ftp"; - text = '' - LDAPServer ${myconfig.env.ftp.ldap.host} - LDAPPort 389 - LDAPUseTLS True - LDAPBaseDN ${myconfig.env.ftp.ldap.base} - LDAPBindDN ${myconfig.env.ftp.ldap.dn} - LDAPBindPW ${myconfig.env.ftp.ldap.password} - LDAPDefaultUID 500 - LDAPForceDefaultUID False - LDAPDefaultGID 100 - LDAPForceDefaultGID False - LDAPFilter ${myconfig.env.ftp.ldap.filter} - - LDAPAuthMethod BIND - - # Pas de possibilite de donner l'Uid/Gid ! - # Compile dans pure-ftpd directement avec immaeFtpUid / immaeFtpGid - LDAPHomeDir immaeFtpDirectory - ''; - }]; - - systemd.services.pure-ftpd = let - configFile = pkgs.writeText "pure-ftpd.conf" '' - PassivePortRange 40000 50000 - ChrootEveryone yes - CreateHomeDir yes - BrokenClientsCompatibility yes - MaxClientsNumber 50 - Daemonize yes - MaxClientsPerIP 8 - VerboseLog no - DisplayDotFiles yes - AnonymousOnly no - NoAnonymous no - SyslogFacility ftp - DontResolve yes - MaxIdleTime 15 - LDAPConfigFile /var/secrets/pure-ftpd-ldap - LimitRecursion 10000 8 - AnonymousCanCreateDirs no - MaxLoad 4 - AntiWarez yes - Umask 133:022 - # ftp - MinUID 8 - AllowUserFXP no - AllowAnonymousFXP no - ProhibitDotFilesWrite no - ProhibitDotFilesRead no - AutoRename no - AnonymousCantUpload no - MaxDiskUsage 99 - CustomerProof yes - TLS 1 - CertFile /var/lib/acme/ftp/full.pem - ''; - in { - description = "Pure-FTPd server"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - serviceConfig.ExecStart = "${pkgs.pure-ftpd}/bin/pure-ftpd ${configFile}"; - serviceConfig.Type = "forking"; - serviceConfig.PIDFile = "/run/pure-ftpd.pid"; - }; - }; - -} diff --git a/nixops/modules/irc.nix b/nixops/modules/irc.nix new file mode 100644 index 0000000..6500ca5 --- /dev/null +++ b/nixops/modules/irc.nix @@ -0,0 +1,48 @@ +{ lib, pkgs, config, myconfig, mylibs, ... }: +{ + options = { + services.irc.enable = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Whether to enable irc stuff. + ''; + }; + }; + + config = lib.mkIf config.services.irc.enable { + security.acme.certs."irc" = config.services.myCertificates.certConfig // { + domain = "irc.immae.eu"; + postRun = '' + systemctl restart stunnel.service + ''; + }; + + networking.firewall.allowedTCPPorts = [ 6697 ]; + services.bitlbee = { + enable = true; + authMode = "Registered"; + libpurple_plugins = [ + pkgs.purple-hangouts + pkgs.purple-matrix + ]; + plugins = [ + pkgs.bitlbee-mastodon + pkgs.bitlbee-facebook + pkgs.bitlbee-discord + pkgs.bitlbee-steam + ]; + }; + + services.stunnel = { + enable = true; + servers = { + bitlbee = { + accept = 6697; + connect = 6667; + cert = "/var/lib/acme/irc/full.pem"; + }; + }; + }; + }; +} diff --git a/nixops/modules/irc/default.nix b/nixops/modules/irc/default.nix deleted file mode 100644 index 6500ca5..0000000 --- a/nixops/modules/irc/default.nix +++ /dev/null @@ -1,48 +0,0 @@ -{ lib, pkgs, config, myconfig, mylibs, ... }: -{ - options = { - services.irc.enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Whether to enable irc stuff. - ''; - }; - }; - - config = lib.mkIf config.services.irc.enable { - security.acme.certs."irc" = config.services.myCertificates.certConfig // { - domain = "irc.immae.eu"; - postRun = '' - systemctl restart stunnel.service - ''; - }; - - networking.firewall.allowedTCPPorts = [ 6697 ]; - services.bitlbee = { - enable = true; - authMode = "Registered"; - libpurple_plugins = [ - pkgs.purple-hangouts - pkgs.purple-matrix - ]; - plugins = [ - pkgs.bitlbee-mastodon - pkgs.bitlbee-facebook - pkgs.bitlbee-discord - pkgs.bitlbee-steam - ]; - }; - - services.stunnel = { - enable = true; - servers = { - bitlbee = { - accept = 6697; - connect = 6667; - cert = "/var/lib/acme/irc/full.pem"; - }; - }; - }; - }; -} diff --git a/nixops/modules/mail.nix b/nixops/modules/mail.nix new file mode 100644 index 0000000..6ec9165 --- /dev/null +++ b/nixops/modules/mail.nix @@ -0,0 +1,15 @@ +{ lib, pkgs, config, myconfig, mylibs, ... }: +{ + config.ids.uids.nullmailer = myconfig.env.users.nullmailer.uid; + config.ids.gids.nullmailer = myconfig.env.users.nullmailer.gid; + config.users.users.nullmailer.uid = config.ids.uids.nullmailer; + config.users.groups.nullmailer.gid = config.ids.gids.nullmailer; + + config.services.nullmailer = { + enable = true; + config = { + me = myconfig.env.mail.host; + remotes = "${myconfig.env.mail.relay} smtp"; + }; + }; +} diff --git a/nixops/modules/mail/default.nix b/nixops/modules/mail/default.nix deleted file mode 100644 index 6ec9165..0000000 --- a/nixops/modules/mail/default.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ lib, pkgs, config, myconfig, mylibs, ... }: -{ - config.ids.uids.nullmailer = myconfig.env.users.nullmailer.uid; - config.ids.gids.nullmailer = myconfig.env.users.nullmailer.gid; - config.users.users.nullmailer.uid = config.ids.uids.nullmailer; - config.users.groups.nullmailer.gid = config.ids.gids.nullmailer; - - config.services.nullmailer = { - enable = true; - config = { - me = myconfig.env.mail.host; - remotes = "${myconfig.env.mail.relay} smtp"; - }; - }; -} diff --git a/nixops/modules/mpd.nix b/nixops/modules/mpd.nix new file mode 100644 index 0000000..7c896ca --- /dev/null +++ b/nixops/modules/mpd.nix @@ -0,0 +1,58 @@ +{ lib, pkgs, config, myconfig, mylibs, ... }: +{ + config = { + mySecrets.keys = [ + { + dest = "mpd"; + permissions = "0400"; + text = myconfig.env.mpd.password; + } + { + dest = "mpd-config"; + permissions = "0400"; + user = "mpd"; + group = "mpd"; + text = '' + password "${myconfig.env.mpd.password}@read,add,control,admin" + ''; + } + ]; + networking.firewall.allowedTCPPorts = [ 6600 ]; + users.users.mpd.extraGroups = [ "wwwrun" "keys" ]; + system.activationScripts.mpd = '' + install -d -m 0755 -o mpd -g mpd /run/mpd + ''; + services.mpd = { + enable = true; + network.listenAddress = "any"; + musicDirectory = myconfig.env.mpd.folder; + extraConfig = '' + include "/var/secrets/mpd-config" + audio_output { + type "null" + name "No Output" + mixer_type "none" + } + audio_output { + type "httpd" + name "OGG" + encoder "vorbis" + bind_to_address "/run/mpd/ogg.sock" + quality "5.0" + format "44100:16:1" + } + audio_output { + type "httpd" + name "MP3" + encoder "lame" + bind_to_address "/run/mpd/mp3.sock" + quality "5.0" + format "44100:16:1" + } + + + ''; + }; + }; +} + diff --git a/nixops/modules/mpd/default.nix b/nixops/modules/mpd/default.nix deleted file mode 100644 index 7c896ca..0000000 --- a/nixops/modules/mpd/default.nix +++ /dev/null @@ -1,58 +0,0 @@ -{ lib, pkgs, config, myconfig, mylibs, ... }: -{ - config = { - mySecrets.keys = [ - { - dest = "mpd"; - permissions = "0400"; - text = myconfig.env.mpd.password; - } - { - dest = "mpd-config"; - permissions = "0400"; - user = "mpd"; - group = "mpd"; - text = '' - password "${myconfig.env.mpd.password}@read,add,control,admin" - ''; - } - ]; - networking.firewall.allowedTCPPorts = [ 6600 ]; - users.users.mpd.extraGroups = [ "wwwrun" "keys" ]; - system.activationScripts.mpd = '' - install -d -m 0755 -o mpd -g mpd /run/mpd - ''; - services.mpd = { - enable = true; - network.listenAddress = "any"; - musicDirectory = myconfig.env.mpd.folder; - extraConfig = '' - include "/var/secrets/mpd-config" - audio_output { - type "null" - name "No Output" - mixer_type "none" - } - audio_output { - type "httpd" - name "OGG" - encoder "vorbis" - bind_to_address "/run/mpd/ogg.sock" - quality "5.0" - format "44100:16:1" - } - audio_output { - type "httpd" - name "MP3" - encoder "lame" - bind_to_address "/run/mpd/mp3.sock" - quality "5.0" - format "44100:16:1" - } - - - ''; - }; - }; -} - diff --git a/nixops/modules/secrets.nix b/nixops/modules/secrets.nix new file mode 100644 index 0000000..8500088 --- /dev/null +++ b/nixops/modules/secrets.nix @@ -0,0 +1,55 @@ +{ lib, pkgs, config, myconfig, mylibs, ... }: +{ + options.mySecrets = { + keys = lib.mkOption { + type = lib.types.listOf lib.types.unspecified; + default = {}; + description = "Keys to upload to server"; + }; + }; + config = let + keys = config.mySecrets.keys; + empty = pkgs.runCommand "empty" { preferLocalBuild = true; } "mkdir -p $out && touch $out/done"; + dumpKey = v: '' + mkdir -p secrets/$(dirname ${v.dest}) + echo -n ${lib.strings.escapeShellArg v.text} > secrets/${v.dest} + cat >> mods < /var/secrets/currentSecrets + find /var/secrets -type d -exec chown root:keys {} \; -exec chmod o-rx {} \; + fi + fi + ''; + }; + deployment.keys."secrets.tar" = { + permissions = "0400"; + # keyFile below is not evaluated at build time by nixops, so the + # `secrets` path doesn’t necessarily exist when uploading the + # keys, and nixops is unhappy. + user = "root${builtins.substring 10000 1 secrets}"; + group = "root"; + keyFile = "${secrets}"; + }; + }; +} diff --git a/nixops/modules/secrets/default.nix b/nixops/modules/secrets/default.nix deleted file mode 100644 index 8500088..0000000 --- a/nixops/modules/secrets/default.nix +++ /dev/null @@ -1,55 +0,0 @@ -{ lib, pkgs, config, myconfig, mylibs, ... }: -{ - options.mySecrets = { - keys = lib.mkOption { - type = lib.types.listOf lib.types.unspecified; - default = {}; - description = "Keys to upload to server"; - }; - }; - config = let - keys = config.mySecrets.keys; - empty = pkgs.runCommand "empty" { preferLocalBuild = true; } "mkdir -p $out && touch $out/done"; - dumpKey = v: '' - mkdir -p secrets/$(dirname ${v.dest}) - echo -n ${lib.strings.escapeShellArg v.text} > secrets/${v.dest} - cat >> mods < /var/secrets/currentSecrets - find /var/secrets -type d -exec chown root:keys {} \; -exec chmod o-rx {} \; - fi - fi - ''; - }; - deployment.keys."secrets.tar" = { - permissions = "0400"; - # keyFile below is not evaluated at build time by nixops, so the - # `secrets` path doesn’t necessarily exist when uploading the - # keys, and nixops is unhappy. - user = "root${builtins.substring 10000 1 secrets}"; - group = "root"; - keyFile = "${secrets}"; - }; - }; -} diff --git a/nixops/modules/websites/default.nix b/nixops/modules/websites/default.nix index 028f60b..06face1 100644 --- a/nixops/modules/websites/default.nix +++ b/nixops/modules/websites/default.nix @@ -121,14 +121,14 @@ in ./ftp/immae.nix ./ftp/release.nix ./ftp/temp.nix - ./tools/db + ./tools/db.nix ./tools/tools ./tools/dav - ./tools/cloud + ./tools/cloud.nix ./tools/git - ./tools/mastodon - ./tools/mediagoblin - ./tools/diaspora + ./tools/mastodon.nix + ./tools/mediagoblin.nix + ./tools/diaspora.nix ./tools/ether ./tools/peertube # built using: diff --git a/nixops/modules/websites/tools/cloud.nix b/nixops/modules/websites/tools/cloud.nix new file mode 100644 index 0000000..a7fcd61 --- /dev/null +++ b/nixops/modules/websites/tools/cloud.nix @@ -0,0 +1,189 @@ +{ lib, pkgs, config, myconfig, mylibs, ... }: +let + nextcloud = pkgs.webapps.nextcloud.withApps (builtins.attrValues pkgs.webapps.nextcloud-apps); + env = myconfig.env.tools.nextcloud; + varDir = "/var/lib/nextcloud"; + webappName = "tools_nextcloud"; + apacheRoot = "/run/current-system/webapps/${webappName}"; + cfg = config.services.myWebsites.tools.cloud; + phpFpm = rec { + basedir = builtins.concatStringsSep ":" ( + [ nextcloud varDir ] + ++ builtins.attrValues pkgs.webapps.nextcloud-apps); + socket = "/var/run/phpfpm/nextcloud.sock"; + phpConfig = '' + extension=${pkgs.phpPackages.redis}/lib/php/extensions/redis.so + extension=${pkgs.phpPackages.apcu}/lib/php/extensions/apcu.so + zend_extension=${pkgs.php}/lib/php/extensions/opcache.so + ''; + pool = '' + listen = ${socket} + user = wwwrun + group = wwwrun + listen.owner = wwwrun + listen.group = wwwrun + pm = ondemand + pm.max_children = 60 + pm.process_idle_timeout = 60 + + php_admin_value[output_buffering] = 0 + php_admin_value[max_execution_time] = 1800 + php_admin_value[zend_extension] = "opcache" + ;already enabled by default? + ;php_value[opcache.enable] = 1 + php_value[opcache.enable_cli] = 1 + php_value[opcache.interned_strings_buffer] = 8 + php_value[opcache.max_accelerated_files] = 10000 + php_value[opcache.memory_consumption] = 128 + php_value[opcache.save_comments] = 1 + php_value[opcache.revalidate_freq] = 1 + php_admin_value[memory_limit] = 512M + + php_admin_value[open_basedir] = "/run/wrappers/bin/sendmail:${basedir}:/proc/meminfo:/dev/urandom:/proc/self/fd:/tmp" + php_admin_value[session.save_path] = "${varDir}/phpSessions" + ''; + }; +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 = [ "proxy_fcgi" ]; + + services.myWebsites.tools.vhostConfs.cloud = { + certName = "eldiron"; + hosts = ["cloud.immae.eu" ]; + root = apacheRoot; + extraConfig = [ + '' + SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 + + AcceptPathInfo On + DirectoryIndex index.php + Options FollowSymlinks + Require all granted + AllowOverride all + + + Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" + + + CGIPassAuth on + SetHandler "proxy:unix:${phpFpm.socket}|fcgi://localhost" + + + + '' + ]; + }; + + mySecrets.keys = [{ + dest = "webapps/tools-nextcloud"; + user = "wwwrun"; + group = "wwwrun"; + permissions = "0600"; + text = '' + '${env.instance_id}1', + 'datadirectory' => '/var/lib/nextcloud/', + 'passwordsalt' => '${env.password_salt}', + 'debug' => false, + 'dbtype' => 'pgsql', + 'version' => '16.0.0.9', + 'dbname' => '${env.postgresql.database}', + 'dbhost' => '${env.postgresql.socket}', + 'dbtableprefix' => 'oc_', + 'dbuser' => '${env.postgresql.user}', + 'dbpassword' => '${env.postgresql.password}', + 'installed' => true, + 'maxZipInputSize' => 0, + 'allowZipDownload' => true, + 'forcessl' => true, + 'theme' => ${"''"}, + 'maintenance' => false, + 'trusted_domains' => + array ( + 0 => 'cloud.immae.eu', + ), + 'secret' => '${env.secret}', + 'appstoreenabled' => false, + 'appstore.experimental.enabled' => true, + 'loglevel' => 2, + 'trashbin_retention_obligation' => 'auto', + 'htaccess.RewriteBase' => '/', + 'mail_smtpmode' => 'sendmail', + 'mail_smtphost' => '127.0.0.1', + 'mail_smtpname' => ''', + 'mail_smtppassword' => ''', + 'mail_from_address' => 'nextcloud', + 'mail_smtpauth' => false, + 'mail_domain' => 'tools.immae.eu', + 'memcache.local' => '\\OC\\Memcache\\APCu', + 'memcache.locking' => '\\OC\\Memcache\\Redis', + 'filelocking.enabled' => true, + 'redis' => + array ( + 'host' => '${env.redis.socket}', + 'port' => 0, + 'dbindex' => ${env.redis.db_index}, + ), + 'overwrite.cli.url' => 'https://cloud.immae.eu', + 'ldapIgnoreNamingRules' => false, + 'ldapProviderFactory' => '\\OCA\\User_LDAP\\LDAPProviderFactory', + 'has_rebuilt_cache' => true, + ); + ''; + }]; + users.users.root.packages = let + occ = pkgs.writeScriptBin "nextcloud-occ" '' + #! ${pkgs.stdenv.shell} + cd ${nextcloud} + NEXTCLOUD_CONFIG_DIR="${nextcloud}/config" \ + exec \ + sudo -u wwwrun ${pkgs.php}/bin/php \ + -c ${pkgs.php}/etc/php.ini \ + occ $* + ''; + in [ occ ]; + + system.activationScripts.nextcloud = { + deps = [ "secrets" ]; + text = let + confs = lib.attrsets.mapAttrs (n: v: pkgs.writeText "${n}.json" (builtins.toJSON v)) nextcloud.otherConfig; + in + '' + install -m 0755 -o wwwrun -g wwwrun -d ${varDir} + install -m 0750 -o wwwrun -g wwwrun -d ${varDir}/phpSessions + ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (n: v: + "install -D -m 0644 -o wwwrun -g wwwrun -T ${v} ${varDir}/config/${n}.json" + ) confs)} + install -D -m 0600 -o wwwrun -g wwwrun -T /var/secrets/webapps/tools-nextcloud ${varDir}/config/config.php + ''; + }; + # FIXME: add a warning when config.php changes + system.extraSystemBuilderCmds = '' + mkdir -p $out/webapps + ln -s ${nextcloud} $out/webapps/${webappName} + ''; + + services.myPhpfpm = { + poolPhpConfigs.nextcloud = phpFpm.phpConfig; + poolConfigs.nextcloud = phpFpm.pool; + }; + + services.cron = { + enable = true; + systemCronJobs = [ + '' + LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive + */15 * * * * wwwrun ${pkgs.php}/bin/php -f ${nextcloud}/cron.php + '' + ]; + }; + }; +} diff --git a/nixops/modules/websites/tools/cloud/default.nix b/nixops/modules/websites/tools/cloud/default.nix deleted file mode 100644 index a7fcd61..0000000 --- a/nixops/modules/websites/tools/cloud/default.nix +++ /dev/null @@ -1,189 +0,0 @@ -{ lib, pkgs, config, myconfig, mylibs, ... }: -let - nextcloud = pkgs.webapps.nextcloud.withApps (builtins.attrValues pkgs.webapps.nextcloud-apps); - env = myconfig.env.tools.nextcloud; - varDir = "/var/lib/nextcloud"; - webappName = "tools_nextcloud"; - apacheRoot = "/run/current-system/webapps/${webappName}"; - cfg = config.services.myWebsites.tools.cloud; - phpFpm = rec { - basedir = builtins.concatStringsSep ":" ( - [ nextcloud varDir ] - ++ builtins.attrValues pkgs.webapps.nextcloud-apps); - socket = "/var/run/phpfpm/nextcloud.sock"; - phpConfig = '' - extension=${pkgs.phpPackages.redis}/lib/php/extensions/redis.so - extension=${pkgs.phpPackages.apcu}/lib/php/extensions/apcu.so - zend_extension=${pkgs.php}/lib/php/extensions/opcache.so - ''; - pool = '' - listen = ${socket} - user = wwwrun - group = wwwrun - listen.owner = wwwrun - listen.group = wwwrun - pm = ondemand - pm.max_children = 60 - pm.process_idle_timeout = 60 - - php_admin_value[output_buffering] = 0 - php_admin_value[max_execution_time] = 1800 - php_admin_value[zend_extension] = "opcache" - ;already enabled by default? - ;php_value[opcache.enable] = 1 - php_value[opcache.enable_cli] = 1 - php_value[opcache.interned_strings_buffer] = 8 - php_value[opcache.max_accelerated_files] = 10000 - php_value[opcache.memory_consumption] = 128 - php_value[opcache.save_comments] = 1 - php_value[opcache.revalidate_freq] = 1 - php_admin_value[memory_limit] = 512M - - php_admin_value[open_basedir] = "/run/wrappers/bin/sendmail:${basedir}:/proc/meminfo:/dev/urandom:/proc/self/fd:/tmp" - php_admin_value[session.save_path] = "${varDir}/phpSessions" - ''; - }; -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 = [ "proxy_fcgi" ]; - - services.myWebsites.tools.vhostConfs.cloud = { - certName = "eldiron"; - hosts = ["cloud.immae.eu" ]; - root = apacheRoot; - extraConfig = [ - '' - SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 - - AcceptPathInfo On - DirectoryIndex index.php - Options FollowSymlinks - Require all granted - AllowOverride all - - - Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" - - - CGIPassAuth on - SetHandler "proxy:unix:${phpFpm.socket}|fcgi://localhost" - - - - '' - ]; - }; - - mySecrets.keys = [{ - dest = "webapps/tools-nextcloud"; - user = "wwwrun"; - group = "wwwrun"; - permissions = "0600"; - text = '' - '${env.instance_id}1', - 'datadirectory' => '/var/lib/nextcloud/', - 'passwordsalt' => '${env.password_salt}', - 'debug' => false, - 'dbtype' => 'pgsql', - 'version' => '16.0.0.9', - 'dbname' => '${env.postgresql.database}', - 'dbhost' => '${env.postgresql.socket}', - 'dbtableprefix' => 'oc_', - 'dbuser' => '${env.postgresql.user}', - 'dbpassword' => '${env.postgresql.password}', - 'installed' => true, - 'maxZipInputSize' => 0, - 'allowZipDownload' => true, - 'forcessl' => true, - 'theme' => ${"''"}, - 'maintenance' => false, - 'trusted_domains' => - array ( - 0 => 'cloud.immae.eu', - ), - 'secret' => '${env.secret}', - 'appstoreenabled' => false, - 'appstore.experimental.enabled' => true, - 'loglevel' => 2, - 'trashbin_retention_obligation' => 'auto', - 'htaccess.RewriteBase' => '/', - 'mail_smtpmode' => 'sendmail', - 'mail_smtphost' => '127.0.0.1', - 'mail_smtpname' => ''', - 'mail_smtppassword' => ''', - 'mail_from_address' => 'nextcloud', - 'mail_smtpauth' => false, - 'mail_domain' => 'tools.immae.eu', - 'memcache.local' => '\\OC\\Memcache\\APCu', - 'memcache.locking' => '\\OC\\Memcache\\Redis', - 'filelocking.enabled' => true, - 'redis' => - array ( - 'host' => '${env.redis.socket}', - 'port' => 0, - 'dbindex' => ${env.redis.db_index}, - ), - 'overwrite.cli.url' => 'https://cloud.immae.eu', - 'ldapIgnoreNamingRules' => false, - 'ldapProviderFactory' => '\\OCA\\User_LDAP\\LDAPProviderFactory', - 'has_rebuilt_cache' => true, - ); - ''; - }]; - users.users.root.packages = let - occ = pkgs.writeScriptBin "nextcloud-occ" '' - #! ${pkgs.stdenv.shell} - cd ${nextcloud} - NEXTCLOUD_CONFIG_DIR="${nextcloud}/config" \ - exec \ - sudo -u wwwrun ${pkgs.php}/bin/php \ - -c ${pkgs.php}/etc/php.ini \ - occ $* - ''; - in [ occ ]; - - system.activationScripts.nextcloud = { - deps = [ "secrets" ]; - text = let - confs = lib.attrsets.mapAttrs (n: v: pkgs.writeText "${n}.json" (builtins.toJSON v)) nextcloud.otherConfig; - in - '' - install -m 0755 -o wwwrun -g wwwrun -d ${varDir} - install -m 0750 -o wwwrun -g wwwrun -d ${varDir}/phpSessions - ${builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (n: v: - "install -D -m 0644 -o wwwrun -g wwwrun -T ${v} ${varDir}/config/${n}.json" - ) confs)} - install -D -m 0600 -o wwwrun -g wwwrun -T /var/secrets/webapps/tools-nextcloud ${varDir}/config/config.php - ''; - }; - # FIXME: add a warning when config.php changes - system.extraSystemBuilderCmds = '' - mkdir -p $out/webapps - ln -s ${nextcloud} $out/webapps/${webappName} - ''; - - services.myPhpfpm = { - poolPhpConfigs.nextcloud = phpFpm.phpConfig; - poolConfigs.nextcloud = phpFpm.pool; - }; - - services.cron = { - enable = true; - systemCronJobs = [ - '' - LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive - */15 * * * * wwwrun ${pkgs.php}/bin/php -f ${nextcloud}/cron.php - '' - ]; - }; - }; -} diff --git a/nixops/modules/websites/tools/db.nix b/nixops/modules/websites/tools/db.nix new file mode 100644 index 0000000..6957e30 --- /dev/null +++ b/nixops/modules/websites/tools/db.nix @@ -0,0 +1,22 @@ +{ 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 { + 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/nixops/modules/websites/tools/db/default.nix b/nixops/modules/websites/tools/db/default.nix deleted file mode 100644 index 2a82bd6..0000000 --- a/nixops/modules/websites/tools/db/default.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ 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 { - 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/nixops/modules/websites/tools/diaspora.nix b/nixops/modules/websites/tools/diaspora.nix new file mode 100644 index 0000000..53989b7 --- /dev/null +++ b/nixops/modules/websites/tools/diaspora.nix @@ -0,0 +1,249 @@ +{ lib, pkgs, config, myconfig, mylibs, ... }: +let + varDir = "/var/lib/diaspora_immae"; + + diaspora = pkgs.webapps.diaspora.override { + ldap = true; + inherit varDir; + podmin_email = "diaspora@tools.immae.eu"; + config_dir = "/var/secrets/webapps/diaspora"; + }; + + railsSocket = "${socketsDir}/diaspora.sock"; + socketsDir = "/run/diaspora"; + env = myconfig.env.tools.diaspora; + root = "/run/current-system/webapps/tools_diaspora"; + cfg = config.services.myWebsites.tools.diaspora; +in { + options.services.myWebsites.tools.diaspora = { + enable = lib.mkEnableOption "enable diaspora's website"; + }; + + config = lib.mkIf cfg.enable { + ids.uids.diaspora = env.user.uid; + ids.gids.diaspora = env.user.gid; + + users.users.diaspora = { + name = "diaspora"; + uid = config.ids.uids.diaspora; + group = "diaspora"; + description = "Diaspora user"; + home = varDir; + useDefaultShell = true; + packages = [ diaspora.gems pkgs.nodejs diaspora.gems.ruby ]; + extraGroups = [ "keys" ]; + }; + + users.groups.diaspora.gid = config.ids.gids.diaspora; + mySecrets.keys = [ + { + dest = "webapps/diaspora/diaspora.yml"; + user = "diaspora"; + group = "diaspora"; + permissions = "0400"; + text = '' + configuration: + environment: + url: "https://diaspora.immae.eu/" + certificate_authorities: '${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt' + redis: '${env.redis_url}' + sidekiq: + s3: + assets: + logging: + logrotate: + debug: + server: + listen: '${socketsDir}/diaspora.sock' + rails_environment: 'production' + chat: + server: + bosh: + log: + map: + mapbox: + privacy: + piwik: + statistics: + camo: + settings: + enable_registrations: false + welcome_message: + invitations: + open: false + paypal_donations: + community_spotlight: + captcha: + enable: false + terms: + maintenance: + remove_old_users: + default_metas: + csp: + services: + twitter: + tumblr: + wordpress: + mail: + enable: true + sender_address: 'diaspora@tools.immae.eu' + method: 'sendmail' + smtp: + sendmail: + location: '/run/wrappers/bin/sendmail' + admins: + account: "ismael" + podmin_email: 'diaspora@tools.immae.eu' + relay: + outbound: + inbound: + ldap: + enable: true + host: ldap.immae.eu + port: 636 + only_ldap: true + mail_attribute: mail + skip_email_confirmation: true + use_bind_dn: true + bind_dn: "cn=diaspora,ou=services,dc=immae,dc=eu" + bind_pw: "${env.ldap.password}" + search_base: "dc=immae,dc=eu" + search_filter: "(&(memberOf=cn=users,cn=diaspora,ou=services,dc=immae,dc=eu)(uid=%{username}))" + production: + environment: + development: + environment: + ''; + } + { + dest = "webapps/diaspora/database.yml"; + user = "diaspora"; + group = "diaspora"; + permissions = "0400"; + text = '' + postgresql: &postgresql + adapter: postgresql + host: "${env.postgresql.socket}" + port: "${env.postgresql.port}" + username: "${env.postgresql.user}" + password: "${env.postgresql.password}" + encoding: unicode + common: &common + <<: *postgresql + combined: &combined + <<: *common + development: + <<: *combined + database: diaspora_development + production: + <<: *combined + database: ${env.postgresql.database} + test: + <<: *combined + database: "diaspora_test" + integration1: + <<: *combined + database: diaspora_integration1 + integration2: + <<: *combined + database: diaspora_integration2 + ''; + } + { + dest = "webapps/diaspora/secret_token.rb"; + user = "diaspora"; + group = "diaspora"; + permissions = "0400"; + text = '' + Diaspora::Application.config.secret_key_base = '${env.secret_token}' + ''; + } + ]; + + systemd.services.diaspora = { + description = "Diaspora"; + wantedBy = [ "multi-user.target" ]; + after = [ + "network.target" "redis.service" "postgresql.service" + ]; + wants = [ + "redis.service" "postgresql.service" + ]; + + environment.RAILS_ENV = "production"; + environment.BUNDLE_PATH = "${diaspora.gems}/${diaspora.gems.ruby.gemPath}"; + environment.BUNDLE_GEMFILE = "${diaspora.gems.confFiles}/Gemfile"; + environment.EYE_SOCK = "${socketsDir}/eye.sock"; + environment.EYE_PID = "${socketsDir}/eye.pid"; + + path = [ diaspora.gems pkgs.nodejs diaspora.gems.ruby pkgs.curl pkgs.which pkgs.gawk ]; + + preStart = '' + ./bin/bundle exec rails db:migrate + ''; + + script = '' + exec ${diaspora}/script/server + ''; + + serviceConfig = { + User = "diaspora"; + PrivateTmp = true; + Restart = "always"; + Type = "simple"; + WorkingDirectory = diaspora; + StandardInput = "null"; + KillMode = "control-group"; + }; + + unitConfig.RequiresMountsFor = varDir; + }; + + system.activationScripts.diaspora = { + deps = [ "users" ]; + text = '' + install -m 0755 -o diaspora -g diaspora -d ${socketsDir} + install -m 0755 -o diaspora -g diaspora -d ${varDir} \ + ${varDir}/uploads ${varDir}/tmp \ + ${varDir}/log + install -m 0700 -o diaspora -g diaspora -d ${varDir}/tmp/pids + if [ ! -f ${varDir}/schedule.yml ]; then + echo "{}" | $wrapperDir/sudo -u diaspora tee ${varDir}/schedule.yml + fi + ''; + }; + + services.myWebsites.tools.modules = [ + "headers" "proxy" "proxy_http" + ]; + security.acme.certs."eldiron".extraDomains."diaspora.immae.eu" = null; + system.extraSystemBuilderCmds = '' + mkdir -p $out/webapps + ln -s ${diaspora}/public/ $out/webapps/tools_diaspora + ''; + services.myWebsites.tools.vhostConfs.diaspora = { + certName = "eldiron"; + hosts = [ "diaspora.immae.eu" ]; + root = root; + extraConfig = [ '' + RewriteEngine On + RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f + RewriteRule ^/(.*)$ unix://${railsSocket}|http://diaspora.immae.eu/%{REQUEST_URI} [P,NE,QSA,L] + + ProxyRequests Off + ProxyVia On + ProxyPreserveHost On + RequestHeader set X_FORWARDED_PROTO https + + + Require all granted + + + + Require all granted + Options -MultiViews + + '' ]; + }; + }; +} diff --git a/nixops/modules/websites/tools/diaspora/default.nix b/nixops/modules/websites/tools/diaspora/default.nix deleted file mode 100644 index 53989b7..0000000 --- a/nixops/modules/websites/tools/diaspora/default.nix +++ /dev/null @@ -1,249 +0,0 @@ -{ lib, pkgs, config, myconfig, mylibs, ... }: -let - varDir = "/var/lib/diaspora_immae"; - - diaspora = pkgs.webapps.diaspora.override { - ldap = true; - inherit varDir; - podmin_email = "diaspora@tools.immae.eu"; - config_dir = "/var/secrets/webapps/diaspora"; - }; - - railsSocket = "${socketsDir}/diaspora.sock"; - socketsDir = "/run/diaspora"; - env = myconfig.env.tools.diaspora; - root = "/run/current-system/webapps/tools_diaspora"; - cfg = config.services.myWebsites.tools.diaspora; -in { - options.services.myWebsites.tools.diaspora = { - enable = lib.mkEnableOption "enable diaspora's website"; - }; - - config = lib.mkIf cfg.enable { - ids.uids.diaspora = env.user.uid; - ids.gids.diaspora = env.user.gid; - - users.users.diaspora = { - name = "diaspora"; - uid = config.ids.uids.diaspora; - group = "diaspora"; - description = "Diaspora user"; - home = varDir; - useDefaultShell = true; - packages = [ diaspora.gems pkgs.nodejs diaspora.gems.ruby ]; - extraGroups = [ "keys" ]; - }; - - users.groups.diaspora.gid = config.ids.gids.diaspora; - mySecrets.keys = [ - { - dest = "webapps/diaspora/diaspora.yml"; - user = "diaspora"; - group = "diaspora"; - permissions = "0400"; - text = '' - configuration: - environment: - url: "https://diaspora.immae.eu/" - certificate_authorities: '${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt' - redis: '${env.redis_url}' - sidekiq: - s3: - assets: - logging: - logrotate: - debug: - server: - listen: '${socketsDir}/diaspora.sock' - rails_environment: 'production' - chat: - server: - bosh: - log: - map: - mapbox: - privacy: - piwik: - statistics: - camo: - settings: - enable_registrations: false - welcome_message: - invitations: - open: false - paypal_donations: - community_spotlight: - captcha: - enable: false - terms: - maintenance: - remove_old_users: - default_metas: - csp: - services: - twitter: - tumblr: - wordpress: - mail: - enable: true - sender_address: 'diaspora@tools.immae.eu' - method: 'sendmail' - smtp: - sendmail: - location: '/run/wrappers/bin/sendmail' - admins: - account: "ismael" - podmin_email: 'diaspora@tools.immae.eu' - relay: - outbound: - inbound: - ldap: - enable: true - host: ldap.immae.eu - port: 636 - only_ldap: true - mail_attribute: mail - skip_email_confirmation: true - use_bind_dn: true - bind_dn: "cn=diaspora,ou=services,dc=immae,dc=eu" - bind_pw: "${env.ldap.password}" - search_base: "dc=immae,dc=eu" - search_filter: "(&(memberOf=cn=users,cn=diaspora,ou=services,dc=immae,dc=eu)(uid=%{username}))" - production: - environment: - development: - environment: - ''; - } - { - dest = "webapps/diaspora/database.yml"; - user = "diaspora"; - group = "diaspora"; - permissions = "0400"; - text = '' - postgresql: &postgresql - adapter: postgresql - host: "${env.postgresql.socket}" - port: "${env.postgresql.port}" - username: "${env.postgresql.user}" - password: "${env.postgresql.password}" - encoding: unicode - common: &common - <<: *postgresql - combined: &combined - <<: *common - development: - <<: *combined - database: diaspora_development - production: - <<: *combined - database: ${env.postgresql.database} - test: - <<: *combined - database: "diaspora_test" - integration1: - <<: *combined - database: diaspora_integration1 - integration2: - <<: *combined - database: diaspora_integration2 - ''; - } - { - dest = "webapps/diaspora/secret_token.rb"; - user = "diaspora"; - group = "diaspora"; - permissions = "0400"; - text = '' - Diaspora::Application.config.secret_key_base = '${env.secret_token}' - ''; - } - ]; - - systemd.services.diaspora = { - description = "Diaspora"; - wantedBy = [ "multi-user.target" ]; - after = [ - "network.target" "redis.service" "postgresql.service" - ]; - wants = [ - "redis.service" "postgresql.service" - ]; - - environment.RAILS_ENV = "production"; - environment.BUNDLE_PATH = "${diaspora.gems}/${diaspora.gems.ruby.gemPath}"; - environment.BUNDLE_GEMFILE = "${diaspora.gems.confFiles}/Gemfile"; - environment.EYE_SOCK = "${socketsDir}/eye.sock"; - environment.EYE_PID = "${socketsDir}/eye.pid"; - - path = [ diaspora.gems pkgs.nodejs diaspora.gems.ruby pkgs.curl pkgs.which pkgs.gawk ]; - - preStart = '' - ./bin/bundle exec rails db:migrate - ''; - - script = '' - exec ${diaspora}/script/server - ''; - - serviceConfig = { - User = "diaspora"; - PrivateTmp = true; - Restart = "always"; - Type = "simple"; - WorkingDirectory = diaspora; - StandardInput = "null"; - KillMode = "control-group"; - }; - - unitConfig.RequiresMountsFor = varDir; - }; - - system.activationScripts.diaspora = { - deps = [ "users" ]; - text = '' - install -m 0755 -o diaspora -g diaspora -d ${socketsDir} - install -m 0755 -o diaspora -g diaspora -d ${varDir} \ - ${varDir}/uploads ${varDir}/tmp \ - ${varDir}/log - install -m 0700 -o diaspora -g diaspora -d ${varDir}/tmp/pids - if [ ! -f ${varDir}/schedule.yml ]; then - echo "{}" | $wrapperDir/sudo -u diaspora tee ${varDir}/schedule.yml - fi - ''; - }; - - services.myWebsites.tools.modules = [ - "headers" "proxy" "proxy_http" - ]; - security.acme.certs."eldiron".extraDomains."diaspora.immae.eu" = null; - system.extraSystemBuilderCmds = '' - mkdir -p $out/webapps - ln -s ${diaspora}/public/ $out/webapps/tools_diaspora - ''; - services.myWebsites.tools.vhostConfs.diaspora = { - certName = "eldiron"; - hosts = [ "diaspora.immae.eu" ]; - root = root; - extraConfig = [ '' - RewriteEngine On - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f - RewriteRule ^/(.*)$ unix://${railsSocket}|http://diaspora.immae.eu/%{REQUEST_URI} [P,NE,QSA,L] - - ProxyRequests Off - ProxyVia On - ProxyPreserveHost On - RequestHeader set X_FORWARDED_PROTO https - - - Require all granted - - - - Require all granted - Options -MultiViews - - '' ]; - }; - }; -} diff --git a/nixops/modules/websites/tools/mastodon.nix b/nixops/modules/websites/tools/mastodon.nix new file mode 100644 index 0000000..3279cf8 --- /dev/null +++ b/nixops/modules/websites/tools/mastodon.nix @@ -0,0 +1,249 @@ +{ lib, pkgs, config, myconfig, mylibs, ... }: +let + varDir = "/var/lib/mastodon_immae"; + socketsDir = "/run/mastodon"; + nodeSocket = "${socketsDir}/live_immae_node.sock"; + railsSocket = "${socketsDir}/live_immae_puma.sock"; + + mastodon = pkgs.webapps.mastodon.override { inherit varDir; }; + + env = myconfig.env.tools.mastodon; + root = "/run/current-system/webapps/tools_mastodon"; + cfg = config.services.myWebsites.tools.mastodon; +in { + options.services.myWebsites.tools.mastodon = { + enable = lib.mkEnableOption "enable mastodon's website"; + }; + + config = lib.mkIf cfg.enable { + mySecrets.keys = [{ + dest = "webapps/tools-mastodon"; + user = "mastodon"; + group = "mastodon"; + permissions = "0400"; + text = '' + REDIS_HOST=${env.redis.host} + REDIS_PORT=${env.redis.port} + REDIS_DB=${env.redis.db} + DB_HOST=${env.postgresql.socket} + DB_USER=${env.postgresql.user} + DB_NAME=${env.postgresql.database} + DB_PASS=${env.postgresql.password} + DB_PORT=${env.postgresql.port} + + LOCAL_DOMAIN=mastodon.immae.eu + LOCAL_HTTPS=true + ALTERNATE_DOMAINS=immae.eu + + PAPERCLIP_SECRET=${env.paperclip_secret} + SECRET_KEY_BASE=${env.secret_key_base} + OTP_SECRET=${env.otp_secret} + + VAPID_PRIVATE_KEY=${env.vapid.private} + VAPID_PUBLIC_KEY=${env.vapid.public} + + SMTP_DELIVERY_METHOD=sendmail + SMTP_FROM_ADDRESS=mastodon@tools.immae.eu + SENDMAIL_LOCATION="/run/wrappers/bin/sendmail" + PAPERCLIP_ROOT_PATH=${varDir} + + STREAMING_CLUSTER_NUM=1 + + RAILS_LOG_LEVEL=warn + + # 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="${env.ldap.password}" + LDAP_UID="uid" + LDAP_SEARCH_FILTER="(&(%{uid}=%{email})(memberOf=cn=users,cn=mastodon,ou=services,dc=immae,dc=eu))" + ''; + }]; + ids.uids.mastodon = env.user.uid; + ids.gids.mastodon = env.user.gid; + + users.users.mastodon = { + name = "mastodon"; + uid = config.ids.uids.mastodon; + group = "mastodon"; + description = "Mastodon user"; + home = varDir; + 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 = 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 = "/var/secrets/webapps/tools-mastodon"; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 15; + Type = "simple"; + WorkingDirectory = mastodon; + }; + + unitConfig.RequiresMountsFor = varDir; + }; + + systemd.services.mastodon-web = { + description = "Mastodon Web app"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + environment.RAILS_ENV = "production"; + environment.BUNDLE_PATH = "${mastodon.gems}/${mastodon.gems.ruby.gemPath}"; + environment.BUNDLE_GEMFILE = "${mastodon.gems.confFiles}/Gemfile"; + environment.SOCKET = railsSocket; + + path = [ mastodon.gems mastodon.gems.ruby pkgs.file ]; + + preStart = '' + ./bin/bundle exec rails db:migrate + ''; + + script = '' + exec ./bin/bundle exec puma -C config/puma.rb + ''; + + serviceConfig = { + User = "mastodon"; + EnvironmentFile = "/var/secrets/webapps/tools-mastodon"; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 60; + Type = "simple"; + WorkingDirectory = mastodon; + }; + + unitConfig.RequiresMountsFor = varDir; + }; + + systemd.services.mastodon-sidekiq = { + description = "Mastodon Sidekiq"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "mastodon-web.service" ]; + + environment.RAILS_ENV="production"; + environment.BUNDLE_PATH = "${mastodon.gems}/${mastodon.gems.ruby.gemPath}"; + environment.BUNDLE_GEMFILE = "${mastodon.gems.confFiles}/Gemfile"; + environment.DB_POOL="5"; + + path = [ mastodon.gems mastodon.gems.ruby pkgs.imagemagick pkgs.ffmpeg pkgs.file ]; + + script = '' + exec ./bin/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push + ''; + + serviceConfig = { + User = "mastodon"; + EnvironmentFile = "/var/secrets/webapps/tools-mastodon"; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 15; + Type = "simple"; + WorkingDirectory = mastodon; + }; + + unitConfig.RequiresMountsFor = varDir; + }; + + system.activationScripts.mastodon = { + deps = [ "users" ]; + text = '' + install -m 0755 -o mastodon -g mastodon -d ${socketsDir} + install -m 0755 -o mastodon -g mastodon -d ${varDir} ${varDir}/tmp/cache + ''; + }; + + services.myWebsites.tools.modules = [ + "headers" "proxy" "proxy_wstunnel" "proxy_http" + ]; + security.acme.certs."eldiron".extraDomains."mastodon.immae.eu" = null; + system.extraSystemBuilderCmds = '' + mkdir -p $out/webapps + ln -s ${mastodon}/public/ $out/webapps/tools_mastodon + ''; + services.myWebsites.tools.vhostConfs.mastodon = { + certName = "eldiron"; + hosts = ["mastodon.immae.eu" ]; + root = root; + 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) ! + + RewriteRule ^/api/v1/streaming/(.+)$ unix://${nodeSocket}|http://mastodon.immae.eu/api/v1/streaming/$1 [P,NE,QSA,L] + RewriteRule ^/api/v1/streaming/$ unix://${nodeSocket}|ws://mastodon.immae.eu/ [P,NE,QSA,L] + ProxyPass / unix://${railsSocket}|http://mastodon.immae.eu/ + ProxyPassReverse / unix://${railsSocket}|http://mastodon.immae.eu/ + + Alias /system ${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/nixops/modules/websites/tools/mastodon/default.nix b/nixops/modules/websites/tools/mastodon/default.nix deleted file mode 100644 index 3279cf8..0000000 --- a/nixops/modules/websites/tools/mastodon/default.nix +++ /dev/null @@ -1,249 +0,0 @@ -{ lib, pkgs, config, myconfig, mylibs, ... }: -let - varDir = "/var/lib/mastodon_immae"; - socketsDir = "/run/mastodon"; - nodeSocket = "${socketsDir}/live_immae_node.sock"; - railsSocket = "${socketsDir}/live_immae_puma.sock"; - - mastodon = pkgs.webapps.mastodon.override { inherit varDir; }; - - env = myconfig.env.tools.mastodon; - root = "/run/current-system/webapps/tools_mastodon"; - cfg = config.services.myWebsites.tools.mastodon; -in { - options.services.myWebsites.tools.mastodon = { - enable = lib.mkEnableOption "enable mastodon's website"; - }; - - config = lib.mkIf cfg.enable { - mySecrets.keys = [{ - dest = "webapps/tools-mastodon"; - user = "mastodon"; - group = "mastodon"; - permissions = "0400"; - text = '' - REDIS_HOST=${env.redis.host} - REDIS_PORT=${env.redis.port} - REDIS_DB=${env.redis.db} - DB_HOST=${env.postgresql.socket} - DB_USER=${env.postgresql.user} - DB_NAME=${env.postgresql.database} - DB_PASS=${env.postgresql.password} - DB_PORT=${env.postgresql.port} - - LOCAL_DOMAIN=mastodon.immae.eu - LOCAL_HTTPS=true - ALTERNATE_DOMAINS=immae.eu - - PAPERCLIP_SECRET=${env.paperclip_secret} - SECRET_KEY_BASE=${env.secret_key_base} - OTP_SECRET=${env.otp_secret} - - VAPID_PRIVATE_KEY=${env.vapid.private} - VAPID_PUBLIC_KEY=${env.vapid.public} - - SMTP_DELIVERY_METHOD=sendmail - SMTP_FROM_ADDRESS=mastodon@tools.immae.eu - SENDMAIL_LOCATION="/run/wrappers/bin/sendmail" - PAPERCLIP_ROOT_PATH=${varDir} - - STREAMING_CLUSTER_NUM=1 - - RAILS_LOG_LEVEL=warn - - # 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="${env.ldap.password}" - LDAP_UID="uid" - LDAP_SEARCH_FILTER="(&(%{uid}=%{email})(memberOf=cn=users,cn=mastodon,ou=services,dc=immae,dc=eu))" - ''; - }]; - ids.uids.mastodon = env.user.uid; - ids.gids.mastodon = env.user.gid; - - users.users.mastodon = { - name = "mastodon"; - uid = config.ids.uids.mastodon; - group = "mastodon"; - description = "Mastodon user"; - home = varDir; - 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 = 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 = "/var/secrets/webapps/tools-mastodon"; - PrivateTmp = true; - Restart = "always"; - TimeoutSec = 15; - Type = "simple"; - WorkingDirectory = mastodon; - }; - - unitConfig.RequiresMountsFor = varDir; - }; - - systemd.services.mastodon-web = { - description = "Mastodon Web app"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - environment.RAILS_ENV = "production"; - environment.BUNDLE_PATH = "${mastodon.gems}/${mastodon.gems.ruby.gemPath}"; - environment.BUNDLE_GEMFILE = "${mastodon.gems.confFiles}/Gemfile"; - environment.SOCKET = railsSocket; - - path = [ mastodon.gems mastodon.gems.ruby pkgs.file ]; - - preStart = '' - ./bin/bundle exec rails db:migrate - ''; - - script = '' - exec ./bin/bundle exec puma -C config/puma.rb - ''; - - serviceConfig = { - User = "mastodon"; - EnvironmentFile = "/var/secrets/webapps/tools-mastodon"; - PrivateTmp = true; - Restart = "always"; - TimeoutSec = 60; - Type = "simple"; - WorkingDirectory = mastodon; - }; - - unitConfig.RequiresMountsFor = varDir; - }; - - systemd.services.mastodon-sidekiq = { - description = "Mastodon Sidekiq"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "mastodon-web.service" ]; - - environment.RAILS_ENV="production"; - environment.BUNDLE_PATH = "${mastodon.gems}/${mastodon.gems.ruby.gemPath}"; - environment.BUNDLE_GEMFILE = "${mastodon.gems.confFiles}/Gemfile"; - environment.DB_POOL="5"; - - path = [ mastodon.gems mastodon.gems.ruby pkgs.imagemagick pkgs.ffmpeg pkgs.file ]; - - script = '' - exec ./bin/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push - ''; - - serviceConfig = { - User = "mastodon"; - EnvironmentFile = "/var/secrets/webapps/tools-mastodon"; - PrivateTmp = true; - Restart = "always"; - TimeoutSec = 15; - Type = "simple"; - WorkingDirectory = mastodon; - }; - - unitConfig.RequiresMountsFor = varDir; - }; - - system.activationScripts.mastodon = { - deps = [ "users" ]; - text = '' - install -m 0755 -o mastodon -g mastodon -d ${socketsDir} - install -m 0755 -o mastodon -g mastodon -d ${varDir} ${varDir}/tmp/cache - ''; - }; - - services.myWebsites.tools.modules = [ - "headers" "proxy" "proxy_wstunnel" "proxy_http" - ]; - security.acme.certs."eldiron".extraDomains."mastodon.immae.eu" = null; - system.extraSystemBuilderCmds = '' - mkdir -p $out/webapps - ln -s ${mastodon}/public/ $out/webapps/tools_mastodon - ''; - services.myWebsites.tools.vhostConfs.mastodon = { - certName = "eldiron"; - hosts = ["mastodon.immae.eu" ]; - root = root; - 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) ! - - RewriteRule ^/api/v1/streaming/(.+)$ unix://${nodeSocket}|http://mastodon.immae.eu/api/v1/streaming/$1 [P,NE,QSA,L] - RewriteRule ^/api/v1/streaming/$ unix://${nodeSocket}|ws://mastodon.immae.eu/ [P,NE,QSA,L] - ProxyPass / unix://${railsSocket}|http://mastodon.immae.eu/ - ProxyPassReverse / unix://${railsSocket}|http://mastodon.immae.eu/ - - Alias /system ${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/nixops/modules/websites/tools/mediagoblin.nix b/nixops/modules/websites/tools/mediagoblin.nix new file mode 100644 index 0000000..a02af38 --- /dev/null +++ b/nixops/modules/websites/tools/mediagoblin.nix @@ -0,0 +1,251 @@ +{ lib, pkgs, config, myconfig, mylibs, ... }: +let + env = myconfig.env.tools.mediagoblin; + socketsDir = "/run/mediagoblin"; + varDir = "/var/lib/mediagoblin"; + cfg = config.services.myWebsites.tools.mediagoblin; + mediagoblin_init = "/var/secrets/webapps/tools-mediagoblin"; + paste_local = pkgs.writeText "paste_local.ini" '' + [DEFAULT] + debug = false + + [pipeline:main] + pipeline = mediagoblin + + [app:mediagoblin] + use = egg:mediagoblin#app + config = ${mediagoblin_init} ${pythonRoot}/mediagoblin.ini + /mgoblin_static = ${pythonRoot}/mediagoblin/static + + [loggers] + keys = root + + [handlers] + keys = console + + [formatters] + keys = generic + + [logger_root] + level = INFO + handlers = console + + [handler_console] + class = StreamHandler + args = (sys.stderr,) + level = NOTSET + formatter = generic + + [formatter_generic] + format = %(levelname)-7.7s [%(name)s] %(message)s + + [filter:errors] + use = egg:mediagoblin#errors + debug = false + + [server:main] + use = egg:waitress#main + unix_socket = ${socketsDir}/mediagoblin.sock + unix_socket_perms = 777 + url_scheme = https + ''; + pythonRoot = pkgs.webapps.mediagoblin-with-plugins; +in { + options.services.myWebsites.tools.mediagoblin = { + enable = lib.mkEnableOption "enable mediagoblin's website"; + }; + + config = lib.mkIf cfg.enable { + mySecrets.keys = [{ + dest = "webapps/tools-mediagoblin"; + user = "mediagoblin"; + group = "mediagoblin"; + permissions = "0400"; + text = '' + [DEFAULT] + data_basedir = "${varDir}" + + [mediagoblin] + direct_remote_path = /mgoblin_static/ + email_sender_address = "mediagoblin@tools.immae.eu" + + #sql_engine = sqlite:///%(data_basedir)s/mediagoblin.db + sql_engine = ${env.psql_url} + + email_debug_mode = false + allow_registration = false + allow_reporting = true + + theme = airymodified + + user_privilege_scheme = "uploader,commenter,reporter" + + # We need to redefine them here since we override data_basedir + # cf /usr/share/webapps/mediagoblin/mediagoblin/config_spec.ini + workbench_path = %(data_basedir)s/media/workbench + crypto_path = %(data_basedir)s/crypto + theme_install_dir = %(data_basedir)s/themes/ + theme_linked_assets_dir = %(data_basedir)s/theme_static/ + plugin_linked_assets_dir = %(data_basedir)s/plugin_static/ + + [storage:queuestore] + base_dir = %(data_basedir)s/media/queue + + [storage:publicstore] + base_dir = %(data_basedir)s/media/public + base_url = /mgoblin_media/ + + [celery] + CELERY_RESULT_DBURI = ${env.redis_url} + BROKER_URL = ${env.redis_url} + CELERYD_CONCURRENCY = 1 + + [plugins] + [[mediagoblin.plugins.geolocation]] + [[mediagoblin.plugins.ldap]] + [[[immae.eu]]] + LDAP_SERVER_URI = 'ldaps://ldap.immae.eu:636' + LDAP_SEARCH_BASE = 'dc=immae,dc=eu' + LDAP_BIND_DN = 'cn=mediagoblin,ou=services,dc=immae,dc=eu' + LDAP_BIND_PW = '${env.ldap.password}' + LDAP_SEARCH_FILTER = '(&(memberOf=cn=users,cn=mediagoblin,ou=services,dc=immae,dc=eu)(uid={username}))' + EMAIL_SEARCH_FIELD = 'mail' + [[mediagoblin.plugins.basicsearch]] + [[mediagoblin.plugins.piwigo]] + [[mediagoblin.plugins.processing_info]] + [[mediagoblin.media_types.image]] + [[mediagoblin.media_types.video]] + ''; + }]; + + ids.uids.mediagoblin = myconfig.env.tools.mediagoblin.user.uid; + ids.gids.mediagoblin = myconfig.env.tools.mediagoblin.user.gid; + + users.users.mediagoblin = { + name = "mediagoblin"; + uid = config.ids.uids.mediagoblin; + group = "mediagoblin"; + description = "Mediagoblin user"; + home = varDir; + useDefaultShell = true; + extraGroups = [ "keys" ]; + }; + + users.groups.mediagoblin.gid = config.ids.gids.mediagoblin; + + systemd.services.mediagoblin-web = { + description = "Mediagoblin service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + wants = [ "postgresql.service" "redis.service" ]; + + environment.SCRIPT_NAME = "/mediagoblin/"; + + script = '' + exec ./bin/paster serve \ + ${paste_local} \ + --pid-file=${socketsDir}/mediagoblin.pid + ''; + + preStop = '' + exec ./bin/paster serve \ + --pid-file=${socketsDir}/mediagoblin.pid \ + ${paste_local} stop + ''; + preStart = '' + ./bin/gmg -cf ${mediagoblin_init} dbupdate + ''; + + serviceConfig = { + User = "mediagoblin"; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 15; + Type = "simple"; + WorkingDirectory = pythonRoot; + PIDFile = "${socketsDir}/mediagoblin.pid"; + }; + + unitConfig.RequiresMountsFor = varDir; + }; + + systemd.services.mediagoblin-celeryd = { + description = "Mediagoblin service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "mediagoblin-web.service" ]; + + environment.MEDIAGOBLIN_CONFIG = "${pythonRoot}/mediagoblin_local.ini"; + environment.CELERY_CONFIG_MODULE = "mediagoblin.init.celery.from_celery"; + + script = '' + exec ./bin/celery worker \ + --logfile=${varDir}/celery.log \ + --loglevel=INFO + ''; + + serviceConfig = { + User = "mediagoblin"; + PrivateTmp = true; + Restart = "always"; + TimeoutSec = 60; + Type = "simple"; + WorkingDirectory = pythonRoot; + PIDFile = "${socketsDir}/mediagoblin-celeryd.pid"; + }; + + unitConfig.RequiresMountsFor = varDir; + }; + + system.activationScripts.mediagoblin = { + deps = [ "users" ]; + text = '' + install -m 0755 -o mediagoblin -g mediagoblin -d ${socketsDir} + install -m 0755 -o mediagoblin -g mediagoblin -d ${varDir} + if [ -d ${varDir}/plugin_static/ ]; then + rm ${varDir}/plugin_static/coreplugin_basic_auth + ln -sf ${pythonRoot}/mediagoblin/plugins/basic_auth/static ${varDir}/plugin_static/coreplugin_basic_auth + fi + ''; + }; + + services.myWebsites.tools.modules = [ + "proxy" "proxy_http" + ]; + users.users.wwwrun.extraGroups = [ "mediagoblin" ]; + security.acme.certs."eldiron".extraDomains."mgoblin.immae.eu" = null; + services.myWebsites.tools.vhostConfs.mgoblin = { + certName = "eldiron"; + hosts = ["mgoblin.immae.eu" ]; + root = null; + extraConfig = [ '' + Alias /mgoblin_media ${varDir}/media/public + + Options -Indexes +FollowSymLinks +MultiViews +Includes + Require all granted + + + Alias /theme_static ${varDir}/theme_static + + Options -Indexes +FollowSymLinks +MultiViews +Includes + Require all granted + + + Alias /plugin_static ${varDir}/plugin_static + + Options -Indexes +FollowSymLinks +MultiViews +Includes + Require all granted + + + ProxyPreserveHost on + ProxyVia On + ProxyRequests Off + ProxyPass /mgoblin_media ! + ProxyPass /theme_static ! + ProxyPass /plugin_static ! + ProxyPassMatch ^/.well-known/acme-challenge ! + ProxyPass / unix://${socketsDir}/mediagoblin.sock|http://mgoblin.immae.eu/ + ProxyPassReverse / unix://${socketsDir}/mediagoblin.sock|http://mgoblin.immae.eu/ + '' ]; + }; + }; +} diff --git a/nixops/modules/websites/tools/mediagoblin/default.nix b/nixops/modules/websites/tools/mediagoblin/default.nix deleted file mode 100644 index a02af38..0000000 --- a/nixops/modules/websites/tools/mediagoblin/default.nix +++ /dev/null @@ -1,251 +0,0 @@ -{ lib, pkgs, config, myconfig, mylibs, ... }: -let - env = myconfig.env.tools.mediagoblin; - socketsDir = "/run/mediagoblin"; - varDir = "/var/lib/mediagoblin"; - cfg = config.services.myWebsites.tools.mediagoblin; - mediagoblin_init = "/var/secrets/webapps/tools-mediagoblin"; - paste_local = pkgs.writeText "paste_local.ini" '' - [DEFAULT] - debug = false - - [pipeline:main] - pipeline = mediagoblin - - [app:mediagoblin] - use = egg:mediagoblin#app - config = ${mediagoblin_init} ${pythonRoot}/mediagoblin.ini - /mgoblin_static = ${pythonRoot}/mediagoblin/static - - [loggers] - keys = root - - [handlers] - keys = console - - [formatters] - keys = generic - - [logger_root] - level = INFO - handlers = console - - [handler_console] - class = StreamHandler - args = (sys.stderr,) - level = NOTSET - formatter = generic - - [formatter_generic] - format = %(levelname)-7.7s [%(name)s] %(message)s - - [filter:errors] - use = egg:mediagoblin#errors - debug = false - - [server:main] - use = egg:waitress#main - unix_socket = ${socketsDir}/mediagoblin.sock - unix_socket_perms = 777 - url_scheme = https - ''; - pythonRoot = pkgs.webapps.mediagoblin-with-plugins; -in { - options.services.myWebsites.tools.mediagoblin = { - enable = lib.mkEnableOption "enable mediagoblin's website"; - }; - - config = lib.mkIf cfg.enable { - mySecrets.keys = [{ - dest = "webapps/tools-mediagoblin"; - user = "mediagoblin"; - group = "mediagoblin"; - permissions = "0400"; - text = '' - [DEFAULT] - data_basedir = "${varDir}" - - [mediagoblin] - direct_remote_path = /mgoblin_static/ - email_sender_address = "mediagoblin@tools.immae.eu" - - #sql_engine = sqlite:///%(data_basedir)s/mediagoblin.db - sql_engine = ${env.psql_url} - - email_debug_mode = false - allow_registration = false - allow_reporting = true - - theme = airymodified - - user_privilege_scheme = "uploader,commenter,reporter" - - # We need to redefine them here since we override data_basedir - # cf /usr/share/webapps/mediagoblin/mediagoblin/config_spec.ini - workbench_path = %(data_basedir)s/media/workbench - crypto_path = %(data_basedir)s/crypto - theme_install_dir = %(data_basedir)s/themes/ - theme_linked_assets_dir = %(data_basedir)s/theme_static/ - plugin_linked_assets_dir = %(data_basedir)s/plugin_static/ - - [storage:queuestore] - base_dir = %(data_basedir)s/media/queue - - [storage:publicstore] - base_dir = %(data_basedir)s/media/public - base_url = /mgoblin_media/ - - [celery] - CELERY_RESULT_DBURI = ${env.redis_url} - BROKER_URL = ${env.redis_url} - CELERYD_CONCURRENCY = 1 - - [plugins] - [[mediagoblin.plugins.geolocation]] - [[mediagoblin.plugins.ldap]] - [[[immae.eu]]] - LDAP_SERVER_URI = 'ldaps://ldap.immae.eu:636' - LDAP_SEARCH_BASE = 'dc=immae,dc=eu' - LDAP_BIND_DN = 'cn=mediagoblin,ou=services,dc=immae,dc=eu' - LDAP_BIND_PW = '${env.ldap.password}' - LDAP_SEARCH_FILTER = '(&(memberOf=cn=users,cn=mediagoblin,ou=services,dc=immae,dc=eu)(uid={username}))' - EMAIL_SEARCH_FIELD = 'mail' - [[mediagoblin.plugins.basicsearch]] - [[mediagoblin.plugins.piwigo]] - [[mediagoblin.plugins.processing_info]] - [[mediagoblin.media_types.image]] - [[mediagoblin.media_types.video]] - ''; - }]; - - ids.uids.mediagoblin = myconfig.env.tools.mediagoblin.user.uid; - ids.gids.mediagoblin = myconfig.env.tools.mediagoblin.user.gid; - - users.users.mediagoblin = { - name = "mediagoblin"; - uid = config.ids.uids.mediagoblin; - group = "mediagoblin"; - description = "Mediagoblin user"; - home = varDir; - useDefaultShell = true; - extraGroups = [ "keys" ]; - }; - - users.groups.mediagoblin.gid = config.ids.gids.mediagoblin; - - systemd.services.mediagoblin-web = { - description = "Mediagoblin service"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - wants = [ "postgresql.service" "redis.service" ]; - - environment.SCRIPT_NAME = "/mediagoblin/"; - - script = '' - exec ./bin/paster serve \ - ${paste_local} \ - --pid-file=${socketsDir}/mediagoblin.pid - ''; - - preStop = '' - exec ./bin/paster serve \ - --pid-file=${socketsDir}/mediagoblin.pid \ - ${paste_local} stop - ''; - preStart = '' - ./bin/gmg -cf ${mediagoblin_init} dbupdate - ''; - - serviceConfig = { - User = "mediagoblin"; - PrivateTmp = true; - Restart = "always"; - TimeoutSec = 15; - Type = "simple"; - WorkingDirectory = pythonRoot; - PIDFile = "${socketsDir}/mediagoblin.pid"; - }; - - unitConfig.RequiresMountsFor = varDir; - }; - - systemd.services.mediagoblin-celeryd = { - description = "Mediagoblin service"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "mediagoblin-web.service" ]; - - environment.MEDIAGOBLIN_CONFIG = "${pythonRoot}/mediagoblin_local.ini"; - environment.CELERY_CONFIG_MODULE = "mediagoblin.init.celery.from_celery"; - - script = '' - exec ./bin/celery worker \ - --logfile=${varDir}/celery.log \ - --loglevel=INFO - ''; - - serviceConfig = { - User = "mediagoblin"; - PrivateTmp = true; - Restart = "always"; - TimeoutSec = 60; - Type = "simple"; - WorkingDirectory = pythonRoot; - PIDFile = "${socketsDir}/mediagoblin-celeryd.pid"; - }; - - unitConfig.RequiresMountsFor = varDir; - }; - - system.activationScripts.mediagoblin = { - deps = [ "users" ]; - text = '' - install -m 0755 -o mediagoblin -g mediagoblin -d ${socketsDir} - install -m 0755 -o mediagoblin -g mediagoblin -d ${varDir} - if [ -d ${varDir}/plugin_static/ ]; then - rm ${varDir}/plugin_static/coreplugin_basic_auth - ln -sf ${pythonRoot}/mediagoblin/plugins/basic_auth/static ${varDir}/plugin_static/coreplugin_basic_auth - fi - ''; - }; - - services.myWebsites.tools.modules = [ - "proxy" "proxy_http" - ]; - users.users.wwwrun.extraGroups = [ "mediagoblin" ]; - security.acme.certs."eldiron".extraDomains."mgoblin.immae.eu" = null; - services.myWebsites.tools.vhostConfs.mgoblin = { - certName = "eldiron"; - hosts = ["mgoblin.immae.eu" ]; - root = null; - extraConfig = [ '' - Alias /mgoblin_media ${varDir}/media/public - - Options -Indexes +FollowSymLinks +MultiViews +Includes - Require all granted - - - Alias /theme_static ${varDir}/theme_static - - Options -Indexes +FollowSymLinks +MultiViews +Includes - Require all granted - - - Alias /plugin_static ${varDir}/plugin_static - - Options -Indexes +FollowSymLinks +MultiViews +Includes - Require all granted - - - ProxyPreserveHost on - ProxyVia On - ProxyRequests Off - ProxyPass /mgoblin_media ! - ProxyPass /theme_static ! - ProxyPass /plugin_static ! - ProxyPassMatch ^/.well-known/acme-challenge ! - ProxyPass / unix://${socketsDir}/mediagoblin.sock|http://mgoblin.immae.eu/ - ProxyPassReverse / unix://${socketsDir}/mediagoblin.sock|http://mgoblin.immae.eu/ - '' ]; - }; - }; -} -- cgit v1.2.3