NixOS Module Reference

This page is auto-generated from the NixOS module options schema. For a user-friendly guide, see NixOS Module.

services.eka-ci.enable

Whether to enable EkaCI, a Nix-aware Continuous Integration server.

Type: boolean

Default:

false

Example:

true

services.eka-ci.package

The eka-ci package to use.

Type: package

Default:

pkgs.eka-ci

services.eka-ci.credentials

Map of credential name to file path, wired through systemd’s LoadCredential=. Each entry becomes available inside the unit at $CREDENTIALS_DIRECTORY/<name> and can be referenced from ekaci.toml via the systemd-credential credential source, e.g.

services.eka-ci.settings.github_apps = [
  {
    id = "main";
    credentials.systemd-credential.name = "github-app-key";
  }
];

Type: attribute set of absolute path

Default:

{ }

Example:

{
  github-app-key = "/run/secrets/github-app.json";
  s3-creds       = "/run/secrets/s3.json";
}

services.eka-ci.dynamicUser

Use systemd’s DynamicUser= to run the service under an ephemeral user/group. Recommended unless you need a stable UID for filesystem permissions on shared storage.

Type: boolean

Default:

true

services.eka-ci.environmentFile

Path to a file passed to systemd as EnvironmentFile=. Use this to provide secrets such as GITHUB_WEBHOOK_SECRET, GITHUB_OAUTH_CLIENT_SECRET, JWT_SECRET, VAULT_TOKEN, AWS keys, and any environment variables referenced from settings.caches.*.credentials.env.vars. The file is read by systemd at start time and never enters the Nix store.

Type: null or absolute path

Default:

null

Example:

"/run/secrets/eka-ci.env"

services.eka-ci.extraEnvironment

Additional Environment= entries passed to the systemd unit.

Type: attribute set of string

Default:

{ }

Example:

{
  RUST_LOG = "eka_ci_server=debug,info";
}

services.eka-ci.group

Group the service runs as when dynamicUser is false. Ignored when dynamicUser = true.

Type: string

Default:

"eka-ci"

services.eka-ci.openFirewall

Open settings.web.port in the system firewall.

Type: boolean

Default:

false

services.eka-ci.settings

Configuration for EkaCI, serialised verbatim to ekaci.toml. The submodule is freeform: any key not explicitly modelled here is still accepted and forwarded as-is to the TOML output.

Type: open submodule of (TOML value)

Default:

{ }

services.eka-ci.settings.build_max_duration_seconds

Hard upper bound, in seconds, on total build wall-clock time.

Type: integer between 60 and 604800 (both inclusive)

Default:

14400

services.eka-ci.settings.build_no_output_timeout_seconds

Number of seconds with no build output after which a build is considered hung.

Type: integer between 30 and 86400 (both inclusive)

Default:

1200

services.eka-ci.settings.caches

List of binary caches the server may push to.

Type: list of (open submodule of (TOML value))

Default:

[ ]

services.eka-ci.settings.caches.*.cache_type

Backend type for this cache.

Type: one of “nix-copy”, “cachix”, “attic”

Example:

"nix-copy"

services.eka-ci.settings.caches.*.credentials

Credential source. One of:

  • { env = { vars = [ ... ]; }; }
  • { file = { path = "/etc/..."; }; }
  • { aws-profile = { profile = "..."; }; }
  • { cachix-token = { env_var = "..."; }; }
  • { vault = { address; secret_path; token_env ? "VAULT_TOKEN"; namespace ? null; }; }
  • { aws-secrets-manager = { secret_name; region ? null; }; }
  • { systemd-credential = { name = "..."; }; }
  • "instance-metadata"
  • { github-app-key-file = { app_id_env; key_file; }; }
  • "none"

Prefer systemd-credential paired with the top-level services.eka-ci.credentials option to keep secrets out of the world-readable Nix store.

Type: TOML value

Example:

