Forgejo Service

Table of Contents

Features
Usage
Debug
Options Reference

Defined in /modules/services/forgejo.nix.

This NixOS module is a service that sets up a Forgejo instance.

Compared to the stock module from nixpkgs, this one sets up, in a fully declarative manner, LDAP and SSO integration as well as one local runner.

Features

Usage

Secrets

All the secrets should be readable by the forgejo user.

Secrets should not be stored in the nix store. If you’re using sops-nix and assuming your secrets file is located at ./secrets.yaml, you can define a secret with:

sops.secrets."forgejo/adminPasswordFile" = {
  sopsFile = ./secrets.yaml;
  mode = "0400";
  owner = "forgejo";
  group = "forgejo";
  restartUnits = [ "forgejo.service" ];
};

Then you can use that secret:

shb.forgejo.adminPasswordFile = config.sops.secrets."forgejo/adminPasswordFile".path;

Forgejo through HTTPS

This will set up a Forgejo service that runs on the NixOS target machine, reachable at http://forgejo.example.com.

shb.forgejo = {
  enable = true;
  domain = "example.com";
  subdomain = "forgejo";
};

If the shb.ssl block is used (see manual on how to set it up), the instance will be reachable at https://fogejo.example.com.

Here is an example with Let’s Encrypt certificates, validated using the HTTP method:

shb.certs.certs.letsencrypt."example.com" = {
  domain = "example.com";
  group = "nginx";
  reloadServices = [ "nginx.service" ];
  adminEmail = "myemail@mydomain.com";
};

Then you can tell Forgejo to use those certificates.

shb.certs.certs.letsencrypt."example.com".extraDomains = [ "forgejo.example.com" ];

shb.forgejo = {
  ssl = config.shb.certs.certs.selfsigned.forgejo;
};

With LDAP Support

Note

We will build upon the HTTPS section, so please follow that first.

We will use the LDAP block provided by Self Host Blocks to setup a LLDAP service.

shb.ldap = {
  enable = true;
  domain = "example.com";
  subdomain = "ldap";
  ssl = config.shb.certs.certs.letsencrypt."example.com";
  ldapPort = 3890;
  webUIListenPort = 17170;
  dcdomain = "dc=example,dc=com";
  ldapUserPassword.result = config.shb.sops.secrets."ldap/userPassword".result;
  jwtSecret.result = config.shb.sops.secrets."ldap/jwtSecret".result;
};

shb.certs.certs.letsencrypt."example.com".extraDomains = [ "ldap.example.com" ];

shb.sops.secrets."ldap/userPassword".request = config.shb.ldap.userPassword.request;
shb.sops.secrets."ldap/jwtSecret".request = config.shb.ldap.jwtSecret.request;

We also need to configure the forgejo service to talk to the LDAP server we just defined:

shb.forgejo.ldap
  enable = true;
  host = "127.0.0.1";
  port = config.shb.ldap.ldapPort;
  dcdomain = config.shb.ldap.dcdomain;
  adminPassword.result = config.shb.sops.secrets."forgejo/ldap/adminPassword".result
};

shb.sops.secrets."forgejo/ldap/adminPassword" = {
  request = config.shb.forgejo.ldap.adminPassword.request;
  settings.key = "ldap/userPassword";
};

The shb.forgejo.ldap.adminPasswordFile must be the same as the shb.ldap.ldapUserPasswordFile. The other secrets can be randomly generated with nix run nixpkgs#openssl -- rand -hex 64.

And that’s it. Now, go to the LDAP server at http://ldap.example.com, create the forgejo_user and forgejo_admin groups, create a user and add it to one or both groups. When that’s done, go back to the Forgejo server at http://forgejo.example.com and login with that user.

With SSO Support

Note

We will build upon the LDAP section, so please follow that first.

We then need to setup the SSO provider, here Authelia thanks to the corresponding SHB block:

shb.authelia = {
  enable = true;
  domain = "example.com";
  subdomain = "auth";
  ssl = config.shb.certs.certs.letsencrypt."example.com";

  ldapHostname = "127.0.0.1";
  ldapPort = config.shb.ldap.ldapPort;
  dcdomain = config.shb.ldap.dcdomain;

  secrets = {
    jwtSecret.result = config.shb.sops.secrets."authelia/jwt_secret".result;
    ldapAdminPassword.result = config.shb.sops.secrets."authelia/ldap_admin_password".result;
    sessionSecret.result = config.shb.sops.secrets."authelia/session_secret".result;
    storageEncryptionKey.result = config.shb.sops.secrets."authelia/storage_encryption_key".result;
    identityProvidersOIDCHMACSecret.result = config.shb.sops.secrets."authelia/hmac_secret".result;
    identityProvidersOIDCIssuerPrivateKey.result = config.shb.sops.secrets."authelia/private_key".result;
  };
};

