diff options
author | EuAndreh <eu@euandre.org> | 2020-09-06 09:53:58 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2020-09-06 15:48:45 -0300 |
commit | 3f1d7201bfc46ff9edaa109bc41b59908f99c23b (patch) | |
tree | 30c89f1f19c156c044855839b62ea3eeca0a739a /vps-configuration.nix | |
parent | nixos-switch.sh: Decouple the update of pires app from deploying the VPS (diff) | |
download | server-3f1d7201bfc46ff9edaa109bc41b59908f99c23b.tar.gz server-3f1d7201bfc46ff9edaa109bc41b59908f99c23b.tar.xz |
Refactor vps-configuration.nix: Split secrets from config and envsubst vars
Also rename thingTLD to thingDomain.
Diffstat (limited to 'vps-configuration.nix')
-rw-r--r-- | vps-configuration.nix | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/vps-configuration.nix b/vps-configuration.nix new file mode 100644 index 0000000..06d0e29 --- /dev/null +++ b/vps-configuration.nix @@ -0,0 +1,410 @@ +{ config, pkgs, ... }: + +let + envsubstConfiguration = + pkgs.callPackage /etc/nixos/envsubst-configuration.nix { }; + config = rec { + letsencryptEmail = + "eu@euandre.org"; # this should change when adding email to the box + authorizedKey = + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDF+uy407LKZAFnfFkJPRiOBzwV98qIEcKhITnLYhqfITfrJvcFVOY0/YDCrs6WHXyLdM29AoywVWsQ1qXiB7xQCwknPV8YZoCnJQcn0gvH8jbCk+C8Po0Rx846wbhL49qYolnmlhe+Uoy30j7XIJSDtPVO9d/hZqt2GPwGVJ98HLyY2ak+j4i1YkHr+mPFgnCaqCAzA374d1Bop18+YENYtMMU0k8hCsomwZny/7qNo4V8mjLxQAS8FvTuljxlthEpOM4Jsjl07yDLgE69kLvU7mmFi8EeC26e50N18Ouse82dZigtVhAMeLBhbJnQbDff4WfUBzSjpKjZPGcxoRaej3qSRbIkcMMqCOSlww6GcjRi+COvlpA4c1i4hKI15wHceoiKghDLA6jbaHfOqEMldflYl5gCVUIYzJ5XehZppH6L7PzO+L4suNs+aFjWPDZ0jqEtcyTmgTMea40p7wwz086ExnBDorbG79oDiJrWc+swJjXuVakS+fQjb3mPsCC/FgUhsxEtqiVfvLo2mphp47pOYvs64aUp3RV9muqQNuS4tEuP9V1urGTLtgPL26LEjF0oLu1ag0H+VZY5O/T9KRYvWre8IWbj/KkZYo1tJaGJyEVr0plmyzLBEy8b3Hu/6Wtq7yB0Eii60fxqFWC24nEkvs1V0cxDa+o6I2iA9w== eu@euandre.org"; + TLD = envsubstConfiguration.TLD; + nextcloudDomain = "cloud.${TLD}"; + gitDomain = "git.${TLD}"; + prosodyDomain = "${TLD}"; + bonecoDomain = "boneco.${TLD}"; + pdfsDomain = "pdfs-da-d-maria.${TLD}"; + ciLogsDomain = "ci.${TLD}"; + songbooksDocumentationDomain = "songbooks.${TLD}"; + piresDocumentationDomain = "pires.${TLD}"; + mediatorDocumentationDomain = "mediator.${TLD}"; + cementDocumentationDomain = "cement.${TLD}"; + piresProdDomain = "pires-prod.${TLD}"; + piresProdPort = "1234"; + piresProdDir = "/home/andreh/pires-git/"; + nextcloudDatabaseUser = "nextcloud"; + nextcloudAdminUser = envsubstConfiguration.userName; + nextcloudTablePrefix = "euandreh_"; + gitPort = "81"; + prosodyConverseDomain = "chat.${TLD}"; + prosodyAdminUser = "eu@${TLD}"; + prosodyMUCDomain = "conference.${TLD}"; + prosodyPort = "5222"; + prosodyHTTPPort = "5280"; + prosodyEnable = envsubstConfiguration.prosodyEnable == "true"; + openSSHPort = 23841; + }; + staticSiteFromRepo = repoName: + pkgs.stdenv.mkDerivation { + name = repoName; + src = fetchTarball + "https://git.sr.ht/~euandreh/${repoName}/archive/master.tar.gz"; + phases = "unpackPhase buildPhase"; + buildPhase = '' + mkdir $out + cp index.html $out + cp favicon.ico $out + ''; + }; + pkgsUnstable = import (builtins.fetchTarball { + url = "https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz"; + }) { }; + piresProd = pkgs.writeShellScriptBin "run-pires.sh" '' + export FLASK_CONFIG=production + + export PIRES_PROD_DIR="$" + if [[ ! -d ${config.piresProdDir} ]]; then + ${pkgs.git}/bin/git clone https://gitlab.com/EuAndreh/pires.git ${config.piresProdDir} + fi + pushd ${config.piresProdDir} + ${pkgs.git}/bin/git pull + ${pkgsUnstable.poetry}/bin/poetry install --no-dev --extras "waitress" + ${pkgsUnstable.poetry}/bin/poetry run flask inicializar-banco + ${pkgsUnstable.poetry}/bin/poetry run waitress-serve --host localhost --port ${config.piresProdPort} --call pires:create_app + ''; +in { + nix = { + binaryCaches = [ "https://euandreh.cachix.org" ]; + binaryCachePublicKeys = + [ "euandreh.cachix.org-1:ms8eOKJJtb20GJDPCf8Nvob8YI0oF8dREAMdx3XF/90=" ]; + }; + + imports = [ ./hardware-configuration.nix ]; + + boot.loader.grub = { + enable = true; + version = 2; + device = "/dev/vda"; + }; + + networking = { + useDHCP = false; + interfaces.ens3.useDHCP = true; + }; + + environment.systemPackages = with pkgs; [ + vim + git + gitAndTools.git-annex + gotop + ]; + + networking.firewall.allowedTCPPorts = [ + config.openSSHPort + + # HTTP and HTPPS: NGINX + 80 + 443 + ] ++ (if config.prosodyEnable then [ + # XMPP: Prosody + # https://prosody.im/doc/ports + 5000 + 5222 + 5269 + 5280 + 5281 + 5347 + 5582 + ] else + [ ]); + + security.acme = { + acceptTerms = true; + email = config.letsencryptEmail; + }; + + services = { + openssh = { + enable = true; + permitRootLogin = "no"; + passwordAuthentication = false; + ports = [ config.openSSHPort ]; + }; + + nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + virtualHosts = { + "${config.nextcloudDomain}" = { + forceSSL = true; + enableACME = true; + }; + "${config.gitDomain}" = { + forceSSL = true; + enableACME = true; + extraConfig = '' + location = /favicon.ico { + alias ${envsubstConfiguration.dataRoot}/favicons/git.ico; + } + location / { + proxy_pass http://localhost:${config.gitPort}; + } + ''; + }; + "${config.bonecoDomain}" = { + forceSSL = true; + enableACME = true; + root = staticSiteFromRepo "boneco"; + }; + "${config.pdfsDomain}" = { + forceSSL = true; + enableACME = true; + root = staticSiteFromRepo "pdfs-da-d-maria"; + }; + "${config.ciLogsDomain}" = { + forceSSL = true; + enableACME = true; + root = "${envsubstConfiguration.ciLogsRoot}"; + }; + "${config.mediatorDocumentationDomain}" = { + forceSSL = true; + enableACME = true; + extraConfig = '' + location = / { + return 301 master/; + } + root ${envsubstConfiguration.staticRoot}/mediator/; + ''; + }; + "${config.cementDocumentationDomain}" = { + forceSSL = true; + enableACME = true; + extraConfig = '' + location = / { + return 301 master/; + } + root ${envsubstConfiguration.staticRoot}/cement/; + ''; + }; + "${config.songbooksDocumentationDomain}" = { + forceSSL = true; + enableACME = true; + extraConfig = '' + location = / { + return 301 en/master/; + } + root ${envsubstConfiguration.staticRoot}/songbooks/; + ''; + }; + "${config.piresDocumentationDomain}" = { + forceSSL = true; + enableACME = true; + root = "${envsubstConfiguration.staticRoot}/pires/"; + }; + "${config.piresProdDomain}" = { + forceSSL = true; + enableACME = true; + locations = { + "/" = { proxyPass = "http://localhost:${config.piresProdPort}/"; }; + }; + }; + # Generate and maintain TLS certificate with NGINX + # to be used by Prosody + "${config.prosodyDomain}" = { + forceSSL = true; + enableACME = true; + }; + "${config.prosodyConverseDomain}" = { + forceSSL = true; + enableACME = true; + extraConfig = '' + location = /favicon.ico { + alias ${envsubstConfiguration.dataRoot}/favicons/conversejs.ico; + } + location = / { + return 301 conversejs; + } + location / { + proxy_pass http://localhost:${config.prosodyHTTPPort}/; + } + ''; + }; + }; + }; + + postgresql = { + enable = true; + ensureDatabases = [ "nextcloud" ]; + package = pkgs.postgresql_11; + ensureUsers = [{ + name = "nextcloud"; + ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES"; + }]; + }; + + nextcloud = { + enable = true; + package = pkgs.nextcloud19; + nginx.enable = true; + hostName = config.nextcloudDomain; + https = true; + maxUploadSize = "4G"; + autoUpdateApps.enable = true; + config = { + overwriteProtocol = "https"; + dbtype = "pgsql"; + dbhost = "/run/postgresql"; + dbuser = envsubstConfiguration.nextcloudDatabaseUser; + dbpassFile = + "${envsubstConfiguration.secretsRoot}/nextcloud-database.txt"; + dbtableprefix = config.nextcloudTablePrefix; + adminuser = config.nextcloudAdminUser; + adminpassFile = + "${envsubstConfiguration.secretsRoot}/nextcloud-admin.txt"; + }; + }; + + prosody = let + XMPP = { + fullchainPEM = "/var/lib/acme/${config.prosodyDomain}/fullchain.pem"; + keyPEM = "/var/lib/acme/${config.prosodyDomain}/key.pem"; + }; + ConverseJS = { + fullchainPEM = + "/var/lib/acme/${config.prosodyConverseDomain}/fullchain.pem"; + keyPEM = "/var/lib/acme/${config.prosodyConverseDomain}/key.pem"; + }; + in { + enable = config.prosodyEnable; + admins = [ config.prosodyAdminUser ]; + allowRegistration = false; + modules = { websocket = true; }; + package = pkgs.prosody.override { + withCommunityModules = [ "http_upload" "conversejs" "bookmarks" ]; + }; + extraModules = [ "http_upload" "conversejs" "bookmarks" ]; + virtualHosts = { + "${config.prosodyDomain}" = { + enabled = true; + domain = "${config.prosodyDomain}"; + ssl = { + cert = XMPP.fullchainPEM; + key = XMPP.keyPEM; + }; + }; + "${config.prosodyConverseDomain}" = { + enabled = true; + domain = "${config.prosodyConverseDomain}"; + ssl = { + cert = ConverseJS.fullchainPEM; + key = ConverseJS.keyPEM; + }; + }; + }; + }; + + lighttpd = { + enable = true; + port = pkgs.lib.toInt config.gitPort; + cgit = { + enable = true; + subdir = ""; + configText = '' + enable-blame=1 + enable-commit-graph=1 + enable-follow-links=1 + enable-index-owner=0 + enable-log-filecount=1 + enable-log-linecount=1 + root-desc=public repositories + root-readme=${envsubstConfiguration.gitRoot}/about.html + readme=:README.md + readme=:README + readme=:README.rst + readme=:README.org + max-repodesc-length=120 + remove-suffix=1 + root-title=EuAndreh's git repositories + snapshots=tar.gz zip + source-filter=${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py + about-filter=${pkgs.cgit}/lib/cgit/filters/about-formatting.sh + scan-path=${envsubstConfiguration.gitRoot} + ''; + }; + }; + + logrotate = { + enable = + false; # disabled due to extraConfig not being yet out of unstable + # extraConfig = '' + # compress + + # ${config.ciLogsRoot}/*/*.log { + # rotate 5 + # daily + # olddir ${config.staticRoot}/logrorate/ + # createolddir 744 andreh users + # su andreh users + # } + # ''; + }; + }; + + systemd.services = { + "nextcloud-setup" = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + }; + "data-folder-init" = { + enable = true; + description = "Setup data folders and permissions"; + wantedBy = [ "multi-user.target" ]; + script = pkgs.lib.fold (p: acc: + acc + '' + mkdir -p ${p} + chown -R andreh:users ${p} + chmod -R 755 ${p} + '') "" (with envsubstConfiguration; [ + staticRoot + gitRoot + faviconsRoot + ciLogsRoot + dataRoot + ]); + serviceConfig = { Type = "oneshot"; }; + }; + "poor-mans-logrotate" = { + enable = true; + description = "Delete old CI log files"; + wantedBy = [ "multi-user.target" ]; + script = '' + pushd ${envsubstConfiguration.ciLogsRoot} + find . -type f -name '*.log' -mtime 1 -delete + find . -type d -empty -delete + ${pkgs.bash}/bin/bash ci-gen-index.sh + ''; + serviceConfig = { Type = "oneshot"; }; + }; + "pires-prod" = { + enable = true; + # Unit + description = "Service for pires server deployment"; + after = [ "network.target" ]; + # Service + serviceConfig = { + User = "${envsubstConfiguration.userName}"; + ExecStart = "${piresProd}/bin/run-pires.sh"; + Restart = "always"; + }; + # Install + wantedBy = [ "multi-user.target" ]; + }; + }; + + users = { + mutableUsers = false; + extraUsers."${envsubstConfiguration.userName}" = { + uid = 1000; + isNormalUser = true; + extraGroups = [ "wheel" ]; + hashedPassword = + builtins.readFile "${envsubstConfiguration.secretsRoot}/user-hash.txt"; + openssh.authorizedKeys.keys = [ config.authorizedKey ]; + }; + }; + + system.stateVersion = envsubstConfiguration.systemStateVersion; +} |