{
  env = {
    vars = [
      "AWS_ACCESS_KEY_ID"
      "AWS_SECRET_ACCESS_KEY"
    ];
  };
}

services.eka-ci.settings.caches.*.destination

Destination URL passed to the chosen backend. Validated for SSRF unless settings.security.allow_private_cache_hosts is set.

Type: string

Example:

"s3://my-bucket/nix-cache?region=us-east-1"

services.eka-ci.settings.caches.*.id

Cache identifier referenced from .ekaci/config.json.

Type: string

Example:

"production-s3"

services.eka-ci.settings.caches.*.permissions

Repository/branch access control for this cache.

Type: submodule

Default:

{ }

services.eka-ci.settings.caches.*.permissions.allow_all

When true, ignores allowed_repos and allowed_branches and grants access to every repository and branch.

Type: boolean

Default:

true

services.eka-ci.settings.caches.*.permissions.allowed_branches

Glob patterns of branch names permitted to use this entry. Ignored when allow_all is true.

Type: list of string

Default:

[ ]

Example:

[
  "main"
  "release/*"
]

services.eka-ci.settings.caches.*.permissions.allowed_repos

Glob patterns of owner/repo strings that are permitted to use this entry. Ignored when allow_all is true.

Type: list of string

Default:

[ ]

Example:

[
  "myorg/*"
]

services.eka-ci.settings.channels

Release channels for automated continuous delivery, keyed by an arbitrary identifier. Each channel monitors a tracking branch and fast-forwards a target branch when specified jobs succeed.

See docs/channels.md for detailed configuration and operational guidance.

Type: attribute set of (open submodule of (TOML value))

Default:

{ }

services.eka-ci.settings.channels.<name>.packages

Job attribute names that must reach a terminal state (success, failure, or interrupted) before promotion. Unlike required, these jobs are allowed to fail without blocking promotion. Useful for tracking optional packages that should be built but aren’t critical.

Type: list of string

Default:

[ ]

Example:

[
  "firefox"
  "chromium"
]

services.eka-ci.settings.channels.<name>.dry_run

When true, the channel performs all evaluation logic but skips the actual git push to target_branch. Useful for testing channel configuration without affecting production branches.

Type: boolean

Default:

false

services.eka-ci.settings.channels.<name>.forge

Git forge type for this release channel.

Type: one of “github”, “gitlab”, “gitea”

Example:

"github"

services.eka-ci.settings.channels.<name>.name

Channel name. Used in GitHub check run titles (release/{name}) and CLI status queries.

Type: string

Example:

"stable"

services.eka-ci.settings.channels.<name>.owner

Repository owner/organization.

Type: string

Example:

"myorg"

services.eka-ci.settings.channels.<name>.repo

Repository name.

Type: string

Example:

"myrepo"

services.eka-ci.settings.channels.<name>.required

Job attribute names that MUST succeed for promotion. Job names must match .ekaci/config.json exactly. If any required job fails or is interrupted, the channel enters Blocked status and will not promote.

Type: list of string

Default:

[ ]

Example:

[
  "coreutils"
  "bash"
  "gcc"
]

services.eka-ci.settings.channels.<name>.target_branch

Branch to fast-forward when promotion criteria are met. The GitHub App/GitLab token/Gitea token must have write access to this branch.

Type: string

Example:

"ekapkgs-stable"

services.eka-ci.settings.channels.<name>.tracking_branch

Branch to monitor for new commits to promote.

Type: string

Example:

"master"

services.eka-ci.settings.checks

Limits for repository check commands.

Type: open submodule of (TOML value)

Default:

{ }

services.eka-ci.settings.checks.memory_limit_mb

Address-space limit (RLIMIT_AS), in MiB, for every process of a check.

Type: integer between 1024 and 1048576 (both inclusive)

Default:

8192

services.eka-ci.settings.checks.timeout_secs

Wall-clock limit, in seconds, for one repository check command. The whole sandbox is killed when it elapses.

