Configuration
=============

This chapter describes how to configure the ZoneControl service.

After changing settings, do not forget to restart the service.

Database configuration
----------------------

ZoneControl, by default, uses an `SQLite <https://sqlite.org/>`__
database located at ``/var/lib/zonecontrol/zonecontrol.db``. Should
another database be needed, it needs to be configured in
``/etc/zonecontrol/settings.py``.

Django offers connectors for many types of database servers, described
in its `online
documentation <https://docs.djangoproject.com/en/1.11/ref/settings/#std:setting-DATABASES>`__.

To enable support for databases other than SQLite, the package with
the database driver must be installed. These packages are named
"zonecontrol-<database>". The following databases are supported:

+------------+-----------------+-------------------------------+
| Database   | Package-suffix  | Engine in ``DATABASES``       |
+============+=================+===============================+
| MySQL      | ``mysql``       | django.db.backends.mysql      |
+------------+-----------------+-------------------------------+

.. todo

  | PostgreSQL | ``psql``        | django.db.backends.postgresql |
  +------------+-----------------+-------------------------------+

Now configure the database in ``/etc/zonecontrol/settings.py``, set the
ENGINE to the Engine from the table. The rest of the settings are
self-explanatory:

.. code:: python

    DATABASES = {
        'default': {
            'ENGINE': '$ENGINE',
            'NAME': 'mydatabase',
            'USER': 'mydatabaseuser',
            'PASSWORD': 'mypassword',
            'HOST': '127.0.0.1',
            'PORT': '',
        }
    }

After setting up a new database, it need to be populated with database
tables. Run the following command as the ``zonecontrol`` user::

    zonecontrol-manage migrate

Secret configuration
--------------------

The Django web framework relies on a “secret key” for encrypting
cookies, password reset tokens and other uses (see the `online
documentation <https://docs.djangoproject.com/en/1.11/ref/settings/#secret-key>`__
for more).

This key is generated upon package installation in
``/var/lib/zonecontrol/secret_key``.

Should this key not be set or if it is too short, ZoneControl will not
start. Generate a new key and add it to the configuration file:

.. code:: shell

    /usr/share/zonecontrol/bin/python3 -c 'import random; import string; print("".join([random.SystemRandom().choice("{}{}{}".format(string.ascii_letters, string.digits, string.punctuation)) for i in range(50)]))' > /var/lib/zonecontrol/secret_key


HTTP Service configuration
--------------------------

The Gunicorn HTTP server is configured in the
``/etc/zonecontrol/gunicorn_config.py`` file. By default, it will listen
for HTTP connections on ``127.0.0.1:8083``.

A sane configuration is below:

.. code:: python

    # Config file for the gunicorn HTTP server
    # See: http://docs.gunicorn.org/en/stable/settings.html
    import multiprocessing
    import os

    # This only has an effect if setproctitle is installed.
    proc_name = 'zonecontrol'

    raw_env = ['DJANGO_SETTINGS_MODULE=project.settings', 'GUNICORN=1']
    bind = ['127.0.0.1:8053']
    workers = multiprocessing.cpu_count() * 2
    threads = 8 # per worker
    timeout = 30 # sec

    chdir = '/usr/share/zonecontrol'

    accesslog = '/var/log/zonecontrol/access.log'
    access_log_format = '%(h)s (%({X-Forwarded-For}i)s) %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
    errorlog = '/var/log/zonecontrol/error.log'
    loglevel = 'info'
    # syslog = True

For more settings, please consult the `online
documentation <http://docs.gunicorn.org/en/latest/settings.html>`__.

Scheduled Changes Deployment
----------------------------
In order to deploy scheduled changes, ZoneControl comes with a small service
called ``zonecontrol-scheduler.service``. This service reads the
:ref:`entities-scheduled-changes` from the database and applies them when needed.

.. _zones-list-caching:
Zones List Caching
------------------
.. versionadded:: 1.2.0

ZoneControl can cache the zones-list in `redis <https://redis.io/>`__ to speed
up calls from the frontend.

.. note::
  Only the list of zones is cached, not the zone contents.

When changes are made, ZoneControl also stores these
mutations in the cache after they have been accepted by PowerDNS. A seperate
service called ``zonecontrol-cache`` loads the list of zones into redis and prunes
the mutations at regular intervals. The zones-list is stored wih an expiry time
so the cache is either empty or recent.

ZoneControl will always attempt to load the zones-list from the cache, if it
cannot find the list *or* caching is explicitly disabled, it will fall back to
loading the list from PowerDNS.

Enabling Caching
^^^^^^^^^^^^^^^^
On installations on CentOS, install the ``zonecontrol-cache`` package, this will
also install ``redis``. For Debian installations, install the ``redis`` package.

Then start and enable both redis and the zonecontrol-cache services::

  systemctl enable redis.service
  systemctl start redis.service
  systemctl enable zonecontrol-cache.service
  systemctl start zonecontrol-cache.service

Cache configuration
^^^^^^^^^^^^^^^^^^^
The caching behaviour is controlled by several options in ``/etc/zonecontrol/settings.py``.

