From 669b87efe9f9e1b9a9954d94f032bb46bd6d36ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 13 Oct 2022 00:03:32 +0100 Subject: [PATCH 1/5] treewide: Refactor in order to clean up flake.nix --- configuration/default.nix | 12 ++ .../linode/default.nix} | 0 .../linode}/hardware-configuration.nix | 0 configuration/hardware-specific/vm.nix | 17 +++ flake.lock | 17 --- flake.nix | 139 ++++++++---------- lib/default.nix | 10 ++ 7 files changed, 97 insertions(+), 98 deletions(-) rename configuration/{linode.nix => hardware-specific/linode/default.nix} (100%) rename configuration/{ => hardware-specific/linode}/hardware-configuration.nix (100%) create mode 100644 configuration/hardware-specific/vm.nix create mode 100644 lib/default.nix diff --git a/configuration/default.nix b/configuration/default.nix index 8f51f0b..cc51bac 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,9 +1,13 @@ { pkgs, lib, + modulesPath, ... }: { imports = [ + "${modulesPath}/profiles/headless.nix" + (import ../modules) + ./services/gitea.nix ./services/nextcloud.nix ./services/webserver.nix @@ -12,6 +16,14 @@ ./sops.nix ]; + nixpkgs.overlays = [ + (final: prev: { + local = import ../pkgs { + pkgs = prev; + }; + }) + ]; + nix = { package = pkgs.nixFlakes; extraOptions = '' diff --git a/configuration/linode.nix b/configuration/hardware-specific/linode/default.nix similarity index 100% rename from configuration/linode.nix rename to configuration/hardware-specific/linode/default.nix diff --git a/configuration/hardware-configuration.nix b/configuration/hardware-specific/linode/hardware-configuration.nix similarity index 100% rename from configuration/hardware-configuration.nix rename to configuration/hardware-specific/linode/hardware-configuration.nix diff --git a/configuration/hardware-specific/vm.nix b/configuration/hardware-specific/vm.nix new file mode 100644 index 0000000..aed39e4 --- /dev/null +++ b/configuration/hardware-specific/vm.nix @@ -0,0 +1,17 @@ +{lib, ...}: { + users.users.tlater.password = "insecure"; + + # Disable graphical tty so -curses works + boot.kernelParams = ["nomodeset"]; + + # Sets the base domain for nginx to localhost so that we + # can easily test locally with the VM. + services.nginx.domain = lib.mkOverride 99 "localhost"; + + # Use the staging secrets + sops.defaultSopsFile = lib.mkOverride 99 ../../keys/staging.yaml; + + # # Set up VM settings to match real VPS + # virtualisation.memorySize = 3941; + # virtualisation.cores = 2; +} diff --git a/flake.lock b/flake.lock index 11b5c2c..c44d4a0 100644 --- a/flake.lock +++ b/flake.lock @@ -190,22 +190,6 @@ "type": "indirect" } }, - "nixos-hardware": { - "locked": { - "lastModified": 1665321371, - "narHash": "sha256-0SO6MTW0bX6lxZmz1AZW/Xmk+hnTd7/hp1vF7Tp7jg0=", - "owner": "nixos", - "repo": "nixos-hardware", - "rev": "236ba4df714131059945d7754c0aa3fbe9d2f74c", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "master", - "repo": "nixos-hardware", - "type": "github" - } - }, "nixpkgs": { "locked": { "lastModified": 1665466769, @@ -299,7 +283,6 @@ }, "root": { "inputs": { - "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", "sops-nix": "sops-nix", "tlaternet-webserver": "tlaternet-webserver" diff --git a/flake.nix b/flake.nix index 5603e08..a67b314 100644 --- a/flake.nix +++ b/flake.nix @@ -3,12 +3,10 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; - nixos-hardware.url = "github:nixos/nixos-hardware/master"; sops-nix = { url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; - tlaternet-webserver = { url = "git+https://gitea.tlater.net/tlaternet/tlaternet.git"; inputs.nixpkgs.follows = "nixpkgs"; @@ -18,118 +16,97 @@ outputs = { self, nixpkgs, - nixos-hardware, sops-nix, tlaternet-webserver, }: let system = "x86_64-linux"; - - overlays = [ - (final: prev: { - local = import ./pkgs { - pkgs = prev; - }; - }) - ]; - - pkgs = import nixpkgs {inherit system overlays;}; - sops-pkgs = sops-nix.packages.${system}; in { - nixosConfigurations = { - tlaternet = nixpkgs.lib.nixosSystem { - inherit system; - - modules = [ - ({modulesPath, ...}: { - imports = [(modulesPath + "/profiles/headless.nix")]; - nixpkgs.overlays = overlays; - }) - (import ./modules) - - (import ./configuration) - (import ./configuration/linode.nix) - (import ./configuration/hardware-configuration.nix) + ################## + # Configurations # + ################## + nixosConfigurations = let + # Modules that should be generic to all systems + genericModule = {...}: { + imports = [ + # Inject flake dependencies sops-nix.nixosModules.sops tlaternet-webserver.nixosModules.default + + # Import actual configuration + (import ./configuration) + ]; + }; + in { + # The actual system definition + tlaternet = nixpkgs.lib.nixosSystem { + inherit system; + modules = [ + genericModule + (import ./configuration/hardware-specific/linode) ]; }; + # A qemu VM to test the above with vm = nixpkgs.lib.nixosSystem { inherit system; - modules = [ - ({modulesPath, ...}: { - imports = [(modulesPath + "/profiles/headless.nix")]; - nixpkgs.overlays = overlays; - }) - (import ./modules) - - (import ./configuration) - sops-nix.nixosModules.sops - tlaternet-webserver.nixosModules.default - ({lib, ...}: { - users.users.tlater.password = "insecure"; - - # Disable graphical tty so -curses works - boot.kernelParams = ["nomodeset"]; - - # Sets the base domain for nginx to localhost so that we - # can easily test locally with the VM. - services.nginx.domain = lib.mkOverride 99 "localhost"; - - # Use the staging secrets - sops.defaultSopsFile = lib.mkOverride 99 ./keys/staging.yaml; - - # # Set up VM settings to match real VPS - # virtualisation.memorySize = 3941; - # virtualisation.cores = 2; - }) + genericModule + (import ./configuration/hardware-specific/vm.nix) ]; }; }; + #################### + # Helper functions # + #################### + lib = import ./lib {lib = nixpkgs.lib;}; + + #################### + # VM launch script # + #################### apps.${system}.default = let inherit (self.nixosConfigurations.vm.config.system.build) vm; inherit (nixpkgs.legacyPackages.${system}) writeShellScript; - inherit (nixpkgs.lib.attrsets) mapAttrsToList; - inherit (nixpkgs.lib.strings) concatStringsSep; - ports = { + qemuNetOpts = self.lib.makeQemuNetOpts { "2222" = "2222"; "3080" = "80"; "3443" = "443"; - "2221" = "2221"; "21025" = "21025"; # Starbound }; - QEMU_NET_OPTS = - concatStringsSep "," - (mapAttrsToList - (host: vm: "hostfwd=::${host}-:${vm}") - ports); in { type = "app"; program = builtins.toString (writeShellScript "run-vm" '' export QEMU_OPTS="-m 3941 -smp 2 -curses" - export QEMU_NET_OPTS="${QEMU_NET_OPTS}" + export QEMU_NET_OPTS="${qemuNetOpts}" "${vm}/bin/run-tlaternet-vm" ''); }; - devShells.${system}.default = pkgs.mkShell { - sopsPGPKeyDirs = ["./keys/hosts/" "./keys/users/"]; - nativeBuildInputs = [ - sops-pkgs.sops-import-keys-hook - ]; - buildInputs = with pkgs; [ - nixfmt - git-lfs - sops-pkgs.sops-init-gpg-key - ]; + ########################### + # Development environment # + ########################### + devShells.${system}.default = let + inherit (sops-nix.packages.${system}) sops-import-keys-hook sops-init-gpg-key; + deploy-rs-bin = deploy-rs.packages.${system}.default; + pkgs = nixpkgs.legacyPackages.${system}; + in + nixpkgs.legacyPackages.${system}.mkShell { + sopsPGPKeyDirs = ["./keys/hosts/" "./keys/users/"]; + nativeBuildInputs = [ + sops-import-keys-hook + ]; + packages = with pkgs; [ + nixfmt + git-lfs + sops-init-gpg-key + deploy-rs-bin + ]; - shellHook = '' - # Work around sudo requiring a full terminal when deploying to - # a remote host - export NIX_SSHOPTS="-t" - ''; - }; + shellHook = '' + # Work around sudo requiring a full terminal when deploying to + # a remote host + export NIX_SSHOPTS="-t" + ''; + }; }; } diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..20d874d --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,10 @@ +{lib}: let + inherit (lib.attrsets) mapAttrsToList; + inherit (lib.strings) concatStringsSep; +in { + makeQemuNetOpts = portMapping: + concatStringsSep "," + (mapAttrsToList + (host: vm: "hostfwd=::${host}-:${vm}") + portMapping); +} From a994fd8ba0e58019d12b760739d26aecb7fc232b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 13 Oct 2022 00:30:07 +0100 Subject: [PATCH 2/5] starbound: Fix post-update issues --- configuration/default.nix | 2 +- pkgs/default.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration/default.nix b/configuration/default.nix index cc51bac..52be9a1 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -35,7 +35,7 @@ }; nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.getName pkg) ["steam-runtime" "steamcmd"]; + builtins.elem (lib.getName pkg) ["steam-original" "steam-runtime" "steamcmd"]; # Optimization for minecraft servers, see: # https://bugs.mojang.com/browse/MC-183518 diff --git a/pkgs/default.nix b/pkgs/default.nix index c92874b..55bf74a 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,5 +1,5 @@ {pkgs, ...}: let - inherit (pkgs.lib) callPackage; + inherit (pkgs) callPackage; in { starbound = callPackage ./starbound {}; } From da5c33955272d4b5fcdac085903768aa75dff36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 13 Oct 2022 00:30:29 +0100 Subject: [PATCH 3/5] nextcloud: Update nextcloud version --- configuration/services/nextcloud.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration/services/nextcloud.nix b/configuration/services/nextcloud.nix index 0d4e299..5186131 100644 --- a/configuration/services/nextcloud.nix +++ b/configuration/services/nextcloud.nix @@ -4,7 +4,7 @@ ... }: let inherit (pkgs) fetchNextcloudApp; - nextcloud = pkgs.nextcloud23; + nextcloud = pkgs.nextcloud24; hostName = "nextcloud.${config.services.nginx.domain}"; in { services.nextcloud = { From efa1558af3ea32313e25653eb5054b118f6181b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Thu, 13 Oct 2022 00:31:08 +0100 Subject: [PATCH 4/5] flake.nix: Add deploy-rs for deployment management --- flake.lock | 84 ++++++++++++++++++++++++++++++++++++++++++++++++------ flake.nix | 25 +++++++++++++++- 2 files changed, 100 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index c44d4a0..d144fcb 100644 --- a/flake.lock +++ b/flake.lock @@ -40,6 +40,26 @@ "type": "github" } }, + "deploy-rs": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs", + "utils": "utils" + }, + "locked": { + "lastModified": 1659725433, + "narHash": "sha256-1ZxuK67TL29YLw88vQ18Y2Y6iYg8Jb7I6/HVzmNB6nM=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "41f15759dd8b638e7b4f299730d94d5aa46ab7eb", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, "devshell": { "flake": false, "locked": { @@ -64,7 +84,7 @@ "flake-utils-pre-commit": "flake-utils-pre-commit", "gomod2nix": "gomod2nix", "mach-nix": "mach-nix", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs_3", "poetry2nix": "poetry2nix", "pre-commit-hooks": "pre-commit-hooks" }, @@ -128,6 +148,22 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1648199409, + "narHash": "sha256-JwPKdC2PoVBkG6E+eWw3j6BMR6sL3COpYWfif7RVb8Y=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "64a525ee38886ab9028e6f61790de0832aa3ef03", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils-pre-commit": { "locked": { "lastModified": 1644229661, @@ -192,16 +228,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1665466769, - "narHash": "sha256-L+qcHpb4Ac3PipMXJY/Ktbu1+KXy23WCZ8pXWmsf7zY=", - "owner": "nixos", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "0b20bf89e0035b6d62ad58f9db8fdbc99c2b01e8", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixos-22.05", + "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } @@ -223,6 +259,22 @@ } }, "nixpkgs_2": { + "locked": { + "lastModified": 1665466769, + "narHash": "sha256-L+qcHpb4Ac3PipMXJY/Ktbu1+KXy23WCZ8pXWmsf7zY=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "0b20bf89e0035b6d62ad58f9db8fdbc99c2b01e8", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-22.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { "locked": { "lastModified": 1657638268, "narHash": "sha256-blBNtQSslAFkg0Gym9fWNJk+bPxGSZib4SOcPrmTPi4=", @@ -283,7 +335,8 @@ }, "root": { "inputs": { - "nixpkgs": "nixpkgs", + "deploy-rs": "deploy-rs", + "nixpkgs": "nixpkgs_2", "sops-nix": "sops-nix", "tlaternet-webserver": "tlaternet-webserver" } @@ -364,6 +417,21 @@ "type": "git", "url": "https://gitea.tlater.net/tlaternet/tlaternet.git" } + }, + "utils": { + "locked": { + "lastModified": 1648297722, + "narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index a67b314..56caaaa 100644 --- a/flake.nix +++ b/flake.nix @@ -3,6 +3,7 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; + deploy-rs.url = "github:serokell/deploy-rs"; sops-nix = { url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; @@ -17,6 +18,7 @@ self, nixpkgs, sops-nix, + deploy-rs, tlaternet-webserver, }: let system = "x86_64-linux"; @@ -56,6 +58,27 @@ }; }; + ############################ + # Deployment configuration # + ############################ + deploy.nodes.tlaternet = { + hostname = "tlater.net"; + + profiles.system = { + user = "root"; + path = deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.tlaternet; + }; + + sshUser = "tlater"; + sshOpts = ["-p" "2222"]; + fastConnection = true; + }; + + ######### + # Tests # + ######### + checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) deploy-rs.lib; + #################### # Helper functions # #################### @@ -76,7 +99,7 @@ in { type = "app"; program = builtins.toString (writeShellScript "run-vm" '' - export QEMU_OPTS="-m 3941 -smp 2 -curses" + export QEMU_OPTS="-m 3941 -smp 2 -display curses" export QEMU_NET_OPTS="${qemuNetOpts}" "${vm}/bin/run-tlaternet-vm" ''); From 72e7eed9d1d92ead802b444a662c4e4da303ec9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Fri, 14 Oct 2022 01:11:15 +0100 Subject: [PATCH 5/5] treewide: Add fail2ban --- configuration/default.nix | 21 +++++++++++++++++++++ configuration/services/gitea.nix | 19 +++++++++++++++++++ configuration/services/nextcloud.nix | 23 +++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/configuration/default.nix b/configuration/default.nix index 52be9a1..da5b45b 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -84,5 +84,26 @@ acceptTerms = true; }; + services.fail2ban = { + enable = true; + extraPackages = [pkgs.ipset]; + banaction = "iptables-ipset-proto6-allports"; + bantime-increment.enable = true; + + jails = { + nginx-botsearch = '' + enabled = true + logpath = /var/log/nginx/access.log + ''; + }; + + ignoreIP = [ + "127.0.0.0/8" + "10.0.0.0/8" + "172.16.0.0/12" + "192.168.0.0/16" + ]; + }; + system.stateVersion = "20.09"; } diff --git a/configuration/services/gitea.nix b/configuration/services/gitea.nix index cd99951..f346097 100644 --- a/configuration/services/gitea.nix +++ b/configuration/services/gitea.nix @@ -28,4 +28,23 @@ in { locations."/".proxyPass = "http://${httpAddress}:${toString httpPort}"; }; + + # Block repeated failed login attempts + # + # TODO(tlater): Update to the new regex, since apparently this one + # is deprecated (but the new one doesn't work on the current version + # of gitea yet): https://docs.gitea.io/en-us/fail2ban-setup/ + environment.etc = { + "fail2ban/filter.d/gitea.conf".text = '' + [Definition] + failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from + journalmatch = _SYSTEMD_UNIT=gitea.service + _COMM=gitea + SYSLOG_IDENTIFIER=gitea + ''; + }; + + services.fail2ban.jails = { + gitea = '' + enabled = true + ''; + }; } diff --git a/configuration/services/nextcloud.nix b/configuration/services/nextcloud.nix index 5186131..7e3a41a 100644 --- a/configuration/services/nextcloud.nix +++ b/configuration/services/nextcloud.nix @@ -40,4 +40,27 @@ in { forceSSL = true; enableACME = true; }; + + # Block repeated failed login attempts + environment.etc = { + "fail2ban/filter.d/nextcloud.conf".text = '' + [Definition] + _groupsre = (?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*) + failregex = \{%(_groupsre)s,?\s*"remoteAddr":""%(_groupsre)s,?\s*"message":"Login failed: + \{%(_groupsre)s,?\s*"remoteAddr":""%(_groupsre)s,?\s*"message":"Trusted domain error. + datepattern = ,?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?" + journalmatch = SYSLOG_IDENTIFIER=Nextcloud + ''; + }; + + services.fail2ban.jails = { + nextcloud = '' + enabled = true + + # Nextcloud does some throttling already, so we need to set + # these to something bigger. + findtime = 43200 + bantime = 86400 + ''; + }; }