diff --git a/.gitignore b/.gitignore
index 21e279e..dbee5b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
 /result
-/tlaternet.qcow2
+*.qcow2
diff --git a/configuration/default.nix b/configuration/default.nix
index ef1c804..d202fe5 100644
--- a/configuration/default.nix
+++ b/configuration/default.nix
@@ -11,7 +11,6 @@
     flake-inputs.sops-nix.nixosModules.sops
     flake-inputs.tlaternet-webserver.nixosModules.default
 
-    "${modulesPath}/profiles/headless.nix"
     "${modulesPath}/profiles/minimal.nix"
     (import ../modules)
 
diff --git a/configuration/hardware-specific/vm.nix b/configuration/hardware-specific/vm.nix
index b2e8826..7f1fcf1 100644
--- a/configuration/hardware-specific/vm.nix
+++ b/configuration/hardware-specific/vm.nix
@@ -14,7 +14,9 @@
 
   systemd.network.networks."10-eth0" = {
     matchConfig.Name = "eth0";
-    networkConfig.DHCP = "yes";
+    networkConfig = {
+      Address = "192.168.9.2/24";
+    };
   };
 
   # Both so we have a predictable key for the staging env, as well as
@@ -33,7 +35,18 @@
     }
   ];
 
-  # # Set up VM settings to match real VPS
-  # virtualisation.memorySize = 3941;
-  # virtualisation.cores = 2;
+  virtualisation.vmVariant = {
+    virtualisation = {
+      memorySize = 3941;
+      cores = 2;
+      graphics = false;
+    };
+
+    virtualisation.qemu = {
+      networkingOptions = lib.mkForce [
+        "-device virtio-net,netdev=n1"
+        "-netdev bridge,id=n1,br=br0,helper=$(which qemu-bridge-helper)"
+      ];
+    };
+  };
 }
diff --git a/flake.nix b/flake.nix
index f8255f6..6f6b386 100644
--- a/flake.nix
+++ b/flake.nix
@@ -36,6 +36,7 @@
     ...
   } @ inputs: let
     system = "x86_64-linux";
+    pkgs = nixpkgs.legacyPackages.${system};
   in {
     ##################
     # Configurations #
@@ -75,69 +76,53 @@
     #########
     checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) deploy-rs.lib;
 
-    ####################
-    # Helper functions #
-    ####################
-    lib = import ./lib {inherit (nixpkgs) lib;};
-
     ###################
     # Utility scripts #
     ###################
