diff --git a/flake.lock b/flake.lock
index 23e82ed..e4f67d5 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2057,11 +2057,11 @@
         "shimmeringvoid": "shimmeringvoid"
       },
       "locked": {
-        "lastModified": 1744141371,
-        "narHash": "sha256-anPwB6x7NvXfivSdZgpCWUQ9BY/zbPwmUtrAOXfGAcs=",
+        "lastModified": 1744558061,
+        "narHash": "sha256-88/C7xbeE5vxb0YFfBeLi8yjOB664u3aYCjn+AQGOaA=",
         "ref": "refs/heads/main",
-        "rev": "42d7de0bb1177ed13a94d64311d70259bd0c789d",
-        "revCount": 91,
+        "rev": "d6b15ed45f32e03e5697b35ed0308d9cf2c8ef66",
+        "revCount": 95,
         "type": "git",
         "url": "ssh://forgejo@ssh.git.moonythm.dev/prescientmoon/shimmeringmoon.git"
       },
@@ -2073,11 +2073,11 @@
     "shimmeringvoid": {
       "flake": false,
       "locked": {
-        "lastModified": 1744140761,
-        "narHash": "sha256-ciOI5UMLxDlAYS4HjTSf6MViEhBgHhUEYjLxP/Xv2G0=",
+        "lastModified": 1744146722,
+        "narHash": "sha256-qvh6UxyLbbaSrrpAJwW3fzA1YqrwnTUT8qj17poi0aY=",
         "ref": "refs/heads/main",
-        "rev": "890b7973dd522ac175e17fb6ea7d6bd74fec9565",
-        "revCount": 10,
+        "rev": "b6ab7c08daac587a1da5649cfdbc082ef2a01a20",
+        "revCount": 13,
         "type": "git",
         "url": "ssh://forgejo@ssh.git.moonythm.dev/prescientmoon/shimmeringvoid.git"
       },
diff --git a/home/features/cli/productivity/smos.nix b/home/features/cli/productivity/smos.nix
index 8724291..67cd554 100644
--- a/home/features/cli/productivity/smos.nix
+++ b/home/features/cli/productivity/smos.nix
@@ -39,7 +39,7 @@ in
   satellite.persistence.at.data.apps.smos.directories = [ config.programs.smos.workflowDir ];
 
   sops.secrets.smos_github_token = {
-    sopsFile = ../secrets.yaml;
+    sopsFile = ./secrets.yaml;
     path = "${config.xdg.dataHome}/smos/.github_token";
   };
   # }}}
diff --git a/hosts/nixos/common/global/ports.nix b/hosts/nixos/common/global/ports.nix
index e73773b..cd2fd83 100644
--- a/hosts/nixos/common/global/ports.nix
+++ b/hosts/nixos/common/global/ports.nix
@@ -29,5 +29,7 @@
     glass-server = 8425;
     glass-server-lp-tcp = 8426;
     glass-server-lp-udp = 8427;
+    sqlite-web-glass = 8428;
+    sqlite-web-shimmer = 8429;
   };
 }
diff --git a/hosts/nixos/lapetus/services/glass-server/default.nix b/hosts/nixos/lapetus/services/glass-server/default.nix
index f3b3452..d50fe44 100644
--- a/hosts/nixos/lapetus/services/glass-server/default.nix
+++ b/hosts/nixos/lapetus/services/glass-server/default.nix
@@ -1,4 +1,4 @@
-{ pkgs, config, ... }:
+{ config, ... }:
 {
   imports = [ ./module.nix ];
 
@@ -20,32 +20,40 @@
     group = config.services.glass-server.user;
     sopsFile = ../../secrets.yaml;
   };
-
-  sops.templates.glass-server-config = {
-    owner = config.services.glass-server.user;
-    group = config.services.glass-server.user;
-    content = builtins.toJSON {
-      CONTENT_BUNDLE_FOLDER_PATH = "${pkgs.shimmeringextra}/bundles";
-      SECRET_KEY = "${config.sops.placeholder.glass_server_secret_key}";
-      PASSWORD = "${config.sops.placeholder.glass_server_admin_password}";
-      API_TOKEN = "${config.sops.placeholder.glass_server_admin_token}";
-    };
-  };
   # }}}
-
-  satellite.cloudflared.at.arcaea.port = config.satellite.ports.glass-server;
+  # {{{ Routing
   satellite.cloudflared.at."tcp.lp.arcaea".port = config.satellite.ports.glass-server-lp-tcp;
   satellite.cloudflared.at."udp.lp.arcaea".port = config.satellite.ports.glass-server-lp-udp;
