Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

NixOS Module

The kennel NixOS module configures the kennel service, Caddy, systemd integration, and resource provisioning on a NixOS host.

{ kennel, ... }:
{
  imports = [ kennel.nixosModules.default ];

  services.kennel = {
    enable = true;
    package = kennel.packages.x86_64-linux.kennel;
    devenvPackage = kennel.packages.x86_64-linux.devenv;
    webhookSecretFile = config.age.secrets.kennel-webhook.path;
    environmentFile = config.age.secrets.kennel.path;

    domains = {
      ephemeral = "scottylabs.net";
      cloudflare.zones."scottylabs.org" = "<zone-id>";
    };

    resources.postgres = {
      enable = true;
      socketDir = "/run/postgresql";
    };

    secrets = {
      enable = true;
      vaultEndpoint = "https://secrets2.scottylabs.org";
    };
  };
}

Options

services.kennel.enable

Whether to enable Kennel deployment platform.

Type: boolean

Default:

false

Example:

true

Declared by:

services.kennel.package

The Kennel package to use

Type: package

Default:

pkgs.kennel

Declared by:

services.kennel.api.host

API server bind address

Type: string

Default:

"0.0.0.0"

Declared by:

services.kennel.api.port

API server port

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

Default:

3000

Declared by:

services.kennel.builder.cachix.enable

Whether to enable pushing build artifacts to a Cachix binary cache.

Type: boolean

Default:

false

Example:

true

Declared by:

services.kennel.builder.cachix.cacheName

Cachix cache name

Type: null or string

Default:

null

Declared by:

services.kennel.builder.maxConcurrentBuilds

Maximum number of concurrent nix builds

Type: signed integer

Default:

2

Declared by:

services.kennel.builder.workDir

Build working directory

Type: absolute path

Default:

"/var/lib/kennel/builds"

Declared by:

services.kennel.caddy.adminUrl

Caddy admin API URL

Type: string

Default:

"http://localhost:2019"

Declared by:

services.kennel.customDomainsFile

Writes the custom domains of all live deployments to this path, one per line, refreshed on each reconciliation pass. Unset disables it.

Type: null or string

Default:

null

Example:

"/run/kennel/custom-domains"

Declared by:

services.kennel.devenvPackage

The devenv package. The build worker uses devenv build to evaluate project kennel configs from their devenv.nix.

Type: package

Declared by:

services.kennel.domain

Public domain for the kennel API and webhook endpoint. The module configures a Caddy virtualhost with automatic TLS for this domain, reverse-proxying to the API server.

Type: string

Default:

"kennel.scottylabs.org"

Declared by:

services.kennel.domains.cloudflare.publicIp

Public IPv4 used as the content of the A records that kennel creates for custom domains. Required to enable DNS automation.

Type: null or string

Default:

null

Declared by:

services.kennel.domains.cloudflare.zones

Map of domain names to Cloudflare zone IDs. When this is non-empty, publicIp is set, and the CLOUDFLARE_API_TOKEN environment variable is provided (typically via the environmentFile secret), kennel automatically manages A records for any custom domain whose suffix matches one of the configured zones. The most specific zone wins for nested domains.

The token must have Zone:DNS:Edit permission on the zones listed.

Records are upserted on deploy and on each reconciliation pass (so they self-heal if pruned externally). Records are deleted only when kennel tears the deployment down, which happens in three cases:

  1. The branch backing the deployment is deleted from the source repo (push event with deleted=true on that ref).
  2. The deployment is associated with a pull request and that pull request is closed.
  3. The deployment is on a dev or preview branch and exceeds DEPLOYMENT_EXPIRY_DAYS since its last update during a reconciliation pass.

Production deployments are not subject to expiry, so a record for a production custom domain stays in place until the project’s main branch is deleted or the deployment row is removed manually.

Type: attribute set of string

Default:

{ }

Declared by:

services.kennel.domains.ephemeral

Base domain for auto-generated deployment URLs. A wildcard DNS record should point *.{domain} to the kennel server.

Type: string

Default:

"scottylabs.net"

Declared by:

services.kennel.environmentFile

Path to an environment file containing secrets like VAULT_TOKEN, CACHIX_AUTH_TOKEN, and GARAGE_ADMIN_TOKEN. Loaded by systemd before the service starts.

Type: null or absolute path

Default:

null

Declared by:

services.kennel.forgejo.apiTokenFile

Path to a file containing a Forgejo API token with the write:issue scope. Kennel uses it to post and update a sticky comment on each pull request listing its deployment URLs, and to mark the comment torn down when the pull request is closed.

Type: absolute path

Declared by:

services.kennel.forgejo.apiUrl

Forgejo API base URL used to post PR deployment comments

Type: string

Default:

"https://codeberg.org/api/v1"

Declared by:

services.kennel.grafanaUrl

Base URL of Grafana for Logs Drilldown links in commit statuses

Type: null or string

Default:

"https://grafana.scottylabs.org"

Declared by:

services.kennel.group

Group to run Kennel as

Type: string

Default:

"kennel"

Declared by:

services.kennel.resources.garage.enable

Whether to enable Garage S3 resource provisioning. Kennel creates a bucket and API key per deployment. Requires GARAGE_ADMIN_TOKEN in the environment file.

Type: boolean

Default:

false

Declared by:

services.kennel.resources.garage.adminEndpoint

Garage admin API endpoint

Type: string

Default:

"http://localhost:3903"

Declared by:

services.kennel.resources.garage.s3Endpoint

Garage S3 API endpoint

Type: string

Default:

"http://localhost:3900"

Declared by:

services.kennel.resources.postgres.enable

Whether to enable PostgreSQL resource provisioning. Kennel creates a database per deployment using the specified socket directory for peer authentication.

Type: boolean

Default:

false

Declared by:

services.kennel.resources.postgres.socketDir

PostgreSQL Unix socket directory

Type: absolute path

Default:

"/run/postgresql"

Declared by:

services.kennel.resources.valkey.enable

Whether to enable Valkey resource provisioning. Kennel allocates a DB number per deployment from the shared instance.

Type: boolean

Default:

false

Declared by:

services.kennel.resources.valkey.socketPath

Valkey Unix socket path

Type: absolute path

Default:

"/run/valkey/valkey.sock"

Declared by:

services.kennel.secrets.enable

Whether to enable secretspec/OpenBao secret resolution at deploy time.

Type: boolean

Default:

false

Example:

true

Declared by:

services.kennel.secrets.vaultEndpoint

secretspec provider URI for OpenBao/Vault

Type: string

Default:

"vault://secrets2.scottylabs.org/secret?auth=approle"

Declared by:

services.kennel.user

User to run Kennel as

Type: string

Default:

"kennel"

Declared by:

services.kennel.webhookSecretFile

Path to a file containing the HMAC secret used to verify all incoming webhooks. This is a single secret shared across all projects, provisioned by governance.

Type: absolute path

Declared by:

What the module configures

  • A systemd service for kennel with Delegate=yes for cgroup v2 access
  • A polkit rule allowing the kennel user to create transient systemd units via D-Bus
  • A kennel.slice for all managed deployment units
  • A Caddy virtualhost for the kennel domain with automatic TLS, plus the admin API for dynamic route management
  • tmpfiles rules for /var/lib/kennel subdirectories
  • Firewall rules for ports 80 and 443
  • Cachix binary cache substituter