1
Fork 0

sqlite-web module & deployment

This commit is contained in:
prescientmoon 2025-04-13 19:24:20 +02:00
parent 9b0255eaad
commit 8bcf0c68e1
Signed by: prescientmoon
SSH key fingerprint: SHA256:UUF9JT2s8Xfyv76b8ZuVL7XrmimH4o49p4b+iexbVH4
9 changed files with 163 additions and 35 deletions
flake.lock
home/features/cli/productivity
hosts/nixos
common/global
lapetus/services
modules/nixos
pkgs

View file

@ -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"
},

View file

@ -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";
};
# }}}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;
};
};
}

View file

@ -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;

View file

@ -7,4 +7,5 @@
nginx = ./nginx.nix;
pilot = ./pilot.nix;
pounce = ./pounce.nix;
sqliteWeb = ./sqlite-web.nix;
}

View file

@ -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;
}

View file

@ -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 = ''