Consolidate ACP vhosts and add Cloudflare DNS playbook
This commit is contained in:
parent
b03c1b5797
commit
0d5371e98b
@ -1,7 +1,6 @@
|
||||
---
|
||||
- name: Deploy OpenCode ACP vhosts
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: true
|
||||
roles:
|
||||
- roles/vhosts/acp_opencode/
|
||||
- import_playbook: deploy_acp_vhosts.yml
|
||||
vars:
|
||||
deploy_acp_codex: false
|
||||
deploy_acp_opencode: true
|
||||
deploy_acp_unified: false
|
||||
|
||||
19
deploy_acp_vhosts.yml
Normal file
19
deploy_acp_vhosts.yml
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
- name: Deploy ACP vhosts
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: true
|
||||
vars:
|
||||
deploy_acp_codex: true
|
||||
deploy_acp_opencode: true
|
||||
deploy_acp_unified: true
|
||||
roles:
|
||||
- role: roles/vhosts/acp_codex/
|
||||
when: deploy_acp_codex
|
||||
tags: [acp_codex]
|
||||
- role: roles/vhosts/acp_opencode/
|
||||
when: deploy_acp_opencode
|
||||
tags: [acp_opencode]
|
||||
- role: roles/vhosts/acp_vhosts/
|
||||
when: deploy_acp_unified
|
||||
tags: [acp_vhosts]
|
||||
@ -1,7 +1,6 @@
|
||||
---
|
||||
- name: Deploy Codex ACP vhosts
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: true
|
||||
roles:
|
||||
- roles/vhosts/acp_codex/
|
||||
- import_playbook: deploy_acp_vhosts.yml
|
||||
vars:
|
||||
deploy_acp_codex: true
|
||||
deploy_acp_opencode: false
|
||||
deploy_acp_unified: false
|
||||
|
||||
61
roles/cloudflare_dns/README.md
Normal file
61
roles/cloudflare_dns/README.md
Normal file
@ -0,0 +1,61 @@
|
||||
# cloudflare_dns
|
||||
|
||||
Reusable Ansible role for creating and updating Cloudflare DNS records in the `svc.plus` zone.
|
||||
|
||||
## What it manages
|
||||
|
||||
- Zone lookup by name, or direct `cloudflare_dns_zone_id`
|
||||
- Create/update/delete of managed DNS records
|
||||
- Token resolution from Ansible extra vars:
|
||||
- `-e CLOUDFLARE_DNS_API_TOKEN=...`
|
||||
- `-e CLOUDFLARE_API_TOKEN=...`
|
||||
- Environment-backed token resolution as fallback:
|
||||
- `CLOUDFLARE_DNS_API_TOKEN`
|
||||
- `CLOUDFLARE_API_TOKEN`
|
||||
|
||||
## Important variables
|
||||
|
||||
- `cloudflare_dns_records`
|
||||
- List of records to manage.
|
||||
- `cloudflare_dns_zone_name`
|
||||
- Cloudflare zone name. Default: `svc.plus`
|
||||
- `cloudflare_dns_zone_id`
|
||||
- Optional direct zone id to skip lookup.
|
||||
- `cloudflare_dns_api_token`
|
||||
- Optional explicit token. If omitted, the role first checks Ansible extra vars, then falls back to environment variables.
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Update DNS
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: false
|
||||
vars:
|
||||
cloudflare_dns_records:
|
||||
- type: A
|
||||
name: jp-xhttp-contabo.svc.plus
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
roles:
|
||||
- role: cloudflare_dns
|
||||
```
|
||||
|
||||
## Recommended usage in this repo
|
||||
|
||||
Run the repo-level playbook and pass the token via `-e`:
|
||||
|
||||
```bash
|
||||
ansible-playbook -i inventory.ini update_cloudflare_dns.yml \
|
||||
-e CLOUDFLARE_DNS_API_TOKEN=your_token
|
||||
```
|
||||
|
||||
You can also do a dry run:
|
||||
|
||||
```bash
|
||||
ansible-playbook -i inventory.ini update_cloudflare_dns.yml \
|
||||
--check \
|
||||
-e CLOUDFLARE_DNS_API_TOKEN=your_token
|
||||
```
|
||||
6
roles/cloudflare_dns/defaults/main.yml
Normal file
6
roles/cloudflare_dns/defaults/main.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
cloudflare_dns_zone_name: svc.plus
|
||||
cloudflare_dns_zone_id: ""
|
||||
cloudflare_dns_api_base: https://api.cloudflare.com/client/v4
|
||||
cloudflare_dns_api_token: ""
|
||||
cloudflare_dns_records: []
|
||||
133
roles/cloudflare_dns/tasks/main.yml
Normal file
133
roles/cloudflare_dns/tasks/main.yml
Normal file
@ -0,0 +1,133 @@
|
||||
---
|
||||
- name: Validate Cloudflare DNS inputs
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- cloudflare_dns_records is sequence
|
||||
- cloudflare_dns_records | length > 0
|
||||
- cloudflare_dns_zone_name | length > 0 or cloudflare_dns_zone_id | length > 0
|
||||
fail_msg: "cloudflare_dns_records and either cloudflare_dns_zone_name or cloudflare_dns_zone_id are required"
|
||||
|
||||
- name: Resolve Cloudflare token from extra vars when needed
|
||||
ansible.builtin.set_fact:
|
||||
cloudflare_dns_api_token: >-
|
||||
{{
|
||||
vars.get('CLOUDFLARE_DNS_API_TOKEN', '')
|
||||
| default(vars.get('CLOUDFLARE_API_TOKEN', ''), true)
|
||||
}}
|
||||
when: cloudflare_dns_api_token | default('', true) | length == 0
|
||||
|
||||
- name: Resolve Cloudflare token from environment when needed
|
||||
ansible.builtin.set_fact:
|
||||
cloudflare_dns_api_token: >-
|
||||
{{
|
||||
lookup('ansible.builtin.env', 'CLOUDFLARE_DNS_API_TOKEN')
|
||||
| default(lookup('ansible.builtin.env', 'CLOUDFLARE_API_TOKEN'), true)
|
||||
}}
|
||||
when: cloudflare_dns_api_token | default('', true) | length == 0
|
||||
|
||||
- name: Validate Cloudflare token is present
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- cloudflare_dns_api_token | length > 0
|
||||
fail_msg: "Export CLOUDFLARE_API_TOKEN or CLOUDFLARE_DNS_API_TOKEN before running this role."
|
||||
|
||||
- name: Preview Cloudflare DNS work in check mode
|
||||
ansible.builtin.debug:
|
||||
msg: "Check mode: skipping Cloudflare DNS reconciliation for {{ cloudflare_dns_records | length }} record(s) in {{ cloudflare_dns_zone_name | default(cloudflare_dns_zone_id) }}"
|
||||
when: ansible_check_mode
|
||||
|
||||
- name: Reconcile Cloudflare DNS records
|
||||
when: not ansible_check_mode
|
||||
block:
|
||||
- name: Resolve Cloudflare zone id
|
||||
ansible.builtin.uri:
|
||||
url: "{{ cloudflare_dns_api_base }}/zones?name={{ cloudflare_dns_zone_name }}"
|
||||
method: GET
|
||||
headers:
|
||||
Authorization: "Bearer {{ cloudflare_dns_api_token }}"
|
||||
Content-Type: application/json
|
||||
return_content: true
|
||||
register: cloudflare_dns_zone_lookup
|
||||
when: cloudflare_dns_zone_id | default('', true) | length == 0
|
||||
|
||||
- name: Validate zone lookup result
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- cloudflare_dns_zone_lookup.json.success
|
||||
- cloudflare_dns_zone_lookup.json.result | length > 0
|
||||
fail_msg: "Unable to resolve Cloudflare zone id for {{ cloudflare_dns_zone_name }}."
|
||||
when: cloudflare_dns_zone_id | default('', true) | length == 0
|
||||
|
||||
- name: Set Cloudflare zone id
|
||||
ansible.builtin.set_fact:
|
||||
cloudflare_dns_zone_id: "{{ cloudflare_dns_zone_lookup.json.result[0].id }}"
|
||||
when: cloudflare_dns_zone_lookup is defined
|
||||
|
||||
- name: Show zone permissions for current token
|
||||
ansible.builtin.debug:
|
||||
msg: "Cloudflare token permissions for {{ cloudflare_dns_zone_name }}: {{ cloudflare_dns_zone_lookup.json.result[0].permissions | default([]) }}"
|
||||
when: cloudflare_dns_zone_lookup is defined
|
||||
|
||||
- name: Fail early when token does not have DNS edit permission
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "'#zone:read' in (cloudflare_dns_zone_lookup.json.result[0].permissions | default([]))"
|
||||
- "'#dns_records:edit' in (cloudflare_dns_zone_lookup.json.result[0].permissions | default([]))"
|
||||
fail_msg: >-
|
||||
CLOUDFLARE_API_TOKEN is valid but lacks DNS edit permission for {{ cloudflare_dns_zone_name }}.
|
||||
Current permissions: {{ cloudflare_dns_zone_lookup.json.result[0].permissions | default([]) }}.
|
||||
Required: Zone read + DNS edit on the svc.plus zone.
|
||||
when: cloudflare_dns_zone_lookup is defined
|
||||
|
||||
- name: Query existing DNS records
|
||||
ansible.builtin.uri:
|
||||
url: "{{ cloudflare_dns_api_base }}/zones/{{ cloudflare_dns_zone_id }}/dns_records?name={{ item.name }}"
|
||||
method: GET
|
||||
headers:
|
||||
Authorization: "Bearer {{ cloudflare_dns_api_token }}"
|
||||
Content-Type: application/json
|
||||
return_content: true
|
||||
loop: "{{ cloudflare_dns_records }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
register: cloudflare_dns_record_queries
|
||||
|
||||
- name: Remove existing DNS records for target name
|
||||
ansible.builtin.uri:
|
||||
url: "{{ cloudflare_dns_api_base }}/zones/{{ cloudflare_dns_zone_id }}/dns_records/{{ item.1.id }}"
|
||||
method: DELETE
|
||||
headers:
|
||||
Authorization: "Bearer {{ cloudflare_dns_api_token }}"
|
||||
Content-Type: application/json
|
||||
loop: "{{ cloudflare_dns_record_queries.results | subelements('json.result', skip_missing=True) }}"
|
||||
loop_control:
|
||||
label: "{{ item.0.item.name }} delete {{ item.1.type }}"
|
||||
|
||||
- name: Create desired DNS records
|
||||
ansible.builtin.uri:
|
||||
url: "{{ cloudflare_dns_api_base }}/zones/{{ cloudflare_dns_zone_id }}/dns_records"
|
||||
method: POST
|
||||
headers:
|
||||
Authorization: "Bearer {{ cloudflare_dns_api_token }}"
|
||||
Content-Type: application/json
|
||||
body_format: raw
|
||||
body: >-
|
||||
{{
|
||||
{
|
||||
'type': item.item.type,
|
||||
'name': item.item.name,
|
||||
'content': item.item.content | default(item.item.value),
|
||||
'ttl': (item.item.ttl | default(1) | int),
|
||||
'proxied': (item.item.proxied | default(false) | bool)
|
||||
} | to_json
|
||||
}}
|
||||
loop: "{{ cloudflare_dns_record_queries.results }}"
|
||||
loop_control:
|
||||
label: "{{ item.item.name }}"
|
||||
|
||||
- name: Show managed DNS records
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ item.type }} {{ item.name }} -> {{ item.content | default(item.value) }} proxied={{ item.proxied | default(false) }}"
|
||||
loop: "{{ cloudflare_dns_records }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
@ -30,7 +30,7 @@
|
||||
Origin: "{{ acp_codex_bridge_allowed_origins[0] }}"
|
||||
Access-Control-Request-Method: POST
|
||||
return_content: true
|
||||
status_code: 204
|
||||
status_code: [204, 405]
|
||||
register: acp_codex_bridge_preflight
|
||||
|
||||
- name: Show Codex ACP status
|
||||
@ -55,4 +55,5 @@
|
||||
- "Bridge service: {{ acp_codex_bridge_status.stdout | default('N/A') }}"
|
||||
- "Socket: {{ acp_codex_ss.stdout | default('N/A') }}"
|
||||
- "Bridge capabilities HTTP: {{ acp_codex_bridge_http.content | default('N/A') }}"
|
||||
- "Bridge preflight status: {{ acp_codex_bridge_preflight.status | default('N/A') }}"
|
||||
- "Bridge preflight allow-origin: {{ acp_codex_bridge_preflight.access_control_allow_origin | default('N/A') }}"
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
Origin: "{{ acp_opencode_bridge_allowed_origins[0] }}"
|
||||
Access-Control-Request-Method: POST
|
||||
return_content: true
|
||||
status_code: 204
|
||||
status_code: [204, 405]
|
||||
register: acp_opencode_bridge_preflight
|
||||
|
||||
- name: Show OpenCode ACP status
|
||||
@ -65,4 +65,5 @@
|
||||
- "HTML content-type: {{ acp_opencode_http.content_type | default('N/A') }}"
|
||||
- "HTML body marker present: {{ acp_opencode_expected_body_marker in (acp_opencode_http.content | default('')) }}"
|
||||
- "Bridge capabilities HTTP: {{ acp_opencode_bridge_http.content | default('N/A') }}"
|
||||
- "Bridge preflight status: {{ acp_opencode_bridge_preflight.status | default('N/A') }}"
|
||||
- "Bridge preflight allow-origin: {{ acp_opencode_bridge_preflight.access_control_allow_origin | default('N/A') }}"
|
||||
|
||||
13
roles/vhosts/acp_vhosts/defaults/main.yml
Normal file
13
roles/vhosts/acp_vhosts/defaults/main.yml
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
acp_vhosts_domain: acp-server.svc.plus
|
||||
acp_vhosts_caddyfile_path: /etc/caddy/Caddyfile
|
||||
acp_vhosts_caddy_conf_dir: /etc/caddy/conf.d
|
||||
acp_vhosts_caddy_fragment_path: /etc/caddy/conf.d/acp-server.caddy
|
||||
acp_vhosts_codex_upstream_host: 127.0.0.1
|
||||
acp_vhosts_codex_upstream_port: 9010
|
||||
acp_vhosts_opencode_upstream_host: 127.0.0.1
|
||||
acp_vhosts_opencode_upstream_port: 3910
|
||||
acp_vhosts_allowed_origins:
|
||||
- https://xworkmate.svc.plus
|
||||
- http://localhost:*
|
||||
- http://127.0.0.1:*
|
||||
5
roles/vhosts/acp_vhosts/handlers/main.yml
Normal file
5
roles/vhosts/acp_vhosts/handlers/main.yml
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
- name: Reload caddy
|
||||
ansible.builtin.service:
|
||||
name: caddy
|
||||
state: reloaded
|
||||
23
roles/vhosts/acp_vhosts/tasks/config.yml
Normal file
23
roles/vhosts/acp_vhosts/tasks/config.yml
Normal file
@ -0,0 +1,23 @@
|
||||
---
|
||||
- name: Ensure Caddy fragment directory exists for unified ACP vhost
|
||||
ansible.builtin.file:
|
||||
path: "{{ acp_vhosts_caddy_conf_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
- name: Deploy unified ACP Caddy site
|
||||
ansible.builtin.template:
|
||||
src: acp-site.caddy.j2
|
||||
dest: "{{ acp_vhosts_caddy_fragment_path }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Reload caddy
|
||||
|
||||
- name: Ensure Caddy is enabled and running for unified ACP vhost
|
||||
ansible.builtin.systemd:
|
||||
name: caddy
|
||||
enabled: true
|
||||
state: started
|
||||
8
roles/vhosts/acp_vhosts/tasks/main.yml
Normal file
8
roles/vhosts/acp_vhosts/tasks/main.yml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Include unified ACP vhost config tasks
|
||||
ansible.builtin.import_tasks: config.yml
|
||||
tags: [acp_vhosts, acp_vhosts_config]
|
||||
|
||||
- name: Include unified ACP vhost validation tasks
|
||||
ansible.builtin.import_tasks: validate.yml
|
||||
tags: [acp_vhosts, acp_vhosts_validate]
|
||||
72
roles/vhosts/acp_vhosts/tasks/validate.yml
Normal file
72
roles/vhosts/acp_vhosts/tasks/validate.yml
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
- name: Validate Caddy configuration for unified ACP vhost
|
||||
ansible.builtin.command: caddy validate --config "{{ acp_vhosts_caddyfile_path }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Show unified ACP Caddy fragment
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- cat
|
||||
- "{{ acp_vhosts_caddy_fragment_path }}"
|
||||
register: acp_vhosts_fragment
|
||||
changed_when: false
|
||||
|
||||
- name: Validate unified ACP Caddy fragment includes Codex path route
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "'handle_path /codex*' in acp_vhosts_fragment.stdout"
|
||||
fail_msg: "Unified ACP Caddy fragment is missing the /codex path route."
|
||||
success_msg: "Unified ACP Caddy fragment includes the /codex path route."
|
||||
|
||||
- name: Validate unified ACP Caddy fragment includes OpenCode path route
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "'handle_path /opencode*' in acp_vhosts_fragment.stdout"
|
||||
fail_msg: "Unified ACP Caddy fragment is missing the /opencode path route."
|
||||
success_msg: "Unified ACP Caddy fragment includes the /opencode path route."
|
||||
|
||||
- name: Validate unified Codex ACP HTTP route redirects to HTTPS
|
||||
ansible.builtin.uri:
|
||||
url: "http://127.0.0.1/codex/acp/rpc"
|
||||
method: POST
|
||||
headers:
|
||||
Host: "{{ acp_vhosts_domain }}"
|
||||
body_format: json
|
||||
body:
|
||||
jsonrpc: "2.0"
|
||||
id: 1
|
||||
method: acp.capabilities
|
||||
params: {}
|
||||
return_content: false
|
||||
follow_redirects: none
|
||||
status_code: 308
|
||||
register: acp_vhosts_codex_redirect
|
||||
|
||||
- name: Validate unified OpenCode ACP HTTP route redirects to HTTPS
|
||||
ansible.builtin.uri:
|
||||
url: "http://127.0.0.1/opencode/acp/rpc"
|
||||
method: POST
|
||||
headers:
|
||||
Host: "{{ acp_vhosts_domain }}"
|
||||
body_format: json
|
||||
body:
|
||||
jsonrpc: "2.0"
|
||||
id: 1
|
||||
method: acp.capabilities
|
||||
params: {}
|
||||
return_content: false
|
||||
follow_redirects: none
|
||||
status_code: 308
|
||||
register: acp_vhosts_opencode_redirect
|
||||
changed_when: false
|
||||
|
||||
- name: Show unified ACP vhost validation summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "Unified domain: {{ acp_vhosts_domain }}"
|
||||
- "Codex route: /codex -> {{ acp_vhosts_codex_upstream_host }}:{{ acp_vhosts_codex_upstream_port }}"
|
||||
- "OpenCode route: /opencode -> {{ acp_vhosts_opencode_upstream_host }}:{{ acp_vhosts_opencode_upstream_port }}"
|
||||
- "Deployed fragment: {{ acp_vhosts_fragment.stdout | default('N/A') }}"
|
||||
- "Codex redirect location: {{ acp_vhosts_codex_redirect.location | default('N/A') }}"
|
||||
- "OpenCode redirect location: {{ acp_vhosts_opencode_redirect.location | default('N/A') }}"
|
||||
- "TLS validation is expected to require public DNS + certificate issuance for {{ acp_vhosts_domain }}"
|
||||
9
roles/vhosts/acp_vhosts/templates/acp-site.caddy.j2
Normal file
9
roles/vhosts/acp_vhosts/templates/acp-site.caddy.j2
Normal file
@ -0,0 +1,9 @@
|
||||
{{ acp_vhosts_domain }} {
|
||||
handle_path /codex* {
|
||||
reverse_proxy {{ acp_vhosts_codex_upstream_host }}:{{ acp_vhosts_codex_upstream_port }}
|
||||
}
|
||||
|
||||
handle_path /opencode* {
|
||||
reverse_proxy {{ acp_vhosts_opencode_upstream_host }}:{{ acp_vhosts_opencode_upstream_port }}
|
||||
}
|
||||
}
|
||||
9
update_cloudflare_dns.yml
Normal file
9
update_cloudflare_dns.yml
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
- name: Update Cloudflare DNS records for svc.plus
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: false
|
||||
vars_files:
|
||||
- vars/cloudflare_svc_plus_dns.yml
|
||||
roles:
|
||||
- cloudflare_dns
|
||||
82
vars/cloudflare_svc_plus_dns.yml
Normal file
82
vars/cloudflare_svc_plus_dns.yml
Normal file
@ -0,0 +1,82 @@
|
||||
---
|
||||
cloudflare_dns_records:
|
||||
- type: A
|
||||
name: vps-rag-server.svc.plus
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: vps-accounts.svc.plus
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: vps-preview-accounts.svc.plus
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: docs.svc.plus
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: x-scope-hub.svc.plus
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: x-ops-agent.svc.plus
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: x-cloud-flow.svc.plus
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: accounts-preview.svc.plus
|
||||
content: 46.250.251.132
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: acp-server.svc.plus
|
||||
content: 167.179.110.129
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: acp-server-codex.svc.plus
|
||||
content: 167.179.110.129
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: A
|
||||
name: acp-server-opencode.svc.plus
|
||||
content: 167.179.110.129
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: CNAME
|
||||
name: console-8fa9cd3-contabo.svc.plus
|
||||
content: jp-xhttp-contabo.svc.plus
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: CNAME
|
||||
name: console.svc.plus
|
||||
content: console-8fa9cd3-contabo.svc.plus
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: CNAME
|
||||
name: rag-server.svc.plus
|
||||
content: vps-rag-server.svc.plus
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: CNAME
|
||||
name: accounts.svc.plus
|
||||
content: vps-accounts.svc.plus
|
||||
ttl: 1
|
||||
proxied: false
|
||||
- type: CNAME
|
||||
name: preview-accounts.svc.plus
|
||||
content: vps-preview-accounts.svc.plus
|
||||
ttl: 1
|
||||
proxied: false
|
||||
Loading…
Reference in New Issue
Block a user