Compare commits

...

2 commits

Author SHA1 Message Date
99c71f0790
docs: update Nix usage instructions
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I8717b49f21f777003787a663feb0467a6a6a6964
2026-02-01 14:44:10 +03:00
05b3dea1c6
nix: initial tooling; add NixOS module
Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I5ff8dfa450ec405e2ead5d16e0de90856a6a6964
2026-02-01 14:44:09 +03:00
5 changed files with 251 additions and 0 deletions

View file

@ -232,6 +232,40 @@ npm start
</details> </details>
<details>
<summary>Nix</summary>
**Flake** (NixOS or flake-enabled systems):
```nix
{
inputs.troutbot.url = "github:notashelf/troutbot";
outputs = { self, nixpkgs, troutbot }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [
troutbot.nixosModules.troutbot
{
services.troutbot = {
enable = true;
environmentFile = "/path/to/.env"; # use Agenix if possible
configPath = "/path/to/config.ts" # use Agenix if possible
};
}
];
};
};
};
```
**Run directly**:
```bash
nix run github:notashelf/troutbot
```
</details>
<details> <details>
<summary>Docker</summary> <summary>Docker</summary>

27
flake.lock generated Normal file
View file

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1769461804,
"narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

36
flake.nix Normal file
View file

@ -0,0 +1,36 @@
{
description = "Troutbot - GitHub webhook bot";
inputs.nixpkgs.url = "github:NixOS/nixpkgs?ref=nixos-unstable";
outputs = {
self,
nixpkgs,
}: let
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forEachSystem = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
in {
nixosModules = {
troutbot = import ./nix/modules/nixos.nix self;
default = self.nixosModules.troutbot;
};
packages = forEachSystem (pkgs: {
troutbot = pkgs.callPackage ./nix/package.nix {};
default = self.packages.${pkgs.hostPlatform.system}.troutbot;
});
devShells = forEachSystem (pkgs: {
default = pkgs.mkShell {
name = "troutbot-dev";
packages = [pkgs.nodejs-slim pkgs.pnpm];
};
});
};
}

83
nix/modules/nixos.nix Normal file
View file

@ -0,0 +1,83 @@
self: {
config,
pkgs,
lib,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.options) mkOption mkEnableOption literalExpression;
inherit (lib.types) nullOr str port package;
defaultPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.troutbot;
cfg = config.services.troutbot;
in {
options.services.troutbot = {
enable = mkEnableOption "troutbot";
package = mkOption {
type = nullOr package;
default = defaultPackage;
defaultText = literalExpression "inputs.troutbot.packages.${pkgs.stdenv.hostPlatform.system}.troutbot";
description = ''
The Troutbot package to use.
By default, this option will use the `packages.default` as exposed by this flake.
'';
};
user = mkOption {
type = str;
default = "troutbot";
};
group = mkOption {
type = str;
default = "troutbot";
};
port = mkOption {
type = port;
default = 3000;
};
environmentFile = mkOption {
type = nullOr str;
default = null;
};
configPath = mkOption {
type = nullOr str;
default = null;
};
};
config = mkIf cfg.enable {
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
};
users.groups.${cfg.group} = {};
systemd.services.troutbot = {
description = "Troutbot";
after = ["network.target"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
ExecStart = "${lib.getExe cfg.package}";
Restart = "on-failure";
EnvironmentFile = cfg.environmentFile;
NODE_ENV = "production";
CONFIG_PATH = cfg.configPath;
PORT = toString cfg.port;
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
NoNewPrivileges = true;
};
};
};
}

71
nix/package.nix Normal file
View file

@ -0,0 +1,71 @@
{
lib,
stdenv,
nodejs,
pnpmConfigHook,
fetchPnpmDeps,
pnpm,
makeBinaryWrapper,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "troutbot";
version = "0-unstable-2026-01-30";
src = lib.fileset.toSource {
root = ../.;
fileset = lib.fileset.unions [
../src
../config.example.ts
../package.json
../pnpm-lock.yaml
../tsconfig.json
];
};
strictDeps = true;
nativeBuildInputs = [
nodejs # in case scripts are run outside of a pnpm call
pnpmConfigHook
pnpm # at least required by pnpmConfigHook, if not other (custom) phases
makeBinaryWrapper
];
pnpmDeps = fetchPnpmDeps {
inherit (finalAttrs) pname version src;
fetcherVersion = 3;
hash = "sha256-y8LV1D+EgGcZ79lmxS20dqYBPEfk4atma+RWf7pJI30=";
};
buildPhase = ''
runHook preBuild
pnpm run build --outDir dist
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/{bin,share}
# Copy transpiled result
cp -rv dist/* $out/share
# Copy the example config
install -Dm755 config.example.ts $out/share
makeWrapper ${lib.getExe nodejs} $out/bin/troutbot \
--set-default NODE_ENV production \
--add-flags "$out/share/index.js"
runHook postInstall
'';
meta = {
description = "The ultimate trout population helper";
license = lib.licenses.eupl12;
maintainers = with lib.maintainers; [NotAShelf];
};
})