From 974a83fe6ec88656566c77bbb7e940b2a24e674c Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Sat, 20 Sep 2025 00:50:31 +0200 Subject: [PATCH] web-app-bluesky: enable custom AppView domain and refactor DNS records - Un-commented `view.bluesky.{{ PRIMARY_DOMAIN }}` in config to allow explicit AppView domain definition. - Reworked `03_dns.yml` to build `cloudflare_records` list programmatically, including conditional addition of AppView records only if the domain is not `api.bsky.app`. - Improved AAAA handling with `| default('')` and proper ternary expressions for `present/absent`. - Updated `vars/main.yml` to remove default port fallback for `BLUESKY_VIEW_PORT`. Refs: https://chatgpt.com/share/68cdde1d-1bd4-800f-a4bb-319372752fcd --- roles/web-app-bluesky/config/main.yml | 2 +- roles/web-app-bluesky/tasks/03_dns.yml | 162 ++++++++++++++----------- roles/web-app-bluesky/vars/main.yml | 2 +- 3 files changed, 90 insertions(+), 76 deletions(-) diff --git a/roles/web-app-bluesky/config/main.yml b/roles/web-app-bluesky/config/main.yml index d4523c61..66a99619 100644 --- a/roles/web-app-bluesky/config/main.yml +++ b/roles/web-app-bluesky/config/main.yml @@ -13,7 +13,7 @@ server: canonical: web: "web.bluesky.{{ PRIMARY_DOMAIN }}" api: "api.bluesky.{{ PRIMARY_DOMAIN }}" -# view: "view.bluesky.{{ PRIMARY_DOMAIN }}" + view: "view.bluesky.{{ PRIMARY_DOMAIN }}" csp: whitelist: connect-src: diff --git a/roles/web-app-bluesky/tasks/03_dns.yml b/roles/web-app-bluesky/tasks/03_dns.yml index 17d8669a..544d014e 100644 --- a/roles/web-app-bluesky/tasks/03_dns.yml +++ b/roles/web-app-bluesky/tasks/03_dns.yml @@ -1,80 +1,94 @@ --- -# Creates Cloudflare DNS records for Bluesky: -# - PDS/API host (A/AAAA) -# - Handle TXT verification (_atproto) -# - Optional Web UI host (A/AAAA) -# - Optional custom AppView host (A/AAAA) -# -# Requirements: -# DNS_PROVIDER == 'cloudflare' -# CLOUDFLARE_API_TOKEN set -# -# Inputs (inventory/vars): -# BLUESKY_API_DOMAIN, BLUESKY_WEB_DOMAIN, BLUESKY_VIEW_DOMAIN -# BLUESKY_WEB_ENABLED (bool), BLUESKY_VIEW_ENABLED (bool) -# PRIMARY_DOMAIN -# networks.internet.ip4 (and optionally networks.internet.ip6) - - name: "DNS (Cloudflare) for Bluesky – base records" include_role: name: sys-dns-cloudflare-records when: DNS_PROVIDER | lower == 'cloudflare' vars: - cloudflare_records: - # 1) PDS / API host - - type: A - zone: "{{ BLUESKY_API_DOMAIN | to_zone }}" - name: "{{ BLUESKY_API_DOMAIN }}" - content: "{{ networks.internet.ip4 }}" - solo: true - proxied: false - - - type: AAAA - zone: "{{ BLUESKY_API_DOMAIN | to_zone }}" - name: "{{ BLUESKY_API_DOMAIN }}" - content: "{{ networks.internet.ip6 | default('') }}" - proxied: false - solo: true - state: "{{ (networks.internet.ip6 is defined and (networks.internet.ip6 | string) | length > 0) | ternary('present','absent') }}" - - # 2) Handle verification for primary handle (Apex) - - type: TXT - zone: "{{ PRIMARY_DOMAIN | to_zone }}" - name: "_atproto.{{ PRIMARY_DOMAIN }}" - value: '"did=did:web:{{ BLUESKY_API_DOMAIN }}"' - solo: true - - # 3) Web UI host (only if enabled) - - type: A - solo: true - zone: "{{ BLUESKY_WEB_DOMAIN | to_zone }}" - name: "{{ BLUESKY_WEB_DOMAIN }}" - content: "{{ networks.internet.ip4 }}" - proxied: true - state: "{{ (BLUESKY_WEB_ENABLED | bool) | ternary('present','absent') }}" - - - type: AAAA - solo: true - zone: "{{ BLUESKY_WEB_DOMAIN | to_zone }}" - name: "{{ BLUESKY_WEB_DOMAIN }}" - content: "{{ networks.internet.ip6 | default('') }}" - proxied: true - state: "{{ (BLUESKY_WEB_ENABLED | bool) and (networks.internet.ip6 is defined) and ((networks.internet.ip6 | string) | length > 0) | ternary('present','absent') }}" - - # 4) Custom AppView host (only if you actually run one and it's not api.bsky.app) - - type: A - solo: true - zone: "{{ BLUESKY_VIEW_DOMAIN | to_zone }}" - name: "{{ BLUESKY_VIEW_DOMAIN }}" - content: "{{ networks.internet.ip4 }}" - proxied: false - state: "{{ (BLUESKY_VIEW_ENABLED | bool) and (BLUESKY_VIEW_DOMAIN != 'api.bsky.app') | ternary('present','absent') }}" - - - type: AAAA - solo: true - zone: "{{ BLUESKY_VIEW_DOMAIN | to_zone }}" - name: "{{ BLUESKY_VIEW_DOMAIN }}" - content: "{{ networks.internet.ip6 | default('') }}" - proxied: false - state: "{{ (BLUESKY_VIEW_ENABLED | bool) and (BLUESKY_VIEW_DOMAIN != 'api.bsky.app') and (networks.internet.ip6 is defined) and ((networks.internet.ip6 | string) | length > 0) | ternary('present','absent') }}" - + cloudflare_records: >- + {{ + [ + { + 'type': 'A', + 'zone': (BLUESKY_API_DOMAIN | to_zone), + 'name': BLUESKY_API_DOMAIN, + 'content': networks.internet.ip4, + 'solo': True, + 'proxied': False, + }, + { + 'type': 'AAAA', + 'zone': (BLUESKY_API_DOMAIN | to_zone), + 'name': BLUESKY_API_DOMAIN, + 'content': (networks.internet.ip6 | default('')), + 'proxied': False, + 'solo': True, + 'state': ( + ((networks.internet.ip6 is defined) and ((networks.internet.ip6 | string) | length > 0)) + | ternary('present','absent') + ), + }, + { + 'type': 'TXT', + 'zone': (PRIMARY_DOMAIN | to_zone), + 'name': "_atproto.%s" % PRIMARY_DOMAIN, + 'value': '"did=did:web:%s"' % BLUESKY_API_DOMAIN, + 'solo': True, + }, + { + 'type': 'A', + 'solo': True, + 'zone': (BLUESKY_WEB_DOMAIN | to_zone), + 'name': BLUESKY_WEB_DOMAIN, + 'content': networks.internet.ip4, + 'proxied': True, + 'state': ((BLUESKY_WEB_ENABLED | bool) | ternary('present','absent')), + }, + { + 'type': 'AAAA', + 'solo': True, + 'zone': (BLUESKY_WEB_DOMAIN | to_zone), + 'name': BLUESKY_WEB_DOMAIN, + 'content': (networks.internet.ip6 | default('')), + 'proxied': True, + 'state': ( + ((BLUESKY_WEB_ENABLED | bool) + and (networks.internet.ip6 is defined) + and ((networks.internet.ip6 | string) | length > 0)) + | ternary('present','absent') + ), + }, + ] + + + ( + (BLUESKY_VIEW_DOMAIN != 'api.bsky.app') + | ternary([ + { + 'type': 'A', + 'solo': True, + 'zone': (BLUESKY_VIEW_DOMAIN | to_zone), + 'name': BLUESKY_VIEW_DOMAIN, + 'content': networks.internet.ip4, + 'proxied': False, + 'state': ( + ((BLUESKY_VIEW_ENABLED | bool)) + | ternary('present','absent') + ), + }, + { + 'type': 'AAAA', + 'solo': True, + 'zone': (BLUESKY_VIEW_DOMAIN | to_zone), + 'name': BLUESKY_VIEW_DOMAIN, + 'content': (networks.internet.ip6 | default('')), + 'proxied': False, + 'state': ( + ((BLUESKY_VIEW_ENABLED | bool) + and (networks.internet.ip6 is defined) + and ((networks.internet.ip6 | string) | length > 0)) + | ternary('present','absent') + ), + } + ], + []) + ) + }} diff --git a/roles/web-app-bluesky/vars/main.yml b/roles/web-app-bluesky/vars/main.yml index 0500aab8..44d3452a 100644 --- a/roles/web-app-bluesky/vars/main.yml +++ b/roles/web-app-bluesky/vars/main.yml @@ -30,7 +30,7 @@ BLUESKY_VIEW_ENABLED: "{{ applications | get_app_conf(application_id, BLUESKY_VIEW_DOMAIN: "{{ domains[application_id].view if BLUESKY_VIEW_ENABLED else 'api.bsky.app' }}" BLUESKY_VIEW_URL: "{{ WEB_PROTOCOL }}://{{ BLUESKY_VIEW_DOMAIN }}" BLUESKY_VIEW_DID: "did:web:{{ BLUESKY_VIEW_DOMAIN }}" -BLUESKY_VIEW_PORT: "{{ ports.localhost.http['web-app-bluesky_view'] | default(8053) }}" +BLUESKY_VIEW_PORT: "{{ ports.localhost.http['web-app-bluesky_view'] }}" ## Server BLUESKY_API_DOMAIN: "{{ domains[application_id].api }}"