Variables
Every role is configured only through variables. This page lists them per role. The data comes from each role’s meta/argument_specs.yml (type and description) and defaults/main.yml (default); Ansible validates the values against the specs before a role runs.
Roles are listed in the order of the role guides. A role’s own page explains how the variables work together; this page is the lookup table.
The list of dict variables take entries with the keys described in the role guide.
Baseline for Debian and Ubuntu servers. See the base guide.
| Variable | Type | Default | Description |
|---|---|---|---|
base_packages | list of str | ["ca-certificates", "curl", "gnupg", "htop", "jq", "rsync", "unattended-upgrades"] | Packages installed on every host. |
base_timezone | str | "Etc/UTC" | System time zone. |
base_swap_size_mb | int | 0 | Size of the swap file in MiB; 0 leaves swap alone. |
base_swap_file | path | "/swapfile" | Path of the swap file. |
base_swappiness | int | 10 | vm.swappiness while a swap file is managed. |
base_journald_max_use | str | "500M" | journald SystemMaxUse. |
base_unattended_upgrades | bool | true | Enable unattended security upgrades. |
base_unattended_reboot | bool | false | Let unattended-upgrades reboot when an upgrade needs it. |
base_unattended_reboot_time | str | "04:00" | Time of day for such a reboot. |
base_sshd_hardening | bool | true | Harden sshd with a drop-in: key-only login, no forwarding of agents, X11 or tunnels, VERBOSE logging (key fingerprints, used by fail2ban and CrowdSec), connection limits and modern algorithms only. The base_sshd_* options below tune it; none of them applies while this is off. |
base_sshd_listen_addresses | list of str | [] | Addresses sshd binds to. Empty keeps the distribution default. When set, socket activation is turned off and the nonlocal bind sysctls are enabled, so sshd starts even before an address is up. |
base_sshd_port | int | 22 | sshd port. |
base_sshd_permit_root_login | str | "prohibit-password" | PermitRootLogin. The default lets root log in with a key only; set “no” once every play connects as an unprivileged user. One of: yes, prohibit-password, forced-commands-only, no. |
base_sshd_allow_users | list of str | [] | AllowUsers patterns (user or user@host). Empty writes no AllowUsers line. Include the user Ansible connects as, or the next run is locked out. |
base_sshd_max_auth_tries | int | 3 | MaxAuthTries; keep it above the number of keys a client offers. |
base_sshd_login_grace_time | int | 30 | LoginGraceTime in seconds. |
base_sshd_max_sessions | int | 10 | MaxSessions per connection; Ansible’s multiplexing needs several. |
base_sshd_max_startups | str | "10:30:60" | MaxStartups (start:rate:full) for unauthenticated connections. |
base_sshd_client_alive_interval | int | 300 | ClientAliveInterval in seconds. |
base_sshd_client_alive_count_max | int | 2 | ClientAliveCountMax; an idle, unresponsive session is closed after interval times count seconds. |
base_sshd_allow_tcp_forwarding | str | "no" | AllowTcpForwarding; “local” is enough for ssh -L tunnels to private services. One of: yes, no, all, local, remote. |
base_sshd_kex_algorithms | list of str | ["sntrup761x25519-sha512@openssh.com", "curve25519-sha256", "curve25519-sha256@libssh.org"] | KexAlgorithms. The default works on OpenSSH 9.6 (Ubuntu 24.04) and later; add mlkem768x25519-sha256 first where every host runs OpenSSH 9.9 or later. |
base_sshd_ciphers | list of str | ["chacha20-poly1305@openssh.com", "aes256-gcm@openssh.com", "aes128-gcm@openssh.com"] | Ciphers. |
base_sshd_macs | list of str | ["hmac-sha2-512-etm@openssh.com", "hmac-sha2-256-etm@openssh.com"] | MACs (only used by non-AEAD ciphers). |
base_nonlocal_bind | bool | false | Enable net.ipv4.ip_nonlocal_bind and net.ipv6.ip_nonlocal_bind, so services (sshd, published container ports) can bind an address before it is up at boot. The IPv6 key is skipped on a kernel without IPv6. Always on when base_sshd_listen_addresses is set. |
base_static_routes | list of dict | [] | Routes (to, via) set by a oneshot unit after the network is up, on the interface the gateway is reached through. For example a home LAN behind a private network gateway on a host that also has a public interface. |
docker
Section titled “docker”Docker CE with the compose plugin. See the docker guide.
| Variable | Type | Default | Description |
|---|---|---|---|
docker_packages | list of str | ["docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin", "docker-compose-plugin"] | Packages installed from the Docker apt repository. |
docker_mtu | int | 1500 | MTU of the default bridge (1450 on Hetzner private networks). Compose networks need their own driver option; the stacks of this collection set it from the same value. |
docker_log_driver | str | "local" | Default log driver. |
docker_log_opts | dict | {"max-size": "20m", "max-file": "5"} | Options of the default log driver. |
docker_address_pools | list of dict | [] | default-address-pools entries (base, size); empty keeps Docker’s default. |
docker_live_restore | bool | true | Keep containers running while the daemon restarts. |
docker_daemon_extra | dict | {} | Further daemon.json keys, merged last. |
docker_users | list of str | [] | Users added to the docker group. |
tailscale
Section titled “tailscale”Tailscale node, optionally a subnet router. See the tailscale guide.
| Variable | Type | Default | Description |
|---|---|---|---|
tailscale_auth_key | str | "" | Auth key used only when the node is not logged in yet. Keep it in a vault. It is handed to tailscale through a temporary file, never on the command line. |
tailscale_hostname | str | "{{ inventory_hostname_short }}" | Node name in the tailnet. |
tailscale_advertise_routes | list of str | [] | Subnets this node routes into the tailnet; enables IP forwarding. |
tailscale_accept_routes | bool | false | Use subnet routes advertised by other nodes. |
tailscale_accept_dns | bool | false | Let Tailscale manage DNS on this host. |
tailscale_advertise_tags | list of str | [] | ACL tags (tag:name) the node advertises when it joins; changing them later needs a re-join. |
tailscale_ssh | bool | false | Enable Tailscale SSH. |
traefik
Section titled “traefik”Standalone Traefik with DNS-01 or HTTP-01 certificates. See the traefik guide.
| Variable | Type | Default | Description |
|---|---|---|---|
traefik_image | str | "traefik:v3.7.17" | Traefik image. |
traefik_socket_proxy_image | str | "tecnativa/docker-socket-proxy:v0.5.0" | Docker socket proxy image; Traefik never sees the socket itself. |
traefik_dir | path | "/opt/traefik" | Directory of the compose project and its state. |
traefik_project | str | "traefik" | Compose project name. |
traefik_log_level | str | "INFO" | Traefik log level. One of: DEBUG, INFO, WARN, ERROR. |
traefik_access_log | bool | false | Write an access log to stdout. |
traefik_mtu | int | 1500 | MTU of the compose networks (1450 on Hetzner private networks). |
traefik_network | str | "proxy" | Name of the shared network. |
traefik_network_subnet | str | "172.31.255.0/24" | Subnet of the shared network. |
traefik_network_range | str | "172.31.255.0/25" | Part of the subnet Docker assigns from; must not contain traefik_address. |
traefik_address | str | "172.31.255.254" | Fixed address of Traefik on the shared network. |
traefik_entrypoints | list of dict | [{"name": "web", "port": 80, "redirect_to": "websecure"}, {"name": "websecure", "port": 443, "tls": true, "as_default": true}] | Entrypoints; see defaults/main.yml for the keys. Keys are name, port, host_port, bind, protocol, tls, as_default, redirect_to and middlewares. host_port publishes the container port on another host port, so two entrypoints can share a host port on different bind addresses. A redirect to such an entrypoint goes to its host_port. middlewares lists middlewares (for example name@file) that every router on the entrypoint gets; an entrypoint with redirect_to cannot have them. |
traefik_acme_email | str | "" | ACME account e-mail; required when an entrypoint terminates TLS. |
traefik_acme_ca_server | str | "https://acme-v02.api.letsencrypt.org/directory" | ACME directory (use the staging directory for tests). |
traefik_acme_challenge | str | "dns" | ACME challenge, also the name of the cert resolver. dns uses DNS-01 through traefik_dns_provider and can issue wildcards. http uses HTTP-01 on traefik_acme_http_entrypoint. Traefik requests a certificate per router host; each host must resolve publicly to this server and reach that entrypoint on host port 80. traefik_cert_domains cannot contain wildcards then. One of: dns, http. |
traefik_acme_http_entrypoint | str | "web" | Entrypoint that answers the HTTP-01 challenge; it must exist and listen on host port 80. |
traefik_dns_provider | str | "hetzner" | lego DNS provider for the DNS-01 challenge. |
traefik_dns_env | dict | {} | Environment for the DNS provider (API tokens); written to a 0600 file. |
traefik_dns_resolvers | list of str | ["1.1.1.1:53", "9.9.9.9:53"] | Resolvers used to check DNS propagation. |
traefik_cert_domains | list of dict | [] | Certificates requested on TLS entrypoints (main, sans). |
traefik_docker_allow_empty_services | bool | false | Docker provider allowEmptyServices: keep the routers of containers without a healthy server, so they answer an error instead of disappearing (Traefik 3.7 answers 500, not 503; see the guide). |
traefik_error_pages_enabled | bool | false | Route errors to an error pages service. The role writes dynamic/error-pages.yml with the middlewares error-pages-errors and error-pages-compress, a router error-pages-<name> per route and the service error-pages; disabling removes it. The role also runs the error pages container unless traefik_error_pages_container is false. |
traefik_error_pages_container | bool | true | Run the error pages container (service error-pages) in the Traefik compose project, read-only, as 65532, with the image’s healthcheck and a volume on /data for maintenance mode. Set to false to run the service elsewhere; then point traefik_error_pages_url at it. |
traefik_error_pages_image | str | "noixdev/error-pages:1" | Error pages image (noixdev/error-pages or compatible). |
traefik_error_pages_env | dict | {"THEME": "glass", "LANGUAGES": "en,de", "DEFAULT_LANGUAGE": "en", "SHOW_DETAILS": "false"} | Environment of the error pages container; replaces the defaults as a whole. |
traefik_error_pages_cpus | str | "0.25" | CPU limit of the error pages container. |
traefik_error_pages_memory | str | "64M" | Memory limit of the error pages container, for example 64M. |
traefik_error_pages_url | str | "http://error-pages:8080" | URL of the error pages service, which serves /<code>.html; the default is the bundled container. |
traefik_error_pages_status | list of str | ["502-504"] | Backend statuses (codes or ranges like 502-504) replaced by the matching page. |
traefik_error_pages_entrypoints | list of str | [] | Entrypoints whose routers all get error-pages-compress (if enabled) and error-pages-errors, before the entrypoint’s own middlewares. Must exist in traefik_entrypoints and must not redirect. |
traefik_error_pages_compress | bool | true | Compress responses on those entrypoints, limited to traefik_error_pages_compress_types. |
traefik_error_pages_compress_types | list of str | ["text/html", "text/plain", "application/json"] | Content types the compress middleware compresses. |
traefik_error_pages_routes | list of dict | [] | Routers that always answer with one page, for unknown hosts or names that must not be served on an entrypoint. Keys are name ([a-z0-9-]+, unique), entrypoints (required), rule (default HostRegexp(.+)), priority (default 1; higher wins) and page (a status code or internal, default 404). The page is requested as /<page>.html. |
traefik_dynamic_files | dict | {} | File-provider files, name to YAML content. |
portainer
Section titled “portainer”Portainer server or agent. See the portainer guide.
| Variable | Type | Default | Description |
|---|---|---|---|
portainer_mode | str | "server" | Run the Portainer server or an agent a server connects to. One of: server, agent. |
portainer_version | str | "2.45.3" | Version of both images; server and agents must match. |
portainer_dir | path | "/opt/portainer" | Directory of the compose project. |
portainer_project | str | "portainer" | Compose project name. |
portainer_mtu | int | 1500 | MTU of the compose network. |
portainer_agent_secret | str | "" | Shared secret of server and agents (AGENT_SECRET). Keep it in a vault. |
portainer_host | str | "" | Server only. Host name Traefik routes to the UI; empty adds no route. |
portainer_traefik_network | str | "proxy" | Server only. External network Traefik routes on. |
portainer_traefik_entrypoint | str | "" | Server only. Traefik entrypoint for the route; empty uses Traefik’s default. |
portainer_bind | list of str | [] | Server only. Addresses the UI port 9443 is published on. |
portainer_agent_bind | list of str | [] | Agent only. Addresses the agent port 9001 is published on. |
pulsix_manager
Section titled “pulsix_manager”Pulsix manager with its database and local workers. See the pulsix_manager guide.
| Variable | Type | Default | Description |
|---|---|---|---|
pulsix_manager_version | str | "0.1.0-rc.1" | Image tag of the manager and worker images (no leading v). |
pulsix_manager_image | str | "noixdev/pulsix-manager" | Manager image without tag. |
pulsix_manager_worker_image | str | "noixdev/pulsix-worker" | Worker image without tag. |
pulsix_manager_db_image | str | "timescale/timescaledb:2.30.0-pg18" | TimescaleDB image; keep it on the version the Pulsix release names. |
pulsix_manager_dir | path | "/opt/pulsix" | Directory of the compose project. |
pulsix_manager_project | str | "pulsix" | Compose project name. |
pulsix_manager_mtu | int | 1500 | MTU of the compose network. |
pulsix_manager_db_password | str | "" | Required. Database password (openssl rand -hex 32). Keep it in a vault. |
pulsix_manager_master_key | str | "" | Required. Master key (openssl rand -hex 32). Encrypts secrets and backups. Keep it in a vault and outside the backups. |
pulsix_manager_public_url | str | "" | Required. URL users reach the web interface at. |
pulsix_manager_status_domain | str | "" | Domain of public status pages. |
pulsix_manager_grpc_server_name | str | "pulsix-manager" | Name in the worker endpoint’s certificate; every worker must use the same value. |
pulsix_manager_grpc_bind | list of str | [] | Host addresses the worker endpoint 8444 is published on, for remote workers. |
pulsix_manager_http_bind | list of str | [] | Host addresses the web interface 8080 is published on. |
pulsix_manager_host | str | "" | Host name Traefik routes to the web interface. |
pulsix_manager_traefik_network | str | "proxy" | External network Traefik routes on. |
pulsix_manager_traefik_entrypoint | str | "" | Traefik entrypoint for the route; empty uses Traefik’s default. |
pulsix_manager_trusted_proxies | str | "" | PULSIX_TRUSTED_PROXIES (CIDRs or addresses, comma separated). |
pulsix_manager_workers | list of dict | [{"name": "worker-1", "zone": "default"}] | Local workers; see defaults/main.yml for the keys. |
pulsix_manager_extra_env | dict | {} | Further manager environment variables. |
pulsix_manager_print_setup_token | bool | true | Print the setup token while the setup wizard is not completed. |
pulsix_worker
Section titled “pulsix_worker”Remote Pulsix workers enrolled with one-time tokens. See the pulsix_worker guide.
| Variable | Type | Default | Description |
|---|---|---|---|
pulsix_worker_version | str | "0.1.0-rc.1" | Worker image tag (no leading v); keep it on the manager’s version. |
pulsix_worker_image | str | "noixdev/pulsix-worker" | Worker image without tag. |
pulsix_worker_dir | path | "/opt/pulsix-worker" | Directory of the compose project; each worker keeps its identity and data in a 0700 subdirectory. |
pulsix_worker_project | str | "pulsix-worker" | Compose project name. |
pulsix_worker_mtu | int | 1500 | MTU of the compose network. |
pulsix_worker_manager_addr | str | "" | Required. The manager’s worker endpoint, host:8444. |
pulsix_worker_server_name | str | "pulsix-manager" | The manager’s PULSIX_GRPC_SERVER_NAME. |
pulsix_worker_instances | list of dict | [] | Workers on this host; see defaults/main.yml for the keys. |
pulsix_worker_enroll_tokens | dict | {} | One-time tokens by worker name, for workers without identity. Pass at run time. |
pulsix_worker_enroll_timeout | int | 120 | Seconds to wait for a new worker’s identity after the start. |
fail2ban
Section titled “fail2ban”fail2ban with nftables bans for sshd and repeat offenders. See the fail2ban guide.
| Variable | Type | Default | Description |
|---|---|---|---|
security_allowlist | list of str | [] | Put your management networks here (VPN, private network) so a typo can’t lock you out. IP addresses or CIDRs that are never banned. Shared with the crowdsec role; set it once for all hosts. |
fail2ban_ignoreip | list of str | ["127.0.0.1/8", "::1"] | Further addresses or CIDRs that are never banned (loopback by default). |
fail2ban_packages | list of str | ["fail2ban", "nftables"] | Packages installed; nftables provides the ban actions. |
fail2ban_bantime | str | "1h" | Default ban duration (fail2ban time abbreviation, e.g. 1h). |
fail2ban_findtime | str | "10m" | Window in which fail2ban_maxretry failures lead to a ban. |
fail2ban_maxretry | int | 5 | Failures within fail2ban_findtime before a ban. |
fail2ban_banaction | str | "nftables-multiport" | Ban action of port-based jails. |
fail2ban_banaction_allports | str | "nftables-allports" | Ban action of jails that block every port (recidive). |
fail2ban_sshd | bool | true | Enable the sshd jail. |
fail2ban_sshd_port | str | "{{ base_sshd_port | default(22) }}" | Port(s) the sshd jail bans; base_sshd_port when that is defined, else 22. |
fail2ban_recidive | bool | true | Enable the recidive jail, which bans repeat offenders on every port. |
fail2ban_recidive_bantime | str | "1w" | Ban duration of the recidive jail. |
fail2ban_recidive_findtime | str | "1d" | Window in which the recidive jail counts earlier bans. |
fail2ban_extra_jails | list of dict | [] | Further jails, each a dict with name and the jail options (enabled, port, filter, logpath, backend, …). Booleans are written as true/false. |
crowdsec
Section titled “crowdsec”CrowdSec agent with the firewall bouncer. See the crowdsec guide.
| Variable | Type | Default | Description |
|---|---|---|---|
security_allowlist | list of str | [] | Put your management networks here (VPN, private network) so a typo can’t lock you out. IP addresses or CIDRs that are never banned (a CrowdSec whitelist parser). Shared with the fail2ban role; set it once for all hosts. |
crowdsec_allowlist | list of str | [] | Further addresses or CIDRs that are never banned by this host’s CrowdSec. |
crowdsec_apt_url | str | "https://packagecloud.io/crowdsec/crowdsec/any" | URL of the CrowdSec apt repository. |
crowdsec_apt_suite | str | "any" | Suite of the repository. “any” carries the same packages for every Debian and Ubuntu release, including ones the per-release suites do not have yet. |
crowdsec_apt_key_url | str | "https://packagecloud.io/crowdsec/crowdsec/gpgkey" | URL of the repository signing key. |
crowdsec_apt_key_fingerprint | str | "6A89E3C2303A901A889971D3376ED5326E93CD0C" | Fingerprint the downloaded key must carry; the run stops, and the key file is removed, if it does not. |
crowdsec_collections | list of str | ["crowdsecurity/linux", "crowdsecurity/sshd"] | Hub collections that must be installed. Collections installed otherwise are left alone. |
crowdsec_acquisitions | list of dict | [{"name": "sshd", "source": "journalctl", "journalctl_filter": ["_SYSTEMD_UNIT=ssh.service"], "labels": {"type": "syslog"}}] | Log sources, one file each in /etc/crowdsec/acquis.d (noixdev-<name>.yaml): name plus the acquisition keys (source, filenames or journalctl_filter, labels). Files of entries removed from the list are deleted. Keep at least one source; CrowdSec does not start without. |
crowdsec_remove_setup_acquisitions | bool | true | Delete the acquis.d/setup.*.yaml files the package generates on first install, so crowdsec_acquisitions is the only source and no log is read twice. |
crowdsec_lapi_port | int | 8080 | Port of the Local API on 127.0.0.1 (8080 by default; change it when the host publishes 8080 itself). |
crowdsec_bouncer_name | str | "firewall-bouncer" | Name the firewall bouncer is registered under in the Local API. |
crowdsec_bouncer_docker_user | bool | null (unset) | Also block in the DOCKER-USER chain, which covers ports published by Docker, and start the bouncer after docker.service. Unset (null): only when /usr/bin/docker exists when the role runs, so run the docker role first. |
crowdsec_console_enroll_key | str | "" | Enrollment key from app.crowdsec.net. Empty skips enrollment. When set, the instance is enrolled unless it already is; accept it in the console afterwards. |
crowdsec_console_name | str | "{{ inventory_hostname_short }}" | Name of the instance in the console. |
CoreDNS for internal names, forwarding everything else. See the dns guide.
| Variable | Type | Default | Description |
|---|---|---|---|
dns_image | str | "coredns/coredns:1.13.1" | CoreDNS image. |
dns_dir | path | "/opt/dns" | Directory of the compose project. |
dns_project | str | "dns" | Compose project name. |
dns_bind | list of str | [] | Addresses CoreDNS binds on UDP and TCP port 53. Wildcard addresses are refused. |
dns_bind_tailscale | bool | false | Also bind the addresses of tailscale ip -4 and tailscale ip -6. |
dns_allow | list of str | required | Client networks (CIDR) that get answers. Every other client is refused. 0.0.0.0/0 and ::/0 are refused. |
dns_upstreams | list of str | ["1.1.1.1", "8.8.8.8"] | Resolvers that names without a local record are forwarded to. |
dns_records | list of dict | [] | Names answered locally, served from a managed hosts file. Keys are name (required, lower-case host name) and addresses (required, IPv4 and IPv6 addresses of the name). |
dns_ttl | int | 60 | TTL of the local records in seconds. |
dns_cache | int | 300 | Seconds forwarded answers are cached; 0 turns the cache off. |
dns_log_queries | bool | false | Log every query. |
dns_cpus | str | "0.25" | CPU limit of the container. |
dns_memory | str | "64M" | Memory limit of the container. |