Skip to content

ZoneControl

ZoneControl is a web-based interface for managing domains on the PowerDNS Authoritative Server.

Example of ZoneControl:

Image title
ZoneControl zones overview

Configuration Reference

Instance Sets

Sets of instances of ZoneControl can be defined under the root node zonecontrols. Each instance set should be a key-value pair, with:

  • key: Name of the instance set
  • value: Dictionary holding the configuration of the instance set
zonecontrols:
  myzonecontrol:
    < ZoneControl configuration >

A minimal, yet functional configuration of ZoneControl requires the following:

zonecontrols:
  myzonecontrol:
    postgres:
      <Configuration of a Postgres Database>
    authEndpoints:
      - <Configuration of an Auth endpoint>

The above shown requirements are:

  • Postgres: ZoneControl needs access to a database in order for it to function
  • Auth Endpoints: ZoneControl connects to Authoritative Server instances via API to manage zones, record sets, etc

Parameters which can be used to configure ZoneControl instances for a specific instance set are shown in the below table.

Parameter Type Default Description
adminUser string "zcadmin" Username of user to create with administrative privileges
adminPassword string Password of the user specified by adminUser.
Default: generated during deployment
adminSecretName string Name of an existing Secret holding the desired username and password of a user to be provisioned with administrative privileges
adminSecretUserKey string "admin_user" Name of the item within Secret referenced by adminSecretName which holds the username of the admin user
adminSecretPasswordKey string "admin_password" Name of the item within Secret referenced by adminSecretName which holds the password of the admin user
affinity k8s:Affinity Pod affinity (Kubernetes docs: Affinity and anti-affinity). If unset, a default anti-affinity is applied using antiAffinityPreset to spread pods across nodes
agentLogLevel string "info" Verbosity of logging for the agent container.
Available options: "debug" "info" "warn" "error"
agentLogFormat string "text" Format of logging for the agent container.
Available options: "text" "json"
agentResources k8s:Resources
limits:
cpu: 250m
memory: 256Mi
Resources allocated to the 'agent' container if resourceDefaults is true
antiAffinityPreset string "preferred" Pod anti affinity preset.
Available options: "preferred" "required"
auditLogEnabled boolean false If true, enable audit logging
auditLogJSON boolean false If true, audit logging is output in JSON
authEndpoints List of AuthEndpoints [] List of endpoints of Authoritative Server instance sets
branding Branding Configuration to customize the appearance of ZoneControl
catalogZonesEnabled boolean true If true, enable management of catalog zones in ZoneControl
config multiline string "" Additional config to be injected into the Django configuration file used by ZoneControl.
Contents of config should be formatted as a multiline string, for example:
config: |
SOME_CONFIG_VARIABLE = 23
containerSecurityContext k8s:SecurityContext
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
seccompProfile:
type: RuntimeDefault
capabilities:
drop:
- "ALL"
SecurityContext applied to each container
disableSticky boolean false If true, disable the operator-controlled selection of a primary pod to handle all inbound traffic
historyEnabled boolean false If true, enable version history tracking in the database. When changes are made, version history of the related object is stored and can be restored via the GUI.
Note: The scope of version history is limited to this instance set's database. If you have multiple separate ZoneControl instance sets interacting with the same Auth API endpoint, you could end up having multiple sets of conflicting history unless those ZoneControl instance sets share the same database.
hostNetwork boolean false Use host networking for pods
ingress Ingress Ingress configuration
initResources k8s:Resources
limits:
cpu: 250m
memory: 256Mi
Resources allocated to the 'zc-init' container if resourceDefaults is true
ldapBackend string Name of a userBackend with type ldap (See: User Backends)
ldapAdminGroup string DN of an LDAP group whose members will be assigned administrative privileges.
Example: cn=staff,ou=groups,dc=example,dc=org
ldapCustomAuthBackendClass string "CustomBackend" Name of the class defined in the custom ldap auth backend. Only used if ldapCustomAuthBackendConfigMap is set
ldapCustomAuthBackendConfigMap string ConfigMap containing Python code for a custom ldap auth backend to use in ZoneControl. Using this disables the default django_auth_ldap.backend.LDAPBackend backend
ldapCustomAuthBackendConfigMapKey string Item in ConfigMap which holds the custom ldap auth backend (default: backend.py). Only used if ldapCustomAuthBackendConfigMap is set
ldapMirrorGroups boolean true Whether or not ZoneControl should synchronize an LDAP user's groups into the ZoneControl user management. This only applies to LDAP users who have successfully logged in and the groups to which they belong. Groups are only synchronized if they belong to one of the group bases and satisfy the optional group base filters
logLevel string "info" ZoneControl log level.
Available options: "debug" "info" "warn" "error"
nginxResources k8s:Resources
limits:
cpu: 250m
memory: 256Mi
Resources allocated to the 'nginx' container
nodeSelector k8s:NodeSelector {} Kubernetes pod nodeSelector
oidcBackend string Name of a userBackend with type oidc (See: User Backends)
oidcDefaultScopes List of string
- "openid"
- "email"
- "profile"
Default scopes requested from OIDC provider
oidcDisableFetchUserInfo boolean false If true, do not fetch data from the userinfo endpoint
oidcEnablePKCE boolean false If true, enable PKCE towards the OIDC provider
oidcExtraScopes List of string [] Extra scopes requested from OIDC provider
oidcRolePath List of string
- "userinfo"
- "groups"
Path inside extra_data to fetch roles from. Defaults to groups within the returned userinfo
oidcRolePrefix string zc: Prefix for ZoneControl roles fetched from OIDC provider
oidcTokenAuthMethod string "" Token endpoint authentication method, if empty the OIDC connector chooses one from the list proposed by the OIDC provider.
Available options: "client_secret_basic" "client_secret_post"
oidcUIDField string "sub" Field used as ZoneControl user ID
podAnnotations k8s:Annotations {} Annotations to be added to each pod
podDisruptionBudget k8s:PodDisruptionBudgetSpec {} Spec of PodDisruptionBudget to be applied to deployment
podLabels k8s:Labels {} Labels to be added to each pod
podPreemptionPolicy string Policy for preempting pods with lower priority
podPriorityClassName string Name of PriorityClass to be assigned to each pod
podRuntimeClassName string Name of RuntimeClass to be assigned to each pod
podSchedulerName string Name of scheduler responsible for dispatching pods
podSecurityContext k8s:PodSecurityContext
fsGroup: 953
runAsUser: 953
runAsGroup: 953
runAsNonRoot: true
SecurityContext applied to each pod
podTerminationGracePeriodSeconds integer Duration after which terminating pods are stopped immediately if they do not exit gracefully
postgres Postgres Postgres database configuration
redisCacheInterval integer 60 Interval in seconds between consecutive updates of zones-lists (default: 60)
redisCacheTTL integer 300 How long in seconds a zones-list is cached before being automatically removed (default: 300)
redisDatabase integer 0 Redis database to connect to for caching. Only used if redisHost is set
redisHost string Redis host to connect to for caching
redisPassword string Password to connect to Redis with. Ignored if redisSecretName is set and omitted if not configured
redisPort integer 6379 Redis port to connect to for caching. Only used if redisHost is set
redisScheme string "redis" Redis scheme to connect with for caching. Only used if redisHost is set
redisSecretName string Name of a pre-existing secret holding password to connect to Redis with. Has priority over redisPassword
redisSecretPasswordKey string "password" Name of item in redisSecretName Secret containing the password (default: password)
redisURI string Redis connect string to enable caching (Must be full connect string, ie: "redis://my.redis.host.local:6379"). Has priority over redisHost
redisUsername string Username to connect to Redis with. Only used if redisHost is set and rarely required. Most Redis endpoints only require the password to be configured.
replicas integer 2 Default number of replicas in a Deployment
resources k8s:Resources
limits:
cpu: 2
memory: 2Gi
Resources allocated to the 'zonecontrol' container
service Service
type: ClusterIP
Service configuration
serviceLabels k8s:Labels {} Labels to be added to each service
tolerations List of k8s:Tolerations [] Kubernetes pod Tolerations
topologySpreadConstraints List of k8s:TopologySpreadConstraint [] Kubernetes pod topology spread constraints