-    packages.${system} = let
-      inherit (nixpkgs.legacyPackages.${system}) writeShellScript writeShellScriptBin;
-      vm = nixpkgs.lib.nixosSystem {
-        inherit system;
-        specialArgs.flake-inputs = inputs;
-
-        modules = [
-          ./configuration
-          ./configuration/hardware-specific/vm.nix
-        ];
-      };
-    in {
-      default = vm.config.system.build.vm;
-
-      run-vm = let
-        qemuNetOpts = self.lib.makeQemuNetOpts {
-          "2222" = "2222";
-          "3080" = "80";
-          "3443" = "443";
-          "8448" = "8448"; # Matrix
-          "21025" = "21025"; # Starbound
-        };
-      in
-        writeShellScript "run-vm" ''
-          export QEMU_OPTS="-m 3941 -smp 2 -display curses"
-          export QEMU_NET_OPTS="${qemuNetOpts}"
-          "${vm.config.system.build.vm}/bin/run-testvm-vm"
-        '';
-
-      update-pkgs = let
-        nvfetcher-bin = "${nvfetcher.packages.${system}.default}/bin/nvfetcher";
-      in
-        writeShellScriptBin "update-pkgs" ''
-          cd "$(git rev-parse --show-toplevel)/pkgs"
-          ${nvfetcher-bin} -o _sources_pkgs -c nvfetcher.toml
-        '';
-
-      update-nextcloud-apps = let
-        nvfetcher-bin = "${nvfetcher.packages.${system}.default}/bin/nvfetcher";
-      in
-        writeShellScript "update-nextcloud-apps" ''
-          cd "$(git rev-parse --show-toplevel)/pkgs"
-          ${nvfetcher-bin} -o _sources_nextcloud -c nextcloud-apps.toml
-        '';
-    };
-
     apps.${system} = {
-      default = {
+      default = self.apps.${system}.run-vm;
+
+      run-vm = {
         type = "app";
-        program = builtins.toString self.packages.${system}.run-vm;
+        program = let
+          vm = nixpkgs.lib.nixosSystem {
+            inherit system;
+            specialArgs.flake-inputs = inputs;
+
+            modules = [
+              ./configuration
+              ./configuration/hardware-specific/vm.nix
+            ];
+          };
+        in
+          (pkgs.writeShellScript "" ''
+            ${vm.config.system.build.vm.outPath}/bin/run-testvm-vm
+          '')
+          .outPath;
+      };
+
+      update-pkgs = {
+        type = "app";
+        program = let
+          nvfetcher-bin = "${nvfetcher.packages.${system}.default}/bin/nvfetcher";
+        in
+          (pkgs.writeShellScript "update-pkgs" ''
+            cd "$(git rev-parse --show-toplevel)/pkgs"
+            ${nvfetcher-bin} -o _sources_pkgs -c nvfetcher.toml
+          '')
+          .outPath;
       };
 
       update-nextcloud-apps = {
         type = "app";
-        program = builtins.toString self.packages.${system}.update-nextcloud-apps;
+        program = let
+          nvfetcher-bin = "${nvfetcher.packages.${system}.default}/bin/nvfetcher";
+        in
+          (pkgs.writeShellScript "update-nextcloud-apps" ''
+            cd "$(git rev-parse --show-toplevel)/pkgs"
+            ${nvfetcher-bin} -o _sources_nextcloud -c nextcloud-apps.toml
+          '')
+          .outPath;
       };
     };
 
diff --git a/keys/staging.yaml b/keys/staging.yaml
index de7686b..9e495ba 100644
--- a/keys/staging.yaml
+++ b/keys/staging.yaml
@@ -14,6 +14,8 @@ wireguard:
     server-key: ENC[AES256_GCM,data:FvY897XdKoa/mckE8JQLCkklsnYD6Wz1wpsu5t3uhEnW3iarnDQxF9msuYU=,iv:jqGXfekM+Vs+J9b5nlZ5Skd1ZKHajoUo2Dc4tMYPm1w=,tag:EehikjI/FCU8wqtpvJRamQ==,type:str]
 restic:
     local-backups: ENC[AES256_GCM,data:3QjEv03t7wE=,iv:y/6Lv4eUbZZfGPwUONykz8VNL62cAJuWaJy9yk3aAmk=,tag:wMlGsepuG9JjwtUKGWSibw==,type:str]
+    storagebox-backups: ENC[AES256_GCM,data:NEHk57B3YtI=,iv:0/qnqMVK0662sgfDQoLxcW7L09SKF8E5liCnjaQ2+2k=,tag:RU0BPwGgvI9bgOPr8VItmA==,type:str]
+    storagebox-ssh-key: ENC[AES256_GCM,data:65+kbJPO90y+rRh3Q5cqLDtQa3VFfbaDPPo1nJLqxgAB7Wm3J7K4qUYAKPcYnkWV4/xFz63R2uCNaq5xv+vuZA==,iv:O7AeE/ujp5p1P7nff7PpghQfN2tQUYBSWL+EHRbE5yA=,tag:Pu/+bEAQuqwmD1Rc//t0cA==,type:str]
 turn:
     env: ENC[AES256_GCM,data:xjIz/AY109lyiL5N01p5T3HcYco/rM5CJSRTtg==,iv:16bW6OpyOK/QL0QPGQp/Baa9xyT8E3ZsYkwqmjuofk0=,tag:J5re3uKxIykw3YunvQWBgg==,type:str]
     secret: ENC[AES256_GCM,data:eQ7dAocoZtg=,iv:fgzjTPv30WqTKlLy+yMn5MsKQgjhPnwlGFFwYEg3gWs=,tag:1ze33U1NBkgMX/9SiaBNQg==,type:str]
@@ -26,8 +28,8 @@ sops:
     azure_kv: []
     hc_vault: []
     age: []
-    lastmodified: "2023-12-30T14:09:03Z"
-    mac: ENC[AES256_GCM,data:kuyzVV1Dhlb2LemqRzw2xPr9jtTWqSbFMv70LUEbRmsDpjwQsAIARgoaj32EXdDRTHYXBplTYieR7KvmxykL/8rkj0g4+IuRLY1TcbRS31Gi74FiXvV2apscHhQWXhHPHIHMbwZAfDSHdMrf8hPu28SC9QdbP3SXYNt28Imstrc=,iv:UALUiWGHlWEBmIVWeSyEa16ZdcDZvgtlpHETDV2CcRY=,tag:rxbd3ph+pPf11jup/CMEzw==,type:str]
+    lastmodified: "2024-03-18T23:13:42Z"
+    mac: ENC[AES256_GCM,data:/6GnUxOkftB07feEwQbeXoueLQUkRXL4pee973bAYbjse8gbmU3IvI8CVoj1PuY5JeC7pOFCMjZAxqbMh90oUbVSHssVDLIuL4/ZhxF3on+sKmC5wa/M8lU+Ld2upL+//bz2p4EsDKy1Fedwm22b3mOkjSAUcKp+uh8ORrRmWZ0=,iv:waVUyPo1VPfTldzbs0DH3mGukAWvy2Ut9w5bw7/bdFA=,tag:Wm4KUZwKI4VylJ1i2QoptA==,type:str]
     pgp:
         - created_at: "2023-12-29T15:25:27Z"
           enc: |
diff --git a/lib/default.nix b/lib/default.nix
deleted file mode 100644
index 20d874d..0000000
--- a/lib/default.nix
+++ /dev/null
@@ -1,10 +0,0 @@
-{lib}: let
-  inherit (lib.attrsets) mapAttrsToList;
-  inherit (lib.strings) concatStringsSep;
-in {
-  makeQemuNetOpts = portMapping:
-    concatStringsSep ","
-    (mapAttrsToList
-      (host: vm: "hostfwd=::${host}-:${vm}")
-      portMapping);
-}