Nginx Block

Table of Contents

Usage
Options Reference

Defined in /modules/blocks/nginx.nix.

This block sets up a Nginx instance.

It complements the upstream nixpkgs with some authentication and debugging improvements as shows in the Usage section.

Usage

Access Logging

JSON access logging is enabled with the shb.nginx.accessLog option:

{
  shb.nginx.accessLog = true;
}

Looking at the systemd logs (journalctl -fu nginx) will show for example:

nginx[969]: server nginx:
  {
    "remote_addr":"192.168.1.1",
    "remote_user":"-",
    "time_local":"29/Dec/2025:14:22:41 +0000",
    "request":"POST /api/firstfactor HTTP/2.0",
    "request_length":"264",
    "server_name":"auth_example_com",
    "status":"200",
    "bytes_sent":"855",
    "body_bytes_sent":"60",
    "referrer":"-",
    "user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0",
    "gzip_ration":"-",
    "post":"{\x22username\x22:\x22charlie\x22,\x22password\x22:\x22CharliePassword\x22,\x22keepMeLoggedIn\x22:false,\x22targetURL\x22:\x22https://f.example.com/\x22,\x22requestMethod\x22:null}",
    "upstream_addr":"127.0.0.1:9091",
    "upstream_status":"200",
    "request_time":"0.873",
    "upstream_response_time":"0.873",
    "upstream_connect_time":"0.001",
    "upstream_header_time":"0.872"
  }

This will log the body of POST queries so it should only be enabled for debug logging.

Debug Logging

Debug logging is enabled with the shb.nginx.debugLog option:

{
  shb.nginx.debugLog = true;
}

If enabled, it sets:

error_log stderr warn;

Virtual Host Upstream Proxy

Easy upstream proxy setup is done with the shb.nginx.vhosts.*.upstream option:

{
  shb.nginx.vhosts = [
    {
      domain = "example.com";
      subdomain = "mysubdomain";
      upstream = "http://127.0.0.1:9090";
    }
  ];
}

This will set also a few headers. Some are shown here and others please see in the nginx module:

  • Host = $host;

  • X-Real-IP = $remote_addr;

  • X-Forwarded-For = $proxy_add_x_forwarded_for;

  • X-Forwarded-Proto = $scheme;

Virtual Host SSL Generator Contract Integration

This module integrates with the SSL Generator Contract to setup HTTPs with the shb.nginx.vhosts.*.ssl option:

{
  shb.nginx.vhosts = [
    {
      domain = "example.com";
      subdomain = "mysubdomain";
      ssl = config.shb.certs.certs.letsencrypt.${domain};;
    }
  ];

  shb.certs.certs.letsencrypt.${domain} = {
    inherit domain;
  };
}

Virtual Host SHB Forward Authentication

For services provided by SelfHostBlocks that do not handle OIDC integration, this block can provide forward authentication which still allows the service to still be protected by an SSO server.

The user could still be required to authenticate to the service itself, although some services can automatically users authorized by Authelia.

Integrating with this block is done with the following code:

shb.<services>.authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";

Virtual Host Forward Authentication

Forward authentication is when Nginx talks with the SSO service directly and the user is authenticated before reaching the upstream application.

The SSO service responds with the username, group and more information about the user. This is then forwarded to the upstream application by Nginx.

Note that every request is authenticated this way with the SSO server so it involves more hops than a direct OIDC integration.

{
  shb.nginx.vhosts = [
    {
      domain = "example.com";
      subdomain = "mysubdomain";
      authEndpoint = "authelia.example.com";
      autheliaRules = [
        [
          # Protect /admin endpoint with 2FA
          # and only allow access to admin users.
          {
            domain = "myapp.example.com";
            policy = "two_factor";
            subject = [ "group:service_admin" ];
            resources = [
              "^/admin"
            ];
          }
          # Leave /api endpoint open - assumes an API key is used to protect it.
          {
            domain = "myapp.example.com";
            policy = "bypass";
            resources = [
              "^/api"
            ];
          },
          # Protect rest of app with 1FA
          # and allow access to normal and admin users.
          {
            domain = "myapp.example.com";
            policy = "one_factor";
            subject = ["group:service_user"];
          },
        ]
      ];
    }
  ];
}

If PHP is used with fastCGI, extra headers must be added by enabling the shb.nginx.vhosts.*.phpForwardAuth option.

Virtual Host Extra Config

To add extra configuration to a virtual host, use the shb.nginx.vhosts.*.extraConfig option. This can be used to add headers, for example:

{
  shb.nginx.vhosts = [
    {
      domain = "example.com";
      subdomain = "mysubdomain";
      extraConfig = ''
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
      '';
    }
  ];
}

Options Reference

shb.nginx.accessLog

Log all requests

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.debugLog

Verbose debug of internal. This will print what servers were matched and why.

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts

Endpoints to be protected by authelia.

Type: list of (submodule)

Default: [ ]

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.authEndpoint

Optional auth endpoint for SSO.

Type: null or string

Default: null

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

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.autheliaRules

Authelia rule configuration

Type: list of attribute set of anything

Default: [ ]

Example:

[
  # Protect /admin endpoint with 2FA
  # and only allow access to admin users.
  {
    domain = "myapp.example.com";
    policy = "two_factor";
    subject = [ "group:service_admin" ];
    resources = [
      "^/admin"
    ];
  }
  # Leave /api endpoint open - assumes an API key is used to protect it.
  {
    domain = "myapp.example.com";
    policy = "bypass";
    resources = [
      "^/api"
    ];
  },
  # Protect rest of app with 1FA
  # and allow access to normal and admin users.
  {
    domain = "myapp.example.com";
    policy = "one_factor";
    subject = ["group:service_user"];
  },
]

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.domain

Domain of the subdomain.

Type: string

Example: "mydomain.com"

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.extraConfig

Extra config to add to the root / location. Strings separated by newlines.

Type: strings concatenated with ā€œ\nā€

Default: ""

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.phpForwardAuth

Authelia rule configuration

Type: boolean

Default: false

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.ssl

Path to SSL files

Type: null or (open submodule of anything)

Default: null

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.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: open submodule of anything

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.ssl.paths.cert

Path to the cert file.

Type: absolute path

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.ssl.paths.key

Path to the key file.

Type: absolute path

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.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/blocks/nginx.nix>
shb.nginx.vhosts.*.subdomain

Subdomain which must be protected.

Type: string

Example: "subdomain"

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>
shb.nginx.vhosts.*.upstream

Upstream url to be protected.

Type: null or string

Default: null

Example: "http://127.0.0.1:1234"

Declared by:

<selfhostblocks/modules/blocks/nginx.nix>