Type: integer between 10 and 86400 (both inclusive)

Default:

1800

services.eka-ci.settings.db_path

SQLite database path. When null the server falls back to $XDG_DATA_HOME/ekaci/sqlite.db which, under this module, resolves to /var/lib/eka-ci/ekaci/sqlite.db.

Type: null or absolute path

Default:

null

services.eka-ci.settings.default_merge_method

Default merge method used by the @eka-ci merge PR comment command.

Type: one of “merge”, “squash”, “rebase”

Default:

"squash"

services.eka-ci.settings.eval

Evaluation sandbox settings. Every iets eval-jobs run happens inside bubblewrap + landlock with a cleared environment; see docs/server-configuration.md.

Type: open submodule of (TOML value)

Default:

{ }

services.eka-ci.settings.eval.memory_limit_mb

Address-space limit (RLIMIT_AS), in MiB, for every process inside the evaluation sandbox. iets eval-jobs workers are recycled at half of this value.

Type: integer between 1024 and 1048576 (both inclusive)

Default:

8192

services.eka-ci.settings.eval.provenance

Pass --provenance to iets eval-jobs, adding source position (file:line:col) to each job in the eval output.

Type: boolean

Default:

false

services.eka-ci.settings.eval.timeout_secs

Wall-clock limit, in seconds, for one iets eval-jobs run. The whole evaluation sandbox is killed when it elapses.

Type: integer between 10 and 86400 (both inclusive)

Default:

1800

services.eka-ci.settings.gitea_instances

List of Gitea instances the server integrates with. Each instance requires a domain and access token. Supports both Gitea.com and self-hosted instances.

Type: list of (open submodule of (TOML value))

Default:

[ ]

services.eka-ci.settings.gitea_instances.*.domain

Gitea instance domain (without protocol).

Type: string

Example:

"gitea.example.com"

services.eka-ci.settings.gitea_instances.*.token

Gitea access token. Avoid setting this in Nix — values here end up in the world-readable Nix store. Use services.eka-ci.environmentFile to supply GITEA_TOKEN instead (for single instance) or configure tokens via systemd credentials.

Type: null or string

Default:

null

services.eka-ci.settings.github_apps

List of GitHub Apps the server authenticates as.

Type: list of (open submodule of (TOML value))

Default:

[ ]

services.eka-ci.settings.github_apps.*.credentials

Credential source. Same shape as services.eka-ci.settings.caches.*.credentials.

Type: TOML value

Example:

{
  file = {
    path = "/etc/eka-ci/github-app.json";
  };
}

services.eka-ci.settings.github_apps.*.id

GitHub App identifier referenced from per-app permission lookups.

Type: string

Example:

"main"

services.eka-ci.settings.github_apps.*.permissions

Repository/branch access control for this GitHub App.

Type: submodule

Default:

{ }

services.eka-ci.settings.github_apps.*.permissions.allow_all

When true, ignores allowed_repos and allowed_branches and grants access to every repository and branch.

Type: boolean

Default:

true

services.eka-ci.settings.github_apps.*.permissions.allowed_branches

Glob patterns of branch names permitted to use this entry. Ignored when allow_all is true.

Type: list of string

Default:

[ ]

Example:

[
  "main"
  "release/*"
]

services.eka-ci.settings.github_apps.*.permissions.allowed_repos

Glob patterns of owner/repo strings that are permitted to use this entry. Ignored when allow_all is true.

Type: list of string

Default:

[ ]

Example:

[
  "myorg/*"
]

services.eka-ci.settings.gitlab_instances

List of GitLab instances the server integrates with. Each instance requires a domain and project access token. Supports both GitLab.com and self-hosted instances.

Type: list of (open submodule of (TOML value))

Default:

[ ]

services.eka-ci.settings.gitlab_instances.*.domain

GitLab instance domain (without protocol).

Type: string

Example:

"gitlab.com"

services.eka-ci.settings.gitlab_instances.*.token

GitLab project access token. Avoid setting this in Nix — values here end up in the world-readable Nix store. Use services.eka-ci.environmentFile to supply GITLAB_TOKEN instead (for single instance) or configure tokens via systemd credentials.

Type: null or string

Default:

null

services.eka-ci.settings.graph_lru_capacity

Capacity of the in-memory derivation-graph LRU cache, in nodes. See docs/lru-cache-tuning.md for sizing guidance.

Type: positive integer, meaning >0

Default:

100000

services.eka-ci.settings.logs_dir

Directory where build logs are stored. When null the server falls back to $XDG_DATA_HOME/ekaci/build-logs.

Type: null or absolute path

Default:

null

services.eka-ci.settings.merge_queue_require_approval

Require approval before building entries pulled from the GitHub merge queue.

Type: boolean

Default:

false

services.eka-ci.settings.oauth

OAuth settings for the (optional) web UI.

Type: open submodule of (TOML value)

Default:

{ }

services.eka-ci.settings.oauth.client_id

GitHub OAuth client ID. May also be supplied via the GITHUB_OAUTH_CLIENT_ID environment variable (preferred — see services.eka-ci.environmentFile).

Type: null or string

Default:

null

services.eka-ci.settings.oauth.client_secret

GitHub OAuth client secret. Avoid setting this in Nix — values here end up in the world-readable Nix store. Use services.eka-ci.environmentFile to supply GITHUB_OAUTH_CLIENT_SECRET instead.

Type: null or string

Default:

null

services.eka-ci.settings.oauth.jwt_secret

JWT signing secret. Avoid setting this in Nix. Provide JWT_SECRET via services.eka-ci.environmentFile. When omitted entirely, the server generates an ephemeral 256-bit secret on each start (sessions invalidate across restarts).

Type: null or string

Default:

null

services.eka-ci.settings.oauth.redirect_url

OAuth callback URL. Defaults to http://{web.address}:{web.port}/github/auth/callback when unset.

Type: null or string

Default:

null

services.eka-ci.settings.require_approval

Require maintainer approval before building PRs from external contributors.

Type: boolean

Default:

false

services.eka-ci.settings.sandbox

Network policy shared by every sandbox with network access; see docs/server-configuration.md.

Type: open submodule of (TOML value)

Default:

{ }

services.eka-ci.settings.sandbox.helper_path

Path to ekaci-sandbox-helper. When null the server uses the helper installed next to its own binary.

Type: null or absolute path

Default:

null

services.eka-ci.settings.sandbox.network_allow

IPv4 prefixes that sandboxes with network access (evaluation, dev-shell capture, checks with allow_network) may reach despite the built-in deny list of private, link-local, CGNAT and reserved ranges and the server’s own addresses.

Type: list of string

Default:

[ ]

Example:

[
  "10.20.0.5/32"
]

services.eka-ci.settings.sandbox.network_deny

Additional IPv4 prefixes made unreachable from sandboxes.

Type: list of string

Default:

[ ]

services.eka-ci.settings.search_index

Search index generation configuration. When set, the server produces a zstd-compressed SQLite database (search.db.zst) with FTS5 indexes after each channel promotion and uploads it to destination.

The database contains packages, all installed files, and configuration options. It powers tab completion (ekapkgs home packages add <TAB>) and search (ekapkgs search packages <query>, ekapkgs search files <query>) in the ekapkgs CLI, replacing the slow nix search nixpkgs --json ^ fallback with instant lookups.

Set to null (the default) to disable index generation entirely.

Type: null or (open submodule of (TOML value))

Default:

null

Example:

{
  destination = "s3://my-bucket/indexes";
  credentials.aws-profile.profile = "default";
}

services.eka-ci.settings.search_index.enabled

Whether search index generation is enabled. Defaults to true when the [search_index] section is present.

