From 2b6112fa7a31f3e981c1d53ff73968a6d11a57b1 Mon Sep 17 00:00:00 2001 From: Damian Poddebniak Date: Wed, 1 Jul 2026 16:08:43 +0200 Subject: [PATCH] build: Add Nix/NixOS support --- .gitignore | 4 +++ flake.lock | 61 ++++++++++++++++++++++++++++++++++++ flake.nix | 67 ++++++++++++++++++++++++++++++++++++++++ nix/module.nix | 75 +++++++++++++++++++++++++++++++++++++++++++++ nix/package-web.nix | 19 ++++++++++++ nix/package.nix | 30 ++++++++++++++++++ 6 files changed, 256 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/module.nix create mode 100644 nix/package-web.nix create mode 100644 nix/package.nix diff --git a/.gitignore b/.gitignore index f43d393d..ed4c391a 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,7 @@ web-src/geckodriver.log venv/ /venv2/ e2e_venv/ + +# Nix / NixOS +/result +/*.qcow2 diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..600c7820 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1782949081, + "narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1780145889, + "narHash": "sha256-md0zn0RnwNvPyASas1yG5YUuwQ4ALA6ucL50l0DvqCo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "8c50a710ddca43d7a530fb805ad55bde8d0141c5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "26.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1782614948, + "narHash": "sha256-ePjCwr1sNm9NYUqywL7QfK3JnlS015msC+eBu2zKlp8=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "db3f255737b94216eb71cce308e2912cf6bc2d7c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..3f418ab1 --- /dev/null +++ b/flake.nix @@ -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"; + } + ]; + }; + }; +} diff --git a/nix/module.nix b/nix/module.nix new file mode 100644 index 00000000..7dc78606 --- /dev/null +++ b/nix/module.nix @@ -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 ."; + }; + + configuration = lib.mkOption { + type = lib.types.str; + default = "/var/lib/script-server/conf"; + description = "Script configuration, see ."; + }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + environment.etc."script-server/conf.json".source = + json.generate "script-server-config" cfg.settings; + + # See + 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. + WorkingDirectory = "${cfg.package-web}"; + StateDirectory = "script-server"; + LogsDirectory = "script-server"; + + DynamicUser = true; + PrivateTmp = true; + }; + }; + }; +} diff --git a/nix/package-web.nix b/nix/package-web.nix new file mode 100644 index 00000000..b6937963 --- /dev/null +++ b/nix/package-web.nix @@ -0,0 +1,19 @@ +{ lib, buildNpmPackage }: +buildNpmPackage { + pname = "script-server-web"; + version = "1.18.0"; + + src = ../web-src; + + npmDepsHash = "sha256-aBZDh2NcDU4OpsdTS8JqwGMa8WeIoyW9I6bUwTXfllU="; + + makeCacheWritable = true; + + # See + NODE_OPTIONS = "--openssl-legacy-provider"; + + installPhase = '' + mkdir "$out" + cp -r ../web "$out" + ''; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 00000000..f18d3753 --- /dev/null +++ b/nix/package.nix @@ -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 + ]; +}