:``ZONECONTROL_CACHE_ZONES``:
   Whether or not to cache zones lists (for ``zonecontrol-cache``) and
   to attempt to retrieve them (for ZoneControl), default ``True``.
:``ZONECONTROL_CACHE_ZONES_LOCATION``:
   Connection URL for Redis. By default database 1 on localhost without
   authentication and encryption. is used. The `redis-py documentation <https://redis-py.readthedocs.io/en/latest/#redis.ConnectionPool.from_url>`__
   describes this URI in detail. Default is ``"redis://127.0.0.1:6379/1"``.
:``ZONECONTROL_CACHE_ZONES_INTERVAL``:
   After ``zonecontrol-cache`` has added a new list to the cache, this setting
   controls how long it will wait before starting a new retrieval. Default
   is ``60``.
:``ZONECONTROL_CACHE_ZONES_EXPIRE_TTL``:
  How long a zones-list is cached in redis before automatically removed, in
  seconds. Default is ``300``.

After changing the settings, restart ``zonecontrol-cache.service``.

Zones Overview DNSSEC Retrieval
-------------------------------
.. versionadded:: 1.2.0

By default, the PowerDNS API includes the ``dnssec`` field when the list of zones
is retrieved. Generating this field takes 5 queries to the database per zone in
the list. When the database is slow, has high latency or the list of zones is
huge, this can severely impact the performance of the zones overview in the ZoneControl
frontend.

PowerDNS Authoritative Server 4.2.1 introduced the possiblity to request the
zones-list *without* dnssec information. ZoneControl takea advantage of this
API feature by default. To have ZoneControl request DNSSEC information from
PowerDNS, set ``ZONECONTROL_ZONE_OVERVIEW_DNSSEC`` to ``True`` in
``/etc/zonecontrol/settings.py``.

The downside of this feature is the loss of the "DNSSEC" column on the overview
page of ZoneControl.

Restriction of Zone Kinds
-------------------------
.. versionadded:: 1.1.0

Operators might want to limit the kind of zones that can be created through
ZoneControl. This can be done using the ``ZONECONTROL_ALLOW_ZONE_KINDS`` list
in ``/etc/zonecontrol/settings.py``.

By default, all kinds are allowed. To only allow Native zones:

.. code-block:: python

  from project.zonecontrol import ZONE_KIND_NATIVE
  ZONECONTROL_ALLOW_ZONE_ACTIONS = [ZONE_KIND_NATIVE]


Advanced DNSSEC
---------------
.. versionadded:: 1.1.0

When a user has the :ref:`"Advanced DNSSEC" <permissions-advanced-dnssec>`
permissions, they can manipulate single DNSSEC keys for zones. The ZoneControl
configuration can limit the DNSSEC algorithms that are allowed to be created.
There are two settings related to this.

:``ZONECONTROL_ADVANCED_DNSSEC_ALGORITHMS``:
   This is the list of algorithms that is shown in the selection box and that
   are allowed when keys are created through the ZoneControl API. By default,
   these are ``[DNSSEC_ALGO_ECDSA256, DNSSEC_ALGO_ECDSA384, DNSSEC_ALGO_ED25519]``.
:``ZONECONTROL_ADVANCED_DNSSEC_DEFAULT_ALGORITHM``:
   This is the algorithm that is set in the Advanced DNSSEC views' selection box
   by default. This algorithm **must** be in the ``ZONECONTROL_ADVANCED_DNSSEC_ALGORITHMS``
   list and is ``DNSSEC_ALGO_ECDSA256`` by default.

Default NSEC3PARAM
------------------
.. versionadded:: 1.4.2

The default ``NSEC3PARAM`` is set to ``1 0 0 -`` in ``/etc/zonecontrol/settings.py`` and can be changed there. These parameters are recommended by
`RFC9276 <https://www.rfc-editor.org/rfc/rfc9276#name-best-practice-for-zone-publ>`__.

Automatic PTR Creation
----------------------
.. versionadded:: 1.1.0

ZoneControl can create PTR records for A and AAAA records that are created or
modified. This can be disabled in the configuration by setting ``ZONECONTROL_ALLOW_AUTOMATIC_PTR``
to ``False`` in ``/etc/zonecontrol/settings.py``.

Zone Actions
------------
.. versionadded:: 1.1.0

Users with permissions to access zones can force actions like queuing NOTIFY
messages to slaves or (re-)retrieving a slave zone. The allowed actions are
specified in ``ZONECONTROL_ALLOW_ZONE_ACTIONS``. By default this is set to
``[ZONE_ACTION_NOTIFY, ZONE_ACTION_AXFR_RETRIEVE]``.

Prometheus Metrics
------------------
.. versionadded:: 1.5.1

Prometheus metrics will be exported on the ``/metrics`` URL path. This is
the default path for Prometheus so just pointing your Prometheus
configuration at the ``host:port`` target should be enough.

The metrics are disabled by default and can be enabled by setting
``ZONECONTROL_METRICS_ENABLED`` to ``True`` in ``/etc/zonecontrol/settings.py``.

The metric for the number of zones (``zonecontrol_zones``) is only available
when the caching of zones is enabled. See :ref:`zones-list-caching`.
