mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-04-29 18:48:39 +02:00
Optimized cloudflare implementation
This commit is contained in:
parent
04deeef385
commit
d796158c61
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user