{ description = "MultiTrain — multi-origin/multi-destination train connection search"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; outputs = { self, nixpkgs }: let systems = [ "x86_64-linux" "aarch64-linux" ]; forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system}); in { devShells = forAllSystems (pkgs: { default = pkgs.mkShell { packages = with pkgs; [ nodejs_22 typescript-language-server ]; }; }); packages = forAllSystems (pkgs: { default = (pkgs.buildNpmPackage.override { nodejs = pkgs.nodejs_22; }) { pname = "multitrain"; version = "0.1.0"; src = self; npmDepsHash = "sha256-HtdR6XNMXgMYdbty7mWxPvpRdQLbnja+fPNA9fUCqZM="; nativeBuildInputs = [ pkgs.makeWrapper ]; installPhase = '' runHook preInstall npm prune --omit=dev mkdir -p $out/lib/multitrain $out/bin cp -r dist public node_modules package.json $out/lib/multitrain/ makeWrapper ${pkgs.nodejs_22}/bin/node $out/bin/multitrain \ --add-flags "$out/lib/multitrain/dist/main.js" runHook postInstall ''; }; }); nixosModules.default = { config, lib, pkgs, ... }: let cfg = config.services.multitrain; in { options.services.multitrain = { enable = lib.mkEnableOption "MultiTrain train connection search"; package = lib.mkOption { type = lib.types.package; default = self.packages.${pkgs.stdenv.hostPlatform.system}.default; defaultText = lib.literalExpression "multitrain from its flake"; description = "The MultiTrain package to run."; }; port = lib.mkOption { type = lib.types.port; default = 3000; description = "Port the HTTP server listens on."; }; host = lib.mkOption { type = lib.types.str; default = "127.0.0.1"; description = "Address the HTTP server binds to."; }; userAgent = lib.mkOption { type = lib.types.str; default = "multitrain"; description = "User-Agent sent to the MOTIS API (identify yourself per Transitous fair-use policy, e.g. with a contact address)."; }; motisBaseUrl = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; example = "https://motis.example.org"; description = "Base URL of a self-hosted MOTIS instance; null uses api.transitous.org."; }; }; config = lib.mkIf cfg.enable { systemd.services.multitrain = { description = "MultiTrain train connection search"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; environment = { PORT = toString cfg.port; HOST = cfg.host; USER_AGENT = cfg.userAgent; } // lib.optionalAttrs (cfg.motisBaseUrl != null) { MOTIS_BASE_URL = cfg.motisBaseUrl; }; serviceConfig = { ExecStart = "${cfg.package}/bin/multitrain"; DynamicUser = true; Restart = "on-failure"; CapabilityBoundingSet = ""; LockPersonality = true; NoNewPrivileges = true; PrivateDevices = true; PrivateTmp = true; ProtectControlGroups = true; ProtectHome = true; ProtectHostname = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectSystem = "strict"; RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; RestrictNamespaces = true; RestrictRealtime = true; SystemCallArchitectures = "native"; }; }; }; }; }; }