aboutsummaryrefslogtreecommitdiff
path: root/vps-configuration.nix
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2020-09-06 09:53:58 -0300
committerEuAndreh <eu@euandre.org>2020-09-06 15:48:45 -0300
commit3f1d7201bfc46ff9edaa109bc41b59908f99c23b (patch)
tree30c89f1f19c156c044855839b62ea3eeca0a739a /vps-configuration.nix
parentnixos-switch.sh: Decouple the update of pires app from deploying the VPS (diff)
downloadserver-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.nix410
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;
+}