{ lib , pkgs , outputs , ... }: let dataDir = "/var/lib/grist"; in { imports = [ # TODO: auto-import via `outputs.modules.nixos` outputs.modules.global.nix-config ]; systemd.services.grist = { description = "Grist Core Spreadsheet Server"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; environment = { APP_HOME_URL = "https://grist.odin.t5.st"; GRIST_ORG_IN_PATH = "true"; GRIST_HOST = "0.0.0.0"; GRIST_SINGLE_PORT = "true"; GRIST_SERVE_SAME_ORIGIN = "true"; GRIST_INST_DIR = "${dataDir}"; GRIST_DATA_DIR = "${dataDir}/docs"; GRIST_SANDBOX_FLAVOR = "unsandboxed"; GRIST_SESSION_COOKIE = "grist_core"; GRIST_DEFAULT_EMAIL = "i@t5.st"; GRIST_TELEMETRY_LEVEL = "off"; GRIST_ALLOW_AUTOMATIC_VERSION_CHECKING = "false"; NODE_OPTIONS = "--no-deprecation"; NODE_ENV = "production"; TYPEORM_DATABASE = "${dataDir}/home.sqlite3"; }; serviceConfig = { ExecStart = "${lib.getExe pkgs.grist-core}"; DynamicUser = true; StateDirectory = "grist"; StateDirectoryMode = "0700"; WorkingDirectory = dataDir; Restart = "always"; ReadWritePaths = [ dataDir ]; ProtectSystem = "strict"; ProtectHome = true; PrivateTmp = true; NoNewPrivileges = true; RestrictSUIDSGID = true; }; preStart = '' mkdir -p ${dataDir}/docs ''; }; networking = { firewall.allowedTCPPorts = [ 8484 ]; interfaces.eth0 = { ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; }; defaultGateway = "192.168.1.1"; nameservers = [ "8.8.8.8" ]; useDHCP = false; }; boot.isContainer = true; system.stateVersion = "25.05"; }