shb.certs.certs.letsencrypt."example.com".extraDomains = [ "auth.example.com" ];

shb.sops.secrets."authelia/jwt_secret".request = config.shb.authelia.secrets.jwtSecret.request;
shb.sops.secrets."authelia/ldap_admin_password".request = config.shb.authelia.secrets.ldapAdminPassword.request;
shb.sops.secrets."authelia/session_secret".request = config.shb.authelia.secrets.sessionSecret.request;
shb.sops.secrets."authelia/storage_encryption_key".request = config.shb.authelia.secrets.storageEncryptionKey.request;
shb.sops.secrets."authelia/hmac_secret".request = config.shb.authelia.secrets.identityProvidersOIDCHMACSecret.request;
shb.sops.secrets."authelia/private_key".request = config.shb.authelia.secrets.identityProvidersOIDCIssuerPrivateKey.request;
shb.sops.secrets."authelia/smtp_password".request = config.shb.authelia.smtp.password.request;

The shb.authelia.secrets.ldapAdminPasswordFile must be the same as the shb.ldap.ldapUserPasswordFile defined in the previous section. The other secrets can be randomly generated with nix run nixpkgs#openssl -- rand -hex 64.

Now, on the forgejo side, you need to add the following options:

shb.forgejo.sso = {
  enable = true;
  endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";

  secretFile = <path/to/oidcForgejoSharedSecret>;
  secretFileForAuthelia = <path/to/oidcForgejoSharedSecret>;
};

Passing the ssl option will auto-configure nginx to force SSL connections with the given certificate.

The shb.foregejo.sso.secretFile and shb.forgejo.sso.secretFileForAuthelia options must have the same content. The former is a file that must be owned by the forgejo user while the latter must be owned by the authelia user. I want to avoid needing to define the same secret twice with a future secrets SHB block.

Backup

Backing up Forgejo using the Restic block is done like so:

shb.restic.instances."forgejo" = {
  request = config.shb.forgejo.backup;
  settings = {
    enable = true;
  };
};

The name "foregjo" in the instances can be anything. The config.shb.forgejo.backup option provides what directories to backup. You can define any number of Restic instances to backup Foregejo multiple times.

Extra Settings

Other Forgejo settings can be accessed through the nixpkgs stock service.

Debug

In case of an issue, check the logs for systemd service forgejo.service.

Enable verbose logging by setting the shb.forgejo.debug boolean to true.

Access the database with sudo -u forgejo psql.

Options Reference

shb.forgejo.enable

Whether to enable selfhostblocks.forgejo.

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.adminPassword

File containing the Forgejo admin user password.

Type: submodule

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.adminPassword.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.adminPassword.request.group

Linux group owning the secret file.

Type: string

Default: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.adminPassword.request.mode

Mode of the secret file.

Type: string

Default: "0440"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.adminPassword.request.owner

Linux user owning the secret file.

Type: string

Default: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.adminPassword.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "forgejo.service"
]

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.adminPassword.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.adminPassword.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.backup

Backup configuration. This is an output option.

Use it to initialize a block implementing the “backup” contract. For example, with the restic block:

shb.restic.instances."forgejo" = {
  request = config.shb.forgejo.backup;
  settings = {
    enable = true;
  };
};

Type: submodule (read only)

Default:

{
  sourceDirectories = [
    "/var/lib/forgejo/dump"
  ];
  user = "forgejo";
}

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.backup.excludePatterns

File patterns to exclude.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.backup.hooks

Hooks to run around the backup.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.backup.hooks.after_backup

Hooks to run after backup.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.backup.hooks.before_backup

Hooks to run before backup.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.backup.sourceDirectories

Directories to backup.

Type: non-empty (list of string)

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.backup.user

Unix user doing the backups.

Type: string

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.databasePassword

File containing the Forgejo database password.

Type: submodule

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.databasePassword.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.databasePassword.request.group

Linux group owning the secret file.

Type: string

Default: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.databasePassword.request.mode

Mode of the secret file.

Type: string

Default: "0440"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.databasePassword.request.owner

Linux user owning the secret file.

Type: string

Default: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.databasePassword.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "forgejo.service"
]

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.databasePassword.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.databasePassword.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.debug

Enable debug logging.

Type: boolean

Default: false

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.domain

Domain under which Forgejo is served.

<subdomain>.<domain>[:<port>]

Type: string

Example: "domain.com"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.hostPackages

