nix: cleanup
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ia88656a1d6bb152398a5c4ce83d40a3e6a6a6964
This commit is contained in:
parent
794e4a8e61
commit
62f8cdf4de
13 changed files with 514 additions and 529 deletions
|
|
@ -4,60 +4,73 @@
|
|||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf mkDefault;
|
||||
inherit (lib.options) mkOption mkEnableOption;
|
||||
inherit (lib.types) bool str int package listOf submodule nullOr;
|
||||
inherit (lib.attrsets) recursiveUpdate optionalAttrs;
|
||||
inherit (lib.lists) optional map;
|
||||
|
||||
cfg = config.services.fc;
|
||||
|
||||
settingsFormat = pkgs.formats.toml {};
|
||||
settingsType = settingsFormat.type;
|
||||
|
||||
# Build the final settings by merging declarative config into settings
|
||||
finalSettings = lib.recursiveUpdate cfg.settings (lib.optionalAttrs (cfg.declarative.projects != [] || cfg.declarative.apiKeys != []) {
|
||||
finalSettings = recursiveUpdate cfg.settings (optionalAttrs (cfg.declarative.projects != [] || cfg.declarative.apiKeys != []) {
|
||||
declarative = {
|
||||
projects = map (p: {
|
||||
name = p.name;
|
||||
repository_url = p.repositoryUrl;
|
||||
description = p.description or null;
|
||||
jobsets = map (j: {
|
||||
name = j.name;
|
||||
nix_expression = j.nixExpression;
|
||||
enabled = j.enabled;
|
||||
flake_mode = j.flakeMode;
|
||||
check_interval = j.checkInterval;
|
||||
}) p.jobsets;
|
||||
}) cfg.declarative.projects;
|
||||
api_keys = map (k: {
|
||||
name = k.name;
|
||||
key = k.key;
|
||||
role = k.role;
|
||||
}) cfg.declarative.apiKeys;
|
||||
projects =
|
||||
map (p: {
|
||||
name = p.name;
|
||||
repository_url = p.repositoryUrl;
|
||||
description = p.description or null;
|
||||
jobsets =
|
||||
map (j: {
|
||||
name = j.name;
|
||||
nix_expression = j.nixExpression;
|
||||
enabled = j.enabled;
|
||||
flake_mode = j.flakeMode;
|
||||
check_interval = j.checkInterval;
|
||||
})
|
||||
p.jobsets;
|
||||
})
|
||||
cfg.declarative.projects;
|
||||
|
||||
api_keys =
|
||||
map (k: {
|
||||
name = k.name;
|
||||
key = k.key;
|
||||
role = k.role;
|
||||
})
|
||||
cfg.declarative.apiKeys;
|
||||
};
|
||||
});
|
||||
|
||||
settingsFile = settingsFormat.generate "fc.toml" finalSettings;
|
||||
|
||||
inherit (builtins) map;
|
||||
|
||||
jobsetOpts = {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = str;
|
||||
description = "Jobset name.";
|
||||
};
|
||||
nixExpression = mkOption {
|
||||
type = str;
|
||||
description = "Nix expression to evaluate (e.g. 'packages', 'checks', 'hydraJobs').";
|
||||
};
|
||||
enabled = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = "Whether this jobset is enabled for evaluation.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = str;
|
||||
description = "Jobset name.";
|
||||
};
|
||||
|
||||
nixExpression = mkOption {
|
||||
type = str;
|
||||
description = "Nix expression to evaluate (e.g. 'packages', 'checks', 'hydraJobs').";
|
||||
};
|
||||
|
||||
flakeMode = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = "Whether to evaluate as a flake.";
|
||||
};
|
||||
|
||||
checkInterval = mkOption {
|
||||
type = int;
|
||||
default = 60;
|
||||
|
|
@ -72,15 +85,18 @@
|
|||
type = str;
|
||||
description = "Project name (unique identifier).";
|
||||
};
|
||||
|
||||
repositoryUrl = mkOption {
|
||||
type = str;
|
||||
description = "Git repository URL.";
|
||||
};
|
||||
|
||||
description = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "Optional project description.";
|
||||
};
|
||||
|
||||
jobsets = mkOption {
|
||||
type = listOf (submodule jobsetOpts);
|
||||
default = [];
|
||||
|
|
@ -95,6 +111,7 @@
|
|||
type = str;
|
||||
description = "Human-readable name for this API key.";
|
||||
};
|
||||
|
||||
key = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
|
|
@ -102,10 +119,21 @@
|
|||
Will be hashed before storage. Consider using a secrets manager.
|
||||
'';
|
||||
};
|
||||
|
||||
role = mkOption {
|
||||
type = str;
|
||||
default = "admin";
|
||||
description = "Role: admin, read-only, create-projects, eval-jobset, cancel-build, restart-jobs, bump-to-front.";
|
||||
description = ''
|
||||
Role:
|
||||
|
||||
* admin,
|
||||
* read-only,
|
||||
* create-projects,
|
||||
* eval-jobset,
|
||||
* cancel-build,
|
||||
* restart-jobs,
|
||||
* bump-to-front.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -121,13 +149,15 @@ in {
|
|||
evaluatorPackage = mkOption {
|
||||
type = package;
|
||||
default = cfg.package;
|
||||
description = "The FC evaluator package. Defaults to cfg.package.";
|
||||
defaultText = "cfg.package";
|
||||
description = "The FC evaluator package.";
|
||||
};
|
||||
|
||||
queueRunnerPackage = mkOption {
|
||||
type = package;
|
||||
default = cfg.package;
|
||||
description = "The FC queue runner package. Defaults to cfg.package.";
|
||||
defaultText = "cfg.package";
|
||||
description = "The FC queue runner package.";
|
||||
};
|
||||
|
||||
migratePackage = mkOption {
|
||||
|
|
@ -139,8 +169,8 @@ in {
|
|||
type = settingsType;
|
||||
default = {};
|
||||
description = ''
|
||||
FC configuration as a Nix attribute set.
|
||||
Will be converted to TOML and written to fc.toml.
|
||||
FC configuration as a Nix attribute set. Will be converted to TOML
|
||||
and written to {file}`fc.toml`.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -152,19 +182,23 @@ in {
|
|||
Declarative project definitions. These are upserted on every
|
||||
server startup, ensuring the database matches this configuration.
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
[
|
||||
{
|
||||
name = "my-project";
|
||||
repositoryUrl = "https://github.com/user/repo";
|
||||
description = "My Nix project";
|
||||
jobsets = [
|
||||
{ name = "packages"; nixExpression = "packages"; }
|
||||
{ name = "checks"; nixExpression = "checks"; }
|
||||
];
|
||||
}
|
||||
]
|
||||
'';
|
||||
example = [
|
||||
{
|
||||
name = "my-project";
|
||||
repositoryUrl = "https://github.com/user/repo";
|
||||
description = "My Nix project";
|
||||
jobsets = [
|
||||
{
|
||||
name = "packages";
|
||||
nixExpression = "packages";
|
||||
}
|
||||
{
|
||||
name = "checks";
|
||||
nixExpression = "checks";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
apiKeys = mkOption {
|
||||
|
|
@ -174,12 +208,18 @@ in {
|
|||
Declarative API key definitions. Keys are upserted on every
|
||||
server startup. Use a secrets manager for production deployments.
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
[
|
||||
{ name = "admin"; key = "fc_admin_secret"; role = "admin"; }
|
||||
{ name = "ci-bot"; key = "fc_ci_bot_key"; role = "eval-jobset"; }
|
||||
]
|
||||
'';
|
||||
example = [
|
||||
{
|
||||
name = "admin";
|
||||
key = "fc_admin_secret";
|
||||
role = "admin";
|
||||
}
|
||||
{
|
||||
name = "ci-bot";
|
||||
key = "fc_ci_bot_key";
|
||||
role = "eval-jobset";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -204,7 +244,7 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
config = mkIf cfg.enable {
|
||||
users.users.fc = {
|
||||
isSystemUser = true;
|
||||
group = "fc";
|
||||
|
|
@ -214,7 +254,7 @@ in {
|
|||
|
||||
users.groups.fc = {};
|
||||
|
||||
services.postgresql = lib.mkIf cfg.database.createLocally {
|
||||
services.postgresql = mkIf cfg.database.createLocally {
|
||||
enable = true;
|
||||
ensureDatabases = ["fc"];
|
||||
ensureUsers = [
|
||||
|
|
@ -225,14 +265,18 @@ in {
|
|||
];
|
||||
};
|
||||
|
||||
services.fc.settings = lib.mkDefault {
|
||||
services.fc.settings = mkDefault {
|
||||
database.url = "postgresql:///fc?host=/run/postgresql";
|
||||
server.host = "127.0.0.1";
|
||||
server.port = 3000;
|
||||
gc.gc_roots_dir = "/nix/var/nix/gcroots/per-user/fc/fc-roots";
|
||||
gc.enabled = true;
|
||||
gc.max_age_days = 30;
|
||||
gc.cleanup_interval = 3600;
|
||||
|
||||
gc = {
|
||||
gc_roots_dir = "/nix/var/nix/gcroots/per-user/fc/fc-roots";
|
||||
enabled = true;
|
||||
max_age_days = 30;
|
||||
cleanup_interval = 3600;
|
||||
};
|
||||
|
||||
logs.log_dir = "/var/lib/fc/logs";
|
||||
cache.enabled = true;
|
||||
evaluator.restrict_eval = true;
|
||||
|
|
@ -240,125 +284,129 @@ in {
|
|||
signing.enabled = false;
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
(lib.mkIf cfg.server.enable "d /var/lib/fc/logs 0750 fc fc -")
|
||||
(lib.mkIf cfg.queueRunner.enable "d /nix/var/nix/gcroots/per-user/fc 0755 fc fc -")
|
||||
];
|
||||
|
||||
systemd.services.fc-server = lib.mkIf cfg.server.enable {
|
||||
description = "FC CI Server";
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target"] ++ lib.optional cfg.database.createLocally "postgresql.target";
|
||||
requires = lib.optional cfg.database.createLocally "postgresql.target";
|
||||
|
||||
path = with pkgs; [nix zstd];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStartPre = "${cfg.migratePackage}/bin/fc-migrate up ${finalSettings.database.url or "postgresql:///fc?host=/run/postgresql"}";
|
||||
ExecStart = "${cfg.package}/bin/fc-server";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
User = "fc";
|
||||
Group = "fc";
|
||||
StateDirectory = "fc";
|
||||
LogsDirectory = "fc";
|
||||
WorkingDirectory = "/var/lib/fc";
|
||||
ReadWritePaths = ["/var/lib/fc"];
|
||||
|
||||
# Hardening
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
|
||||
environment = {
|
||||
FC_CONFIG_FILE = "${settingsFile}";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.fc-evaluator = lib.mkIf cfg.evaluator.enable {
|
||||
description = "FC CI Evaluator";
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target" "fc-server.service"] ++ lib.optional cfg.database.createLocally "postgresql.target";
|
||||
requires = ["fc-server.service"] ++ lib.optional cfg.database.createLocally "postgresql.target";
|
||||
|
||||
path = with pkgs; [
|
||||
nix
|
||||
git
|
||||
nix-eval-jobs
|
||||
systemd = {
|
||||
tmpfiles.rules = [
|
||||
(mkIf cfg.server.enable "d /var/lib/fc/logs 0750 fc fc -")
|
||||
(mkIf cfg.queueRunner.enable "d /nix/var/nix/gcroots/per-user/fc 0755 fc fc -")
|
||||
];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.evaluatorPackage}/bin/fc-evaluator";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
User = "fc";
|
||||
Group = "fc";
|
||||
StateDirectory = "fc";
|
||||
WorkingDirectory = "/var/lib/fc";
|
||||
ReadWritePaths = ["/var/lib/fc"];
|
||||
services = {
|
||||
fc-server = mkIf cfg.server.enable {
|
||||
description = "FC CI Server";
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target"] ++ optional cfg.database.createLocally "postgresql.target";
|
||||
requires = optional cfg.database.createLocally "postgresql.target";
|
||||
|
||||
# Hardening
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
path = with pkgs; [nix zstd];
|
||||
|
||||
environment = {
|
||||
FC_CONFIG_FILE = "${settingsFile}";
|
||||
FC_EVALUATOR__WORK_DIR = "/var/lib/fc/evaluator";
|
||||
FC_EVALUATOR__RESTRICT_EVAL = "true";
|
||||
};
|
||||
};
|
||||
serviceConfig = {
|
||||
ExecStartPre = "${cfg.migratePackage}/bin/fc-migrate up ${finalSettings.database.url or "postgresql:///fc?host=/run/postgresql"}";
|
||||
ExecStart = "${cfg.package}/bin/fc-server";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
User = "fc";
|
||||
Group = "fc";
|
||||
StateDirectory = "fc";
|
||||
LogsDirectory = "fc";
|
||||
WorkingDirectory = "/var/lib/fc";
|
||||
ReadWritePaths = ["/var/lib/fc"];
|
||||
|
||||
systemd.services.fc-queue-runner = lib.mkIf cfg.queueRunner.enable {
|
||||
description = "FC CI Queue Runner";
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target" "fc-server.service"] ++ lib.optional cfg.database.createLocally "postgresql.target";
|
||||
requires = ["fc-server.service"] ++ lib.optional cfg.database.createLocally "postgresql.target";
|
||||
# Hardening
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
|
||||
path = with pkgs; [
|
||||
nix
|
||||
];
|
||||
environment = {
|
||||
FC_CONFIG_FILE = "${settingsFile}";
|
||||
};
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.queueRunnerPackage}/bin/fc-queue-runner";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
User = "fc";
|
||||
Group = "fc";
|
||||
StateDirectory = "fc";
|
||||
LogsDirectory = "fc";
|
||||
WorkingDirectory = "/var/lib/fc";
|
||||
ReadWritePaths = [
|
||||
"/var/lib/fc"
|
||||
"/nix/var/nix/gcroots/per-user/fc"
|
||||
];
|
||||
fc-evaluator = mkIf cfg.evaluator.enable {
|
||||
description = "FC CI Evaluator";
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target" "fc-server.service"] ++ optional cfg.database.createLocally "postgresql.target";
|
||||
requires = ["fc-server.service"] ++ optional cfg.database.createLocally "postgresql.target";
|
||||
|
||||
# Hardening
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
path = with pkgs; [
|
||||
nix
|
||||
git
|
||||
nix-eval-jobs
|
||||
];
|
||||
|
||||
environment = {
|
||||
FC_CONFIG_FILE = "${settingsFile}";
|
||||
FC_QUEUE_RUNNER__WORK_DIR = "/var/lib/fc/queue-runner";
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.evaluatorPackage}/bin/fc-evaluator";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
User = "fc";
|
||||
Group = "fc";
|
||||
StateDirectory = "fc";
|
||||
WorkingDirectory = "/var/lib/fc";
|
||||
ReadWritePaths = ["/var/lib/fc"];
|
||||
|
||||
# Hardening
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
|
||||
environment = {
|
||||
FC_CONFIG_FILE = "${settingsFile}";
|
||||
FC_EVALUATOR__WORK_DIR = "/var/lib/fc/evaluator";
|
||||
FC_EVALUATOR__RESTRICT_EVAL = "true";
|
||||
};
|
||||
};
|
||||
|
||||
fc-queue-runner = mkIf cfg.queueRunner.enable {
|
||||
description = "FC CI Queue Runner";
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target" "fc-server.service"] ++ optional cfg.database.createLocally "postgresql.target";
|
||||
requires = ["fc-server.service"] ++ optional cfg.database.createLocally "postgresql.target";
|
||||
|
||||
path = with pkgs; [
|
||||
nix
|
||||
];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.queueRunnerPackage}/bin/fc-queue-runner";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
User = "fc";
|
||||
Group = "fc";
|
||||
StateDirectory = "fc";
|
||||
LogsDirectory = "fc";
|
||||
WorkingDirectory = "/var/lib/fc";
|
||||
ReadWritePaths = [
|
||||
"/var/lib/fc"
|
||||
"/nix/var/nix/gcroots/per-user/fc"
|
||||
];
|
||||
|
||||
# Hardening
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
|
||||
environment = {
|
||||
FC_CONFIG_FILE = "${settingsFile}";
|
||||
FC_QUEUE_RUNNER__WORK_DIR = "/var/lib/fc/queue-runner";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue