{ 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 = "xmpp.${TLD}"; bonecoDomain = "boneco.${TLD}"; pdfsDomain = "pdfs-da-d-maria.${TLD}"; ciLogsDomain = "ci.${TLD}"; songbooksDocumentationDomain = "songbooks.${TLD}"; mediatorDocumentationDomain = "mediator.${TLD}"; cementDocumentationDomain = "cement.${TLD}"; piresProdDomain = "pires.${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; elementDomain = "element.${TLD}"; matrixDomain = "matrix.${TLD}"; matrixServerJSON = { "m.server" = "${matrixDomain}:443"; }; matrixClientJSON = { "m.homeserver" = { "base_url" = "https://${TLD}"; }; }; matrixPort = 8008; }; 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 git clone https://gitlab.com/EuAndreh/pires.git ${config.piresProdDir} fi pushd ${config.piresProdDir} git pull poetry install --no-dev --extras "waitress" poetry run flask inicializar-banco poetry run waitress-serve --host localhost --port ${config.piresProdPort} --call pires:create_app '').overrideAttrs (baseAttrs: { buildInputs = with pkgs; [ git poetry ]; }); mautrix-whatsapp = pkgs.writeShellScriptBin "run-mautrix-whatsapp.sh" '' pushd $HOME mkdir -p logs ${pkgsUnstable.mautrix-whatsapp}/bin/mautrix-whatsapp -g -c /data/mautrix-whatsapp-config.yaml -r /data/mautrix-whatsapp-registration.yaml ${pkgsUnstable.mautrix-whatsapp}/bin/mautrix-whatsapp -c /data/mautrix-whatsapp-config.yaml ''; mautrix-telegram = pkgs.writeShellScriptBin "run-mautrix-telegram.sh" '' DIR=$HOME/mautrix-telegram if [[ ! -d "$DIR" ]]; then ${pkgs.git}/bin/git clone https://github.com/tulir/mautrix-telegram.git "$DIR" fi pushd "$DIR" ${pkgs.git}/bin/git pull ${pkgsUnstable.mautrix-telegram}/bin/mautrix-telegram -g -c /data/mautrix-telegram-config.yaml -r /data/mautrix-telegram-registration.yaml ${pkgs.python3Packages.alembic}/bin/alembic -x config=/data/mautrix-telegram-config.yaml upgrade head ${pkgsUnstable.mautrix-telegram}/bin/mautrix-telegram -c /data/mautrix-telegram-config.yaml ''; 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 matrix-synapse poetry pkgsUnstable.mautrix-whatsapp pkgsUnstable.mautrix-telegram ]; 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.TLD}" = { locations."= /.well-known/matrix/server".extraConfig = '' add_header Content-Type application/json; return 200 '${builtins.toJSON config.matrixServerJSON}'; ''; locations."= /.well-known/matrix/client".extraConfig = '' add_header Content-Type application/json; add_header Access-Control-Allow-Origin *; return 200 '${builtins.toJSON config.matrixClientJSON}'; ''; }; "${config.matrixDomain}" = { enableACME = true; forceSSL = true; locations."/_matrix" = { proxyPass = "http://[::1]:${toString config.matrixPort}"; }; }; "${config.elementDomain}" = { enableACME = true; forceSSL = true; root = pkgs.element-web.override { conf = { default_server_config."m.homeserver" = { "base_url" = "https://${config.matrixDomain}"; "server_name" = "https://${config.matrixDomain}"; }; }; }; }; "${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.piresProdDomain}" = { forceSSL = true; enableACME = true; locations = { "/" = { proxyPass = "http://localhost:${config.piresProdPort}/"; }; }; }; "${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 # } # ''; }; matrix-synapse = { enable = true; server_name = config.matrixDomain; # Created the new user by temporarily setting this to true enable_registration = false; listeners = [{ port = config.matrixPort; bind_address = "::1"; type = "http"; tls = false; x_forwarded = true; resources = [{ names = [ "client" "federation" ]; compress = false; }]; }]; app_service_config_files = [ "/data/mautrix-whatsapp-registration.yaml" # "/data/mautrix-telegram-registration.yaml" ]; }; }; 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 = false; # 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" ]; }; "mautrix-whatsapp" = { enable = true; # Unit description = "mautrix-whatsapp systemd service"; after = [ "network.target" ]; # Service serviceConfig = { User = "${envsubstConfiguration.userName}"; ExecStart = "${mautrix-whatsapp}/bin/run-mautrix-whatsapp.sh"; Restart = "always"; }; # Install wantedBy = [ "multi-user.target" ]; }; "mautrix-telegram" = { enable = false; # Unit description = "mautrix-telegram systemd service"; after = [ "network.target" ]; # Service serviceConfig = { User = "${envsubstConfiguration.userName}"; ExecStart = "${mautrix-telegram}/bin/run-mautrix-telegram.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; }