Skip to content
Merged
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
2 changes: 2 additions & 0 deletions nixos/doc/manual/release-notes/rl-2511.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@

- [fw-fanctrl](https://github.com/TamtamHero/fw-fanctrl), a simple systemd service to better control Framework Laptop's fan(s). Available as [hardware.fw-fanctrl](#opt-hardware.fw-fanctrl.enable).

- [SillyTavern](https://sillytavern.app/), LLM Frontend for Power Users. Available as [services.sillytavern](#opt-services.sillytavern.enable).

- [mautrix-discord](https://github.com/mautrix/discord), a Matrix-Discord puppeting/relay bridge. Available as [services.mautrix-discord](#opt-services.mautrix-discord.enable).

- [Timekpr-nExT](https://mjasnik.gitlab.io/timekpr-next/), a time managing application that helps optimizing time spent at computer for your subordinates, children or even for yourself. Available as [](#opt-services.timekpr.enable).
Expand Down
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1688,6 +1688,7 @@
./services/web-apps/sftpgo.nix
./services/web-apps/sharkey.nix
./services/web-apps/shiori.nix
./services/web-apps/sillytavern.nix
./services/web-apps/silverbullet.nix
./services/web-apps/simplesamlphp.nix
./services/web-apps/slskd.nix
Expand Down
170 changes: 170 additions & 0 deletions nixos/modules/services/web-apps/sillytavern.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
{
config,
lib,
pkgs,
...
}:

let
cfg = config.services.sillytavern;
defaultUser = "sillytavern";
defaultGroup = "sillytavern";
in
{
meta.maintainers = [
lib.maintainers.wrvsrx
lib.maintainers.A1ca7raz
];

options = {
services.sillytavern = {
enable = lib.mkEnableOption "sillytavern";

user = lib.mkOption {
type = lib.types.str;
default = defaultUser;
description = ''
User account under which the web-application run.
'';
};
group = lib.mkOption {
type = lib.types.str;
default = defaultGroup;
description = ''
Group account under which the web-application run.
'';
};

package = lib.mkPackageOption pkgs "sillytavern" { };

configFile = lib.mkOption {
type = lib.types.path;
default = "${pkgs.sillytavern}/lib/node_modules/sillytavern/config.yaml";
defaultText = lib.literalExpression "\${pkgs.sillytavern}/lib/node_modules/sillytavern/config.yaml";
description = ''
Path to the SillyTavern configuration file.
'';
};

port = lib.mkOption {
type = lib.types.nullOr lib.types.port;
default = null;
example = 8045;
description = ''
Port on which SillyTavern will listen.
'';
};

listenAddressIPv4 = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "127.0.0.1";
description = ''
Specific IPv4 address to listen to.
'';
};

listenAddressIPv6 = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "::1";
description = ''
Specific IPv6 address to listen to.
'';
};

listen = lib.mkOption {
type = lib.types.nullOr lib.types.bool;
default = null;
example = true;
description = ''
Whether to listen on all network interfaces.
'';
};

whitelist = lib.mkOption {
type = lib.types.nullOr lib.types.bool;
default = null;
example = true;
description = ''
Enables whitelist mode.
'';
};
};
};

config = lib.mkIf cfg.enable {
systemd.services.sillytavern = {
description = "Silly Tavern";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
# required by sillytavern's extension manager
path = [ pkgs.git ];
environment.XDG_DATA_HOME = "%S";
serviceConfig = {
Type = "simple";
ExecStart =
let
f = x: name: lib.optional (x != null) "--${name}=${builtins.toString x}";
in
lib.concatStringsSep " " (
[
"${lib.getExe pkgs.sillytavern}"
]
++ f cfg.port "port"
++ f cfg.listen "listen"
++ f cfg.listenAddressIPv4 "listenAddressIPv4"
++ f cfg.listenAddressIPv6 "listenAddressIPv6"
++ f cfg.whitelist "whitelist"
);
User = cfg.user;
Group = cfg.group;
Restart = "always";
StateDirectory = "SillyTavern";
BindPaths = [
"%S/SillyTavern/extensions:${pkgs.sillytavern}/lib/node_modules/sillytavern/public/scripts/extensions/third-party"
];

# Security hardening
CapabilityBoundingSet = [ "" ];
LockPersonality = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
};
};

users.users.${cfg.user} = lib.mkIf (cfg.user == defaultUser) {
description = "sillytavern service user";
isSystemUser = true;
inherit (cfg) group;
};

users.groups.${cfg.group} = lib.mkIf (cfg.group == defaultGroup) { };

systemd.tmpfiles.settings.sillytavern = {
"/var/lib/SillyTavern/data".d = {
mode = "0700";
inherit (cfg) user group;
};
"/var/lib/SillyTavern/extensions".d = {
mode = "0700";
inherit (cfg) user group;
};
"/var/lib/SillyTavern/config.yaml"."L+" = {
mode = "0600";
argument = cfg.configFile;
inherit (cfg) user group;
};
};
};
}
Loading