mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-11-04 12:18:17 +00:00 
			
		
		
		
	Optimized cloudflare implementation
This commit is contained in:
		@@ -79,6 +79,8 @@ activate_all_timers:                       false   # Activates all timers, indep
 | 
			
		||||
# You SHOULD NOT enable this on production servers
 | 
			
		||||
enable_debug:                             false
 | 
			
		||||
 | 
			
		||||
dns_provider:                             cloudflare              # The DNS Provider\Registrar for the domain
 | 
			
		||||
 | 
			
		||||
# Which ACME method to use: webroot, cloudflare, or hetzner
 | 
			
		||||
certbot_acme_challenge_method:            "cloudflare"
 | 
			
		||||
certbot_credentials_dir:                  /etc/certbot
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
collections:
 | 
			
		||||
  - name: kewlfft.aur
 | 
			
		||||
  - name: community.general
 | 
			
		||||
pacman:
 | 
			
		||||
  - ansible
 | 
			
		||||
  - python-passlib
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								roles/dns-records-cloudflare/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								roles/dns-records-cloudflare/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
# Cloudflare DNS Records
 | 
			
		||||
 | 
			
		||||
## Description
 | 
			
		||||
 | 
			
		||||
This Ansible role automates the management of DNS A-records in Cloudflare zones. It uses the [community.general.cloudflare_dns](https://docs.ansible.com/ansible/latest/collections/community/general/cloudflare_dns_module.html) module to create or update A-records for a list of domains, automatically detects the correct zone for each record, and supports configurable proxy settings.
 | 
			
		||||
 | 
			
		||||
## Overview
 | 
			
		||||
 | 
			
		||||
Looping over a provided list of domains (`cloudflare_domains`), this role:
 | 
			
		||||
- Determines the zone name by extracting the last two labels of each domain.
 | 
			
		||||
- Ensures an A-record for each domain points to the specified IP (`cloudflare_target_ip`).
 | 
			
		||||
- Honors the `proxied` flag to switch between DNS-only and Cloudflare-proxied modes.
 | 
			
		||||
- Provides an optional debug task (`enable_debug`) to output the domain list before changes.
 | 
			
		||||
 | 
			
		||||
Ideal for environments where bulk or dynamic DNS updates are needed, this role abstracts away the complexity of Cloudflare’s zone and record API.
 | 
			
		||||
 | 
			
		||||
## Purpose
 | 
			
		||||
 | 
			
		||||
Cloudflare DNS Records delivers an idempotent, scalable solution for managing A-records across multiple Cloudflare zones. Whether you need to onboard hundreds of domains or toggle proxy settings in CI/CD pipelines, this role handles the orchestration and ensures consistency.
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
- **Automatic Zone Detection:** Parses each domain to derive its zone (`example.com`) without manual intervention.  
 | 
			
		||||
- **Bulk Record Management:** Creates or updates A-records for all entries in `cloudflare_domains`.  
 | 
			
		||||
- **Proxy Toggle:** Configure `proxied: true` or `false` per record to switch between DNS-only and proxied modes.  
 | 
			
		||||
- **Debug Support:** Enable `enable_debug` to print the domain list for validation before execution.  
 | 
			
		||||
- **Flexible Authentication:** Supports both API token (`api_token`) and Global API key + email.  
 | 
			
		||||
- **Low-TTL Option:** Use `ttl: 1` for rapid DNS propagation during dynamic updates.
 | 
			
		||||
 | 
			
		||||
## Author
 | 
			
		||||
 | 
			
		||||
Kevin Veen-Birkenbach
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
 | 
			
		||||
CyMaIS NonCommercial License (CNCL)  
 | 
			
		||||
<https://s.veen.world/cncl>
 | 
			
		||||
							
								
								
									
										26
									
								
								roles/dns-records-cloudflare/meta/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								roles/dns-records-cloudflare/meta/main.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
---
 | 
			
		||||
galaxy_info:
 | 
			
		||||
  author: "Kevin Veen-Birkenbach"
 | 
			
		||||
  description: "Manages DNS A-records in Cloudflare zones."
 | 
			
		||||
  license: "CyMaIS NonCommercial License (CNCL)"
 | 
			
		||||
  license_url: "https://s.veen.world/cncl"
 | 
			
		||||
  company: |
 | 
			
		||||
    Kevin Veen-Birkenbach
 | 
			
		||||
    Consulting & Coaching Solutions
 | 
			
		||||
    https://www.veen.world
 | 
			
		||||
  min_ansible_version: "2.9"
 | 
			
		||||
  platforms:
 | 
			
		||||
    - name: "All"
 | 
			
		||||
      versions:
 | 
			
		||||
        - "all"
 | 
			
		||||
  galaxy_tags:
 | 
			
		||||
    - "cloudflare"
 | 
			
		||||
    - "dns"
 | 
			
		||||
    - "records"
 | 
			
		||||
    - "ansible"
 | 
			
		||||
    - "network"
 | 
			
		||||
    - "automation"
 | 
			
		||||
  repository: "https://s.veen.world/cymais"
 | 
			
		||||
  issue_tracker_url: "https://s.veen.world/cymaisissues"
 | 
			
		||||
  documentation: "https://s.veen.world/cymais"
 | 
			
		||||
dependencies: []
 | 
			
		||||
							
								
								
									
										18
									
								
								roles/dns-records-cloudflare/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								roles/dns-records-cloudflare/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
- name: "Debug: cloudflare_domains"
 | 
			
		||||
  debug:
 | 
			
		||||
    var: cloudflare_domains
 | 
			
		||||
  when: enable_debug
 | 
			
		||||
 | 
			
		||||
- name: Create or update Cloudflare A-record for {{ item }}
 | 
			
		||||
  community.general.cloudflare_dns:
 | 
			
		||||
    api_token: "{{ cloudflare_api_token }}"
 | 
			
		||||
    zone: "{{ item.split('.')[-2:] | join('.') }}"
 | 
			
		||||
    state: present
 | 
			
		||||
    type: A
 | 
			
		||||
    name: "{{ item }}"
 | 
			
		||||
    content: "{{ cloudflare_target_ip }}"
 | 
			
		||||
    ttl: 1
 | 
			
		||||
    proxied: "{{ cloudflare_target_ip }}"
 | 
			
		||||
  loop: "{{ cloudflare_domains }}"
 | 
			
		||||
  loop_control:
 | 
			
		||||
    label: "{{ item }}"
 | 
			
		||||
@@ -1,12 +1,13 @@
 | 
			
		||||
---
 | 
			
		||||
- name: "include role nginx-domain-setup for {{application_id}}"
 | 
			
		||||
  include_role:
 | 
			
		||||
    name: nginx-domain-setup
 | 
			
		||||
 | 
			
		||||
# Docker Central Database Role can't be used here
 | 
			
		||||
- name: "include docker-compose role"
 | 
			
		||||
  include_role: 
 | 
			
		||||
    name: docker-compose
 | 
			
		||||
 | 
			
		||||
- name: "include role nginx-domain-setup for {{application_id}}"
 | 
			
		||||
  include_role:
 | 
			
		||||
    name: nginx-domain-setup
 | 
			
		||||
 | 
			
		||||
- name: pull docker repository
 | 
			
		||||
  git:
 | 
			
		||||
    repo: "https://github.com/bigbluebutton/docker.git"
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,6 @@ RAILS_SECRET={{applications.bigbluebutton.credentials.rails_secret}}
 | 
			
		||||
POSTGRESQL_SECRET={{applications.bigbluebutton.credentials.postgresql_secret}}
 | 
			
		||||
FSESL_PASSWORD={{applications.bigbluebutton.credentials.fsesl_password}}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# ====================================
 | 
			
		||||
# CONNECTION
 | 
			
		||||
# ====================================
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,7 @@ docker_compose_file_origine:  "{{ docker_compose.directories.services }}docker-c
 | 
			
		||||
docker_compose_file_final:      "{{ docker_compose.directories.instance }}docker-compose.yml"
 | 
			
		||||
 | 
			
		||||
# Database configuration
 | 
			
		||||
database_instance:            "bigbluebutton"
 | 
			
		||||
database_name:                "multiple_databases"
 | 
			
		||||
database_username:            "postgres"
 | 
			
		||||
database_type:                  "postgres"
 | 
			
		||||
database_password:              "{{ applications.bigbluebutton.credentials.postgresql_secret }}"
 | 
			
		||||
 | 
			
		||||
domain: 	                      "{{ domains[application_id] }}"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
database_instance:  "{{ 'central-' + database_type if applications[application_id].features.database | bool else application_id }}"
 | 
			
		||||
database_host:      "{{ 'central-' + database_type if applications[application_id].features.database | bool else 'database' }}"
 | 
			
		||||
database_name:      "{{ application_id }}"
 | 
			
		||||
database_username:  "{{ application_id }}"
 | 
			
		||||
database_name:      "{{ applications[application_id].credentials.database.name | default( application_id ) }}"      # The overwritte configuration is needed by bigbluebutton
 | 
			
		||||
database_username:  "{{ applications[application_id].credentials.database.username | default( application_id )}}"   # The overwritte configuration is needed by bigbluebutton
 | 
			
		||||
database_port:      "{{ 3306 if database_type == 'mariadb' else 5432 }}"
 | 
			
		||||
database_env:       "{{docker_compose.directories.env}}{{database_type}}.env"
 | 
			
		||||
database_url_jdbc:  "jdbc:{{ database_type if database_type == 'mariadb' else 'postgresql' }}://{{ database_host }}:{{ database_port }}/{{ database_name }}"
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,5 @@ server {
 | 
			
		||||
    listen {{ports.public.ldaps.ldap}}ssl;
 | 
			
		||||
    proxy_pass 127.0.0.1:{{ports.localhost.ldap.ldap}};
 | 
			
		||||
    
 | 
			
		||||
    # SSL Configuration for LDAPS
 | 
			
		||||
    {% include 'roles/letsencrypt/templates/ssl_credentials.j2' %}
 | 
			
		||||
    ssl_protocols TLSv1.2 TLSv1.3;
 | 
			
		||||
    ssl_ciphers HIGH:!aNULL:!MD5;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,15 @@
 | 
			
		||||
listen 443 ssl;
 | 
			
		||||
listen [::]:443 ssl;
 | 
			
		||||
http2 on;
 | 
			
		||||
listen 443 ssl http2;
 | 
			
		||||
listen [::]:443 ssl http2;
 | 
			
		||||
 | 
			
		||||
ssl_protocols TLSv1.2 TLSv1.3;
 | 
			
		||||
ssl_ecdh_curve X25519:P-256;
 | 
			
		||||
ssl_prefer_server_ciphers on;
 | 
			
		||||
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
 | 
			
		||||
 | 
			
		||||
ssl_session_timeout 1d;
 | 
			
		||||
ssl_session_cache shared:SSL:50m;
 | 
			
		||||
ssl_session_tickets on;
 | 
			
		||||
ssl_prefer_server_ciphers on;
 | 
			
		||||
add_header Strict-Transport-Security max-age=15768000;
 | 
			
		||||
ssl_stapling on;
 | 
			
		||||
ssl_stapling_verify on;
 | 
			
		||||
{% include 'roles/letsencrypt/templates/ssl_credentials.j2' %}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
    --domains "{{ all_domains | join(',') }}"
 | 
			
		||||
    --certbot-email "{{ users.administrator.email }}"
 | 
			
		||||
    --certbot-acme-challenge-method "{{ certbot_acme_challenge_method }}"
 | 
			
		||||
    --chunk-size 100
 | 
			
		||||
    {% if certbot_acme_challenge_method != 'webroot' %}
 | 
			
		||||
    --certbot-credentials-file "{{ certbot_credentials_file }}"
 | 
			
		||||
    --certbot-dns-propagation-seconds "{{ certbot_dns_propagation_wait_seconds }}"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,13 @@
 | 
			
		||||
---
 | 
			
		||||
# 1. Filter all domains with the “www.” prefix
 | 
			
		||||
- name: "Debug: all_domains"
 | 
			
		||||
  debug:
 | 
			
		||||
    var: all_domains
 | 
			
		||||
  when: enable_debug
 | 
			
		||||
 | 
			
		||||
- name: Filter www-prefixed domains from all_domains
 | 
			
		||||
  set_fact:
 | 
			
		||||
    www_domains: "{{ all_domains | select('match', '^www\\.') | list }}"
 | 
			
		||||
 | 
			
		||||
# 2. Build redirect mappings (www.domain → domain)
 | 
			
		||||
- name: Build redirect mappings for www domains
 | 
			
		||||
  set_fact:
 | 
			
		||||
    domain_mappings: >-
 | 
			
		||||
@@ -14,10 +17,19 @@
 | 
			
		||||
         | list
 | 
			
		||||
      }}
 | 
			
		||||
 | 
			
		||||
