mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 12:25:22 +00:00
241 lines
8.3 KiB
Nix
241 lines
8.3 KiB
Nix
self: {
|
|
config,
|
|
pkgs,
|
|
lib ? pkgs.lib,
|
|
...
|
|
}:
|
|
with lib; let
|
|
cfg = config.services.sourcebot;
|
|
in {
|
|
options.services.sourcebot = {
|
|
enable = mkEnableOption "Enable SourceBot";
|
|
dataDir = mkOption {
|
|
type = types.path;
|
|
default = "/var/lib/sourcebot";
|
|
description = "Root data directory for SourceBot";
|
|
};
|
|
package = lib.mkOption {
|
|
type = types.package;
|
|
default = self.packages.${pkgs.system}.sourcebot;
|
|
description = "Package to use for nixos-cli";
|
|
};
|
|
# Override default, based on DATA_DIR
|
|
dataCacheDir = mkOption {
|
|
type = types.path;
|
|
default = "/var/cache/sourcebot";
|
|
description = "Directory for SourceBot data cache";
|
|
};
|
|
envFile = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
description = "Environment file for additional settings";
|
|
};
|
|
|
|
logLevel = mkOption {
|
|
type = types.enum ["debug" "info" "warn" "error"];
|
|
default = "info";
|
|
description = "SourceBot logging level";
|
|
};
|
|
authEnabled = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Enables authentication in SourceBot";
|
|
};
|
|
telemetryDisabled = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Disables telemetry collection in SourceBot";
|
|
};
|
|
openFirewall = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Open Firwall ports for SourceBot";
|
|
};
|
|
|
|
configPath = mkOption {
|
|
type = types.str;
|
|
description = "Path to the SourceBot configuration file";
|
|
};
|
|
port = mkOption {
|
|
type = types.int;
|
|
default = 7734;
|
|
description = "TCP port for the SourceBot web server to listen on";
|
|
};
|
|
hostname = mkOption {
|
|
type = types.str;
|
|
default = "0.0.0.0";
|
|
description = "Hostname or IP address for the SourceBot web server to bind to";
|
|
};
|
|
authUrl = mkOption {
|
|
type = types.str;
|
|
default = "http://${cfg.hostname}:${toString cfg.port}";
|
|
description = "Hostname or IP address for the SourceBot web server to bind to";
|
|
};
|
|
redisPort = mkOption {
|
|
type = types.int;
|
|
default = 16379;
|
|
description = "TCP port for the SourceBot Redis server to listen on";
|
|
};
|
|
databaseUrl = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = "postgresql://sourcebot@localhost:${toString config.services.postgresql.settings.port}/sourcebot";
|
|
description = "PostgreSQL connection URL for SourceBot. If not set, a local PostgreSQL server will be configured and used.";
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
# Create a dedicated system group for SourceBot
|
|
users.groups.sourcebot = {};
|
|
# Create a dedicated system user for SourceBot
|
|
users.users.sourcebot = {
|
|
isSystemUser = true;
|
|
group = "sourcebot"; # primary group
|
|
description = "Service account for SourceBot";
|
|
home = cfg.dataDir;
|
|
shell = "/run/current-system/sw/bin/false";
|
|
};
|
|
|
|
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.port];
|
|
# Enable redis using the existing NixOS module
|
|
services.redis.servers.sourcebot = {
|
|
enable = true;
|
|
user = "sourcebot";
|
|
port = cfg.redisPort;
|
|
};
|
|
|
|
# Enable Postgres for SourceBot with isolated data directory and database
|
|
services.postgresql = {
|
|
enable = true;
|
|
enableTCPIP = true;
|
|
ensureDatabases = ["sourcebot"];
|
|
ensureUsers = [
|
|
{
|
|
name = "sourcebot";
|
|
ensureDBOwnership = true;
|
|
}
|
|
];
|
|
# Allow connections from any container IP addresses
|
|
authentication = mkBefore ''
|
|
local sourcebot sourcebot trust
|
|
host sourcebot sourcebot 127.0.0.1/32 trust
|
|
host sourcebot sourcebot ::1/128 trust
|
|
'';
|
|
};
|
|
|
|
# Create and own data directories
|
|
systemd.tmpfiles.rules = [
|
|
# ensure root data dir
|
|
"d ${cfg.dataDir} 0755 sourcebot sourcebot -"
|
|
# ensure cache dir
|
|
"d ${cfg.dataCacheDir} 0755 sourcebot sourcebot -"
|
|
];
|
|
|
|
# Zoekt search service
|
|
systemd.services.sourcebot-zoekt = {
|
|
description = "SourceBot Zoekt Search Service";
|
|
after = ["network.target" "redis.service"];
|
|
wants = ["redis.service"];
|
|
serviceConfig = {
|
|
# Run under the sourcebot user
|
|
User = "sourcebot";
|
|
Group = "sourcebot";
|
|
ExecStart = "${pkgs.zoekt}/bin/zoekt-webserver -index ${cfg.dataCacheDir}/index -rpc";
|
|
Restart = "on-failure";
|
|
RestartSec = "5s";
|
|
Environment = [
|
|
"DATA_DIR=${cfg.dataDir}"
|
|
"DATA_CACHE_DIR=${cfg.dataCacheDir}"
|
|
];
|
|
};
|
|
};
|
|
|
|
systemd.services.sourcebot-db-setup = {
|
|
description = "SourceBot Database setup";
|
|
after = ["network.target" "postgresql.service"];
|
|
wants = ["postgresql.service"];
|
|
serviceConfig = {
|
|
# Run under the sourcebot user
|
|
Type = "oneshot";
|
|
User = "sourcebot";
|
|
Group = "sourcebot";
|
|
ExecStart = "${pkgs.prisma}/bin/prisma migrate deploy --schema ${cfg.package}/packages/db/prisma/schema.prisma";
|
|
Environment = [
|
|
"PATH=${makeBinPath (with pkgs; [prisma openssl])}"
|
|
"DATABASE_URL=${cfg.databaseUrl}"
|
|
];
|
|
Restart = "on-failure";
|
|
RestartSec = "5s";
|
|
};
|
|
};
|
|
# Web frontend service
|
|
systemd.services.sourcebot-web = {
|
|
description = "SourceBot Web Service";
|
|
after = ["network.target" "sourcebot-zoekt.service" "sourcebot-db-setup.service"];
|
|
wants = ["sourcebot-zoekt.service" "sourcebot-db-setup.service"];
|
|
wantedBy = ["multi-user.target"];
|
|
serviceConfig = {
|
|
# Run under the sourcebot user
|
|
User = "sourcebot";
|
|
Group = "sourcebot";
|
|
Environment =
|
|
[
|
|
"DATA_DIR=${cfg.dataDir}"
|
|
"DATA_CACHE_DIR=${cfg.dataCacheDir}"
|
|
"PORT=${toString cfg.port}"
|
|
"HOSTNAME=${cfg.hostname}"
|
|
"DATABASE_URL=${cfg.databaseUrl}"
|
|
"REDIS_URL=redis://localhost:${toString cfg.redisPort}"
|
|
"CONFIG_PATH=${cfg.configPath}"
|
|
"SOURCEBOT_LOG_LEVEL=${cfg.logLevel}"
|
|
"SOURCEBOT_TENANCY_MODE=single"
|
|
"AUTH_CREDENTIALS_LOGIN_ENABLED=${boolToString cfg.authEnabled}"
|
|
"SOURCEBOT_TELEMETRY_DISABLED=${boolToString cfg.telemetryDisabled}"
|
|
"SOURCEBOT_PUBLIC_KEY_PATH=${cfg.package}/public.pem"
|
|
"AUTH_URL=http://${cfg.hostname}:${toString cfg.port}"
|
|
]
|
|
++ optional (cfg.envFile == null) [
|
|
"AUTH_SECRET=00000000000000000000000000000000000000000000"
|
|
"SOURCEBOT_ENCRYPTION_KEY=00000000000000000000000000000000"
|
|
];
|
|
EnvironmentFile = cfg.envFile;
|
|
ExecStart = "${cfg.package}/bin/sourcebot-web";
|
|
Restart = "always";
|
|
};
|
|
};
|
|
|
|
# Backend API service
|
|
systemd.services.sourcebot-backend = {
|
|
description = "SourceBot Backend Service";
|
|
after = ["network.target" "sourcebot-zoekt.service" "sourcebot-db-setup.service"];
|
|
wants = ["sourcebot-zoekt.service" "sourcebot-db-setup.service"];
|
|
wantedBy = ["multi-user.target"];
|
|
serviceConfig = {
|
|
# Run under the sourcebot user
|
|
User = "sourcebot";
|
|
Group = "sourcebot";
|
|
Environment =
|
|
[
|
|
"DATA_DIR=${cfg.dataDir}"
|
|
"DATA_CACHE_DIR=${cfg.dataCacheDir}"
|
|
"DATABASE_URL=postgresql://sourcebot@localhost:${toString config.services.postgresql.settings.port}/sourcebot"
|
|
"REDIS_URL=redis://localhost:${toString cfg.redisPort}"
|
|
"CONFIG_PATH=${cfg.configPath}"
|
|
"SOURCEBOT_LOG_LEVEL=${cfg.logLevel}"
|
|
"SOURCEBOT_TENANCY_MODE=single"
|
|
"AUTH_CREDENTIALS_LOGIN_ENABLED=${boolToString cfg.authEnabled}"
|
|
"SOURCEBOT_TELEMETRY_DISABLED=${boolToString cfg.telemetryDisabled}"
|
|
"SOURCEBOT_PUBLIC_KEY_PATH=${cfg.package}/public.pem"
|
|
"AUTH_URL=http://${cfg.hostname}:${toString cfg.port}"
|
|
]
|
|
++ optional (cfg.envFile == null) [
|
|
"AUTH_SECRET=00000000000000000000000000000000000000000000"
|
|
"SOURCEBOT_ENCRYPTION_KEY=00000000000000000000000000000000"
|
|
];
|
|
EnvironmentFile = cfg.envFile;
|
|
ExecStart = "${cfg.package}/bin/sourcebot-backend --cacheDir ${cfg.dataCacheDir}";
|
|
Restart = "on-failure";
|
|
RestartSec = "5s";
|
|
};
|
|
};
|
|
};
|
|
}
|