Type: boolean

Default:

true

services.eka-ci.settings.search_index.channels

List of channel IDs that trigger index generation. When empty (the default), indexes are generated for every promoted channel.

Type: list of string

Default:

[ ]

services.eka-ci.settings.search_index.credentials

Credential source for upload authentication. Same shape as services.eka-ci.settings.caches.*.credentials. Defaults to "none" (no authentication).

Type: TOML value

Default:

"none"

Example:

{
  aws-profile = {
    profile = "default";
  };
}

services.eka-ci.settings.search_index.destination

Storage destination for uploading generated indexes. Supports:

  • s3://bucket/prefix — upload via aws s3 cp
  • A local filesystem path — write files directly

When using S3, configure credentials to provide authentication.

Type: string

Example:

"s3://my-bucket/indexes"

services.eka-ci.settings.search_index.public_url

Publicly-reachable base URL where the uploaded indexes are served (e.g. a CloudFront distribution in front of the S3 bucket, or a static file server).

Exposed through the GET /v1/search-index API endpoint so third-party tools can discover index locations without out-of-band configuration. Clients fetch indexes at {public_url}/{channel_name}/search.db.zst.

Type: null or string

Default:

null

Example:

"https://indexes.example.com"

services.eka-ci.settings.security

Security-related settings.

Type: open submodule of (TOML value)

Default:

{ }

services.eka-ci.settings.security.allow_insecure_webhooks

Allow the server to start without a webhook secret. Intended for local development only; never enable in production.

Type: boolean

Default:

false

services.eka-ci.settings.security.allow_private_cache_hosts

Allow cache destinations whose DNS resolves to private/loopback addresses. Disables built-in SSRF protection; only enable in trusted, isolated networks.

Type: boolean

Default:

false

services.eka-ci.settings.security.audit_hooks

Emit structured audit log records every time a hook runs.

Type: boolean

Default:

true

services.eka-ci.settings.security.max_hook_timeout_seconds

Maximum wall-clock time, in seconds, that any post-build hook is allowed to run.

Type: integer between 1 and 86400 (both inclusive)

Default:

300

services.eka-ci.settings.security.webhook_secret

GitHub webhook HMAC secret. Avoid setting this in Nix. Provide GITHUB_WEBHOOK_SECRET via services.eka-ci.environmentFile.

The server refuses to start if no webhook secret is available unless allow_insecure_webhooks is true.

Type: null or string

Default:

null

services.eka-ci.settings.unix

Unix-domain-socket settings used by the CLI client.

Type: open submodule of (TOML value)

Default:

{ }

services.eka-ci.settings.unix.socket_path

Unix domain socket the CLI client connects to. When null the server falls back to $XDG_RUNTIME_DIR/ekaci.socket, which under this module resolves to /run/eka-ci/ekaci.socket.

Type: null or absolute path

Default:

null

services.eka-ci.settings.web

HTTP server settings.

Type: open submodule of (TOML value)

Default:

{ }

services.eka-ci.settings.web.address

IPv4 address the HTTP server binds to.

Type: string

Default:

"127.0.0.1"

services.eka-ci.settings.web.allowed_origins

CORS allow-list. Each entry must be a fully-qualified http:// or https:// origin with no path, query, fragment, or * wildcard. An empty list rejects all cross-origin requests.

Type: list of string

Default:

[ ]

Example:

[
  "https://app.example.com"
]

services.eka-ci.settings.web.port

TCP port the HTTP server binds to.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default:

3030

services.eka-ci.settings.web.static_dir

Directory containing static frontend files (HTML, CSS, JS). If null, defaults to $XDG_DATA_HOME/ekaci/static. Note: bundle_path is a deprecated alias for static_dir.

Type: null or absolute path

Default:

null

services.eka-ci.user

User the service runs as when dynamicUser is false. Ignored when dynamicUser = true.

Type: string

Default:

"eka-ci"