# 3. Include the nginx-redirect-domain role to apply these mappings
 | 
			
		||||
- name: Include nginx-redirect-domain role for www-to-bare redirects
 | 
			
		||||
  include_role:
 | 
			
		||||
    name: nginx-redirect-domain
 | 
			
		||||
  vars:
 | 
			
		||||
    domain_mappings: "{{ domain_mappings }}"
 | 
			
		||||
  when: certbot_flavor == 'dedicated'
 | 
			
		||||
 | 
			
		||||
- name: Include DNS role to set redirects
 | 
			
		||||
  include_role:
 | 
			
		||||
    name: dns-records-cloudflare
 | 
			
		||||
  vars:
 | 
			
		||||
    cloudflare_api_token:     "{{ certbot_dns_api_token }}"
 | 
			
		||||
    cloudflare_domains:       "{{ www_domains }}"
 | 
			
		||||
    cloudflare_target_ip:     "{{ networks.internet.ip4 }}"
 | 
			
		||||
    cloudflare_proxied_false: false
 | 
			
		||||
  when: dns_provider == 'cloudflare'
 | 
			
		||||
@@ -62,22 +62,28 @@
 | 
			
		||||
    set_fact:
 | 
			
		||||
      service_provider: "{{ defaults_service_provider | combine(service_provider | default({}, true), recursive=True) }}"
 | 
			
		||||
 | 
			
		||||
  - name: Collect all domains (domains, redirect sources + www)
 | 
			
		||||
  - name: Gather base domains (without www)
 | 
			
		||||
    set_fact:
 | 
			
		||||
      all_domains: >-
 | 
			
		||||
      base_domains: >-
 | 
			
		||||
        {{
 | 
			
		||||
          (
 | 
			
		||||
            (
 | 
			
		||||
              domains.values() | flatten
 | 
			
		||||
          domains.values()
 | 
			
		||||
          | flatten
 | 
			
		||||
          + (redirect_domain_mappings | map(attribute='source') | list)
 | 
			
		||||
            )
 | 
			
		||||
            + (
 | 
			
		||||
              domains.values() | flatten
 | 
			
		||||
              + (redirect_domain_mappings | map(attribute='source') | list)
 | 
			
		||||
            ) | map('regex_replace', '^(.*)$', 'www.\\1') | list
 | 
			
		||||
          ) | unique | sort
 | 
			
		||||
        }}
 | 
			
		||||
 | 
			
		||||
  - name: Initialise all_domains as empty list
 | 
			
		||||
    set_fact:
 | 
			
		||||
      all_domains: []
 | 
			
		||||
 | 
			
		||||
  - name: Build all_domains with base + www via loop
 | 
			
		||||
    set_fact:
 | 
			
		||||
      all_domains: "{{ all_domains + [ item, 'www.' ~ item ] }}"
 | 
			
		||||
    loop: "{{ base_domains }}"
 | 
			
		||||
 | 
			
		||||
  - name: Deduplicate and sort all_domains
 | 
			
		||||
    set_fact:
 | 
			
		||||
      all_domains: "{{ all_domains | unique | sort }}"
 | 
			
		||||
 | 
			
		||||
  - name: "Merged Variables"
 | 
			
		||||
    # Add new merged variables here
 | 
			
		||||
    debug:
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ defaults_applications:
 | 
			
		||||
  'iframe':   true,
 | 
			
		||||
  'ldap':     false,
 | 
			
		||||
  'oidc':     true,
 | 
			
		||||
  'database': true,
 | 
			
		||||
  'database': false,
 | 
			
		||||
}) }}{% raw %}
 | 
			
		||||
    credentials:
 | 
			
		||||
#      shared_secret:                                                       # Needs to be defined in inventory file
 | 
			
		||||
@@ -75,6 +75,9 @@ defaults_applications:
 | 
			
		||||
#      postgresql_secret:                                                   # Needs to be defined in inventory file   
 | 
			
		||||
#      fsesl_password:                                                      # Needs to be defined in inventory file
 | 
			
		||||
#      turn_secret:                                                         # Needs to be defined in inventory file  
 | 
			
		||||
      database:
 | 
			
		||||
        name:      "multiple_databases"
 | 
			
		||||
        username:  "postgres2"
 | 
			
		||||
    urls:
 | 
			
		||||
      api:                        "{{ web_protocol }}://{{domains.bigbluebutton}}/bigbluebutton/"  # API Address used by Nextcloud Integration
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user