+  satellite.cloudflared.at.arcaea.port = 80;
+
+  services.nginx.virtualHosts."arcaea.moonythm.dev" = {
+    locations."/web/".proxyPass =
+      "http://localhost:${toString config.satellite.ports.glass-server}/web/";
+    locations."/db/glass/".proxyPass =
+      "http://localhost:${toString config.satellite.ports.sqlite-web-glass}/db/glass/";
+    locations."/db/shimmer/".proxyPass =
+      "http://localhost:${toString config.satellite.ports.sqlite-web-shimmer}/db/shimmer/";
+    locations."/" = {
+      return = "301 https://arcaea.lowiro.com/en";
+      priority = 2000; # 1000 is the default for everything else
+    };
+  };
+
+  satellite.sqliteWeb.databases.glass.location = "/db/glass/";
+  satellite.sqliteWeb.databases.shimmer.location = "/db/shimmer/";
+  # }}}
 
   services.glass-server = {
     enable = true;
     adminUsername = "prescientmoon";
-
     dataDir = "/persist/state/var/lib/arcaea/server";
-    secretConfig = config.sops.templates.glass-server-config.path;
 
     port = config.satellite.ports.glass-server;
     linkPlayTCPPort = config.satellite.ports.glass-server-lp-tcp;
     linkPlayUDPPort = config.satellite.ports.glass-server-lp-udp;
+
+    secretKeyFile = config.sops.secrets.glass_server_secret_key.path;
+    passwordFile = config.sops.secrets.glass_server_admin_password.path;
+    apiTokenFile = config.sops.secrets.glass_server_admin_token.path;
   };
 }
diff --git a/hosts/nixos/lapetus/services/glass-server/module.nix b/hosts/nixos/lapetus/services/glass-server/module.nix
index 522bfa9..9fec5a4 100644
--- a/hosts/nixos/lapetus/services/glass-server/module.nix
+++ b/hosts/nixos/lapetus/services/glass-server/module.nix
@@ -57,6 +57,8 @@ let
     SAVE_FULL_UNLOCK = false;
     STAMINA_RECOVER_TICK = 1; # Recover stamina instantly
     SKILL_FATALIS_WORLD_LOCKED_TIME = 1; # Recover from Fatalis instantly
+
+    CONTENT_BUNDLE_FOLDER_PATH = "${pkgs.shimmeringextra}/bundles";
     # }}}
   };
 
@@ -87,13 +89,21 @@ in
       '';
     };
 
-    secretConfig = lib.mkOption {
+    secretKeyFile = lib.mkOption {
       type = lib.types.path;
-      description = ''
-        Path to additional config that might be generated at runtime by a tool
-        like sops. This might be useful for things like the admin password
-      '';
+      description = "Path to a file containing the secret key to use for the server";
     };
+
+    passwordFile = lib.mkOption {
+      type = lib.types.path;
+      description = "Path to a file containing the admin password for the server";
+    };
+
+    apiTokenFile = lib.mkOption {
+      type = lib.types.path;
+      description = "Path to a file containing the api token for the server";
+    };
+
   };
   # }}}
 
@@ -121,15 +131,24 @@ in
         User = cfg.user;
         Group = cfg.user;
         ExecStart = pkgs.writeShellScript "glass-server-startup" ''
-          # Merge the given configs
-          ${lib.getExe pkgs.jq} -s ".[0] * .[1]" \
-            ${cfg.secretConfig} \
+          # Copy secrets into config
+          ${lib.getExe pkgs.jq} "\
+              .SECRET_KEY=\"$(cat ${cfg.secretKeyFile})\" |\
+              .PASSWORD=\"$(cat ${cfg.passwordFile})\" |\
+              .API_TOKEN=\"$(cat ${cfg.apiTokenFile})\" \
+            " \
             ${serverConfigPath} \
             > ${configPath}
 
+          # TODO: only do this if the db file already exists...
+          # Update the db
+          ${lib.getExe pkgs.glass-server-db-updater} \
+            ${glassServerConfig.SQLITE_DATABASE_PATH}
+
           # Start the server
           ARCAEA_JSON_CONFIG_PATH=${configPath} ${pkg}/bin/glass-server
         '';
+
         Restart = "on-failure";
       };
     };
@@ -144,5 +163,13 @@ in
       groups.${defaultUser} = { };
     };
     # }}}
+
+    satellite.sqliteWeb.databases.glass = {
+      port = config.satellite.ports.sqlite-web-glass;
+      user = cfg.user;
+      group = cfg.user;
+      file = glassServerConfig.SQLITE_DATABASE_PATH;
+      passwordFile = cfg.passwordFile;
+    };
   };
 }
