Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,7 @@ web-src/geckodriver.log
venv/
/venv2/
e2e_venv/

# Nix / NixOS

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

result is for Nix build artifacts. There is also a qemu demo startable via nix run .#demo. Since the demo will instantiate a VM, we ignore the .qcow2 hard drive, too.

/result
/*.qcow2
61 changes: 61 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 67 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
description = "Script-server";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/26.05";
flake-parts.url = "github:hercules-ci/flake-parts";
};

outputs =
inputs@{
self,
nixpkgs,
flake-parts,
...
}:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
];
perSystem =
{ pkgs, ... }:
{
packages = {
script-server = pkgs.python3Packages.callPackage ./nix/package.nix { };

script-server-web = pkgs.callPackage ./nix/package-web.nix { };

demo = self.nixosConfigurations.demo.config.system.build.vm;
};

formatter = pkgs.nixfmt-tree;
};
}
// {
overlays.default = final: prev: {
script-server = final.python3Packages.callPackage ./nix/package.nix { };

script-server-web = final.callPackage ./nix/package-web.nix { };
};

nixosModules.default = import ./nix/module.nix;

nixosConfigurations.demo = nixpkgs.lib.nixosSystem {
modules = [
self.nixosModules.default
{
nixpkgs = {
overlays = [ self.overlays.default ];
hostPlatform = "x86_64-linux";
};

users.users.root.password = "changeit";

services = {
script-server = {
enable = true;
};
};

system.stateVersion = "26.05";
}
];
};
};
}
75 changes: 75 additions & 0 deletions nix/module.nix

@duesee duesee Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defines how the script-server would be configured in NixOS.

With enable = true; we "install" the script-server. settings is a Nix "attribute set" / dictionary that is placed unchanged in JSON format to /etc/script-server/conf.json. configuration is the path to the script configuration.

Example:

services.script-server = {
  enable = true;

  # Optional
  settings = { }; # JSON config in Nix syntax
  # Optional
  configuration = "..."; # Path to `conf` / `database` folder; Default: "/var/lib/script-server/conf"
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.script-server;
json = pkgs.formats.json { };
in
{
options.services.script-server = {
enable = lib.mkEnableOption "Whether to enable script-server.";

package = lib.mkOption {
type = lib.types.package;
default = pkgs.script-server;
description = "Script-server package to use.";
};

package-web = lib.mkOption {
type = lib.types.package;
default = pkgs.script-server-web;
description = "Script-server-web package to use.";
};

settings = lib.mkOption {
type = json.type;
default = { };
description = "Server configuration, see <https://github.com/bugy/script-server/wiki/Server-configuration>.";
};

configuration = lib.mkOption {
type = lib.types.str;
default = "/var/lib/script-server/conf";
description = "Script configuration, see <https://github.com/bugy/script-server/wiki/Script-config>.";
};
};

config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];

environment.etc."script-server/conf.json".source =

@duesee duesee Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Settings" could be put under /etc/script-server/conf.json when using NixOS.

json.generate "script-server-config" cfg.settings;

# See <https://github.com/bugy/script-server/wiki/Running-as-a-linux-service#systemd>
systemd.services.script-server = {
enable = true;

description = "Script Server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];

serviceConfig = {
Restart = "always";
RestartSec = "1s";
ExecStart = ''
${cfg.package}/bin/script-server \
--config-file /etc/script-server/conf.json \
--config-dir ${cfg.configuration} \
--log-folder /var/log/script-server \
--tmp-folder /tmp
'';

# `main.py` expects `web` to be in working directory.

@duesee duesee Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my understanding: When launcher.py is used, the web folder must be co-located to it. We could bundle the NixOS package so that this is always the case and keep calling launcher.py. But... according to the Filesystem Hierarchy Standard, we probably should put launcher.py under /usr/bin/launcher.py and would then need to put the web folder there as well which feels off.

Instead, we call main.py and set the working directory to where the web package is located in the systemd unit. It feels hacky and I think we need to put version.txt there as well...

(I think this is not specific to NixOS. Packaging for e.g. Ubuntu would raise the same questions?)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But working dir is used not only for web, is it? All other folders from the release are expected to be there

WorkingDirectory = "${cfg.package-web}";
StateDirectory = "script-server";
LogsDirectory = "script-server";

DynamicUser = true;
PrivateTmp = true;
};
};
};
}
19 changes: 19 additions & 0 deletions nix/package-web.nix

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This builds/bundles the frontend.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{ lib, buildNpmPackage }:
buildNpmPackage {
pname = "script-server-web";
version = "1.18.0";

src = ../web-src;

npmDepsHash = "sha256-aBZDh2NcDU4OpsdTS8JqwGMa8WeIoyW9I6bUwTXfllU=";

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it be automatically calculated as a result of some build tool?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it would be the same for "version"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hash ensures that we always downloaded the exact same npm dependencies. We could adapt the hash in CI when updating the deps, though, to make our life easier. But I would suggest to tackle this later.

If you don't mind, I'll take care about the maintenance of the Nix support. Ideally, the files can eventually be moved into nixpkgs but I don't have experience here and probably want to ask someone before starting anything :-) Let's see first how well this works.

Since you seem fine with the direction, I'll try to finalize the PR soon(tm) and write a short NixOS Wiki entry.

@duesee duesee Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

soon = "probably next week";


makeCacheWritable = true;

# See <https://stackoverflow.com/questions/75959563/node-js-err-ossl-evp-unsupported-error-when-running-npm-run-start>
NODE_OPTIONS = "--openssl-legacy-provider";

installPhase = ''
mkdir "$out"
cp -r ../web "$out"
'';
}
30 changes: 30 additions & 0 deletions nix/package.nix

@duesee duesee Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This builds the backend.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
let
toml = builtins.fromTOML (builtins.readFile ./../pyproject.toml);
in
{
lib,
buildPythonPackage,
tornado,
setuptools,
}:
buildPythonPackage {
pname = toml.project.name;
version = toml.project.version;
pyproject = true;

src = lib.fileset.toSource {
root = ./..;
fileset = lib.fileset.unions [
./../pyproject.toml
./../src
];
};

build-system = [
setuptools
];

dependencies = [
tornado
];
}