p0: skeleton, dialer-Control URL guard, flake, Makefile
Go service with /healthz, SSRF guard (parse + resolve-all + Control), exhaustive tests, NixOS module, and Makefile as source of truth for build flags. nix flake check runs make test lint.
This commit is contained in:
+150
@@ -0,0 +1,150 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.sift;
|
||||
settingsFormat = pkgs.formats.toml { };
|
||||
in
|
||||
{
|
||||
options.services.sift = {
|
||||
enable = lib.mkEnableOption "sift LLM-oriented fetch and search";
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
description = "sift package. The flake module sets this to packages.sift.";
|
||||
};
|
||||
|
||||
listen = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1:8890";
|
||||
description = "Address the HTTP server binds to (loopback by default).";
|
||||
};
|
||||
|
||||
tailscaleServe = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Advertise the listener on tailscale serve at https://<host>:8443.";
|
||||
};
|
||||
|
||||
tailscaleHttpsPort = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8443;
|
||||
description = "HTTPS port for tailscale serve (443 is SearXNG on orion).";
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = { };
|
||||
description = "Written to /etc/sift/config.toml. Unused keys are reserved for P1+.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.package != null;
|
||||
message = "services.sift.package must be set (the flake module does this).";
|
||||
}
|
||||
];
|
||||
|
||||
users.users.sift = {
|
||||
isSystemUser = true;
|
||||
group = "sift";
|
||||
home = "/var/lib/sift";
|
||||
};
|
||||
users.groups.sift = { };
|
||||
|
||||
environment.etc."sift/config.toml".source = settingsFormat.generate "sift.toml" (
|
||||
{ listen = cfg.listen; } // cfg.settings
|
||||
);
|
||||
|
||||
# Keys and env secrets are created on-box, never in the store.
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/sift 0750 root sift -"
|
||||
];
|
||||
|
||||
system.activationScripts.sift-secrets = {
|
||||
deps = [ "users" ];
|
||||
text = ''
|
||||
install -d -m 0750 -o root -g sift /var/lib/sift
|
||||
if [ ! -f /var/lib/sift/keys.toml ]; then
|
||||
umask 027
|
||||
printf '%s\n' '# key-hash → { name, workspace }. Generated empty; fill on-box.' > /var/lib/sift/keys.toml
|
||||
chown root:sift /var/lib/sift/keys.toml
|
||||
chmod 0640 /var/lib/sift/keys.toml
|
||||
fi
|
||||
if [ ! -f /var/lib/sift/secret.env ]; then
|
||||
umask 027
|
||||
printf '%s\n' '# BRAVE_API_KEY= (set on-box; do not read SearXNG secret.env)' > /var/lib/sift/secret.env
|
||||
chown root:sift /var/lib/sift/secret.env
|
||||
chmod 0640 /var/lib/sift/secret.env
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.sift = {
|
||||
description = "sift LLM-oriented fetch and search";
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "sift";
|
||||
Group = "sift";
|
||||
ExecStart = "${lib.getExe cfg.package} -listen ${cfg.listen} -config /etc/sift/config.toml";
|
||||
WorkingDirectory = "/var/lib/sift";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5s";
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX"
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
];
|
||||
CapabilityBoundingSet = "";
|
||||
AmbientCapabilities = "";
|
||||
ReadWritePaths = [ "/var/lib/sift" ];
|
||||
ConfigurationDirectory = "sift";
|
||||
StateDirectory = "sift";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.tailscale-serve-sift = lib.mkIf cfg.tailscaleServe {
|
||||
description = "Advertise sift on Tailscale Serve :${toString cfg.tailscaleHttpsPort}";
|
||||
after = [
|
||||
"tailscaled.service"
|
||||
"network-online.target"
|
||||
"sift.service"
|
||||
];
|
||||
wants = [
|
||||
"tailscaled.service"
|
||||
"network-online.target"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5s";
|
||||
ExecStart = "${lib.getExe pkgs.tailscale} serve --bg --yes --https=${toString cfg.tailscaleHttpsPort} http://${cfg.listen}";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user