diff --git a/docs/generate-man-pages.py b/docs/generate-man-pages.py index ddf7e0d73bd1..22a718d44ce3 100755 --- a/docs/generate-man-pages.py +++ b/docs/generate-man-pages.py @@ -3,7 +3,6 @@ import argparse import glob import itertools -import os import subprocess import sys import venv @@ -14,8 +13,8 @@ def main(): """Start the script.""" args = create_argument_parser() - source_root = Path(os.environ["MESON_SOURCE_ROOT"]) - build_root = Path(os.environ["MESON_BUILD_ROOT"]) + source_root = args.source_root + build_root = args.build_root # Create the venv. venv_directory = build_root.joinpath(args.venv_name) @@ -30,8 +29,8 @@ def main(): # Install some stuff into the venv. requirements_file = source_root.joinpath(args.requirements_file) pip = venv_directory.joinpath("bin").joinpath("pip") - subprocess.run([pip, "install", "-U", "pip", "setuptools", "wheel"]) - subprocess.run([pip, "install", "-r", requirements_file]) + subprocess.run([pip, "install", "-U", "pip", "setuptools", "wheel"], check=True) + subprocess.run([pip, "install", "-r", requirements_file], check=True) # Run sphinx to generate the man-pages. source_directory = source_root.joinpath(args.source_directory) @@ -47,7 +46,8 @@ def main(): source_directory, target_directory, ] - + files + + files, + check=True ) @@ -56,6 +56,18 @@ def create_argument_parser(): parser = argparse.ArgumentParser( description="Create a virtualenv from a requirements file" ) + parser.add_argument( + "--build-root", + type=Path, + required=True, + help="Build root", + ) + parser.add_argument( + "--source-root", + type=Path, + required=True, + help="Source root", + ) parser.add_argument( "--venv-name", type=str, diff --git a/meson.build b/meson.build index 6a67f093ec0d..f914ed454038 100644 --- a/meson.build +++ b/meson.build @@ -1011,16 +1011,30 @@ summary('Path', python.full_path(), section: 'Manual Pages') summary('Version', python.version(), section: 'Manual Pages') if python.found() - run_target( - 'man-pages', - command: [ - python, - product_source_dir / docs_dir / 'generate-man-pages.py', - '--venv-name', 'venv-auth-man-pages', - '--requirements-file', docs_dir / 'requirements.txt', - '--source-directory', docs_dir, - '--target-directory', 'auth-man-pages', - ] + man_pages, + generated_man_pages = [] + foreach tool, info: tools + if 'manpages' in info + foreach man_page: info['manpages'] + generated_man_pages += man_page + endforeach + endif + endforeach + custom_target( + 'man-pages', + input: man_pages, + output: generated_man_pages, + install: true, + install_dir: join_paths(get_option('mandir'), 'man1'), + command: [ + python, + product_source_dir / docs_dir / 'generate-man-pages.py', + '--build-root', '@BUILD_ROOT@', + '--source-root', '@SOURCE_ROOT@', + '--venv-name', 'venv-auth-man-pages', + '--requirements-file', docs_dir / 'requirements.txt', + '--source-directory', docs_dir, + '--target-directory', '@BUILD_ROOT@', + ] + man_pages, ) endif diff --git a/pdns/dnsdistdist/dnsdist.service.meson.in b/pdns/dnsdistdist/dnsdist.service.meson.in new file mode 100644 index 000000000000..41501cc4cd52 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist.service.meson.in @@ -0,0 +1,61 @@ +[Unit] +Description=@Description@ +Documentation=man:dnsdist(1) +Documentation=https://dnsdist.org +Wants=network-online.target +After=network-online.target time-sync.target + +[Service] +ExecStartPre=@BinDir@/dnsdist --check-config +# Note: when editing the ExecStart command, keep --supervised and --disable-syslog +ExecStart=@BinDir@/dnsdist --supervised --disable-syslog +User=@ServiceUser@ +Group=@ServiceGroup@ +SyslogIdentifier=dnsdist +Type=notify +Restart=on-failure +RestartSec=2 +TimeoutStopSec=5 +StartLimitInterval=0 + +# Tuning +TasksMax=8192 +LimitNOFILE=16384 +# Note: increasing the amount of lockable memory is required to use eBPF support +# LimitMEMLOCK=infinity + +# Sandboxing +# Note: adding CAP_SYS_ADMIN is required to use eBPF support, +# and CAP_NET_RAW to be able to set the source interface to contact a backend +# If an AppArmor policy is in use, it might have to be updated to allow dnsdist to keep the +# capability: adding a 'capability sys_admin,' line to the policy is usually enough. +CapabilityBoundingSet=CAP_NET_BIND_SERVICE +AmbientCapabilities=CAP_NET_BIND_SERVICE +@LockPersonality@ +NoNewPrivileges=true +@PrivateDevices@ +@PrivateTmp@ +# Setting PrivateUsers=true prevents us from opening our sockets +@ProtectClock@ +@ProtectControlGroups@ +@ProtectHome@ +@ProtectHostname@ +@ProtectKernelLogs@ +@ProtectKernelModules@ +@ProtectKernelTunables@ +@ProtectSystem@ +@RestrictAddressFamilies@ +@RestrictNamespaces@ +@RestrictRealtime@ +@RestrictSUIDSGID@ +@SystemCallArchitectures@ +@SystemCallFilter@ +@ProtectProc@ +@PrivateIPC@ +@RemoveIPC@ +DevicePolicy=closed +# Not enabled by default because it does not play well with LuaJIT +@MemoryDenyWriteExecute@ + +[Install] +WantedBy=multi-user.target diff --git a/pdns/dnsdistdist/docs/generate-man-pages.py b/pdns/dnsdistdist/docs/generate-man-pages.py new file mode 120000 index 000000000000..c19dc3bef129 --- /dev/null +++ b/pdns/dnsdistdist/docs/generate-man-pages.py @@ -0,0 +1 @@ +../../../docs/generate-man-pages.py \ No newline at end of file diff --git a/pdns/dnsdistdist/meson.build b/pdns/dnsdistdist/meson.build index 4baa479869d9..1cc990021fe5 100644 --- a/pdns/dnsdistdist/meson.build +++ b/pdns/dnsdistdist/meson.build @@ -416,6 +416,7 @@ tools = { dep_json11, dep_systemd, ], + 'install': true, }, } @@ -523,6 +524,7 @@ foreach tool, info: tools files_extra = 'files-extra' in info ? info['files-extra'] : [] deps_extra = 'deps-extra' in info ? info['deps-extra'] : [] link_args = 'link-args' in info ? info['link-args'] : [] + install = 'install' in info ? info['install'] : false set_variable( var_name, @@ -537,6 +539,7 @@ foreach tool, info: tools libdnsdist_common, deps_extra, ], + install: install, ) ) @@ -559,16 +562,129 @@ summary('Python', python.found(), bool_yn: true, section: 'Manual Pages') summary('Path', python.full_path(), section: 'Manual Pages') summary('Version', python.version(), section: 'Manual Pages') -if python.found() - run_target( - 'man-pages', - command: [ - python, - product_source_dir / docs_dir / 'generate-man-pages.py', - '--venv-name', 'venv-dnsdist-man-pages', - '--requirements-file', docs_dir / 'requirements.txt', - '--source-directory', docs_dir, - '--target-directory', 'dnsdist-man-pages', - ] + man_pages, +if get_option('man-pages') and python.found() + generated_man_pages = [] + foreach tool, info: tools + if 'manpages' in info + foreach man_page: info['manpages'] + generated_man_pages += man_page + endforeach + endif + endforeach + custom_target( + 'man-pages', + input: man_pages, + output: generated_man_pages, + install: true, + install_dir: join_paths(get_option('mandir'), 'man1'), + command: [ + python, + product_source_dir / docs_dir / 'generate-man-pages.py', + '--build-root', '@BUILD_ROOT@', + '--source-root', '@SOURCE_ROOT@', + '--venv-name', 'venv-dnsdist-man-pages', + '--requirements-file', docs_dir / 'requirements.txt', + '--source-directory', docs_dir, + '--target-directory', '@BUILD_ROOT@', + ] + man_pages, ) endif + +if dep_systemd_prog.found() + + systemd_system_unit_dir = dep_systemd_prog.get_variable( + 'systemdsystemunitdir', + ) + + systemd_service_conf = configuration_data() + systemd_service_conf.set('Description', 'DNS Loadbalancer') + systemd_service_conf.set('BinDir', get_option('prefix') / get_option('bindir')) + systemd_service_user = get_option('systemd-service-user') + systemd_service_group = get_option('systemd-service-group') + systemd_service_conf.set('ServiceUser', systemd_service_user) + systemd_service_conf.set('ServiceGroup', systemd_service_group) + summary('Service User', systemd_service_user, section: 'Systemd') + summary('Service Group', systemd_service_group, section: 'Systemd') + + systemd_service_conf.set( + 'ProtectSystem', have_systemd_protect_system ? 'ProtectSystem=full' : '', + ) + systemd_service_conf.set( + 'SystemCallArchitectures', + have_systemd_system_call_architectures ? 'SystemCallArchitectures=native' : '', + ) + systemd_system_call_filter = '~ @clock @debug @module @mount @raw-io @reboot @swap @cpu-emulation @obsolete' + systemd_service_conf.set( + 'SystemCallFilter', + have_systemd_system_call_filter ? 'SystemCallFilter=' + systemd_system_call_filter : '', + ) + systemd_service_conf.set( + 'ProtectProc', + have_systemd_protect_proc ? 'ProtectProc=invisible' : '', + ) + + systemd_features = { + 'LockPersonality': have_systemd_lock_personality, + 'PrivateDevices': have_systemd_private_devices, + 'PrivateTmp': have_systemd_private_tmp, + 'PrivateUsers': false, # Setting it to true prevents us from opening our sockets. + 'ProtectClock': have_systemd_protect_clock, + 'ProtectControlGroups': have_systemd_protect_control_groups, + 'ProtectHome': have_systemd_protect_home, + 'ProtectHostname': have_systemd_protect_hostname, + 'ProtectKernelLogs': have_systemd_protect_kernel_logs, + 'ProtectKernelModules': have_systemd_protect_kernel_modules, + 'ProtectKernelTunables': have_systemd_protect_kernel_tunables, + 'RestrictNamespaces': have_systemd_restrict_namespaces, + 'RestrictRealtime': have_systemd_restrict_realtime, + 'RestrictSUIDSGID': have_systemd_restrict_suidsgid, + 'PrivateIPC': have_systemd_private_ipc, + 'RemoveIPC': have_systemd_remove_ipc, + } + + foreach feature, enable_it: systemd_features + systemd_service_conf.set(feature, enable_it ? feature + '=true': '') + endforeach + + # Disabled, it breaks LuaJIT. + systemd_service_conf.set( + 'MemoryDenyWriteExecute', + have_systemd_memory_deny_write_execute ? 'MemoryDenyWriteExecute=false' : '', + ) + systemd_service_conf.set( + 'RestrictAddressFamilies', + have_systemd_restrict_address_families ? 'RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6' : '', + ) + + dnsdist_service_conf_general = configuration_data() + dnsdist_service_conf_general.set('Description', 'DNS Loadbalancer') + dnsdist_service_conf_general.merge_from(systemd_service_conf) + dnsdist_service_conf_general.set('SyslogIdentifier', 'dnsdist') + + configure_file( + input: 'dnsdist.service.meson.in', + output: 'dnsdist.service', + configuration: dnsdist_service_conf_general, + install: true, + install_dir: systemd_system_unit_dir, + ) + + dnsdist_service_conf_instance = configuration_data() + dnsdist_service_conf_instance.merge_from(systemd_service_conf) + dnsdist_service_conf_instance.set('Description', 'DNS Loadbalancer %i') + dnsdist_service_conf_instance.set('SyslogIdentifier', 'dnsdist-%i') + + configure_file( + input: 'dnsdist.service.meson.in', + output: 'dnsdist@.service', + configuration: dnsdist_service_conf_instance, + install: true, + install_dir: systemd_system_unit_dir, + ) +endif + +install_data( + 'dnsdist.conf-dist', + install_dir : get_option('sysconfdir'), + follow_symlinks: true +) \ No newline at end of file diff --git a/pdns/dnsdistdist/meson_options.txt b/pdns/dnsdistdist/meson_options.txt index e860bdf833be..80361de207f9 100644 --- a/pdns/dnsdistdist/meson_options.txt +++ b/pdns/dnsdistdist/meson_options.txt @@ -37,3 +37,4 @@ option('fuzz-targets', type: 'boolean', value: false, description: 'Enable fuzzi option('ebpf', type: 'feature', value: 'disabled', description: 'Enable eBPF support') option('fuzzer_ldflags', type: 'string', value: '', description: 'Linker flags used for the fuzzing targets (a path to the libFuzzer static library, for example)') option('yaml', type: 'feature', value: 'disabled', description: 'Enable YAML configuration') +option('man-pages', type: 'boolean', value: true, description: 'Generate man pages') diff --git a/pdns/recursordist/meson.build b/pdns/recursordist/meson.build index 81d740568fe5..239aa91dd99a 100644 --- a/pdns/recursordist/meson.build +++ b/pdns/recursordist/meson.build @@ -576,16 +576,30 @@ summary('Path', python.full_path(), section: 'Manual Pages') summary('Version', python.version(), section: 'Manual Pages') if python.found() - run_target( - 'man-pages', - command: [ - python, - product_source_dir / docs_dir / 'generate-man-pages.py', - '--venv-name', 'venv-rec-man-pages', - '--requirements-file', docs_dir / 'requirements.txt', - '--source-directory', docs_dir, - '--target-directory', 'rec-man-pages', - ] + man_pages, + generated_man_pages = [] + foreach tool, info: tools + if 'manpages' in info + foreach man_page: info['manpages'] + generated_man_pages += man_page + endforeach + endif + endforeach + custom_target( + 'man-pages', + input: man_pages, + output: generated_man_pages, + install: true, + install_dir: join_paths(get_option('mandir'), 'man1'), + command: [ + python, + product_source_dir / docs_dir / 'generate-man-pages.py', + '--build-root', '@BUILD_ROOT@', + '--source-root', '@SOURCE_ROOT@', + '--venv-name', 'venv-rec-man-pages', + '--requirements-file', docs_dir / 'requirements.txt', + '--source-directory', docs_dir, + '--target-directory', '@BUILD_ROOT@', + ] + man_pages, ) endif