List of packages, that are available to actions, when the runner is configured with a host execution label.

Type: list of package

Default:

with pkgs; [
  bash
  coreutils
  curl
  gawk
  gitMinimal
  gnused
  nodejs
  wget
]

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap

LDAP Integration.

Type: null or (submodule)

Default: { }

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.enable

Whether to enable LDAP integration…

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminGroup

Group users must belong to be admins.

Type: string

Default: "forgejo_admin"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminName

Admin user of the LDAP server.

Type: string

Default: "admin"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminPassword

LDAP admin password.

Type: submodule

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminPassword.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminPassword.request.group

Linux group owning the secret file.

Type: string

Default: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminPassword.request.mode

Mode of the secret file.

Type: string

Default: "0440"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminPassword.request.owner

Linux user owning the secret file.

Type: string

Default: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminPassword.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "forgejo.service"
]

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminPassword.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.adminPassword.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.dcdomain

dc domain for ldap.

Type: string

Example: "dc=mydomain,dc=com"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.host

Host serving the LDAP server.

Type: string

Default: "127.0.0.1"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.port

Port of the service serving the LDAP server.

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

Default: 389

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.provider

LDAP provider name, used for display.

Type: value “LLDAP” (singular enum)

Default: "LLDAP"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ldap.userGroup

Group users must belong to be able to login.

Type: string

Default: "forgejo_user"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.localActionRunner

Enable local action runner that runs for all labels.

Type: boolean

Default: true

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.mount

Mount configuration. This is an output option.

Use it to initialize a block implementing the “mount” contract. For example, with a zfs dataset:

shb.zfs.datasets."forgejo" = {
  poolName = "root";
} // config.shb.forgejo.mount;

Type: anything (read only)

Default:

{
  path = "/var/lib/forgejo";
}

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.mount.path

Path to be mounted.

Type: string

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.repositoryRoot

Path where to store the repositories. If null, uses the default under the Forgejo StateDir.

Type: null or string

Default: null

Example: "/srv/forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.smtp

Send notifications by smtp.

Type: null or (submodule)

Default: null

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.smtp.from_address

SMTP address from which the emails originate.

Type: string

Example: "authelia@mydomain.com"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.smtp.host

SMTP host to send the emails to.

Type: string

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.smtp.passwordFile

File containing the password to connect to the SMTP host.

Type: string

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.smtp.port

SMTP port to send the emails to.

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

Default: 25

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.smtp.username

Username to connect to the SMTP host.

Type: string

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ssl

Path to SSL files

Type: null or (anything)

Default: null

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ssl.paths

Paths where the files for the certificate will be located.

This option is the contract output of the shb.certs.certs SSL block.

Type: anything

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ssl.paths.cert

Path to the cert file.

Type: path

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ssl.paths.key

Path to the key file.

Type: path

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.ssl.systemdService

Systemd oneshot service used to generate the certificate. Ends with the .service suffix.

Use this if downstream services must wait for the certificates to be generated before starting.

Type: string

Example: "cert-generator.service"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso

Setup SSO integration.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.enable

Whether to enable SSO integration…

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.authorization_policy

Require one factor (password) or two factor (device) authentication.

Type: one of “one_factor”, “two_factor”

Default: "one_factor"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.clientID

Client ID for the OIDC endpoint.

Type: string

Default: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.endpoint

OIDC endpoint for SSO.

Type: string

Example: "https://authelia.example.com"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.provider

OIDC provider name, used for display.

Type: value “Authelia” (singular enum)

Default: "Authelia"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecret

OIDC shared secret for Forgejo.

Type: submodule

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecret.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecret.request.group

Linux group owning the secret file.

Type: string

Default: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecret.request.mode

Mode of the secret file.

Type: string

Default: "0440"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecret.request.owner

Linux user owning the secret file.

Type: string

Default: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecret.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "forgejo.service"
]

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecret.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecret.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecretForAuthelia

OIDC shared secret for Authelia.

Type: submodule

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecretForAuthelia.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecretForAuthelia.request.group

Linux group owning the secret file.

Type: string

Default: "root"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecretForAuthelia.request.mode

Mode of the secret file.

Type: string

Default: "0400"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecretForAuthelia.request.owner

Linux user owning the secret file.

Type: string

Default: "authelia"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecretForAuthelia.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecretForAuthelia.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.sso.sharedSecretForAuthelia.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>
shb.forgejo.subdomain

Subdomain under which Forgejo will be served.

<subdomain>.<domain>[:<port>]

Type: string

Example: "forgejo"

Declared by:

<selfhostblocks/modules/services/forgejo.nix>