diff --git a/hosts b/hosts index 82b5537..3769153 100644 --- a/hosts +++ b/hosts @@ -44,7 +44,7 @@ [servers] 192.168.0.28 -192.168.0.99 +##192.168.0.99 [all:vars] ansible_python_interpreter=/usr/bin/python3 diff --git a/playbooks/nginx/error_page.j2 b/playbooks/nginx/error_page.j2 new file mode 100644 index 0000000..7421a52 --- /dev/null +++ b/playbooks/nginx/error_page.j2 @@ -0,0 +1,57 @@ + +
+
+
|
+ ||||||||||||||||||||
Most of the time, a 502 error occurs because the server is too busy or because there's maintenance being performed on it.
Please check back in a few minutes.
" } + - { type: "503", title: "Error 503: Service unavailable", message: "Most of the time, a 503 error occurs because there's maintenance being performed.
Please check back in a few minutes.
" } + - { type: "401", title: "Error 401: Unauthorized", message: "You are not allowed to access this page.
Please log in to access this page.
" } + - { type: "403", title: "Error 403: Forbidden", message: "You don't have permission to access this page or directory on this server
" } + - { type: "404", title: "Error 404: File not found", message: "The requested URL was not found on this server. Maybe it was a valid URL once, but the file/directory has been removed.
Please double-check the URL and try again.
" } diff --git a/playbooks/nginx/extra b/playbooks/nginx/extra new file mode 100644 index 0000000..0c104e9 --- /dev/null +++ b/playbooks/nginx/extra @@ -0,0 +1,11 @@ + add_header Content-Security-Policy "default-src 'none'; font-src 'self'; script-src 'self' 'sha256-2XPtiIriLCRC9BnusBjoTHsfh5zn7F+h7Cr17XwSN50='; img-src * data:; object-src 'none'; style-src 'self' 'sha256-PEo9RAB0C7Pw0EzsgS+HuVOHFPZRr93dZNJ9mYzz95A=' 'sha256-lrhGtO62QsLjBNsk1WGpvRZbHmXYMG/CmjhMFhLDJpg=' 'sha256-4SHcbKIX1Fx5rhlottWqqHggM5MSJz+xg9uwwq8UK74=' 'sha256-bQfd5MwpJ1ZxnVh373acxlqXQ8VwM88QhEHNuQ0ppNg=' 'sha256-yIJ6JcbosmUis6IDdnDV7NU2qPkU/1KUJHRwj44Q32o='; frame-src 'self'; connect-src 'self'; form-action 'self'; base-uri 'self';frame-ancestors 'self'; report-uri https://searx.report-uri.com/r/d/csp/enforce;"; + add_header X-Content-Security-Policy "default-src 'none'; font-src 'self'; script-src 'self' 'sha256-2XPtiIriLCRC9BnusBjoTHsfh5zn7F+h7Cr17XwSN50='; img-src * data:; object-src 'none'; style-src 'self' 'sha256-PEo9RAB0C7Pw0EzsgS+HuVOHFPZRr93dZNJ9mYzz95A=' 'sha256-lrhGtO62QsLjBNsk1WGpvRZbHmXYMG/CmjhMFhLDJpg=' 'sha256-4SHcbKIX1Fx5rhlottWqqHggM5MSJz+xg9uwwq8UK74=' 'sha256-bQfd5MwpJ1ZxnVh373acxlqXQ8VwM88QhEHNuQ0ppNg=' 'sha256-yIJ6JcbosmUis6IDdnDV7NU2qPkU/1KUJHRwj44Q32o='; frame-src 'self'; connect-src 'self'; form-action 'self'; base-uri 'self';frame-ancestors 'self'; report-uri https://https://searx.report-uri.com/r/d/csp/enforce;"; + add_header X-WebKit-CSP "default-src 'none'; font-src 'self'; script-src 'self' 'sha256-2XPtiIriLCRC9BnusBjoTHsfh5zn7F+h7Cr17XwSN50='; img-src * data:; object-src 'none'; style-src 'self' 'sha256-PEo9RAB0C7Pw0EzsgS+HuVOHFPZRr93dZNJ9mYzz95A=' 'sha256-lrhGtO62QsLjBNsk1WGpvRZbHmXYMG/CmjhMFhLDJpg=' 'sha256-4SHcbKIX1Fx5rhlottWqqHggM5MSJz+xg9uwwq8UK74=' 'sha256-bQfd5MwpJ1ZxnVh373acxlqXQ8VwM88QhEHNuQ0ppNg=' 'sha256-yIJ6JcbosmUis6IDdnDV7NU2qPkU/1KUJHRwj44Q32o='; frame-src 'self'; connect-src 'self'; base-uri 'self'; form-action 'self';frame-ancestors 'self'; report-uri https://searx.report-uri.com/r/d/csp/enforce;"; + + add_header Expect-CT "max-age=0; report-uri=https://searx.report-uri.com/r/d/ct/reportOnly;"; + add_header Expect-Staple "max-age=0; report-uri=https://searx.report-uri.com/r/d/staple/reportOnly"; + } + + location /stats { + rewrite / https://stats.searx.xyz; + } diff --git a/playbooks/nginx/hosts b/playbooks/nginx/hosts new file mode 100644 index 0000000..c4ccfd8 --- /dev/null +++ b/playbooks/nginx/hosts @@ -0,0 +1,2 @@ +[nginx_hosts] +62.75.247.110 diff --git a/playbooks/nginx/main.yml b/playbooks/nginx/main.yml new file mode 100644 index 0000000..527354b --- /dev/null +++ b/playbooks/nginx/main.yml @@ -0,0 +1,81 @@ +- hosts: scn.21x9.org + + tasks: + + - include_vars: vhosts.yml + - include_vars: error_pages.yml + + - name: "Install nginx" + apt: name=nginx state=present + notify: + - "Restart nginx" + + - name: "Generate global config" + template: + src: ./nginx.j2 + dest: /etc/nginx/nginx.conf + owner: root + group: root + mode: 0644 + notify: + - "Restart nginx" + + - name: "Generate default config" + template: + src: ./default.j2 + dest: /etc/nginx/sites-available/default.conf + owner: root + group: root + mode: 0644 + notify: + - "Restart nginx" + + - name: "Generate vhosts config" + template: + src: ./vhosts.j2 + dest: /etc/nginx/sites-available/{{ item['name'] }}.conf + owner: root + group: root + mode: 0644 + notify: + - "Restart nginx" + with_items: + - "{{ nginx_vhosts }}" + + - name: "Create symlinks" + file: + src: /etc/nginx/sites-available/{{ item['name'] }}.conf + dest: /etc/nginx/sites-enabled/{{ item['name'] }}.conf + state: link + with_items: + - {name: 'default'} + - "{{ nginx_vhosts }}" + register: managed_files + + - set_fact: + nginx_confs: "{{ managed_files.results|selectattr('dest', 'string')|map(attribute='dest')|list + managed_files.results|selectattr('path', 'string')|map(attribute='path')|select|list }}" + + - shell: ls -d -1 /etc/nginx/sites-enabled/* + register: contents + + - name: "Remove unmanaged symlinks" + file: path={{ item }} state=absent + with_items: "{{ contents.stdout_lines }}" + when: nginx_confs and item not in nginx_confs + notify: + - "Restart nginx" + + - name: "Generate error pages" + template: + src: ./error_page.j2 + dest: /var/www/html/{{ item['type'] }}.html + owner: root + group: root + mode: 0644 + with_items: + - "{{ error_pages }}" + + handlers: + + - name: "Restart nginx" + shell: /usr/sbin/nginx -t && /etc/init.d/nginx reload diff --git a/playbooks/nginx/roles/nginx/tasks/main.yml b/playbooks/nginx/roles/nginx/tasks/main.yml new file mode 100644 index 0000000..df98f82 --- /dev/null +++ b/playbooks/nginx/roles/nginx/tasks/main.yml @@ -0,0 +1,4 @@ +--- + +- name: install nginx + apt: name=nginx state=latest diff --git a/playbooks/nginx/roles/update/tasks/main.yml b/playbooks/nginx/roles/update/tasks/main.yml new file mode 100644 index 0000000..a944e9c --- /dev/null +++ b/playbooks/nginx/roles/update/tasks/main.yml @@ -0,0 +1,4 @@ +--- + +- name: apt update the server + apt: update_cache=yes diff --git a/playbooks/nginx/vhosts.j2 b/playbooks/nginx/vhosts.j2 new file mode 100644 index 0000000..2d1223a --- /dev/null +++ b/playbooks/nginx/vhosts.j2 @@ -0,0 +1,188 @@ +############################################################################### +### {{ item['name'] }} +############################################################################### + +server { +{% if 'ip' in item %} + listen {{ item['ip']}}:80; +{% else %} + listen 80; + listen [::]:80; +{% endif %} +{% if item['alias'] != "none" %} + server_name {{ item['name'] }} + {{ item['alias'] }}; +{% else %} + server_name {{ item['name'] }}; +{% endif %} + +{% if 'root' in item %} + root {{ item['root'] }}; +{% else %} + root /var/www/html; +{% endif %} + + # For letsencrypt.sh + location /.well-known/acme-challenge/ { + root /var/www/html/; + try_files $uri $uri/ =404; + } + + # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response. + return 301 https://{{ item['name'] }}$request_uri; + + access_log off; + error_log syslog,tag=nginx,severity=error,facility=local7; +} + +server { +{% if 'ip' in item %} + listen {{ item['ip']}}:443 ssl{% if 'spdy' in item %} http2{% endif %}; +{% else %} + listen 443 ssl{% if 'spdy' in item %} http2{% endif %}; + listen [::]:443 ssl{% if 'spdy' in item %} http2{% endif %}; +{% endif %} + +{% if item['alias'] != "none" %} + server_name {{ item['name'] }} + {{ item['alias'] }}; +{% else %} + server_name {{ item['name'] }}; +{% endif %} + + gzip off; + +{% if 'ssl' in item %} + ssl_certificate /etc/letsencrypt.sh/certs/{{ item['ssl'] }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt.sh/certs/{{ item['ssl'] }}/privkey.pem; + #ssl_trusted_certificate /etc/letsencrypt.sh/certs/{{ item['ssl'] }}/fullchain.pem; +{% else %} + ssl_certificate /etc/letsencrypt.sh/certs/{{ item['name'] }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt.sh/certs/{{ item['name'] }}/privkey.pem; + #ssl_trusted_certificate /etc/letsencrypt.sh/certs/{{ item['name'] }}/fullchain.pem; +{% endif %} + ssl_stapling on; + ssl_stapling_verify on; + ssl_dhparam /etc/nginx/dhparam.pem; + + ssl_session_cache shared:SSL:50m; + ssl_session_timeout 10m; + ssl_session_tickets off; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers 'AES256+EECDH:AES256+EDH:!aNULL'; + ssl_ecdh_curve secp384r1; + + resolver 8.8.8.8 8.8.4.4 valid=300s; + resolver_timeout 5s; + + server_tokens off; + + access_log /var/log/nginx/{{ item['name'] }}.log extended; + error_log /var/log/nginx/{{ item['name'] }}.log; + +{% if 'root' in item %} + root {{ item['root'] }}; +{% else %} + root /var/www/html; +{% endif %} + + # For letsencrypt.sh + location /.well-known/acme-challenge/ { + root /var/www/html/; + try_files $uri $uri/ =404; + } + + location ~ /\.ht { + deny all; + } + +{% for error in error_pages %} +{% if error['type'] == '401' %} + error_page {{ error['type'] }} /{{ error['type'] }}.html; +{% else %} + error_page {{ error['type'] }} /{{ error['type'] }}.html; +{% endif %} +{% endfor %} + +{% for error in error_pages %} + location /{{ error['type'] }}.html { + root /var/www/html; + internal; + break; + } +{% endfor %} + + location / { +{% if 'maintenance' in item %} + set $maintenance true; +{% else %} + set $maintenance false; +{% endif %} + + if (-f $document_root/maintenance.html) { + set $maintenance true; + } + if ($maintenance = true) { + rewrite / /503.html; + } + +{% if 'port' in item %} + proxy_pass http://localhost:{{ item['port'] }}/; + + proxy_redirect off; + proxy_intercept_errors on; + proxy_read_timeout 86400; + proxy_ignore_client_abort on; + proxy_connect_timeout 120s; + + proxy_buffer_size 128k; + proxy_buffers 4 256k; + proxy_busy_buffers_size 256k; + + proxy_headers_hash_max_size 512; + proxy_buffering on; + proxy_cache_bypass $http_pragma $http_authorization $cookie_nocache; + + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Scheme $scheme; + + proxy_hide_header Strict-Transport-Security; + proxy_hide_header Public-Key-Pins; + proxy_hide_header Content-Security-Policy; + proxy_hide_header X-Content-Security-Policy; + proxy_hide_header X-WebKit-CSP; + proxy_hide_header X-Content-Type-Options; + proxy_hide_header X-XSS-Protection; + proxy_hide_header X-Frame-Options; + proxy_hide_header Alternate-Protocol; + proxy_hide_header X-Powered-By; + + add_header Front-End-Https on; +{% endif %} + +{% if 'hsts' in item %} + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; +{% endif %} +{% if 'hpkp' in item %} + add_header Public-Key-Pins "pin-sha256=\"YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=\"; pin-sha256=\"sRHdihwgkaib1P1gxX8HFszlD+7/gTfNvuAybgLPNis=\"; pin-sha256=\"dd9ClLS4xSTx8j2dH5/hjS6dPXTkzpzDcKeEX+3J74E=\"; pin-sha256=\"NO6gHdYxKGz47EYVvoXpJhxY3RXfoM1O56gPrOGmrg8=\"; max-age=7776000; includeSubDomains;"; +{% endif %} +{% if 'security' in item %} + add_header X-Frame-Options "sameorigin"; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Content-Type-Options "nosniff"; +{% endif %} +{% if 'noref' in item %} + add_header Referrer-Policy "no-referrer, strict-origin-when-cross-origin"; +{% endif %} + +{% if 'extra' in item %} +{% include item['extra'] %} +{% else %} + } +{% endif %} +} diff --git a/playbooks/nginx/vhosts.yml b/playbooks/nginx/vhosts.yml new file mode 100644 index 0000000..bb871ed --- /dev/null +++ b/playbooks/nginx/vhosts.yml @@ -0,0 +1,6 @@ +nginx_vhosts: + - { name: "21x9.org", alias: "www.21x9.org", port: "8000", extra: 'wordpress.j2', hsts: "on", hpkp: "on", security: "on", noref: "on", spdy: "on" } + - { name: "legacy.21x9.org", alias: "www.legacy.21x9.org", port: "8002", extra: 'legacy.j2', hsts: "off", hpkp: "off", security: "off", noref: "off", ip: "1.2.3.4" } + - { name: "searx.xyz", alias: "www.searx.xyz ipv4.searx.xyz ipv6.searx.xyz", port: "8888", extra: 'searx.j2', hsts: "on", hpkp: "on", security: "on", noref: "on", spdy: "on" } + - { name: "stats.searx.xyz", alias: "none", hsts: "on", hpkp: "on", security: "on", noref: "on", spdy: "on", root: "/var/www/html/stats/" } + - { name: "pukiyama-kakuzo.com", alias: "www.pukiyama-kakuzo.com", hsts: "on", hpkp: "on", security: "on", noref: "on", spdy: "on", root: "/var/www/html/pukiyama-kakuzo/" } diff --git a/roles/zfuller.pihole/README.md b/roles/zfuller.pihole/README.md new file mode 100644 index 0000000..0312d7e --- /dev/null +++ b/roles/zfuller.pihole/README.md @@ -0,0 +1,69 @@ +# pihole raspberry pi ansible role + +Role installs and configures Pihole https://pi-hole.net/ with unattentded setup + +Documents relating to pi-hole are at https://docs.pi-hole.net/ + +## Requirements +User with sudo access to the machine. + +other [prerequisites](https://docs.pi-hole.net/main/prerequisites/) + +### Required Variables +#### pihole_setupvars_webpassword +You will need to generate a admin password for the `pihole_setupvars_webpassword` variable, password is hashed with sha256 twice. You can genearte a password with the following shell command. + +With the password in a file (recommended). +```shell +echo -n $(cat ~/piholepass.word) | sha256sum | awk '{printf "%s", $1}' | sha256sum +``` + +With the password in shell command (not recommended) +```shell +echo -n notsosecretpassword | sha256sum | awk '{printf "%s", $1}' | sha256sum +``` + +recommended to store this variable in ansible vault. + +#### pihole_setupvars_ipv4_address +IPv4 adress of the pihole + +#### pihole_setupvars_pihole_dns_1/2 +DNS servers you want the pihole to use + +##### DNS +Alternative DNS Providers +```yaml +Google: https://developers.google.com/speed/public-dns + - 8.8.8.8 + - 8.8.4.4 + +OpenDNS: https://use.opendns.com/ + - 208.67.222.222 + - 208.67.220.220 + +Cloudflare: https://1.1.1.1/dns/ + - 1.1.1.1 + - 1.0.0.1 +``` + +## Role Variables +[defaults/main.yml](defaults/main.yml) for default values + +## Example Playbook +```yaml +--- +- name: pihole + hosts: pi + strategy: free + become_method: sudo + become: yes + gather_facts: yes + vars: + pihole_setupvars_ipv4_address: 192.168.1.100 + pihole_setupvars_webpassword: 35030714f1136486a612d7014b739a6c7ef3be589bb14b14a3d01f521dd7ef18 + pihole_setupvars_pihole_dns_1: 1.1.1.1 + pihole_setupvars_pihole_dns_2: 1.0.0.1 + roles: + - zfuller.pihole +``` diff --git a/roles/zfuller.pihole/defaults/main.yml b/roles/zfuller.pihole/defaults/main.yml new file mode 100644 index 0000000..62a9a35 --- /dev/null +++ b/roles/zfuller.pihole/defaults/main.yml @@ -0,0 +1,37 @@ +--- +# task variables +pihole_repo: https://github.com/pi-hole/pi-hole.git +pihole_repo_depth: 1 +pihole_user: pihole +pihole_group: pihole +pihole_directory: "/home/{{ pihole_user }}/pihole" +pihole_branch: "master" +pihole_etc_dir: /etc/pihole/ +pihole_bin_path: /usr/local/bin/pihole +pihole_update: true +pihole_reinstall: false + +## setupVars.conf +pihole_setupvars_pihole_interface: "eth0" +pihole_setupvars_ipv4_address: +pihole_setupvars_ipv6_address: +pihole_setupvars_query_logging: "true" +pihole_setupvars_install_web_server: "true" +pihole_setupvars_install_web_interface: "true" +pihole_setupvars_lighttpd_enabled: "true" +pihole_setupvars_webpassword: +pihole_setupvars_blocking_enabled: "true" +pihole_setupvars_pihole_dns_1: 8.8.8.8 +pihole_setupvars_pihole_dns_2: +pihole_setupvars_dns_fqdn_required: "true" +pihole_setupvars_dns_bogus_priv: "true" +pihole_setupvars_dnssec: "true" +pihole_setupvars_conditional_forwarding: "false" +pihole_setupvars_conditional_forwarding_ip: +pihole_setupvars_conditional_forwarding_domain: +pihole_setupvars_conditional_forwarding_reverse: +pihole_setupvars_dnsmasq_listening: "single" +pihole_setupvars_admin_email: +pihole_setupvars_weblayout: "boxed" +pihole_setupvars_webtheme: "default-dark" +pihole_setupvars_rev_server: "false" diff --git a/roles/zfuller.pihole/meta/.galaxy_install_info b/roles/zfuller.pihole/meta/.galaxy_install_info new file mode 100644 index 0000000..0c268dc --- /dev/null +++ b/roles/zfuller.pihole/meta/.galaxy_install_info @@ -0,0 +1 @@ +{install_date: 'Fri Nov 27 08:26:14 2020', version: master} diff --git a/roles/zfuller.pihole/meta/main.yml b/roles/zfuller.pihole/meta/main.yml new file mode 100644 index 0000000..d429eb9 --- /dev/null +++ b/roles/zfuller.pihole/meta/main.yml @@ -0,0 +1,28 @@ +--- +galaxy_info: + author: zfuller + description: Simple role to install and configure pihole + issue_tracker_url: https://github.com/zfuller/pihole/issues + license: GPLv2 + min_ansible_version: 2.4 + platforms: + - name: Fedora + versions: + - 31 + - 32 + - name: CentOS + versions: + - 7 + - 8 + - name: Debian + versions: + - buster + - stretch + - name: Ubuntu + versions: + - xenial + - bionic + - focal + galaxy_tags: + - pihole + - raspberrypi diff --git a/roles/zfuller.pihole/tasks/main.yml b/roles/zfuller.pihole/tasks/main.yml new file mode 100644 index 0000000..5db67cd --- /dev/null +++ b/roles/zfuller.pihole/tasks/main.yml @@ -0,0 +1,99 @@ +--- +- name: ensure git + package: + name: git + state: present + +- name: check for existing installation of pihole + stat: + path: "{{ pihole_bin_path }}" + register: pihole_bin + +- name: install pihole + block: + - name: ensure pihole group exists for pi user + group: + name: "{{ pihole_group }}" + state: present + + - name: create pihole user + user: + name: "{{ pihole_user }}" + comment: pihole + groups: "{{ pihole_group }}" + + - name: Ensure pihole destination exists + stat: + path: "{{ pihole_directory }}" + register: pihole_dir + + - name: making pihole git directory + file: + path: "{{ pihole_directory }}" + state: directory + mode: 0755 + owner: "{{ pihole_user }}" + group: "{{ pihole_group }}" + when: + - pihole_dir.stat.isdir is not defined + + - name: cloning pihole + git: + repo: "{{ pihole_repo }}" + dest: "{{ pihole_directory }}" + depth: "{{ pihole_repo_depth }}" + version: "{{ pihole_branch }}" + become_user: "{{ pihole_user }}" + become: true + + - name: check if pihole etc dir exists + stat: + path: "{{ pihole_etc_dir }}" + register: pi_etc_dir + + - name: making pihole etc directory + file: + path: "{{ pihole_etc_dir }}" + state: directory + mode: 0755 + when: + - not pi_etc_dir.stat.exists + + - name: pushing config file setupVars + template: + src: templates/setupVars.conf.j2 + dest: "{{ pihole_etc_dir }}/setupVars.conf" + mode: 0644 + + - name: installing pihole # noqa 305 + shell: + chdir: "{{ pihole_directory }}/automated install/" + cmd: "bash basic-install.sh --unattended" + + when: + - not pihole_bin.stat.exists or pihole_reinstall + +- name: "check and apply updates to pihole" + command: "{{ pihole_bin_path }} updatePihole" + register: updatePihole + when: + - pihole_bin.stat.exists + - pihole_update|bool + - not pihole_reinstall + +- name: Output from update + debug: + var: updatePihole.stdout_lines + when: updatePihole.changed == true + +- name: Finished! ipv4 + debug: + msg: "visit http://{{ pihole_setupvars_ipv4_address }}/admin/ to start managing your pi-hole" + when: + - pihole_setupvars_ipv4_address and pihole_setupvars_ipv4_address|length > 0 + +- name: Finished! ipv6 + debug: + msg: "visit http://{{ pihole_setupvars_ipv6_address }}/admin/ to start managing your pi-hole" + when: + - pihole_setupvars_ipv6_address and pihole_setupvars_ipv6_address|length > 0 diff --git a/roles/zfuller.pihole/templates/setupVars.conf.j2 b/roles/zfuller.pihole/templates/setupVars.conf.j2 new file mode 100644 index 0000000..1f28089 --- /dev/null +++ b/roles/zfuller.pihole/templates/setupVars.conf.j2 @@ -0,0 +1,23 @@ +WEBPASSWORD={{ pihole_setupvars_webpassword }} +DNS_FQDN_REQUIRED={{ pihole_setupvars_dns_fqdn_required }} +DNS_BOGUS_PRIV={{ pihole_setupvars_dns_bogus_priv }} +DNSSEC={{ pihole_setupvars_dnssec }} +CONDITIONAL_FORWARDING={{ pihole_setupvars_conditional_forwarding }} +DNSMASQ_LISTENING={{ pihole_setupvars_dnsmasq_listening }} +CONDITIONAL_FORWARDING_IP={{ pihole_setupvars_conditional_forwarding_ip }} +CONDITIONAL_FORWARDING_DOMAIN={{ pihole_setupvars_conditional_forwarding_domain }} +CONDITIONAL_FORWARDING_REVERSE={{ pihole_setupvars_conditional_forwarding_reverse }} +PIHOLE_INTERFACE={{ pihole_setupvars_pihole_interface }} +IPV4_ADDRESS={{ pihole_setupvars_ipv4_address }} +IPV6_ADDRESS={{ pihole_setupvars_ipv6_address }} +PIHOLE_DNS_1={{ pihole_setupvars_pihole_dns_1 }} +PIHOLE_DNS_2={{ pihole_setupvars_pihole_dns_2 }} +QUERY_LOGGING={{ pihole_setupvars_query_logging }} +INSTALL_WEB_SERVER={{ pihole_setupvars_install_web_server }} +INSTALL_WEB_INTERFACE={{ pihole_setupvars_install_web_interface }} +LIGHTTPD_ENABLED={{ pihole_setupvars_lighttpd_enabled }} +BLOCKING_ENABLED={{ pihole_setupvars_blocking_enabled }} +ADMIN_EMAIL={{ pihole_setupvars_admin_email }} +WEBUIBOXEDLAYOUT={{ pihole_setupvars_weblayout }} +WEBTHEME={{ pihole_setupvars_webtheme }} +REV_SERVER={{ pihole_setupvars_rev_server }}