Auth Endpoints

There are 3 ways to configure endpoints of Authoritative instances in ZoneControl:

  • URL + Static API key
  • URL + API key from Secret
  • Learned from a set of Auth instances part of the same Userplane deployment

URL + Static API Key

To configure an Auth endpoint with a static URL and a static API key:

zonecontrols:
  myzc:
    postgres:
      <database config here>
    authEndpoints:
      - name: myendpoint
        url: http://url.of.auth:8080
        key: "SomeAPIKey"

Note: url must specify a protocol (either http:// or https://)

URL + API Key from secret

To configure an Auth endpoint with a static URL and an API key from a secret:

zonecontrols:
  myzc:
    postgres:
      <database config here>
    authEndpoints:
      - name: myendpoint
        url: http://url.of.auth:8080
        keySecret: some-secret
        keySecretItem: "api_key"

Where api_key is the name of the data item within the some-secret secret which holds the API key.

Note: url must specify a protocol (either http:// or https://)

Learned from set of Auth instances

To configure an Auth endpoint learned automatically from a set of Auth instances:

auths:
  testauth:
    <Auth configuration>

zonecontrols:
  myzc:
    postgres:
      <database config here>
    authEndpoints:
      - name: myendpoint
        auth: testauth

Branding

Parameters to configure the appearance of ZoneControl. For example, to change the logo using a URL:

zonecontrols:
  myzonecontrol:
    branding:
      logoURL: https://path.to.my/custom/logo.png

Alternatively, you can configure a logo to be taken from a ConfigMap:

zonecontrols:
  myzonecontrol:
    branding:
      logoConfigMap: my-logo-configmap
      logoConfigMapKey: "logo_name.gif"

You can further configure the appearance using the following parameters::

Parameter Type Default Description
logoConfigMap string Name of the configmap containing the logo
logoConfigMapKey string "logo.svg" Name of the item inside the configmap containing the logo
logoURL string URL of a logo. This should be accessible by anyone interacting with the ZoneControl GUI

Ingress

Parameters to configure an Ingress for ZoneControl. For example:

zonecontrols:
  myzonecontrol:
    ingress:
      enabled: true
      ingressClassName: "nginx"
      hosts:
        - zc.example.local
Parameter Type Default Description
annotations k8s:Annotations {} Annotations for the ingress
enabled boolean false If true, create an ingress object
hosts List of string [] List of hosts for which the ingress should accept traffic (If using tls, this should also include the hosts listed on the tls object)
ingressClassName string Name of the ingress class
tls List of AuthAPIIngressTLS [] List of ingress tls configurations

Ingress TLS

Parameters to configure TLS for an ingress. For example:

zonecontrols:
  myzonecontrol:
    ingress:
      enabled: true
      ingressClassName: "nginx"
      hosts:
        - zc.example.local
      tls:
        - secretName: zc-ingress-cert
          hosts:
          - zc.example.local

The above example will result in an ingress for ZoneControl listening for zc.example.local and serving the certificate contained in the secret zc-ingress-cert.

Note: tls is a list of configurations. Below shows the parameters which can be used for each entry in that list:

Parameter Type Default Description
hosts List of string [] List of hosts for which the ingress should accept TLS traffic
secretName string "" Name of a secret containing the certificate to be used for this ingress

OIDC Configuration

OIDC can be enabled by setting the oidcBackend parameter to a OIDC User Backend.

Scopes

The default behaviour is for ZoneControl to request the following scopes from the OIDC provider:

  • openid
  • email
  • profile

This list is controlled by the oidcDefaultScopes list. Additional scopes can be configured by adding to the oidcExtraScopes list. If you wish to remove one or more of the default scopes you can overwrite the oidcDefaultScopes entirely.

Example to add the scope roles:

zonecontrols:
  myzonecontrol:
    oidcBackend: myoidcconfig
    oidcExtraScopes:
      - "roles"

Roles

By default, ZoneControl has the following roles available when OIDC is enabled:

ZoneControl Role Name Internal Role Name Default Prefixed OIDC Role Name
oauth_default_readonly readonly zc:readonly
oauth_default_add_zones add_zones zc:add_zones
oauth_default_delete_zones delete_zones zc:delete_zones
oauth_default_change_settings change_settings zc:change_settings
oauth_default_change_dnssec change_dnssec zc:change_dnssec
oauth_default_advanced_dnssec advanced_dnssec zc:advanced_dnssec
oauth_default_restore_version restore_version zc:restore_version
oauth_default_all_permissions all_permissions zc:all_permissions

The different columns explained:

  • ZoneControl Role Name: Name of the role as observed in the ZoneControl admin GUI (Internal Role Name, prefixed by oauth_default)
  • Internal Role Name: Internal name of the role
  • Default Prefixed OIDC Role Name: Name of the role as expected to be returned by the OIDC provider (Internal Role Name, prefixed by value of oidcRolePrefix)

This means that if the OIDC provider returns userinfo which contains zc:all_permissions in the correct item, the role visible as oauth_default_all_permissions in the ZoneControl admin GUI will be assigned to that user in ZoneControl. If you wish to have a different prefix used in OIDC, you can change the default zc: prefix to any other value by configuring oidcRolePrefix.

By default, ZoneControl looks inside the data returned by the OIDC endpoint to fetch the role(s) from the item at the path configured in oidcRolePath (groups inside userinfo).

With the defaults, this means ZoneControl will look for an item groups for the roles within the userinfo. This is the default behaviour of Authentik when you use groups to provide access to users, but differs per OIDC provider.

Example: Scope & Roles

Assume we have an OIDC provider configured as follows:

  • Custom scope zcroles to allow ZoneControl to request role assignments
  • Custom scope mapping to return a user's roles in the userinfo.zonecontrol.roles item when the scope zcroles is requested
  • Roles returned by the OIDC provider are prefixed with zcrole_, for example: zcrole_all_permissions

We can then configure ZoneControl as follows:

zonecontrols:
  myzonecontrol:
    oidcBackend: myoidcconfig
    oidcExtraScopes:
      - "zcroles"
    oidcRolePath:
      - "userinfo"
      - "zonecontrol"
      - "roles"
    oidcRolePrefix: "zcrole_"

Note the format of the oidcRolePath, this is a top-to-bottom traversal of the extra_data object based on the items in this list.

Postgres

If you have an existing Postgres database available, you can configure ZoneControl to use it as follows:

zonecontrols:
  myzonecontrol:
    postgres:
      host: host-of-postgres-cluster
      dbname: name-of-db
      user: some_user
      password: some_user_password

You can further configure the Postgres connection using the following parameters::

Parameter Type Required Default Description
dbname string yes Name of the database
host string yes Host/IP of the Postgres endpoint
password string Password to use for authentication.
Using secretName is preferred
port integer 5432 Port over which to access the Postgres endpoint
secretName string Name of a pre-existing Kubernetes Secret containing a username & password for authentication
secretPasswordKey string "password" If secretName is specified: name of the item inside the Secret which holds the password
secretUsernameKey string "username" If secretName is specified: name of the item inside the Secret which holds the username
sslmode string Postgres sslmode to use while connecting.
Optional, omitted if no value is provided
user string Username to use for authentication.
Using secretName is preferred

If you do not have a Postgres database available but you deployed the powerdns-operators Helm Chart, you can request the Postgres operator to create and manage one for you:

zonecontrols:
  myzonecontrol:
    postgres:
      operator: true

powerdns-operators

The powerdns-operators Helm Chart was originally made available to help easily deploy Postgres databases for use by ZoneControl. You can still use it for this purpose, but we highly recommend using a self-managed database for ZoneControl.

Service

Parameters to configure the service object for ZoneControl. For example:

zonecontrols:
  myzonecontrol:
    service:
      type: LoadBalancer
      annotations:
        metallb.universe.tf/address-pool: name_of_pool
Parameter Type Default Description
allocateLoadBalancerNodePorts boolean true If true, services with type LoadBalancer automatically assign NodePorts. Can be set to false if the LoadBalancer provider does not rely on NodePorts
annotations k8s:Annotations {} Annotations for the service
clusterIP string Static cluster IP, must be in the cluster's range of cluster IPs and not in use. Randomly assigned when not specified.
clusterIPs List of string List of static cluster IPs, must be in the cluster's range of cluster IPs and not in use.
externalIPs List of string List of IP addresses for which nodes in the cluster will also accept traffic for this service. These IPs are not managed by Kubernetes and must be user-defined on the cluster's nodes
externalTrafficPolicy string Cluster Can be set to Local to let nodes distribute traffic received on one of the externally-facing addresses (NodePort and LoadBalancer) solely to endpoints on the node itself
healthCheckNodePort integer For services with type LoadBalancer and externalTrafficPolicy Local you can configure this value to choose a static port for the NodePort which external systems (LoadBalancer provider mainly) can use to determine which node holds endpoints for this service
internalTrafficPolicy string Cluster Can be set to Local to let nodes distribute traffic received on the ClusterIP solely to endpoints on the node itself
ipv4 boolean false If true, force the Service to include support for IPv4, ignoring globally configured IP Family settings and/or cluster defaults. If ipv4 is set to true and ipv6 remains false, the result will be an ipv4-only SingleStack Service. If both are false, global settings and/or cluster defaults are used. If both are true, a PreferDualStack Service is created
ipv6 boolean false If true, force the Service to include support for IPv6, ignoring globally configured IP Family settings and/or cluster defaults. If ipv6 is set to true and ipv4 remains false, the result will be an ipv6-only SingleStack Service. If both are false, global settings and/or cluster defaults are used. If both are true, a PreferDualStack Service is created
labels k8s:Labels {} Labels to be added to the service
loadBalancerIP string Deprecated Kubernetes feature, available for backwards compatibility: IP address to attempt to claim for use by this LoadBalancer. Replaced by annotations specific to each LoadBalancer provider
loadBalancerSourceRanges List of string If supported by the LoadBalancer provider, restrict traffic to this LoadBalancer to these ranges
loadBalancerClass string Used to select a non-default type of LoadBalancer class to ensure the appropriate LoadBalancer provisioner attempt to manage this LoadBalancer service
publishNotReadyAddresses boolean false Service is populated with endpoints regardless of readiness state
sessionAffinity string None Can be set to ClientIP to attempt to maintain session affinity.
sessionAffinityConfig k8s:SessionAffinityConfig {} Configuration of session affinity
type string ClusterIP Type of service.
Available options: "ClusterIP" "LoadBalancer" "NodePort"