# Static web and gemini hosting # Copyright (C) 2022 Nguyễn Gia Phong # # This file is part of loang configuration. # # Loang configuration is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Loang configuration is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with loang configuration. If not, see . { config, lib, pkgs, ... }: let inherit (config.networking) domain; bindUserDirs = sources: target: lib.mapAttrs' (user: dir: { name = target + user; value = { device = "${config.users.users.${user}.home}/${dir}"; options = [ "bind" ]; }; }) sources; phylactery = config.services.phylactery; in { fileSystems = bindUserDirs { cnx = "www"; } "${config.services.nginx.virtualHosts.${domain}.root}/~"; networking.firewall.allowedTCPPorts = [ 80 # HTTP 443 # TLS 1965 # Gemini ]; security = { acme = { acceptTerms = true; defaults.email = "mcsinyx@disroot.org"; }; pam.services.nginx.setEnvironment = false; }; services = { molly-brown = let certDir = config.security.acme.certs.${domain}.directory; in { certPath = "${certDir}/cert.pem"; docBase = "/var/lib/gemini/${domain}"; enable = true; hostName = domain; keyPath = "${certDir}/key.pem"; }; nginx = { additionalModules = [ pkgs.nginxModules.pam ]; appendHttpConfig = '' access_log off; ''; enable = true; enableReload = true; logError = "/dev/null"; recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; virtualHosts = { ${domain} = { enableACME = true; extraConfig = '' add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; ''; forceSSL = true; locations = { "/".index = "index.html index.xhtml"; "/~mingnho/chat" = { proxyPass = "http://127.0.0.1:3000"; proxyWebsockets = true; }; }; root = "/var/lib/www/${domain}"; }; "adol.pw" = { enableACME = true; forceSSL = true; root = "/var/lib/www/adol.pw"; }; "septagram.suricrasia.online" = { enableACME = true; extraConfig = '' autoindex on; ''; forceSSL = true; root = "/var/lib/www/septagram.suricrasia.online"; }; } // (let aliasOpenNIC = openNIC: icann: config: { ${openNIC} = { # https://wiki.opennic.org/opennic/tls addSSL = true; useACMEHost = icann; } // config; ${icann} = { enableACME = true; forceSSL = true; } // config; }; in (aliasOpenNIC "cercle.libre" "khoanh.${domain}" { root = "/var/lib/www/cercle.libre"; }) // (aliasOpenNIC "sinyx.indy" "cnx.gdn" { root = "/var/lib/www/cnx.gdn"; }) // (aliasOpenNIC "pix.sinyx.indy" "px.cnx.gdn" { locations = { "/".index = "index.xhtml"; "~ /index.xhtml$".extraConfig = '' expires -1; ''; }; root = "/mnt/nas/www/px.cnx.gdn"; }) // (aliasOpenNIC "striproman.pirate" "xem.${domain}" (let address = "http://${phylactery.host}:${toString phylactery.port}"; in { locations."/" = { proxyPass = address; extraConfig = '' auth_pam "Password Required"; auth_pam_service_name "nginx"; ''; }; }))); }; phylactery = { enable = true; library = "/mnt/nas/www/striproman.pirate"; port = 42069; }; }; systemd.services = { molly-brown.serviceConfig.SupplementaryGroups = [ config.security.acme.certs.${domain}.group ]; nginx.serviceConfig.SupplementaryGroups = [ "shadow" ]; }; }