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
This commit is contained in:
2025-09-20 00:50:31 +02:00
parent 0168167769
commit 974a83fe6e
3 changed files with 90 additions and 76 deletions

View File

@@ -13,7 +13,7 @@ server:
canonical: canonical:
web: "web.bluesky.{{ PRIMARY_DOMAIN }}" web: "web.bluesky.{{ PRIMARY_DOMAIN }}"
api: "api.bluesky.{{ PRIMARY_DOMAIN }}" api: "api.bluesky.{{ PRIMARY_DOMAIN }}"
# view: "view.bluesky.{{ PRIMARY_DOMAIN }}" view: "view.bluesky.{{ PRIMARY_DOMAIN }}"
csp: csp:
whitelist: whitelist:
connect-src: connect-src:

View File

@@ -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" - name: "DNS (Cloudflare) for Bluesky base records"
include_role: include_role:
name: sys-dns-cloudflare-records name: sys-dns-cloudflare-records
when: DNS_PROVIDER | lower == 'cloudflare' when: DNS_PROVIDER | lower == 'cloudflare'
vars: vars:
cloudflare_records: cloudflare_records: >-
# 1) PDS / API host {{
- type: A [
zone: "{{ BLUESKY_API_DOMAIN | to_zone }}" {
name: "{{ BLUESKY_API_DOMAIN }}" 'type': 'A',
content: "{{ networks.internet.ip4 }}" 'zone': (BLUESKY_API_DOMAIN | to_zone),
solo: true 'name': BLUESKY_API_DOMAIN,
proxied: false 'content': networks.internet.ip4,
'solo': True,
- type: AAAA 'proxied': False,
zone: "{{ BLUESKY_API_DOMAIN | to_zone }}" },
name: "{{ BLUESKY_API_DOMAIN }}" {
content: "{{ networks.internet.ip6 | default('') }}" 'type': 'AAAA',
proxied: false 'zone': (BLUESKY_API_DOMAIN | to_zone),
solo: true 'name': BLUESKY_API_DOMAIN,
state: "{{ (networks.internet.ip6 is defined and (networks.internet.ip6 | string) | length > 0) | ternary('present','absent') }}" 'content': (networks.internet.ip6 | default('')),
'proxied': False,
# 2) Handle verification for primary handle (Apex) 'solo': True,
- type: TXT 'state': (
zone: "{{ PRIMARY_DOMAIN | to_zone }}" ((networks.internet.ip6 is defined) and ((networks.internet.ip6 | string) | length > 0))
name: "_atproto.{{ PRIMARY_DOMAIN }}" | ternary('present','absent')
value: '"did=did:web:{{ BLUESKY_API_DOMAIN }}"' ),
solo: true },
{
# 3) Web UI host (only if enabled) 'type': 'TXT',
- type: A 'zone': (PRIMARY_DOMAIN | to_zone),
solo: true 'name': "_atproto.%s" % PRIMARY_DOMAIN,
zone: "{{ BLUESKY_WEB_DOMAIN | to_zone }}" 'value': '"did=did:web:%s"' % BLUESKY_API_DOMAIN,
name: "{{ BLUESKY_WEB_DOMAIN }}" 'solo': True,
content: "{{ networks.internet.ip4 }}" },
proxied: true {
state: "{{ (BLUESKY_WEB_ENABLED | bool) | ternary('present','absent') }}" 'type': 'A',
'solo': True,
- type: AAAA 'zone': (BLUESKY_WEB_DOMAIN | to_zone),
solo: true 'name': BLUESKY_WEB_DOMAIN,
zone: "{{ BLUESKY_WEB_DOMAIN | to_zone }}" 'content': networks.internet.ip4,
name: "{{ BLUESKY_WEB_DOMAIN }}" 'proxied': True,
content: "{{ networks.internet.ip6 | default('') }}" 'state': ((BLUESKY_WEB_ENABLED | bool) | ternary('present','absent')),
proxied: true },
state: "{{ (BLUESKY_WEB_ENABLED | bool) and (networks.internet.ip6 is defined) and ((networks.internet.ip6 | string) | length > 0) | ternary('present','absent') }}" {
'type': 'AAAA',
# 4) Custom AppView host (only if you actually run one and it's not api.bsky.app) 'solo': True,
- type: A 'zone': (BLUESKY_WEB_DOMAIN | to_zone),
solo: true 'name': BLUESKY_WEB_DOMAIN,
zone: "{{ BLUESKY_VIEW_DOMAIN | to_zone }}" 'content': (networks.internet.ip6 | default('')),
name: "{{ BLUESKY_VIEW_DOMAIN }}" 'proxied': True,
content: "{{ networks.internet.ip4 }}" 'state': (
proxied: false ((BLUESKY_WEB_ENABLED | bool)
state: "{{ (BLUESKY_VIEW_ENABLED | bool) and (BLUESKY_VIEW_DOMAIN != 'api.bsky.app') | ternary('present','absent') }}" and (networks.internet.ip6 is defined)
and ((networks.internet.ip6 | string) | length > 0))
- type: AAAA | ternary('present','absent')
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') }}" (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')
),
}
],
[])
)
}}

View File

@@ -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_DOMAIN: "{{ domains[application_id].view if BLUESKY_VIEW_ENABLED else 'api.bsky.app' }}"
BLUESKY_VIEW_URL: "{{ WEB_PROTOCOL }}://{{ BLUESKY_VIEW_DOMAIN }}" BLUESKY_VIEW_URL: "{{ WEB_PROTOCOL }}://{{ BLUESKY_VIEW_DOMAIN }}"
BLUESKY_VIEW_DID: "did:web:{{ 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 ## Server
BLUESKY_API_DOMAIN: "{{ domains[application_id].api }}" BLUESKY_API_DOMAIN: "{{ domains[application_id].api }}"