From 056f0cdb1d35af68dd4fe03e4da6f7c650e00d77 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 8 Nov 2025 21:38:24 -0300 Subject: [PATCH] =?UTF-8?q?Agregando=20nueva=20configuraci=C3=B3n=20para?= =?UTF-8?q?=20instalar=20pihole?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- proxmox/pihole/README.md | 58 + proxmox/pihole/ansible/.gitignore | 1 + proxmox/pihole/ansible/ansible.cfg | 3 + proxmox/pihole/ansible/install.yaml | 38 + proxmox/pihole/ansible/inventory.yaml | 8 + proxmox/pihole/ansible/pihole.toml.example | 1674 +++++++++++++++++ proxmox/pihole/terraform/.gitignore | 47 + proxmox/pihole/terraform/.terraform.lock.hcl | 44 + proxmox/pihole/terraform/main.tf | 127 ++ .../pihole/terraform/terraform.tfvars.example | 14 + proxmox/pihole/terraform/variables.tf | 19 + 11 files changed, 2033 insertions(+) create mode 100644 proxmox/pihole/README.md create mode 100644 proxmox/pihole/ansible/.gitignore create mode 100644 proxmox/pihole/ansible/ansible.cfg create mode 100644 proxmox/pihole/ansible/install.yaml create mode 100755 proxmox/pihole/ansible/inventory.yaml create mode 100644 proxmox/pihole/ansible/pihole.toml.example create mode 100644 proxmox/pihole/terraform/.gitignore create mode 100644 proxmox/pihole/terraform/.terraform.lock.hcl create mode 100644 proxmox/pihole/terraform/main.tf create mode 100644 proxmox/pihole/terraform/terraform.tfvars.example create mode 100644 proxmox/pihole/terraform/variables.tf diff --git a/proxmox/pihole/README.md b/proxmox/pihole/README.md new file mode 100644 index 0000000..8d23985 --- /dev/null +++ b/proxmox/pihole/README.md @@ -0,0 +1,58 @@ +# Pi-hole instalation + +These files allow you to install Pi-hole in an idempotent way. Terraform creates +the VM on Proxmox, and Ansible installs Pi-hole unattended, using the configuration +defined in `pihole.toml`. + +## Terraform execution + +To create the VM with Terraform, the configuration must be defined in the `terraform.tfvars` +file. You can use `terraform.tfvars.example` as a base. + +Then to execute the following commands: + +1. Intialize terraform + ```bash + terraform init + ``` + +2. Review the plan + ```bash + terraform plan + ``` + +3. Apply the plan. + + This step might take a few minutes but if it takes significantly longer, + there may be an issue with cloud-init. + ```bash + terraform apply + ``` + +After execution, the `ansible` folder should contain a new `inventory.yaml` file. + +## Ansible execution + +To install Pi-hole with Ansible, make sure the `inventory.yaml` file exists, +and adjust `pihole.toml` if needed. + +Then run: + +```bash +ansible-playbook install.yaml +``` + + +## Reinstallation + +If you need to reinstall everything in the same environment, +destroy and recreate the Terraform resources using: + +```bash +terraform destroy +``` + +## Reference +[Unattended Pi-hole v6 Setup with Ansible](https://www.paulcourt.co.uk/articles/2025/unattended-pihole-ansible) + +[Configure a VM with Cloud-Init](https://registry.terraform.io/providers/bpg/proxmox/latest/docs/guides/cloud-init) diff --git a/proxmox/pihole/ansible/.gitignore b/proxmox/pihole/ansible/.gitignore new file mode 100644 index 0000000..3dc7902 --- /dev/null +++ b/proxmox/pihole/ansible/.gitignore @@ -0,0 +1 @@ +pihole.toml diff --git a/proxmox/pihole/ansible/ansible.cfg b/proxmox/pihole/ansible/ansible.cfg new file mode 100644 index 0000000..74be0dd --- /dev/null +++ b/proxmox/pihole/ansible/ansible.cfg @@ -0,0 +1,3 @@ +[defaults] +inventory = ./inventory.yaml +host_key_checking = False diff --git a/proxmox/pihole/ansible/install.yaml b/proxmox/pihole/ansible/install.yaml new file mode 100644 index 0000000..e9252f9 --- /dev/null +++ b/proxmox/pihole/ansible/install.yaml @@ -0,0 +1,38 @@ +- name: Install Pihole + hosts: all + become: true + + tasks: + - name: Update packages + apt: + update_cache: true + upgrade: safe + + - name: Install curl + apt: + name: curl + + - name: Create pihole directory + file: + path: /etc/pihole + state: directory + force: false + + - name: Load pihole pre-configuration + copy: + src: pihole.toml + dest: /etc/pihole/pihole.toml + + - name: Download install script + get_url: + url: https://install.pi-hole.net + dest: /tmp/install_pihole.sh + mode: "0755" + + - name: Install pihole + command: /tmp/install_pihole.sh --unattended + args: + creates: "/usr/local/bin/pihole" + + - name: Update gravity lists + command: pihole -g diff --git a/proxmox/pihole/ansible/inventory.yaml b/proxmox/pihole/ansible/inventory.yaml new file mode 100755 index 0000000..65fbfc5 --- /dev/null +++ b/proxmox/pihole/ansible/inventory.yaml @@ -0,0 +1,8 @@ +all: + children: + servers: + hosts: + pihole: + ansible_host: 192.168.3.1 + ansible_user: ubuntu + ansible_ssh_private_key_file: /home/ryuuji/.ssh/id_ed25519 diff --git a/proxmox/pihole/ansible/pihole.toml.example b/proxmox/pihole/ansible/pihole.toml.example new file mode 100644 index 0000000..15785d5 --- /dev/null +++ b/proxmox/pihole/ansible/pihole.toml.example @@ -0,0 +1,1674 @@ +# Pi-hole configuration file (v6.3.3) +# Encoding: UTF-8 +# This file is managed by pihole-FTL +# Last updated on 2025-11-08 20:55:48 -03 + +[dns] + # Upstream DNS Servers to be used by Pi-hole. If this is not set, Pi-hole will not + # resolve any non-local queries. + # + # Example: [ "8.8.8.8", "127.0.0.1#5335", "docker-resolver" ] + # + # Allowed values are: + # Array of IP addresses and/or hostnames, optionally with a port (#...) + upstreams = [ + "8.8.8.8", + "8.8.4.4", + "208.67.222.222", + "208.67.220.220", + "1.0.0.1", + "1.1.1.1" + ] ### CHANGED, default = [] + + # Use this option to control deep CNAME inspection. Disabling it might be beneficial + # for very low-end devices + # + # Allowed values are: + # true or false + CNAMEdeepInspect = true + + # Should _esni. subdomains be blocked by default? Encrypted Server Name Indication + # (ESNI) is certainly a good step into the right direction to enhance privacy on the + # web. It prevents on-path observers, including ISPs, coffee shop owners and + # firewalls, from intercepting the TLS Server Name Indication (SNI) extension by + # encrypting it. This prevents the SNI from being used to determine which websites + # users are visiting. + # + # ESNI will obviously cause issues for pixelserv-tls which will be unable to generate + # matching certificates on-the-fly when it cannot read the SNI. Cloudflare and Firefox + # are already enabling ESNI. According to the IETF draft (link above), we can easily + # restore pixelserv-tls's operation by replying NXDOMAIN to _esni. subdomains of + # blocked domains as this mimics a "not configured for this domain" behavior. + # + # Allowed values are: + # true or false + blockESNI = true + + # Should we overwrite the query source when client information is provided through + # EDNS0 client subnet (ECS) information? This allows Pi-hole to obtain client IPs even + # if they are hidden behind the NAT of a router. This feature has been requested and + # discussed on Discourse where further information how to use it can be found: + # https://discourse.pi-hole.net/t/support-for-add-subnet-option-from-dnsmasq-ecs-edns0-client-subnet/35940 + # + # Allowed values are: + # true or false + EDNS0ECS = true + + # Should FTL hide queries made by localhost? + # + # Allowed values are: + # true or false + ignoreLocalhost = false + + # Should FTL analyze and show internally generated DNSSEC queries? + # + # Allowed values are: + # true or false + showDNSSEC = true + + # Should FTL analyze *only* A and AAAA queries? + # + # Allowed values are: + # true or false + analyzeOnlyAandAAAA = false + + # Controls whether and how FTL will reply with for address for which a local interface + # exists. Changing this setting causes FTL to restart. + # + # Allowed values are: + # - "NONE" + # Pi-hole will not respond automatically on PTR requests to local interface + # addresses. Ensure pi.hole and/or hostname records exist elsewhere. + # - "HOSTNAME" + # Serve the machine's hostname. The hostname is queried from the kernel through + # uname(2)->nodename. If the machine has multiple network interfaces, it can + # also have multiple nodenames. In this case, it is unspecified and up to the + # kernel which one will be returned. On Linux, the returned string is what has + # been set using sethostname(2) which is typically what has been set in + # /etc/hostname. + # - "HOSTNAMEFQDN" + # Serve the machine's hostname (see limitations above) as fully qualified domain + # by adding the local domain. If no local domain has been defined (config option + # dns.domain.name), FTL tries to query the domain name from the kernel using + # getdomainname(2). If this fails, FTL appends ".no_fqdn_available" to the + # hostname. + # - "PI.HOLE" + # Respond with "pi.hole". + piholePTR = "PI.HOLE" + + # How should FTL handle queries when the gravity database is not available? + # + # Allowed values are: + # - "BLOCK" + # Block all queries when the database is busy. + # - "ALLOW" + # Allow all queries when the database is busy. + # - "REFUSE" + # Refuse all queries which arrive while the database is busy. + # - "DROP" + # Just drop the queries, i.e., never reply to them at all. Despite "REFUSE" + # sounding similar to "DROP", it turned out that many clients will just + # immediately retry, causing up to several thousands of queries per second. This + # does not happen in "DROP" mode. + replyWhenBusy = "ALLOW" + + # FTL's internal TTL to be handed out for blocked queries in seconds. This settings + # allows users to select a value different from the dnsmasq config option local-ttl. + # This is useful in context of locally used hostnames that are known to stay constant + # over long times (printers, etc.). + # + # Note that large values may render whitelisting ineffective due to client-side + # caching of blocked queries. + # + # Allowed values are: + # A positive integer value in seconds + blockTTL = 2 + + # Array of custom DNS records + # + # Example: [ "127.0.0.1 mylocal", "192.168.0.1 therouter" ] + # + # Allowed values are: + # Array of custom DNS records each one in HOSTS form: "IP HOSTNAME [HOSTNAME ...]" + hosts = [] + + # If set, queries for plain names, without dots or domain parts, are never forwarded to + # upstream nameservers + # + # Allowed values are: + # true or false + domainNeeded = false + + # If set, the domain is added to simple names (without a period) in /etc/hosts in the + # same way as for DHCP-derived names + # + # Allowed values are: + # true or false + expandHosts = false + + # Should all reverse lookups for private IP ranges (i.e., 192.168.x.y, etc) which are + # not found in /etc/hosts or the DHCP leases file be answered with "no such domain" + # rather than being forwarded upstream? + # + # Allowed values are: + # true or false + bogusPriv = true + + # Validate DNS replies using DNSSEC? + # + # Allowed values are: + # true or false + dnssec = true ### CHANGED, default = false + + # Interface to use for DNS (see also dns.listeningMode) and DHCP (if enabled). Leave + # empty for auto-detection. + # + # Allowed values are: + # a valid interface name + interface = "" + + # Add an A, AAAA and PTR record to the DNS. This adds a singular name to the DNS with + # associated IPv4 (A) and IPv6 (AAAA) records + # + # Example: "laptop,laptop.lan,192.168.0.1,1234::100" + # + # Allowed values are: + # A string in the format + # "[,....],[],[][,]" + hostRecord = "" + + # Pi-hole interface listening modes + # + # Allowed values are: + # - "LOCAL" + # Allow only local requests. This setting accepts DNS queries only from hosts + # whose address is on a local subnet, i.e., a subnet for which an interface + # exists on the server. It is intended to be set as a default on installation, + # to allow unconfigured installations to be useful but also safe from being used + # for DNS amplification attacks if (accidentally) running public. + # - "SINGLE" + # Permit all origins, accept only on the specified interface. Respond only to + # queries arriving on the specified interface. The loopback (lo) interface is + # automatically added to the list of interfaces to use when this option is used. + # Make sure your Pi-hole is properly firewalled! + # - "BIND" + # By default, FTL binds the wildcard address. If this is not what you want, you + # can use this option as it forces FTL to really bind only the interfaces it is + # listening on. Note that this may result in issues when the interface may go + # down (cable unplugged, etc.). About the only time when this is useful is when + # running another nameserver on the same port on the same machine. This may also + # happen if you run a virtualization API such as libvirt. When this option is + # used, IP alias interface labels (e.g. enp2s0:0) are checked rather than + # interface names. + # - "ALL" + # Permit all origins, accept on all interfaces. Make sure your Pi-hole is + # properly firewalled! This truly allows any traffic to be replied to and is a + # dangerous thing to do as your Pi-hole could become an open resolver. You + # should always ask yourself if the first option doesn't work for you as well. + # - "NONE" + # Do not add any configuration concerning the listening mode to the dnsmasq + # configuration file. This is useful if you want to manually configure the + # listening mode in auxiliary configuration files. This option is really meant + # for advanced users only, support for this option may be limited. + listeningMode = "LOCAL" + + # Log DNS queries and replies to pihole.log + # + # Allowed values are: + # true or false + queryLogging = true + + # List of CNAME records which indicate that is really . If the is + # given, it overwrites the value of local-ttl + # + # Allowed values are: + # Array of CNAMEs, each one in the following form: ",[,]" + cnameRecords = [] + + # Port used by the DNS server + # + # Allowed values are: + # Any available valid (1 - 65535) port number + port = 53 + + # Enable/Disable the localise-queries option of dnsmasq. When this setting is disabled + # dnsmasq will return all possible values for local DNS Records. Enabled by default + # + # Allowed values are: + # true or false + localise = true + + # Reverse server (formerly called "conditional forwarding") + # + # If not configured as your DHCP server, Pi-hole typically won't be able to determine + # the names of devices on your local network. As a result, tables such as Top Clients + # will only show IP addresses. + # + # One solution for this is to configure Pi-hole to forward these requests to your DHCP + # server (most likely your router), but only for devices on your home network. To + # configure this we will need to know the IP address of your DHCP server and which + # addresses belong to your local network. + # + # Example: [ "true,192.168.0.0/24,192.168.0.1,fritz.box" ] + # + # Allowed values are: + # Array of reverse servers each one in the following form: + # + # ",[/],[#][,]" + # + # Explanation of individual components: + # + # - "": either "true" or "false" + # + # - "[/]": Address range for the reverse server feature in + # CIDR notation. If the prefix length is omitted, either 32 (IPv4) or 128 (IPv6) + # are substituted (exact address match). This is almost certainly not what you + # want here. + # Example: "192.168.0.0/24" for the range 192.168.0.1 - 192.168.0.255 + # + # - "[#]": Target server to be used for the reverse server feature + # Example: "192.168.0.1#53" + # + # - "": Domain used for the reverse server feature (e.g., "fritz.box") + # Example: "fritz.box" + revServers = [] + + [dns.domain] + # The DNS domain used by your Pi-hole. + # + # This DNS domain is purely local. FTL may answer queries from its local cache and + # configuration but *never* forwards any requests upstream *unless* you have + # configured a dns.revServer exactly for this domain. In the latter case, all queries + # for this domain are sent exclusively to this server (including reverse lookups). + # + # For DHCP, this has two effects; firstly it causes the DHCP server to return the + # domain to any hosts which request it, and secondly it sets the domain which it is + # legal for DHCP-configured hosts to claim. The intention is to constrain hostnames so + # that an untrusted host on the LAN cannot advertise its name via DHCP as e.g. + # "google.com" and capture traffic not meant for it. If no domain suffix is specified, + # then any DHCP hostname with a domain part (ie with a period) will be disallowed and + # logged. If a domain is specified, then hostnames with a domain part are allowed, + # provided the domain part matches the suffix. In addition, when a suffix is set then + # hostnames without a domain part have the suffix added as an optional domain part. + # For instance, we can set domain=mylab.com and have a machine whose DHCP hostname is + # "laptop". The IP address for that machine is available both as "laptop" and + # "laptop.mylab.com". + # + # You can disable setting a domain by setting this option to an empty string. + # + # Allowed values are: + # Any valid domain + name = "lan" + + # If set, the domain configured by dns.domain.name is considered local and queries for + # this domain are never forwarded upstream unless a dns.revServer is configured for + # this domain. + # + # If unset, queries for this domain are forwarded upstream to (possibly public) server + # which is probably not what you want *unless* you have added extra configuration for + # this domain *or* your upstream servers are able to handle local domains (e.g., + # router). + # + # Allowed values are: + # true or false + local = true + + [dns.cache] + # Cache size of the DNS server. Note that expiring cache entries naturally make room + # for new insertions over time. + # + #Setting this number too high will have an adverse effect as not only more space is + # needed, but also lookup speed gets degraded in the 10,000+ range. dnsmasq may issue + # a warning when you go beyond 10,000+ cache entries. + # + # Allowed values are: + # A positive integer value + size = 10000 + + # Query cache optimizer: If a DNS name exists in the cache, but its time-to-live has + # expired only recently, the data will be used anyway (a refreshing from upstream is + # triggered). This can improve DNS query delays especially over unreliable Internet + # connections. This feature comes at the expense of possibly sometimes returning + # out-of-date data and less efficient cache utilization, since old data cannot be + # flushed when its TTL expires, so the cache becomes mostly least-recently-used. To + # mitigate issues caused by massively outdated DNS replies, the maximum overaging of + # cached records is limited. We strongly recommend staying below 86400 (1 day) with + # this option. + # + # Setting the TTL excess time to zero will serve stale cache data regardless how long + # it has expired. This is not recommended as it may lead to stale data being served + # for a long time. Setting this option to any negative value will disable this feature + # altogether. + # + # Allowed values are: + # A positive integer value in seconds, or any negative to disable this feature + optimizer = 3600 + + # This setting allows you to specify the TTL used for queries blocked upstream. Once + # the TTL expires, the query will be forwarded to the upstream server again to check + # if the block is still valid. Defaults to caching for one day (86400 seconds). + # Setting this value to zero disables caching of queries blocked upstream. + # + # Allowed values are: + # A positive integer value in seconds, or zero to disable caching of upstream + # blocked queries + upstreamBlockedTTL = 86400 + + [dns.blocking] + # Should FTL block queries? + # + # Allowed values are: + # true or false + active = true + + # How should FTL reply to blocked queries? + # + # Allowed values are: + # - "NULL" + # In NULL mode, which is both the default and recommended mode for Pi-hole + # FTLDNS, blocked queries will be answered with the "unspecified address" + # (0.0.0.0 or ::). The "unspecified address" is a reserved IP address specified + # by RFC 3513 - Internet Protocol Version 6 (IPv6) Addressing Architecture, + # section 2.5.2. + # - "IP_NODATA_AAAA" + # In IP-NODATA-AAAA mode, blocked queries will be answered with the local IPv4 + # addresses of your Pi-hole. Blocked AAAA queries will be answered with + # NODATA-IPV6 and clients will only try to reach your Pi-hole over its static + # IPv4 address. + # - "IP" + # In IP mode, blocked queries will be answered with the local IP addresses of + # your Pi-hole. + # - "NX" + # In NXDOMAIN mode, blocked queries will be answered with an empty response + # (i.e., there won't be an answer section) and status NXDOMAIN. A NXDOMAIN + # response should indicate that there is no such domain to the client making the + # query. + # - "NODATA" + # In NODATA mode, blocked queries will be answered with an empty response (no + # answer section) and status NODATA. A NODATA response indicates that the domain + # exists, but there is no record for the requested query type. + mode = "NULL" + + # Should FTL enrich blocked replies with EDNS0 information? + # + # Allowed values are: + # - "NONE" + # In NONE mode, no additional EDNS information is added to blocked queries + # - "CODE" + # In CODE mode, blocked queries will be enriched with EDNS info-code BLOCKED (15) + # - "TEXT" + # In TEXT mode, blocked queries will be enriched with EDNS info-code BLOCKED (15) + # and a text message describing the reason for the block + edns = "TEXT" + + [dns.specialDomains] + # Should Pi-hole always reply with NXDOMAIN to A and AAAA queries of + # use-application-dns.net to disable Firefox automatic DNS-over-HTTP? + # + # This follows the recommendation on + # https://support.mozilla.org/en-US/kb/configuring-networks-disable-dns-over-https + # + # Allowed values are: + # true or false + mozillaCanary = true + + # Should Pi-hole always reply with NXDOMAIN to A and AAAA queries of mask.icloud.com + # and mask-h2.icloud.com to disable Apple's iCloud Private Relay to prevent Apple + # devices from bypassing Pi-hole? + # + # This follows the recommendation on + # https://developer.apple.com/support/prepare-your-network-for-icloud-private-relay + # + # Allowed values are: + # true or false + iCloudPrivateRelay = true + + # Should Pi-hole always reply with NODATA to all queries to zone resolver.arpa to + # prevent devices from bypassing Pi-hole using Discovery of Designated Resolvers? + # + # This is based on recommendations at the end of RFC 9462, section 4. + # + # Allowed values are: + # true or false + designatedResolver = true + + [dns.reply.host] + # Use a specific IPv4 address for the Pi-hole host? By default, FTL determines the + # address of the interface a query arrived on and uses this address for replying to A + # queries with the most suitable address for the requesting client. + # + # This setting can be used to use a fixed, rather than the dynamically obtained, + # address when Pi-hole responds to the following names: + # - "pi.hole" + # - "" + # - "pi.hole." + # - "." + # + # Allowed values are: + # true or false + force4 = false + + # Custom IPv4 address for the Pi-hole host + # + # Allowed values are: + # A valid IPv4 address or empty string ("") + IPv4 = "" + + # Use a specific IPv6 address for the Pi-hole host? See description for the IPv4 + # variant above for further details. + # + # Allowed values are: + # true or false + force6 = false + + # Custom IPv6 address for the Pi-hole host + # + # Allowed values are: + # A valid IPv6 address or empty string ("") + IPv6 = "" + + [dns.reply.blocking] + # Use a specific IPv4 address in IP blocking mode? By default, FTL determines the + # address of the interface a query arrived on and uses this address for replying to A + # queries with the most suitable address for the requesting client. + # + # This setting can be used to use a fixed, rather than the dynamically obtained, + # address when Pi-hole responds in the following cases: + # - IP blocking mode is used and this query is to be blocked + # - regular expressions with the ;reply=IP regex extension. + # + # Allowed values are: + # true or false + force4 = false + + # Custom IPv4 address for IP blocking mode + # + # Allowed values are: + # A valid IPv4 address or empty string ("") + IPv4 = "" + + # Use a specific IPv6 address in IP blocking mode? See description for the IPv4 variant + # above for further details. + # + # Allowed values are: + # true or false + force6 = false + + # Custom IPv6 address for IP blocking mode + # + # Allowed values are: + # A valid IPv6 address or empty string ("") + IPv6 = "" + + [dns.rateLimit] + # Rate-limited queries are answered with a REFUSED reply and not further processed by + # FTL. + # + # The default settings for FTL's rate-limiting are to permit no more than 1000 queries + # in 60 seconds. Both numbers can be customized independently. It is important to note + # that rate-limiting is happening on a per-client basis. Other clients can continue to + # use FTL while rate-limited clients are short-circuited at the same time. + # + # For this setting, both numbers, the maximum number of queries within a given time, + # and the length of the time interval (seconds) have to be specified. For instance, if + # you want to set a rate limit of 1 query per hour, the option should look like + # dns.rateLimit.count=1 and dns.rateLimit.interval=3600. The time interval is relative + # to when FTL has finished starting (start of the daemon + possible delay by + # DELAY_STARTUP) then it will advance in steps of the rate-limiting interval. If a + # client reaches the maximum number of queries it will be blocked until the end of the + # current interval. This will be logged to /var/log/pihole/FTL.log, e.g. Rate-limiting + # 10.0.1.39 for at least 44 seconds. If the client continues to send queries while + # being blocked already and this number of queries during the blocking exceeds the + # limit the client will continue to be blocked until the end of the next interval + # (FTL.log will contain lines like Still rate-limiting 10.0.1.39 as it made additional + # 5007 queries). As soon as the client requests less than the set limit, it will be + # unblocked (Ending rate-limitation of 10.0.1.39). + # + # Rate-limiting may be disabled altogether by setting both values to zero (this + # results in the same behavior as before FTL v5.7). + # + # How many queries are permitted... + # + # Allowed values are: + # A positive integer value + count = 1000 + + # ... in the set interval before rate-limiting? + # + # Allowed values are: + # A positive integer value in seconds + interval = 60 + +[dhcp] + # Is the embedded DHCP server enabled? + # + # Allowed values are: + # true or false + active = true ### CHANGED, default = false + + # Start address of the DHCP address pool + # + # Example: "192.168.0.10" + # + # Allowed values are: + # A valid IPv4 address, or empty string ("") + start = "192.168.1.2" ### CHANGED, default = "" + + # End address of the DHCP address pool + # + # Example: "192.168.0.250" + # + # Allowed values are: + # A valid IPv4 address, or empty string ("") + end = "192.168.1.100" ### CHANGED, default = "" + + # Address of the gateway to be used (typically the address of your router in a home + # installation) + # + # Example: "192.168.0.1" + # + # Allowed values are: + # A valid IPv4 address, or empty string ("") + router = "192.168.1.1" ### CHANGED, default = "" + + # The netmask used by your Pi-hole. For directly connected networks (i.e., networks on + # which the machine running Pi-hole has an interface) the netmask is optional and may + # be set to an empty string (""): it will then be determined from the interface + # configuration itself. + # + # For networks which receive DHCP service via a relay agent, we cannot determine the + # netmask itself, so it should explicitly be specified, otherwise Pi-hole guesses + # based on the class (A, B or C) of the network address. + # + # Example: "255.255.255.0" + # + # Allowed values are: + # Any valid netmask, or an empty string ("") for auto-discovery + netmask = "255.255.0.0" ### CHANGED, default = "" + + # If the lease time is given, then leases will be given for that length of time. If not + # given, the default lease time is one hour for IPv4 and one day for IPv6. + # + # Allowed values are: + # The lease time can be in seconds, or minutes (e.g., "45m") or hours (e.g., "1h") + # or days (like "2d") or even weeks ("1w"). You may also use "infinite" as string + # but be aware of the drawbacks + leaseTime = "" + + # Should Pi-hole make an attempt to also satisfy IPv6 address requests (be aware that + # IPv6 works a whole lot different than IPv4) + # + # Allowed values are: + # true or false + ipv6 = false + + # Enable DHCPv4 Rapid Commit Option specified in RFC 4039. Should only be enabled if + # either the server is the only server for the subnet to avoid conflicts + # + # Allowed values are: + # true or false + rapidCommit = false + + # Advertise DNS server multiple times to clients. Some devices will add their own + # proprietary DNS servers to the list of DNS servers, which can cause issues with + # Pi-hole. This option will advertise the Pi-hole DNS server multiple times to + # clients, which should prevent this from happening. + # + # Allowed values are: + # true or false + multiDNS = false + + # Enable logging for DHCP. This will log all relevant DHCP-related activity, including, + # e.g., all the options sent to DHCP clients and the tags used to determine them (if + # any). This can be useful for debugging DHCP issues. The generated output is saved to + # the file specified by files.log.dnsmasq below. + # + # Allowed values are: + # true or false + logging = false + + # Ignore unknown DHCP clients. + # If this option is set, Pi-hole ignores all clients which are not explicitly + # configured through dhcp.hosts. This can be useful to prevent unauthorized clients + # from getting an IP address from the DHCP server. + # + # It should be noted that this option is not a security feature, as clients can still + # assign themselves an IP address and use the network. It is merely a convenience + # feature to prevent unknown clients from getting a valid IP configuration assigned + # automatically. + # + # Note that you will need to configure new clients manually in dhcp.hosts before they + # can use the network when this feature is enabled. + # + # Allowed values are: + # true or false + ignoreUnknownClients = false + + # Per host parameters for the DHCP server. This allows a machine with a particular + # hardware address to be always allocated the same hostname, IP address and lease time + # or to specify static DHCP leases + # + # Example: [ "00:20:e0:3b:13:af,192.168.0.123,laptop,24h", + # "00:20:e0:ab:cd:ef,192.168.0.124,desktop,24h"] + # + # Allowed values are: + # Array of static leases each one in the following form: + # "[][,id:|*][,set:][,tag:][,][,][,][,ignore]" + hosts = [] + + [ntp.ipv4] + # Should FTL act as network time protocol (NTP) server (IPv4)? + # + # Allowed values are: + # true or false + active = true + + # IPv4 address to listen on for NTP requests + # + # Allowed values are: + # A valid IPv4 address, or empty string (""). For wildcard (0.0.0.0) + address = "" + + [ntp.ipv6] + # Should FTL act as network time protocol (NTP) server (IPv6)? + # + # Allowed values are: + # true or false + active = true + + # IPv6 address to listen on for NTP requests + # + # Allowed values are: + # A valid IPv6 address, or empty string (""). For wildcard (::) + address = "" + + [ntp.sync] + # Should FTL try to synchronize the system time with an upstream NTP server? + # + # Allowed values are: + # true or false + active = true + + # NTP upstream server to sync with, e.g., "pool.ntp.org". Note that the NTP server + # should be located as close as possible to you in order to minimize the time offset + # possibly introduced by different routing paths. + # + # Allowed values are: + # A valid NTP upstream server + server = "pool.ntp.org" + + # Interval in seconds between successive synchronization attempts with the NTP server + # + # Allowed values are: + # A positive integer value in seconds + interval = 3600 + + # Number of NTP syncs to perform and average before updating the system time + # + # Allowed values are: + # A positive integer value + count = 8 + + [ntp.sync.rtc] + # Should FTL update a real-time clock (RTC) if available? + # + # Allowed values are: + # true or false + set = false + + # Path to the RTC device to update. + # + # Example: "/dev/rtc0" + # + # Allowed values are: + # A valid RTC device path, or empty string ("") for auto-discovery + device = "" + + # Should the RTC be set to UTC? + # + # Allowed values are: + # true or false + utc = true + +[resolver] + # Should FTL try to resolve IPv4 addresses to hostnames? + # + # Allowed values are: + # true or false + resolveIPv4 = true + + # Should FTL try to resolve IPv6 addresses to hostnames? + # + # Allowed values are: + # true or false + resolveIPv6 = true + + # Control whether FTL should use the fallback option to try to obtain client names from + # checking the network table. This behavior can be disabled with this option. + # + # Assume an IPv6 client without a host names. However, the network table knows - + # though the client's MAC address - that this is the same device where we have a host + # name for another IP address (e.g., a DHCP server managed IPv4 address). In this + # case, we use the host name associated to the other address as this is the same + # device. + # + # Allowed values are: + # true or false + networkNames = true + + # With this option, you can change how (and if) hourly PTR requests are made to check + # for changes in client and upstream server hostnames. + # + # Allowed values are: + # - "IPV4_ONLY" + # Do hourly PTR lookups only for IPv4 addresses. This is the new default since + # Pi-hole FTL v5.3.2. It should resolve issues with more and more very + # short-lived PE IPv6 addresses coming up in a lot of networks. + # - "ALL" + # Do hourly PTR lookups for all addresses. This was the default until FTL + # v5.3(.1). It has been replaced as it can create a lot of PTR queries for those + # with many IPv6 addresses in their networks. + # - "UNKNOWN" + # Only resolve unknown hostnames. Already existing hostnames are never refreshed, + # i.e., there will be no PTR queries made for clients where hostnames are known. + # This also means that known hostnames will not be updated once known. + # - "NONE" + # Don't do any hourly PTR lookups. This means we look host names up exactly once + # (when we first see a client) and never again. You may miss future changes of + # host names. + refreshNames = "IPV4_ONLY" + +[database] + # Should FTL load information from the database on startup to be aware of the most + # recent history? + # + # Allowed values are: + # true or false + DBimport = true + + # How long should queries be stored in the database [days]? + # + # Allowed values are: + # A positive integer value in days, or 0 to disable the database + maxDBdays = 91 + + # How often do we store queries in FTL's database [seconds]? + # + # Allowed values are: + # A positive integer value in seconds + DBinterval = 60 + + # Should FTL enable Write-Ahead Log (WAL) mode for the on-disk query database + # (configured via files.database)? + # + # It is recommended to leave this setting enabled for performance reasons. About the + # only reason to disable WAL mode is if you are experiencing specific issues with it, + # e.g., when using a database that is accessed from multiple hosts via a network + # share. When this setting is disabled, FTL will use SQLite3's default journal mode + # (rollback journal in DELETE mode). + # + # Allowed values are: + # true or false + useWAL = true + + [database.network] + # Should FTL analyze the local ARP cache? When disabled, client identification and the + # network table will stop working reliably. + # + # Allowed values are: + # true or false + parseARPcache = true + + # How long should IP addresses be kept in the network_addresses table [days]? IP + # addresses (and associated host names) older than the specified number of days are + # removed to avoid dead entries in the network overview table. + # + # Allowed values are: + # A positive integer value in days + expire = 91 + +[webserver] + # On which domain is the web interface served? + # + # Allowed values are: + # A valid domain + domain = "pi.hole" + + # Webserver access control list (ACL) allowing for restrictions to be put on the list + # of IP addresses which have access to the web server. The ACL is a comma separated + # list of IP subnets, where each subnet is prepended by either a - or a + sign. A plus + # sign means allow, where a minus sign means deny. + # + # If a subnet mask is omitted, such as -1.2.3.4, this means to deny only that single + # IP address. If this value is not set (empty string), all accesses are allowed. + # Otherwise, the default setting is to deny all accesses. On each request the full + # list is traversed, and the last (!) match wins. IPv6 addresses may be specified in + # CIDR-form [a:b::c]/64. + # + # Example 1: "+127.0.0.1,+[::1]" ---> deny all access, except from 127.0.0.1 and ::1 + # + # Example 2: "+192.168.0.0/16" ---> deny all accesses, except from the 192.168.0.0/16 + # subnet + # + # Example 3: "+[::]/0" ---> allow only IPv6 access. + # + # Allowed values are: + # A valid ACL + acl = "" + + # Ports to be used by the webserver. + # + # Comma-separated list of ports to listen on. It is possible to specify an IP address + # to bind to. In this case, an IP address and a colon must be prepended to the port + # number. For example, to bind to the loopback interface on port 80 (IPv4) and to all + # interfaces port 8080 (IPv4), use "127.0.0.1:80,8080". "[::]:80" can be used to + # listen to IPv6 connections to port 80. IPv6 addresses of network interfaces can be + # specified as well, e.g. "[::1]:80" for the IPv6 loopback interface. "[::]:80" will + # bind to port 80 IPv6 only. + # + # In order to use port 80 for all interfaces, both IPv4 and IPv6, use either the + # configuration "80,[::]:80" (create one socket for IPv4 and one for IPv6 only), or + # "+80" (create one socket for both, IPv4 and IPv6). The '+' notation to use IPv4 and + # IPv6 will only work if no network interface is specified. Depending on your + # operating system version and IPv6 network environment, some configurations might not + # work as expected, so you have to test to find the configuration most suitable for + # your needs. In case "+80" does not work for your environment, you need to use + # "80,[::]:80". + # + # If the port is TLS/SSL, a letter 's' (secure) must be appended, for example, + # "80,443s" will open port 80 and port 443, and connections on port 443 will be + # encrypted. For non-encrypted ports, it is allowed to append letter 'r' (as in + # redirect). Redirected ports will redirect all their traffic to the first configured + # SSL port. For example, if webserver.port is "80r,443s", then all HTTP traffic coming + # at port 80 will be redirected to HTTPS port 443. + # + # When specifying 'o' (optional) behind a port, inability to use this port is not + # considered an error. For instance, specifying "80o,8080o" will allow the webserver + # to listen on either 80, 8080, both or even none of the two ports. This flag may be + # combined with 'r' and 's' like "80or,443os,8080,4443s" (80 redirecting to SSL if + # available, 443 encrypted if available, 8080 mandatory and unencrypted, 4443 + # mandatory and encrypted). + # + # If this value is not set (empty string), the web server will not be started and, + # hence, the API will not be available. + # + # Allowed values are: + # A comma-separated list of <[ip_address:]port> + port = "80o,443os,[::]:80o,[::]:443os" + + # Maximum number of worker threads allowed. + # + # The Pi-hole web server handles each incoming connection in a separate thread. + # Therefore, the value of this option is effectively the number of concurrent HTTP + # connections that can be handled. Any other connections are queued until they can be + # processed by a unoccupied thread. + # + # The total number of threads you see may be lower than the configured value as + # threads are only created when needed due to incoming connections. + # + # The value 0 means the number of threads is 50 (as per default settings of CivetWeb) + # for backwards-compatible behavior. + # + # Allowed values are: + # A positive integer value, or 0 for default (50) + threads = 50 + + # Additional HTTP headers added to the web server responses. + # + # The headers are added to all responses, including those for the API. + # Note about the default additional headers: + # - X-DNS-Prefetch-Control: off: Usually browsers proactively perform domain name + # resolution on links that the user may choose to follow. We disable DNS prefetching + # here. + # - Content-Security-Policy: [...] 'unsafe-inline' is both required by Chart.js + # styling some elements directly, and index.html containing some inlined Javascript + # code. + # - X-Frame-Options: DENY: The page can not be displayed in a frame, regardless of the + # site attempting to do so. + # - X-Xss-Protection: 0: Disables XSS filtering in browsers that support it. This + # header is usually enabled by default in browsers, and is not recommended as it can + # hurt the security of the site. + # (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection). + # - X-Content-Type-Options: nosniff: Marker used by the server to indicate that the + # MIME types advertised in the Content-Type headers should not be changed and be + # followed. This allows to opt-out of MIME type sniffing, or, in other words, it is a + # way to say that the webmasters knew what they were doing. Site security testers + # usually expect this header to be set. + # - Referrer-Policy: strict-origin-when-cross-origin: A referrer will be sent for + # same-site origins, but cross-origin requests will send no referrer information. + # The latter four headers are set as expected by https://securityheaders.io + # + # Allowed values are: + # An array of HTTP headers + headers = [ + "X-DNS-Prefetch-Control: off", + "Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;", + "X-Frame-Options: DENY", + "X-XSS-Protection: 0", + "X-Content-Type-Options: nosniff", + "Referrer-Policy: strict-origin-when-cross-origin" + ] + + # Should the web server serve all files in webserver.paths.webroot directory? + # + # If disabled, only files within the path defined through webserver.paths.webhome and + # /api will be served. + # + # Allowed values are: + # true or false + serve_all = false + + # Additional options passed directly to the web server. + # + # This can be used to set any option supported by the underlying web server + # (CivetWeb). See the CivetWeb documentation for a list of supported options. The + # options are passed as an array of strings, where each string is an option in the + # form "