diff options
author | github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> | 2023-09-24 00:02:23 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-24 00:02:23 +0000 |
commit | 0e6413dbff4a5cd6d29e9f2bf349d3aefe89990b (patch) | |
tree | 3217d639d7832d6cfd2d3ef43c125441e8284528 /nixos | |
parent | ab2ecc25c1a4f0a029e6a1c2152fb18d5a9505d1 (diff) | |
parent | 74970765262f0958d124b5b43afdd45e8285d527 (diff) | |
download | nixlib-0e6413dbff4a5cd6d29e9f2bf349d3aefe89990b.tar nixlib-0e6413dbff4a5cd6d29e9f2bf349d3aefe89990b.tar.gz nixlib-0e6413dbff4a5cd6d29e9f2bf349d3aefe89990b.tar.bz2 nixlib-0e6413dbff4a5cd6d29e9f2bf349d3aefe89990b.tar.lz nixlib-0e6413dbff4a5cd6d29e9f2bf349d3aefe89990b.tar.xz nixlib-0e6413dbff4a5cd6d29e9f2bf349d3aefe89990b.tar.zst nixlib-0e6413dbff4a5cd6d29e9f2bf349d3aefe89990b.zip |
Merge master into staging-next
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/doc/manual/release-notes/rl-2311.section.md | 4 | ||||
-rwxr-xr-x | nixos/maintainers/scripts/oci/create-image.sh | 24 | ||||
-rwxr-xr-x | nixos/maintainers/scripts/oci/upload-image.sh | 100 | ||||
-rw-r--r-- | nixos/modules/module-list.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/networking/knot.nix | 132 | ||||
-rw-r--r-- | nixos/modules/virtualisation/oci-common.nix | 60 | ||||
-rw-r--r-- | nixos/modules/virtualisation/oci-config-user.nix | 12 | ||||
-rw-r--r-- | nixos/modules/virtualisation/oci-image.nix | 50 | ||||
-rw-r--r-- | nixos/modules/virtualisation/oci-options.nix | 14 | ||||
-rw-r--r-- | nixos/tests/kea.nix | 51 | ||||
-rw-r--r-- | nixos/tests/knot.nix | 140 |
11 files changed, 483 insertions, 105 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md index b7c856f7a127..efb0f17873ea 100644 --- a/nixos/doc/manual/release-notes/rl-2311.section.md +++ b/nixos/doc/manual/release-notes/rl-2311.section.md @@ -103,6 +103,8 @@ - `pass` now does not contain `password-store.el`. Users should get `password-store.el` from Emacs lisp package set `emacs.pkgs.password-store`. +- `services.knot` now supports `.settings` from RFC42. The change is not 100% compatible with the previous `.extraConfig`. + - `mu` now does not install `mu4e` files by default. Users should get `mu4e` from Emacs lisp package set `emacs.pkgs.mu4e`. - `mariadb` now defaults to `mariadb_1011` instead of `mariadb_106`, meaning the default version was upgraded from 10.6.x to 10.11.x. See the [upgrade notes](https://mariadb.com/kb/en/upgrading-from-mariadb-10-6-to-mariadb-10-11/) for potential issues. @@ -225,6 +227,8 @@ - `networking.networkmanager.firewallBackend` was removed as NixOS is now using iptables-nftables-compat even when using iptables, therefore Networkmanager now uses the nftables backend unconditionally. +- `rome` was removed because it is no longer maintained and is succeeded by `biome`. + ## Other Notable Changes {#sec-release-23.11-notable-changes} - The Cinnamon module now enables XDG desktop integration by default. If you are experiencing collisions related to xdg-desktop-portal-gtk you can safely remove `xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];` from your NixOS configuration. diff --git a/nixos/maintainers/scripts/oci/create-image.sh b/nixos/maintainers/scripts/oci/create-image.sh new file mode 100755 index 000000000000..0d7332a0b272 --- /dev/null +++ b/nixos/maintainers/scripts/oci/create-image.sh @@ -0,0 +1,24 @@ +#! /usr/bin/env bash + +set -euo pipefail + +export NIX_PATH=nixpkgs=$(dirname $(readlink -f $0))/../../../.. +export NIXOS_CONFIG=$(dirname $(readlink -f $0))/../../../modules/virtualisation/oci-image.nix + +if (( $# < 1 )); then + ( + echo "Usage: create-image.sh <architecture>" + echo + echo "Where <architecture> is one of:" + echo " x86_64-linux" + echo " aarch64-linux" + ) >&2 +fi + +system="$1"; shift + +nix-build '<nixpkgs/nixos>' \ + -A config.system.build.OCIImage \ + --argstr system "$system" \ + --option system-features kvm \ + -o oci-image diff --git a/nixos/maintainers/scripts/oci/upload-image.sh b/nixos/maintainers/scripts/oci/upload-image.sh new file mode 100755 index 000000000000..e4870e94bf54 --- /dev/null +++ b/nixos/maintainers/scripts/oci/upload-image.sh @@ -0,0 +1,100 @@ +#! /usr/bin/env bash + +set -euo pipefail + +script_dir="$(dirname $(readlink -f $0))" +nixpkgs_root="$script_dir/../../../.." +export NIX_PATH="nixpkgs=$nixpkgs_root" + +cat - <<EOF +This script will locally build a NixOS image and upload it as a Custom Image +using oci-cli. Make sure that an API key for the tenancy administrator has been +added to '~/.oci'. +For more info about configuring oci-cli, please visit +https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm#Required_Keys_and_OCIDs + +EOF + +qcow="oci-image/nixos.qcow2" +if [ ! -f "$qcow" ]; then + echo "OCI image $qcow does not exist" + echo "Building image with create-image.sh for 'x86_64-linux'" + "$script_dir/create-image.sh" x86_64-linux + [ -f "$qcow" ] || { echo "Build failed: image not present after build"; exit 1; } +else + echo "Using prebuilt image $qcow" +fi + +cli="$( + nix-build '<nixpkgs>' \ + --no-out-link \ + -A oci-cli +)" + +PATH="$cli/bin:$PATH" +bucket="_TEMP_NIXOS_IMAGES_$RANDOM" + +echo "Creating a temporary bucket" +root_ocid="$( + oci iam compartment list \ + --all \ + --compartment-id-in-subtree true \ + --access-level ACCESSIBLE \ + --include-root \ + --raw-output \ + --query "data[?contains(\"id\",'tenancy')].id | [0]" +)" +bucket_ocid=$( + oci os bucket create \ + -c "$root_ocid" \ + --name "$bucket" \ + --raw-output \ + --query "data.id" +) +# Clean up bucket on script termination +trap 'echo Removing temporary bucket; oci os bucket delete --force --name "$bucket"' INT TERM EXIT + +echo "Uploading image to temporary bucket" +oci os object put -bn "$bucket" --file "$qcow" + +echo "Importing image as a Custom Image" +bucket_ns="$(oci os ns get --query "data" --raw-output)" +image_id="$( + oci compute image import from-object \ + -c "$root_ocid" \ + --namespace "$bucket_ns" \ + --bucket-name "$bucket" \ + --name nixos.qcow2 \ + --operating-system NixOS \ + --source-image-type QCOW2 \ + --launch-mode PARAVIRTUALIZED \ + --display-name NixOS \ + --raw-output \ + --query "data.id" +)" + +cat - <<EOF +Image created! Please mark all available shapes as compatible with this image by +visiting the following link and by selecting the 'Edit Details' button on: +https://cloud.oracle.com/compute/images/$image_id +EOF + +# Workaround until https://github.com/oracle/oci-cli/issues/399 is addressed +echo "Sleeping for 15 minutes before cleaning up files in the temporary bucket" +sleep $((15 * 60)) + +echo "Deleting image from bucket" +par_id="$( + oci os preauth-request list \ + --bucket-name "$bucket" \ + --raw-output \ + --query "data[0].id" +)" + +if [[ -n $par_id ]]; then + oci os preauth-request delete \ + --bucket-name "$bucket" \ + --par-id "$par_id" +fi + +oci os object delete -bn "$bucket" --object-name nixos.qcow2 --force diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 22724138d5dd..7744bbd76e61 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1485,6 +1485,7 @@ ./virtualisation/nixos-containers.nix ./virtualisation/oci-containers.nix ./virtualisation/openstack-options.nix + ./virtualisation/oci-options.nix ./virtualisation/openvswitch.nix ./virtualisation/parallels-guest.nix ./virtualisation/podman/default.nix diff --git a/nixos/modules/services/networking/knot.nix b/nixos/modules/services/networking/knot.nix index e97195d82919..d98c0ce25bf4 100644 --- a/nixos/modules/services/networking/knot.nix +++ b/nixos/modules/services/networking/knot.nix @@ -5,10 +5,110 @@ with lib; let cfg = config.services.knot; - configFile = pkgs.writeTextFile { + yamlConfig = let + result = assert secsCheck; nix2yaml cfg.settings; + + secAllow = n: hasPrefix "mod-" n || elem n [ + "module" + "server" "xdp" "control" + "log" + "statistics" "database" + "keystore" "key" "remote" "remotes" "acl" "submission" "policy" + "template" + "zone" + "include" + ]; + secsCheck = let + secsBad = filter (n: !secAllow n) (attrNames cfg.settings); + in if secsBad == [] then true else throw + ("services.knot.settings contains unknown sections: " + toString secsBad); + + nix2yaml = nix_def: concatStrings ( + # We output the config section in the upstream-mandated order. + # Ordering is important due to forward-references not being allowed. + # See definition of conf_export and 'const yp_item_t conf_schema' + # upstream for reference. Last updated for 3.3. + # When changing the set of sections, also update secAllow above. + [ (sec_list_fa "id" nix_def "module") ] + ++ map (sec_plain nix_def) + [ "server" "xdp" "control" ] + ++ [ (sec_list_fa "target" nix_def "log") ] + ++ map (sec_plain nix_def) + [ "statistics" "database" ] + ++ map (sec_list_fa "id" nix_def) + [ "keystore" "key" "remote" "remotes" "acl" "submission" "policy" ] + + # Export module sections before the template section. + ++ map (sec_list_fa "id" nix_def) (filter (hasPrefix "mod-") (attrNames nix_def)) + + ++ [ (sec_list_fa "id" nix_def "template") ] + ++ [ (sec_list_fa "domain" nix_def "zone") ] + ++ [ (sec_plain nix_def "include") ] + ); + + # A plain section contains directly attributes (we don't really check that ATM). + sec_plain = nix_def: sec_name: if !hasAttr sec_name nix_def then "" else + n2y "" { ${sec_name} = nix_def.${sec_name}; }; + + # This section contains a list of attribute sets. In each of the sets + # there's an attribute (`fa_name`, typically "id") that must exist and come first. + # Alternatively we support using attribute sets instead of lists; example diff: + # -template = [ { id = "default"; /* other attributes */ } { id = "foo"; } ] + # +template = { default = { /* those attributes */ }; foo = { }; } + sec_list_fa = fa_name: nix_def: sec_name: if !hasAttr sec_name nix_def then "" else + let + elem2yaml = fa_val: other_attrs: + " - " + n2y "" { ${fa_name} = fa_val; } + + " " + n2y " " other_attrs + + "\n"; + sec = nix_def.${sec_name}; + in + sec_name + ":\n" + + (if isList sec + then flip concatMapStrings sec + (elem: elem2yaml elem.${fa_name} (removeAttrs elem [ fa_name ])) + else concatStrings (mapAttrsToList elem2yaml sec) + ); + + # This convertor doesn't care about ordering of attributes. + # TODO: it could probably be simplified even more, now that it's not + # to be used directly, but we might want some other tweaks, too. + n2y = indent: val: + if doRecurse val then concatStringsSep "\n${indent}" + (mapAttrsToList + # This is a bit wacky - set directly under a set would start on bad indent, + # so we start those on a new line, but not other types of attribute values. + (aname: aval: "${aname}:${if doRecurse aval then "\n${indent} " else " "}" + + n2y (indent + " ") aval) + val + ) + + "\n" + else + /* + if isList val && stringLength indent < 4 then concatMapStrings + (elem: "\n${indent}- " + n2y (indent + " ") elem) + val + else + */ + if isList val /* and long indent */ then + "[ " + concatMapStringsSep ", " quoteString val + " ]" else + if isBool val then (if val then "on" else "off") else + quoteString val; + + # We don't want paths like ./my-zone.txt be converted to plain strings. + quoteString = s: ''"${if builtins.typeOf s == "path" then s else toString s}"''; + # We don't want to walk the insides of derivation attributes. + doRecurse = val: isAttrs val && !isDerivation val; + + in result; + + configFile = if cfg.settingsFile != null then + assert cfg.settings == {} && cfg.keyFiles == []; + cfg.settingsFile + else pkgs.writeTextFile { name = "knot.conf"; - text = (concatMapStringsSep "\n" (file: "include: ${file}") cfg.keyFiles) + "\n" + - cfg.extraConfig; + text = (concatMapStringsSep "\n" (file: "include: ${file}") cfg.keyFiles) + "\n" + yamlConfig; + # TODO: maybe we could do some checks even when private keys complicate this? checkPhase = lib.optionalString (cfg.keyFiles == []) '' ${cfg.package}/bin/knotc --config=$out conf-check ''; @@ -60,11 +160,21 @@ in { ''; }; - extraConfig = mkOption { - type = types.lines; - default = ""; + settings = mkOption { + type = types.attrs; + default = {}; description = lib.mdDoc '' - Extra lines to be added verbatim to knot.conf + Extra configuration as nix values. + ''; + }; + + settingsFile = mkOption { + type = types.nullOr types.path; + default = null; + description = lib.mdDoc '' + As alternative to ``settings``, you can provide whole configuration + directly in the almost-YAML format of Knot DNS. + You might want to utilize ``writeTextFile`` for this. ''; }; @@ -78,6 +188,12 @@ in { }; }; }; + imports = [ + # Compatibility with NixOS 23.05. At least partial, as it fails assert if used with keyFiles. + (mkChangedOptionModule [ "services" "knot" "extraConfig" ] [ "services" "knot" "settingsFile" ] + (config: pkgs.writeText "knot.conf" config.services.knot.extraConfig) + ) + ]; config = mkIf config.services.knot.enable { users.groups.knot = {}; @@ -87,6 +203,8 @@ in { description = "Knot daemon user"; }; + environment.etc."knot/knot.conf".source = configFile; # just for user's convenience + systemd.services.knot = { unitConfig.Documentation = "man:knotd(8) man:knot.conf(5) man:knotc(8) https://www.knot-dns.cz/docs/${cfg.package.version}/html/"; description = cfg.package.meta.description; diff --git a/nixos/modules/virtualisation/oci-common.nix b/nixos/modules/virtualisation/oci-common.nix new file mode 100644 index 000000000000..ac9405e3ecfa --- /dev/null +++ b/nixos/modules/virtualisation/oci-common.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.oci; +in +{ + imports = [ ../profiles/qemu-guest.nix ]; + + # Taken from /proc/cmdline of Ubuntu 20.04.2 LTS on OCI + boot.kernelParams = [ + "nvme.shutdown_timeout=10" + "nvme_core.shutdown_timeout=10" + "libiscsi.debug_libiscsi_eh=1" + "crash_kexec_post_notifiers" + + # VNC console + "console=tty1" + + # x86_64-linux + "console=ttyS0" + + # aarch64-linux + "console=ttyAMA0,115200" + ]; + + boot.growPartition = true; + + fileSystems."/" = { + device = "/dev/disk/by-label/nixos"; + fsType = "ext4"; + autoResize = true; + }; + + fileSystems."/boot" = lib.mkIf cfg.efi { + device = "/dev/disk/by-label/ESP"; + fsType = "vfat"; + }; + + boot.loader.efi.canTouchEfiVariables = false; + boot.loader.grub = { + device = if cfg.efi then "nodev" else "/dev/sda"; + splashImage = null; + extraConfig = '' + serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1 + terminal_input --append serial + terminal_output --append serial + ''; + efiInstallAsRemovable = cfg.efi; + efiSupport = cfg.efi; + }; + + # https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/configuringntpservice.htm#Configuring_the_Oracle_Cloud_Infrastructure_NTP_Service_for_an_Instance + networking.timeServers = [ "169.254.169.254" ]; + + services.openssh.enable = true; + + # Otherwise the instance may not have a working network-online.target, + # making the fetch-ssh-keys.service fail + networking.useNetworkd = true; +} diff --git a/nixos/modules/virtualisation/oci-config-user.nix b/nixos/modules/virtualisation/oci-config-user.nix new file mode 100644 index 000000000000..70c0b34efe7a --- /dev/null +++ b/nixos/modules/virtualisation/oci-config-user.nix @@ -0,0 +1,12 @@ +{ modulesPath, ... }: + +{ + # To build the configuration or use nix-env, you need to run + # either nixos-rebuild --upgrade or nix-channel --update + # to fetch the nixos channel. + + # This configures everything but bootstrap services, + # which only need to be run once and have already finished + # if you are able to see this comment. + imports = [ "${modulesPath}/virtualisation/oci-common.nix" ]; +} diff --git a/nixos/modules/virtualisation/oci-image.nix b/nixos/modules/virtualisation/oci-image.nix new file mode 100644 index 000000000000..d4af5016dd71 --- /dev/null +++ b/nixos/modules/virtualisation/oci-image.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.oci; +in +{ + imports = [ ./oci-common.nix ]; + + config = { + system.build.OCIImage = import ../../lib/make-disk-image.nix { + inherit config lib pkgs; + name = "oci-image"; + configFile = ./oci-config-user.nix; + format = "qcow2"; + diskSize = 8192; + partitionTableType = if cfg.efi then "efi" else "legacy"; + }; + + systemd.services.fetch-ssh-keys = { + description = "Fetch authorized_keys for root user"; + + wantedBy = [ "sshd.service" ]; + before = [ "sshd.service" ]; + + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + + path = [ pkgs.coreutils pkgs.curl ]; + script = '' + mkdir -m 0700 -p /root/.ssh + if [ -f /root/.ssh/authorized_keys ]; then + echo "Authorized keys have already been downloaded" + else + echo "Downloading authorized keys from Instance Metadata Service v2" + curl -s -S -L \ + -H "Authorization: Bearer Oracle" \ + -o /root/.ssh/authorized_keys \ + http://169.254.169.254/opc/v2/instance/metadata/ssh_authorized_keys + chmod 600 /root/.ssh/authorized_keys + fi + ''; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + StandardError = "journal+console"; + StandardOutput = "journal+console"; + }; + }; + }; +} diff --git a/nixos/modules/virtualisation/oci-options.nix b/nixos/modules/virtualisation/oci-options.nix new file mode 100644 index 000000000000..0dfedc6a530c --- /dev/null +++ b/nixos/modules/virtualisation/oci-options.nix @@ -0,0 +1,14 @@ +{ config, lib, pkgs, ... }: +{ + options = { + oci = { + efi = lib.mkOption { + default = true; + internal = true; + description = '' + Whether the OCI instance is using EFI. + ''; + }; + }; + }; +} diff --git a/nixos/tests/kea.nix b/nixos/tests/kea.nix index b4095893b482..c8ecf771fa13 100644 --- a/nixos/tests/kea.nix +++ b/nixos/tests/kea.nix @@ -134,31 +134,32 @@ import ./make-test-python.nix ({ pkgs, lib, ...}: { extraArgs = [ "-v" ]; - extraConfig = '' - server: - listen: 0.0.0.0@53 - - log: - - target: syslog - any: debug - - acl: - - id: dhcp_ddns - address: 10.0.0.1 - action: update - - template: - - id: default - storage: ${zonesDir} - zonefile-sync: -1 - zonefile-load: difference-no-serial - journal-content: all - - zone: - - domain: lan.nixos.test - file: lan.nixos.test.zone - acl: [dhcp_ddns] - ''; + settings = { + server.listen = [ + "0.0.0.0@53" + ]; + + log.syslog.any = "info"; + + acl.dhcp_ddns = { + address = "10.0.0.1"; + action = "update"; + }; + + template.default = { + storage = zonesDir; + zonefile-sync = "-1"; + zonefile-load = "difference-no-serial"; + journal-content = "all"; + }; + + zone."lan.nixos.test" = { + file = "lan.nixos.test.zone"; + acl = [ + "dhcp_ddns" + ]; + }; + }; }; }; diff --git a/nixos/tests/knot.nix b/nixos/tests/knot.nix index 2ecbf69194bb..44efd93b6fa9 100644 --- a/nixos/tests/knot.nix +++ b/nixos/tests/knot.nix @@ -60,44 +60,43 @@ in { services.knot.enable = true; services.knot.extraArgs = [ "-v" ]; services.knot.keyFiles = [ tsigFile ]; - services.knot.extraConfig = '' - server: - listen: 0.0.0.0@53 - listen: ::@53 - automatic-acl: true - - remote: - - id: secondary - address: 192.168.0.2@53 - key: xfr_key - - template: - - id: default - storage: ${knotZonesEnv} - notify: [secondary] - dnssec-signing: on - # Input-only zone files - # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-3 - # prevents modification of the zonefiles, since the zonefiles are immutable - zonefile-sync: -1 - zonefile-load: difference - journal-content: changes - # move databases below the state directory, because they need to be writable - journal-db: /var/lib/knot/journal - kasp-db: /var/lib/knot/kasp - timer-db: /var/lib/knot/timer - - zone: - - domain: example.com - file: example.com.zone - - - domain: sub.example.com - file: sub.example.com.zone - - log: - - target: syslog - any: info - ''; + services.knot.settings = { + server = { + listen = [ + "0.0.0.0@53" + "::@53" + ]; + automatic-acl = true; + }; + + acl.secondary_acl = { + address = "192.168.0.2"; + key = "xfr_key"; + action = "transfer"; + }; + + remote.secondary.address = "192.168.0.2@53"; + + template.default = { + storage = knotZonesEnv; + notify = [ "secondary" ]; + acl = [ "secondary_acl" ]; + dnssec-signing = true; + # Input-only zone files + # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-3 + # prevents modification of the zonefiles, since the zonefiles are immutable + zonefile-sync = -1; + zonefile-load = "difference"; + journal-content = "changes"; + }; + + zone = { + "example.com".file = "example.com.zone"; + "sub.example.com".file = "sub.example.com.zone"; + }; + + log.syslog.any = "info"; + }; }; secondary = { lib, ... }: { @@ -113,41 +112,36 @@ in { services.knot.enable = true; services.knot.keyFiles = [ tsigFile ]; services.knot.extraArgs = [ "-v" ]; - services.knot.extraConfig = '' - server: - listen: 0.0.0.0@53 - listen: ::@53 - automatic-acl: true - - remote: - - id: primary - address: 192.168.0.1@53 - key: xfr_key - - template: - - id: default - master: primary - # zonefileless setup - # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-2 - zonefile-sync: -1 - zonefile-load: none - journal-content: all - # move databases below the state directory, because they need to be writable - journal-db: /var/lib/knot/journal - kasp-db: /var/lib/knot/kasp - timer-db: /var/lib/knot/timer - - zone: - - domain: example.com - file: example.com.zone - - - domain: sub.example.com - file: sub.example.com.zone - - log: - - target: syslog - any: info - ''; + services.knot.settings = { + server = { + listen = [ + "0.0.0.0@53" + "::@53" + ]; + automatic-acl = true; + }; + + remote.primary = { + address = "192.168.0.1@53"; + key = "xfr_key"; + }; + + template.default = { + master = "primary"; + # zonefileless setup + # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-2 + zonefile-sync = "-1"; + zonefile-load = "none"; + journal-content = "all"; + }; + + zone = { + "example.com".file = "example.com.zone"; + "sub.example.com".file = "sub.example.com.zone"; + }; + + log.syslog.any = "info"; + }; }; client = { lib, nodes, ... }: { imports = [ common ]; |