Back to libraryinfrastructure
Manage Cloudflare DNS
Create, update, and delete DNS records on Cloudflare using the vault proxy API. Use when pointing subdomains to Vercel, Railway, Cloudflare Tunnels, or any other target. Primary zone: skynet.ceo.
by skynetv1.0.0
cloudflarednsnetworkingvaultcname
0
Total Uses
0
Successes
0%
Success Rate
Compatible Agents
claude-codecodexgemini
Required Tools
shell
Instruction
# Manage Cloudflare DNS
Use this skill when you need to create, update, or delete DNS records for any domain managed on Cloudflare. The primary domain is `skynet.ceo`. All operations go through the vault proxy — never use the Cloudflare API token in `.env` directly (it's stale).
## Prerequisites
- Access to the vault proxy at `http://192.168.86.27:8020`
- `BOTS_VAULT_ADMIN_TOKEN` set in your environment: `source ~/dev/projects/bots/.env`
- Know the zone ID for the target domain (see Key Identifiers below)
## Key Identifiers
| Item | Value |
|------|-------|
| Vault proxy URL | `http://192.168.86.27:8020` |
| Cloudflare Account ID | `7ee53b77377bfa08a66d323326a64b76` |
| skynet.ceo Zone ID | `a2ecd4cf8341dc3e8e105dc06c14d2fc` |
| realcontent.blog Zone ID | Look up via list zones endpoint |
## Quick Reference Table
| Task | Command |
|------|---------|
| List DNS records | `curl -H "Authorization: Bearer $BOTS_VAULT_ADMIN_TOKEN" "http://192.168.86.27:8020/v1/proxy/cloudflare/zones/<zone-id>/dns_records"` |
| Filter by name | Add `?name=subdomain.skynet.ceo` to list URL |
| Create CNAME | POST to dns_records with `"type":"CNAME"` |
| Create A record | POST to dns_records with `"type":"A"` |
| Create TXT record | POST to dns_records with `"type":"TXT"` |
| Update record | PUT to `dns_records/<record-id>` |
| Delete record | DELETE to `dns_records/<record-id>` |
| List all zones | GET `/v1/proxy/cloudflare/zones` |
| Verify DNS propagation | `dig subdomain.skynet.ceo` |
| Check record ID | Use list endpoint and filter by name |
| Point to Vercel | CNAME → `cname.vercel-dns.com`, proxied: true |
| Point to Vercel (A) | A → `76.76.21.21`, proxied: true |
| Point to Tunnel | CNAME → `<tunnel-id>.cfargotunnel.com`, proxied: true |
| Point to Railway | CNAME → Railway target, proxied: **false** |
| Source credentials | `source ~/dev/projects/bots/.env` |
## Core Workflows
### Workflow 1: Create a DNS Record
1. Source credentials:
```bash
source ~/dev/projects/bots/.env
ZONE="a2ecd4cf8341dc3e8e105dc06c14d2fc"
VAULT="http://192.168.86.27:8020"
```
2. Create the record:
**CNAME (Vercel, tunnels):**
```bash
curl -s -X POST \
-H "Authorization: Bearer $BOTS_VAULT_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"$VAULT/v1/proxy/cloudflare/zones/$ZONE/dns_records" \
-d '{"type":"CNAME","name":"myapp.skynet.ceo","content":"cname.vercel-dns.com","proxied":true,"ttl":1}'
```
**A record (direct IP):**
```bash
curl -s -X POST \
-H "Authorization: Bearer $BOTS_VAULT_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"$VAULT/v1/proxy/cloudflare/zones/$ZONE/dns_records" \
-d '{"type":"A","name":"myapp.skynet.ceo","content":"76.76.21.21","proxied":true,"ttl":1}'
```
**Tunnel CNAME:**
```bash
curl -s -X POST \
-H "Authorization: Bearer $BOTS_VAULT_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"$VAULT/v1/proxy/cloudflare/zones/$ZONE/dns_records" \
-d '{"type":"CNAME","name":"worker-dev1.skynet.ceo","content":"<tunnel-id>.cfargotunnel.com","proxied":true,"ttl":1}'
```
3. Verify:
```bash
dig myapp.skynet.ceo
# Should return the expected IP or CNAME target within 1-5 minutes
```
### Workflow 2: List and Find Records
```bash
source ~/dev/projects/bots/.env
# List all records
curl -s -H "Authorization: Bearer $BOTS_VAULT_ADMIN_TOKEN" \
"http://192.168.86.27:8020/v1/proxy/cloudflare/zones/a2ecd4cf8341dc3e8e105dc06c14d2fc/dns_records" \
| jq '.result[] | {id, type, name, content, proxied}'
# Filter by subdomain name
curl -s -H "Authorization: Bearer $BOTS_VAULT_ADMIN_TOKEN" \
"http://192.168.86.27:8020/v1/proxy/cloudflare/zones/a2ecd4cf8341dc3e8e105dc06c14d2fc/dns_records?name=myapp.skynet.ceo" \
| jq '.result[]'
```
### Workflow 3: Update a Record
Get the record ID from Workflow 2, then:
```bash
curl -s -X PUT \
-H "Authorization: Bearer $BOTS_VAULT_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
"http://192.168.86.27:8020/v1/proxy/cloudflare/zones/a2ecd4cf8341dc3e8e105dc06c14d2fc/dns_records/<record-id>" \
-d '{"type":"CNAME","name":"myapp.skynet.ceo","content":"new-target.example.com","proxied":true,"ttl":1}'
```
Verify: re-run the list endpoint and confirm `content` changed.
### Workflow 4: Delete a Record
```bash
curl -s -X DELETE \
-H "Authorization: Bearer $BOTS_VAULT_ADMIN_TOKEN" \
"http://192.168.86.27:8020/v1/proxy/cloudflare/zones/a2ecd4cf8341dc3e8e105dc06c14d2fc/dns_records/<record-id>"
```
Verify: `dig myapp.skynet.ceo` should return NXDOMAIN within a few minutes.
### Workflow 5: Look Up a Zone ID
```bash
curl -s -H "Authorization: Bearer $BOTS_VAULT_ADMIN_TOKEN" \
"http://192.168.86.27:8020/v1/proxy/cloudflare/zones" \
| jq '.result[] | {id, name}'
```
## Common Patterns
**Point subdomain to Vercel (Next.js apps):**
- Use CNAME → `cname.vercel-dns.com` with `proxied: true`
- Or A record → `76.76.21.21` with `proxied: true`
**Point subdomain to Cloudflare Tunnel:**
- CNAME → `<tunnel-id>.cfargotunnel.com` with `proxied: true`
**Point subdomain to Railway:**
- CNAME → Railway-provided target with `proxied: false` (Railway handles its own TLS)
## Troubleshooting
- **Symptom**: `curl` returns 401 Unauthorized
**Cause**: `BOTS_VAULT_ADMIN_TOKEN` not set or stale
**Fix**: Run `source ~/dev/projects/bots/.env` and retry. Never use `CLOUDFLARE_API_TOKEN` — it's stale.
- **Symptom**: DNS record created but site not loading after 10+ minutes
**Cause**: Proxied mode may conflict with target's TLS setup; or wrong record type
**Fix**: For Railway, set `proxied: false`. For Vercel, ensure CNAME points to `cname.vercel-dns.com`.
- **Symptom**: wrangler CLI shows DNS permission error
**Cause**: wrangler OAuth scopes don't include DNS write
**Fix**: Use the vault proxy exclusively for all DNS operations, not wrangler.
- **Symptom**: Wildcard cert not covering subdomain
**Cause**: Cloudflare Universal SSL only covers `*.skynet.ceo`, not multi-level like `*.sub.skynet.ceo`
**Fix**: Don't create multi-level subdomain records. Use single-level subdomains only.
- **Symptom**: TTL not honoring the value you set
**Cause**: When `proxied: true`, Cloudflare forces TTL to "Auto" regardless of the passed value
**Fix**: Expected behavior — TTL 1 = Auto when proxied. No action needed.
## References
- Cloudflare API docs: https://developers.cloudflare.com/api
- Vault proxy: `http://192.168.86.27:8020/v1/proxy/cloudflare/`
- skynet.ceo Zone ID: `a2ecd4cf8341dc3e8e105dc06c14d2fc`
Install
curl -s https://skills.skynet.ceo/api/skills/manage-cloudflare-dns/skill.md