diff --git a/hosts/nixos/lapetus/services/shimmeringmoon.nix b/hosts/nixos/lapetus/services/shimmeringmoon.nix
index 8a177b8..6837558 100644
--- a/hosts/nixos/lapetus/services/shimmeringmoon.nix
+++ b/hosts/nixos/lapetus/services/shimmeringmoon.nix
@@ -26,6 +26,14 @@ in
 
   systemd.tmpfiles.rules = [ "d ${dataDir} 0755 ${user} ${user}" ];
 
+  satellite.sqliteWeb.databases.shimmer = {
+    port = config.satellite.ports.sqlite-web-shimmer;
+    user = user;
+    group = user;
+    file = "${dataDir}/db.sqlite";
+    passwordFile = config.services.glass-server.passwordFile;
+  };
+
   # {{{ Secrets
   sops.secrets.shimmering_discord_token = {
     owner = user;
diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix
index e984101..88694b0 100644
--- a/modules/nixos/default.nix
+++ b/modules/nixos/default.nix
@@ -7,4 +7,5 @@
   nginx = ./nginx.nix;
   pilot = ./pilot.nix;
   pounce = ./pounce.nix;
+  sqliteWeb = ./sqlite-web.nix;
 }
diff --git a/modules/nixos/sqlite-web.nix b/modules/nixos/sqlite-web.nix
new file mode 100644
index 0000000..2156ead
--- /dev/null
+++ b/modules/nixos/sqlite-web.nix
@@ -0,0 +1,82 @@
+{
+  config,
+  lib,
+  pkgs,
+  ...
+}:
+let
+  cfg = config.satellite.sqliteWeb;
+in
+{
+  options.satellite.sqliteWeb = {
+    databases = lib.mkOption {
+      description = "Per-database sqlite-web configuration";
+      type = lib.types.attrsOf (
+        lib.types.submodule (
+          { ... }:
+          {
+            options.port = lib.mkOption {
+              description = "Port to serve UI on";
+              type = lib.types.nullOr lib.types.port;
+              default = null;
+            };
+
+            options.user = lib.mkOption {
+              description = "The user the GUI should run as";
+              type = lib.types.str;
+            };
+
+            options.group = lib.mkOption {
+              description = "The group the GUI should run as";
+              type = lib.types.str;
+            };
+
+            options.file = lib.mkOption {
+              description = "Path to serve files from";
+              type = lib.types.path;
+            };
+
+            options.passwordFile = lib.mkOption {
+              description = "File containing the password to use for authentication";
+              type = lib.types.nullOr lib.types.path;
+              default = null;
+            };
+
+            options.location = lib.mkOption {
+              description = "Prefix path to add to all urls";
+              type = lib.types.path;
+              default = "";
+            };
+          }
+        )
+      );
+
+      default = { };
+    };
+  };
+
+  config.systemd.services = lib.attrsets.mapAttrs' (name: value: {
+    name = "sqlite-web-${name}";
+    value = {
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      description = "Sqlite web GUI";
+
+      serviceConfig = {
+        User = value.user;
+        Group = value.user;
+        ExecStart = pkgs.writeShellScript "sqlite-web-startup" ''
+          export SQLITE_WEB_PASSWORD=$(cat ${value.passwordFile})
+
+          ${lib.getExe pkgs.sqlite-web} \
+            --port=${toString value.port} \
+            --url-prefix=${value.location} \
+            --password \
+            --no-browser \
+            ${value.file}
+        '';
+        Restart = "on-failure";
+      };
+    };
+  }) cfg.databases;
+}
diff --git a/pkgs/glass-server.nix b/pkgs/glass-server.nix
index 9eddd68..128ed51 100644
--- a/pkgs/glass-server.nix
+++ b/pkgs/glass-server.nix
@@ -17,8 +17,8 @@ pkgs.stdenv.mkDerivation {
   src = pkgs.fetchFromGitHub {
     owner = "starlitcanopy";
     repo = "ArcaeaServerFork";
-    rev = "2ee761f49462eabd6e26d2951cdd32205808261c";
-    sha256 = "i0h3lXo1k99h0h1P4VIFoYvugOtcY4vZZx9+8L//z1A=";
+    rev = "eb9bd4849b429d9228ae9509b3367f2a921c2a0b";
+    sha256 = "HGBQ0Pib6f7o7QGbcbnvnQ3mIOiXnNRuGAkLDNzFpPw=";
   };
 
   buildPhase = ''