Skip to content

Checking access...

IC Custom Domain Setup Runbook ​

⚠️ SUPERSEDED for the member frontend suites — see note. The think-tank-suite, governance-suite, otter-camp-suite, dao-suite, dao-admin-suite, and marketing-suite frontends migrated OFF IC asset canisters to OVH MKS (epic-frontend-001, 2026-06-16), where TLS is handled by cert-manager (Let's Encrypt) — there is no IC custom-domain to register for them. think-tank-suite is additionally deprecated → FounderyOS (repo DELETED). This runbook and its "✅ Working" suite tables below are historical; the IC custom-domain procedure applies only to any remaining IC-hosted canister. (bl-746-1)

Overview ​

This runbook documents how to configure custom domains for Internet Computer canisters. IC uses DNS TXT records to map custom domains to canister IDs.

Prerequisites ​

  • Access to DNS management (Cloudflare for helloworlddao.com — see Infrastructure)
  • Canister deployed to IC mainnet
  • Canister ID (get via dfx canister --network ic id <canister-name>)

How IC Custom Domains Work ​

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│  User Browser   │────▶│  IC Boundary     │────▶│   Canister      │
│                 │     │  Nodes           │     │                 │
└─────────────────┘     └──────────────────┘     └─────────────────┘
        │                       │
        │  1. Request to        │  2. Lookup TXT record
        │     custom domain     │     _canister-id.domain
        │                       │
        │                       │  3. Route to canister
        │                       │     + generate SSL cert

IC boundary nodes:

  1. Receive requests for custom domains
  2. Query DNS for _canister-id.<domain> TXT record
  3. Route traffic to the specified canister
  4. Automatically provision Let's Encrypt SSL certificates

Current Domain Configuration ​

Active Suite Domains ​

Historical — all six suite rows below migrated to OVH MKS (epic-frontend-001, 2026-06-16) and no longer serve from these IC asset canisters.

DomainCanisterCanister IDStatus
staging-think-tank.helloworlddao.comthink-tank-suite (deprecated → FounderyOS)wnfjk-biaaa-aaaao-a6dhq-cai➖ Migrated to OVH MKS (no longer on IC)
staging-governance.helloworlddao.comgovernance-suitewkep6-mqaaa-aaaao-a6dha-cai➖ Migrated to OVH MKS (no longer on IC)
staging-ottercamp.helloworlddao.comotter-camp-suitedzt3i-sqaaa-aaaao-a6uaa-cai➖ Migrated to OVH MKS (no longer on IC)
staging-portal.helloworlddao.comdao-suited6s54-7iaaa-aaaao-a6uaq-cai➖ Migrated to OVH MKS (no longer on IC)
staging-admin.helloworlddao.comdao-admin-suitedxrwa-jaaaa-aaaao-a6uba-cai➖ Migrated to OVH MKS (no longer on IC)
www.helloworlddao.commarketing-suited5fe6-hqaaa-aaaao-a6t5q-cai➖ Migrated to OVH MKS (no longer on IC)
docs.staging.helloworlddao.comdocs (VitePress)n/a — migrated to OVH MKS (frontend-001-4)✅ Working (OVH MKS, not IC)

Legacy Monolith Domains (Archived) ​

DomainCanisterCanister IDStatus
staging.helloworlddao.comwww (frontend)vlmti-wqaaa-aaaad-acoiq-caiDELETED 2026-02-17 — domain no longer routed
(admin monolith)admin (frontend)ehbll-kiaaa-aaaac-qc2aa-caiDELETED 2026-02-17

Both legacy canisters were deleted as part of the FAS (Frontend Application Split) migration and are no longer valid IC custom-domain targets. Use the 6-suite canisters listed above instead.

Step 1: Get Canister ID ​

bash
# Set environment to suppress warnings
export DFX_WARNING=-mainnet_plaintext_identity

# Get canister ID (run from the suite repo)
cd <repo-root>/dao-admin-suite        # or whichever suite you are configuring
dfx canister --network ic id dao_admin_suite_assets
# Output (example): dxrwa-jaaaa-aaaao-a6uba-cai

cd <repo-root>/marketing-suite
dfx canister --network ic id marketing_suite_assets
# Output (example): d5fe6-hqaaa-aaaao-a6t5q-cai

<repo-root> is wherever you've cloned the repos locally — substitute your own path. See Workspace Setup for the canonical clone instructions.

Step 2: Configure DNS Records ​

Required Records ​

For each custom domain, add these DNS records in Cloudflare. The canonical script is ops-infra/scripts/cloudflare-dns-sync.sh — prefer adding records there over editing the dashboard manually:

A Record (Points domain to IC) ​

Type: A
Name: <subdomain> (e.g., "staging-admin" or "staging")
Value: 23.142.184.129
TTL: 600

Note: IC boundary nodes are at multiple IPs. Using icp0.io as CNAME is preferred:

Type: CNAME
Name: <subdomain>
Value: icp0.io
TTL: 600
Type: TXT
Name: _canister-id.<subdomain>
Value: <canister-id>
TTL: 600

Example: staging-admin.helloworlddao.com ​

# Option 1: CNAME (preferred)
Type: CNAME
Name: staging-admin
Value: icp0.io
TTL: 600
Proxied: false  # CRITICAL — IC boundary nodes need DNS-only

# Required: Canister ID TXT record
Type: TXT
Name: _canister-id.staging-admin
Value: dxrwa-jaaaa-aaaao-a6uba-cai
TTL: 600

Example: www.helloworlddao.com (Production) ​

# Option 1: CNAME
Type: CNAME
Name: www
Value: icp0.io
TTL: 600
Proxied: false

# Required: Canister ID TXT record
Type: TXT
Name: _canister-id.www
Value: d5fe6-hqaaa-aaaao-a6t5q-cai
TTL: 600

Step 3: Verify DNS Propagation ​

Wait for DNS propagation (typically 1-2 hours, maximum 24 hours), then verify:

bash
# Check A/CNAME record
dig staging-admin.helloworlddao.com +short
# Should return: icp0.io or 23.142.184.129

# Check TXT record (critical!)
dig _canister-id.staging-admin.helloworlddao.com TXT +short
# Should return: "dxrwa-jaaaa-aaaao-a6uba-cai"

Step 4: Register Domain with IC API ​

CRITICAL: DNS records alone are not enough. You must explicitly register the domain with IC's custom domain API.

New Domain Registration ​

For a new domain (first time setup):

bash
# Validate configuration first
curl -s "https://icp0.io/custom-domains/v1/staging-admin.helloworlddao.com/validate" | jq .

# Register the domain (POST for new domains)
curl -s -X POST "https://icp0.io/custom-domains/v1/staging-admin.helloworlddao.com" | jq .

# Check registration status
curl -s "https://icp0.io/custom-domains/v1/staging-admin.helloworlddao.com" | jq .

Domain Transfer (Moving Between Canisters) ​

If you need to transfer a domain from one canister to another:

bash
# Update DNS records first (change _canister-id TXT record to new canister ID)
# Wait for DNS propagation (1-2 hours typically, max 24 hours)

# Transfer the domain (PATCH for existing domains)
curl -s -X PATCH "https://icp0.io/custom-domains/v1/YOUR_DOMAIN" | jq .

# IMPORTANT: Also remove domain from old canister's .well-known/ic-domains file
# The domain must be removed from the old canister to complete the transfer

Note: IC boundary nodes now auto-discover domains from DNS records, but explicit registration via the API is still best practice to ensure proper SSL certificate provisioning.

Expected Registration Flow ​

  1. validation_status: "valid" - DNS is correctly configured
  2. registration_status: "registering" - Processing request
  3. registration_status: "registered" - Complete, SSL will be provisioned

Step 5: Verify SSL Certificate ​

After registration completes, IC will provision SSL. Verify:

bash
# Check SSL certificate
echo | openssl s_client -connect staging-admin.helloworlddao.com:443 \
  -servername staging-admin.helloworlddao.com 2>&1 | grep "subject="
# Should return: subject=CN = staging-admin.helloworlddao.com

If SSL shows wrong domain (e.g., ai.icpex.org):

  • TXT record is missing or incorrect
  • DNS hasn't propagated yet
  • Wait 10-15 minutes and retry

Step 6: Test the Domain ​

bash
# Test HTTPS
curl -s -o /dev/null -w "%{http_code}\n" https://staging-admin.helloworlddao.com

# Should return: 200

Troubleshooting ​

Problem: SSL Certificate Mismatch (Wrong Domain) ​

Symptom: Browser shows SSL error, certificate for wrong domain (e.g., ai.icpex.org)

Cause: Domain was never registered with IC's custom domain API, or domain transfer incomplete

Solution:

  1. Check registration status:
    bash
    curl -s "https://icp0.io/custom-domains/v1/YOUR_DOMAIN" | jq .
  2. If not_found, register the domain:
    bash
    curl -s -X POST "https://icp0.io/custom-domains/v1/YOUR_DOMAIN" | jq .
  3. If transferring from another canister:
    bash
    # Use PATCH instead of POST for existing domains
    curl -s -X PATCH "https://icp0.io/custom-domains/v1/YOUR_DOMAIN" | jq .
    
    # Also remove domain from old canister's .well-known/ic-domains file
  4. Wait for registration_status: "registered"
  5. Certificate will be provisioned automatically

Problem: _canister-id TXT Record Missing ​

Symptom: Validation fails, can't register domain

Cause: _canister-id TXT record missing or incorrect

Solution:

  1. Verify TXT record: dig _canister-id.<domain> TXT +short
  2. If missing, add the TXT record in DNS
  3. Wait 10-15 minutes for propagation
  4. Re-run validation and registration

Problem: DNS Not Resolving ​

Symptom: dig <domain> +short returns nothing

Cause: A/CNAME record missing

Solution:

  1. Add A record pointing to 23.142.184.129 or CNAME to icp0.io
  2. Wait 5-10 minutes for propagation

Problem: HTTP 308 Redirect Loop ​

Symptom: Constant redirects, never loads

Cause: Usually a caching issue

Solution:

  1. Clear browser cache
  2. Try incognito/private window
  3. Try curl -L to follow redirects

Problem: Canister Returns 404 ​

Symptom: Domain works but shows 404

Cause: Canister assets not deployed or wrong path

Solution:

  1. Verify canister has assets: dfx canister --network ic info <name>
  2. Redeploy if needed: dfx deploy --network ic <name>

Fallback: Raw IC URL ​

If custom domain isn't working, use the raw IC URL:

CanisterRaw URL
Foundery OS Suitehttps://wnfjk-biaaa-aaaao-a6dhq-cai.icp0.io/
Governance Suitehttps://wkep6-mqaaa-aaaao-a6dha-cai.icp0.io/
Marketing Suitehttps://d5fe6-hqaaa-aaaao-a6t5q-cai.icp0.io/
Otter Camp Suitehttps://dzt3i-sqaaa-aaaao-a6uaa-cai.icp0.io/
DAO Suitehttps://d6s54-7iaaa-aaaao-a6uaq-cai.icp0.io/
DAO Admin Suitehttps://dxrwa-jaaaa-aaaao-a6uba-cai.icp0.io/
Docs Sitehttps://docs.staging.helloworlddao.com/ (OVH MKS — no IC canister)

DNS Records Checklist ​

Staging Environment ​

Record TypeNameValueStatus
CNAMEstaging-think-tankicp0.io✅
TXT_canister-id.staging-think-tankwnfjk-biaaa-aaaao-a6dhq-cai✅
CNAMEstaging-governanceicp0.io✅
TXT_canister-id.staging-governancewkep6-mqaaa-aaaao-a6dha-cai✅
CNAMEstaging-ottercampicp0.io✅
TXT_canister-id.staging-ottercampdzt3i-sqaaa-aaaao-a6uaa-cai✅
CNAMEstaging-portalicp0.io✅
TXT_canister-id.staging-portald6s54-7iaaa-aaaao-a6uaq-cai✅
CNAMEstaging-adminicp0.io✅
TXT_canister-id.staging-admindxrwa-jaaaa-aaaao-a6uba-cai✅
CNAMEstaging-docs—➖ Retired (bl-1120) — docs serves from OVH MKS at docs.staging.helloworlddao.com, not IC
TXT_canister-id.staging-docs—➖ Retired (bl-1120) — no IC canister

Production Environment ​

Record TypeNameValueStatus
CNAMEwwwicp0.io✅
TXT_canister-id.wwwd5fe6-hqaaa-aaaao-a6t5q-cai✅
CNAMEfounderyicp0.io⚠️ Configure when ready
TXT_canister-id.founderywnfjk-biaaa-aaaao-a6dhq-cai⚠️ Configure when ready
CNAMEgovernanceicp0.io⚠️ Configure when ready
TXT_canister-id.governancewkep6-mqaaa-aaaao-a6dha-cai⚠️ Configure when ready
CNAMEottercampicp0.io⚠️ Configure when ready
TXT_canister-id.ottercampdzt3i-sqaaa-aaaao-a6uaa-cai⚠️ Configure when ready
CNAMEportalicp0.io⚠️ Configure when ready
TXT_canister-id.portald6s54-7iaaa-aaaao-a6uaq-cai⚠️ Configure when ready
CNAMEadminicp0.io⚠️ Configure when ready
TXT_canister-id.admindxrwa-jaaaa-aaaao-a6uba-cai⚠️ Configure when ready
CNAMEdocs—➖ Retired (bl-1120) — docs will not run on IC; served from OVH MKS
TXT_canister-id.docs—➖ Retired (bl-1120) — no IC canister

Estimated Time ​

  • DNS record addition: 5 minutes
  • DNS propagation: 1-2 hours typically (max 24 hours)
  • API registration: 1-2 minutes
  • SSL certificate provisioning: 5-10 minutes
  • Total: ~2-3 hours (wait for DNS), then 5-10 minutes for SSL

Hello World DAO