diff --git a/default.nix b/default.nix
index 62d9000e..7763d61c 100644
--- a/default.nix
+++ b/default.nix
@@ -77,6 +77,7 @@ pkgs.buildNpmPackage {
do
makeWrapper ${pkgs.nodejs_24}/bin/node $out/bin/start-`dirname ''${i/dist\//}` --prefix NODE_PATH : $out/node_modules --add-flags --enable-source-maps --add-flags $out/$i
done
+ makeWrapper ${pkgs.nodejs_24}/bin/node $out/bin/apply-migrations --prefix NODE_PATH : $out/node_modules --add-flags --enable-source-maps --add-flags $out/dist/apply-migrations.js
# set +x
runHook postInstall
diff --git a/flake.nix b/flake.nix
index 3f8cb421..ab482c6a 100644
--- a/flake.nix
+++ b/flake.nix
@@ -76,6 +76,7 @@
)
// {
nixosModules.default = import ./nix/modules/default self;
+ testVm = import ./nix/testVm/default.nix { inherit self nixpkgs; };
checks =
let
pkgs = import nixpkgs { system = "x86_64-linux"; };
diff --git a/nix/modules/default/default.nix b/nix/modules/default/default.nix
index 30c15d59..e3a65fb7 100644
--- a/nix/modules/default/default.nix
+++ b/nix/modules/default/default.nix
@@ -221,8 +221,27 @@ in
# }
];
+ systemd.services.spacebar-apply-migrations = makeServerTsService {
+ description = "Spacebar Server - Apply DB migrations";
+ after = [ "network-online.target" "postgresql.service" ];
+ environment = builtins.mapAttrs (_: val: builtins.toString val) (
+ cfg.extraEnvironment
+ // {
+ # things we force...
+ CONFIG_PATH = configFile;
+ CONFIG_READONLY = 1;
+ }
+ );
+ serviceConfig = {
+ ExecStart = "${cfg.package}/bin/apply-migrations";
+ Type = "oneshot";
+ };
+ };
+
systemd.services.spacebar-api = makeServerTsService {
description = "Spacebar Server - API";
+ after = [ "spacebar-apply-migrations.service" ];
+ requires = [ "spacebar-apply-migrations.service" ];
environment = builtins.mapAttrs (_: val: builtins.toString val) (
{
# things we set by default...
@@ -245,6 +264,8 @@ in
systemd.services.spacebar-gateway = makeServerTsService {
description = "Spacebar Server - Gateway";
+ after = [ "spacebar-apply-migrations.service" ];
+ requires = [ "spacebar-apply-migrations.service" ];
environment = builtins.mapAttrs (_: val: builtins.toString val) (
{
# things we set by default...
@@ -267,6 +288,8 @@ in
systemd.services.spacebar-cdn = makeServerTsService {
description = "Spacebar Server - CDN";
+ after = [ "spacebar-apply-migrations.service" ];
+ requires = [ "spacebar-apply-migrations.service" ];
environment = builtins.mapAttrs (_: val: builtins.toString val) (
{
# things we set by default...
diff --git a/nix/testVm/configuration.nix b/nix/testVm/configuration.nix
new file mode 100644
index 00000000..c826ca0a
--- /dev/null
+++ b/nix/testVm/configuration.nix
@@ -0,0 +1,45 @@
+{ pkgs, lib, ... }:
+{
+ networking.hostName = "sbtest";
+
+ services.spacebarchat-server =
+ let
+ cfg = {
+ enable = true;
+ apiEndpoint = { useSsl = false; host = "api.sb.localhost"; localPort = 3001; publicPort = 8080; };
+ gatewayEndpoint = { useSsl = false; host = "gw.sb.localhost"; localPort = 3002; publicPort = 8080; };
+ cdnEndpoint = { useSsl = false; host = "cdn.sb.localhost"; localPort = 3003; publicPort = 8080; };
+ nginx.enable = true;
+ serverName = "sb.localhost";
+ extraEnvironment = {
+ DATABASE = "postgres://postgres:postgres@127.0.0.1/spacebar";
+ #WEBRTC_PORT_RANGE=60000-61000;
+ #PUBLIC_IP=216.230.228.60;
+ LOG_REQUESTS = "-200,204,304";
+ LOG_VALIDATION_ERRORS = true;
+ #DB_LOGGING=true;
+ #LOG_GATEWAY_TRACES=true;
+ #LOG_PROTO_UPDATES=true;
+ #LOG_PROTO_FRECENCY_UPDATES=true;
+ #LOG_PROTO_SETTINGS_UPDATES=true;
+ #WRTC_PUBLIC_IP=webrtc.old.server.spacebar.chat;
+ WRTC_PUBLIC_IP = "216.230.228.19";
+ WRTC_PORT_MIN = 60000;
+ WRTC_PORT_MAX = 65000;
+ WRTC_LIBRARY = "@spacebarchat/medooze-webrtc";
+ #WRTC_LIBRARY=mediasoup-spacebar-wrtc;
+ };
+ };
+ in
+ lib.trace ("Testing with config: " + builtins.toJSON cfg) cfg;
+ services.nginx.enable = true;
+
+ users.users.root.initialPassword = "root";
+ services.getty.autologinUser = "root";
+
+ environment.systemPackages = with pkgs; [
+ btop
+ duf
+ lnav
+ ];
+}
diff --git a/nix/testVm/default.nix b/nix/testVm/default.nix
new file mode 100644
index 00000000..3b67f492
--- /dev/null
+++ b/nix/testVm/default.nix
@@ -0,0 +1,15 @@
+{ self, nixpkgs }:
+
+nixpkgs.lib.nixosSystem {
+ system = "x86_64-linux";
+ modules = [
+ self.nixosModules.default
+ ./configuration.nix
+ ./postgres.nix
+ ./perlless.nix
+ ./vm.nix
+ ];
+ specialArgs = { inherit self nixpkgs; };
+}
+
+#DERIVATION=".#nixosConfigurations.${CONFIG}.config.system.build.toplevel"
\ No newline at end of file
diff --git a/nix/testVm/perlless.nix b/nix/testVm/perlless.nix
new file mode 100644
index 00000000..6d391569
--- /dev/null
+++ b/nix/testVm/perlless.nix
@@ -0,0 +1,26 @@
+{ pkgs, lib, ... }:
+{
+ #perlless profile
+# system.switch.enable = lib.mkForce false;
+
+ # Remove perl from activation
+ #system.etc.overlay.enable = lib.mkForce true;
+ #systemd.sysusers.enable = lib.mkForce true;
+
+ # Random perl remnants
+ programs.less.lessopen = lib.mkForce null;
+ programs.command-not-found.enable = lib.mkForce false;
+ environment.defaultPackages = lib.mkForce [ ];
+ documentation.info.enable = lib.mkForce false;
+ documentation.man.enable = false;
+
+ system = {
+ #activatable = false;
+ copySystemConfiguration = false;
+ includeBuildDependencies = false;
+ disableInstallerTools = lib.mkForce true;
+ build = {
+ separateActivationScript = true;
+ };
+ };
+}
diff --git a/nix/testVm/postgres.nix b/nix/testVm/postgres.nix
new file mode 100644
index 00000000..015f6d96
--- /dev/null
+++ b/nix/testVm/postgres.nix
@@ -0,0 +1,82 @@
+{ config, pkgs, ... }:
+
+{
+ services.postgresql = {
+ enable = true;
+ package = pkgs.postgresql_18_jit;
+ initdbArgs = [
+ "--encoding=UTF8"
+ "--locale=C.UTF-8"
+ "--data-checksums"
+ "--allow-group-access"
+ ];
+ enableTCPIP = true;
+ authentication = pkgs.lib.mkOverride 10 ''
+ # TYPE, DATABASE, USER, ADDRESS, METHOD
+ local all all trust
+ host all all 127.0.0.1/32 trust
+ host all all ::1/128 trust
+ host all all 0.0.0.0/0 md5
+ '';
+ initialScript = pkgs.writeText "backend-initScript" ''
+ CREATE ROLE spacebar WITH LOGIN PASSWORD 'spacebar' CREATEDB;
+ CREATE DATABASE spacebar;
+ GRANT ALL PRIVILEGES ON DATABASE spacebar TO spacebar;
+ '';
+ settings = {
+ # https://pgconfigurator.cybertec.at/
+ max_connections = 2500;
+ superuser_reserved_connections = 3;
+
+ shared_buffers = "128MB";
+ work_mem = "64MB";
+ maintenance_work_mem = "512MB";
+ huge_pages = "try";
+ effective_cache_size = "512MB";
+ effective_io_concurrency = 100;
+ random_page_cost = 1.1;
+
+ # can use this to view stats: SELECT query, total_time, calls, rows FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;
+ shared_preload_libraries = "pg_stat_statements";
+ track_io_timing = "on";
+ track_functions = "pl";
+ "pg_stat_statements.max" = "10000"; # additional
+ "pg_stat_statements.track" = "all"; # additional
+
+ wal_level = "replica";
+ max_wal_senders = 0;
+ synchronous_commit = "on"; # was ond3
+
+ checkpoint_timeout = "15min";
+ checkpoint_completion_target = "0.9";
+ max_wal_size = "2GB";
+ min_wal_size = "1GB";
+
+ wal_compression = "off";
+ wal_buffers = "-1";
+ wal_writer_delay = "500ms"; # was 100
+ wal_writer_flush_after = "32MB"; # was 1
+ #checkpoint_segments = "64"; # additional
+ default_statistics_target = "250"; # additional
+
+ bgwriter_delay = "200ms";
+ bgwriter_lru_maxpages = "100";
+ bgwriter_lru_multiplier = "2.0";
+ bgwriter_flush_after = "0";
+
+ max_worker_processes = "64"; # was 14
+ max_parallel_workers_per_gather = "32"; # was 7
+ max_parallel_maintenance_workers = "32"; # was 7
+ max_parallel_workers = "64"; # was 14
+ parallel_leader_participation = "on";
+
+ enable_partitionwise_join = "on";
+ enable_partitionwise_aggregate = "on";
+ jit = "on";
+ max_slot_wal_keep_size = "1GB";
+ track_wal_io_timing = "on";
+ maintenance_io_concurrency = "4";
+ wal_recycle = "on";
+ };
+ };
+}
diff --git a/nix/testVm/vm.nix b/nix/testVm/vm.nix
new file mode 100644
index 00000000..8a282135
--- /dev/null
+++ b/nix/testVm/vm.nix
@@ -0,0 +1,68 @@
+{
+ nixpkgs,
+ modulesPath,
+ pkgs,
+ lib,
+ ...
+}:
+{
+ imports = [
+ # (modulesPath + "/virtualisation/qemu-vm.nix")
+ ];
+ virtualisation.vmVariant = {
+ services.xserver.videoDrivers = [ "qxl" ];
+ services.spice-vdagentd.enable = true;
+ virtualisation.qemu.guestAgent.enable = true;
+ services.qemuGuest.enable = true;
+ virtualisation.qemu.options = [
+ "-vga qxl -device virtio-serial-pci -spice port=5930,disable-ticketing=on -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent"
+ "-display gtk,zoom-to-fit=off,show-cursor=on"
+ "-device virtio-balloon"
+ ];
+ virtualisation.memorySize = 4096;
+ virtualisation.cores = 6;
+ virtualisation.forwardPorts = [
+ # { hostPort = 2222; guestPort = 22; } # Probably shouldn't do this with root:root lol
+ { from = "host"; host.port = 8080; guest.port = 80; }
+ ];
+ networking.useDHCP = lib.mkForce true;
+ };
+
+ networking.firewall.enable = false;
+
+ boot = {
+ initrd = {
+ systemd.enable = true;
+ systemd.emergencyAccess = true;
+ };
+ kernelParams = [
+ "console=ttyS0,115200"
+ "systemd.gpt_auto=0"
+ #"console=tty1"
+ #"quiet"
+ ];
+ loader.timeout = 1;
+ };
+ boot.supportedFilesystems = lib.mkForce [ ];
+ hardware.enableRedistributableFirmware = lib.mkForce false;
+ #environment.systemPackages = lib.mkForce [ ];
+ documentation.enable = lib.mkForce false;
+ documentation.nixos.enable = lib.mkForce false;
+ networking.wireless.enable = lib.mkForce false;
+
+ console = {
+ earlySetup = true;
+ font = "${pkgs.cozette}/share/consolefonts/cozette6x13.psfu";
+ packages = with pkgs; [ cozette ];
+ };
+
+ system = {
+ #activatable = false;
+ copySystemConfiguration = false;
+ includeBuildDependencies = false;
+ disableInstallerTools = lib.mkForce true;
+ build = {
+ separateActivationScript = true;
+ };
+ };
+}
diff --git a/src/apply-migrations.ts b/src/apply-migrations.ts
new file mode 100644
index 00000000..5c806024
--- /dev/null
+++ b/src/apply-migrations.ts
@@ -0,0 +1,15 @@
+import moduleAlias from "module-alias";
+moduleAlias(__dirname + "../../package.json");
+process.on("uncaughtException", console.error);
+process.on("unhandledRejection", console.error);
+
+import { config } from "dotenv";
+config({ quiet: true });
+
+process.env.DB_LOGGING = "true";
+
+import { closeDatabase, initDatabase } from "@spacebar/util";
+
+initDatabase().then(() => {
+ closeDatabase().then((r) => {});
+});
|