Stubby (DNS over TLS) - Could not parse config file "/nix/store/*-stubby.yml"

Hi everyone,

I have issue with formatting of the Stubby YAML config file. This is the snippet from configuration.nix:

# Enable Stubby DNS resolver for DNS-over-TLS with CZ.NIC ODVR and TLS pinning
  services.stubby = {
    enable = true;
    settings = {
      appdata_dir = "/var/cache/stubby";
      dns_transport_list = [ "GETDNS_TRANSPORT_TLS" ];
      dnssec_return_status = "GETDNS_EXTENSION_TRUE";
      edns_client_subnet_private = 1;
      idle_timeout = 10000;
      listen_addresses = [ "127.0.0.1" "::1" ];
      resolution_type = "GETDNS_RESOLUTION_STUB";
      round_robin_upstreams = true;
      tls_authentication = "GETDNS_AUTHENTICATION_REQUIRED";
      tls_query_padding_blocksize = 128;
      upstream_recursive_servers = [
        {
          address_data = "193.17.47.1";
          tls_auth_name = "odvr.nic.cz";
          tls_pubkey_pinset = [
            { digest = "sha256"; value = "j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0="; }
          ];
        }
        {
          address_data = "185.43.135.1";
          tls_auth_name = "odvr.nic.cz";
          tls_pubkey_pinset = [
            { digest = "sha256"; value = "j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0="; }
          ];
        }
        {
          address_data = "2001:148f:ffff::1";
          tls_auth_name = "odvr.nic.cz";
          tls_pubkey_pinset = [
            { digest = "sha256"; value = "j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0="; }
          ];
        }
        {
          address_data = "2001:148f:fffe::1";
          tls_auth_name = "odvr.nic.cz";
          tls_pubkey_pinset = [
            { digest = "sha256"; value = "j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0="; }
          ];
        }
      ];
    };
  };

I am not 100% sure if its correct configuration but the formatting of the resulting YAML block to start Stubby service - "Generic error"Could not parse config file "/nix/store/*-stubby.yml": Generic error:

× stubby.service - Stubby local DNS resolver
     Loaded: loaded (/etc/systemd/system/stubby.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Wed 2024-10-09 11:05:46 CEST; 126ms ago
    Process: 83810 ExecStart=/nix/store/*-stubby-0.4.3/bin/stubby -C /nix/store/*-stubby.yml (code=exited, status=1/FAILURE)
   Main PID: 83810 (code=exited, status=1/FAILURE)
         IP: 0B in, 0B out
        CPU: 13ms

Oct 09 11:05:46 jupiter stubby[83810]:     value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=
Oct 09 11:05:46 jupiter stubby[83810]: - address_data: 2001:148f:fffe::1
Oct 09 11:05:46 jupiter stubby[83810]:   tls_auth_name: odvr.nic.cz
Oct 09 11:05:46 jupiter stubby[83810]:   tls_pubkey_pinset:
Oct 09 11:05:46 jupiter stubby[83810]:   - digest: sha256
Oct 09 11:05:46 jupiter stubby[83810]:     value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=
Oct 09 11:05:46 jupiter stubby[83810]: , "Generic error"Could not parse config file "/nix/store/*-stubby.yml": Generic error
Oct 09 11:05:46 jupiter systemd[1]: stubby.service: Main process exited, code=exited, status=1/FAILURE
Oct 09 11:05:46 jupiter systemd[1]: stubby.service: Failed with result 'exit-code'.
Oct 09 11:05:46 jupiter systemd[1]: Failed to start Stubby local DNS resolver.
warning: error(s) occurred while switching to the new configuration

Here is the generated YAML file:

[root@laptop:/etc/nixos]# cat /nix/store/*-stubby.yml
appdata_dir: /var/cache/stubby
dns_transport_list:
- GETDNS_TRANSPORT_TLS
dnssec_return_status: GETDNS_EXTENSION_TRUE
edns_client_subnet_private: 1
idle_timeout: 10000
listen_addresses:
- 127.0.0.1
- ::1
resolution_type: GETDNS_RESOLUTION_STUB
round_robin_upstreams: true
tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
tls_query_padding_blocksize: 128
upstream_recursive_servers:
- address_data: 193.17.47.1
  tls_auth_name: odvr.nic.cz
  tls_pubkey_pinset:
  - digest: sha256
    value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=
- address_data: 185.43.135.1
  tls_auth_name: odvr.nic.cz
  tls_pubkey_pinset:
  - digest: sha256
    value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=
- address_data: 2001:148f:ffff::1
  tls_auth_name: odvr.nic.cz
  tls_pubkey_pinset:
  - digest: sha256
    value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=
- address_data: 2001:148f:fffe::1
  tls_auth_name: odvr.nic.cz
  tls_pubkey_pinset:
  - digest: sha256
    value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=

And the linter find those wrong indentations:

[root@laptop:/etc/nixos]# yamllint /nix/store/*-stubby.yml
/nix/store/*-stubby.yml
  1:1       warning  missing document start "---"  (document-start)
  3:1       error    wrong indentation: expected at least 1  (indentation)
  8:1       error    wrong indentation: expected at least 1  (indentation)
  15:1      error    wrong indentation: expected at least 1  (indentation)
  18:3      error    wrong indentation: expected at least 3  (indentation)
  23:3      error    wrong indentation: expected at least 3  (indentation)
  28:3      error    wrong indentation: expected at least 3  (indentation)
  33:3      error    wrong indentation: expected at least 3  (indentation)

As expected the stubby.yml is read-only.

[root@laptop:/etc/nixos]# yamlfmt /nix/store/*-stubby.yml
open /nix/store/*-stubby.yml: read-only file system

When I format the copy of stubby.yml, it corrects the indentations of course:

[root@laptop:/etc/nixos]# yamlfmt /home/user/stubby.yml 
[root@laptop:/etc/nixos]# cat /home/user/stubby.yml
appdata_dir: /var/cache/stubby
dns_transport_list:
  - GETDNS_TRANSPORT_TLS
dnssec_return_status: GETDNS_EXTENSION_TRUE
edns_client_subnet_private: 1
idle_timeout: 10000
listen_addresses:
  - 127.0.0.1
  - ::1
resolution_type: GETDNS_RESOLUTION_STUB
round_robin_upstreams: true
tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
tls_query_padding_blocksize: 128
upstream_recursive_servers:
  - address_data: 193.17.47.1
    tls_auth_name: odvr.nic.cz
    tls_pubkey_pinset:
      - digest: sha256
        value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=
  - address_data: 185.43.135.1
    tls_auth_name: odvr.nic.cz
    tls_pubkey_pinset:
      - digest: sha256
        value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=
  - address_data: 2001:148f:ffff::1
    tls_auth_name: odvr.nic.cz
    tls_pubkey_pinset:
      - digest: sha256
        value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=
  - address_data: 2001:148f:fffe::1
    tls_auth_name: odvr.nic.cz
    tls_pubkey_pinset:
      - digest: sha256
        value: j4VwsGEwyioMzYiATU8bjfgSlas+A/Cut3U5f5tENb0=

How can I achieve the correct formatting of the YAML file? Is it possible to load YAML file with correct formatting (however I prefer nix options)?

Thank you in advance for advice and answers!

OS: NixOS 24.05.5562.1bfbbbe5bbf8 (Uakari) x86_64
Kernel: 6.11.2

Original CZ.NIC recommended YAML config:

resolution_type: GETDNS_RESOLUTION_STUB
dnssec_return_status: GETDNS_EXTENSION_TRUE
dns_transport_list:
  - GETDNS_TRANSPORT_TLS
tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
tls_query_padding_blocksize: 128
edns_client_subnet_private: 1
idle_timeout: 10000
listen_addresses:
  - 127.0.0.1
  - 0::1
round_robin_upstreams: 1
upstream_recursive_servers:
  #IPv4 ODVR
  - address_data: 193.17.47.1
    tls_auth_name: "odvr.nic.cz"
  - address_data: 185.43.135.1
    tls_auth_name: "odvr.nic.cz"
    #IPv6 ODVR
  - address_data: 2001:148f:ffff::1
    tls_auth_name: "odvr.nic.cz"
  - address_data: 2001:148f:fffe::1
    tls_auth_name: "odvr.nic.cz"

The generated YAML file is valid. Indentation is not required in these places, yamllint is a linter, and thus is more strict than YAML parsers, enforcing certain syntax conventions.

I recommend investigating how to make stubby spit out a more meaningful message than “Generic error”.