api.mycompany.com) instead of the default Phala Cloud domain.
Prerequisites
- A domain with DNS hosted on Cloudflare (Linode and Namecheap also supported)
- Access to your DNS provider’s API token
- A deployed CVM application
Step 1: Create DNS API Token
- Cloudflare
- Linode
- Namecheap
- Go to your Cloudflare Dashboard
- Select your domain
- Go to Get Your API Token
- Click Create Token
- Use the Edit zone DNS template
- Select your domain in Zone Resources
- Click Continue to summary and create the token
- Copy the token for later use
Step 2: Add dstack-ingress to Your Deployment
Update yourdocker-compose.yml to include the dstack-ingress container:
DOMAIN and TARGET_ENDPOINT based on your deployment. The DOMAIN variable defines the domain name to expose the web service. The TARGET_ENDPOINT tells dstack-ingress where to forward incoming traffic:
http://app:80- Forward to service named “app” on port 80http://api:3000- Forward to service named “api” on port 3000- Use the service name from docker-compose, not localhost
Step 3: Configure Environment Variables
In the Phala Cloud dashboard, add these encrypted secrets:- Cloudflare
- Linode
- Namecheap
CLOUDFLARE_API_TOKEN: Your API token from Step 1CERTBOT_EMAIL: Your email for Let’s Encrypt notifications
Step 4: Deploy
Deploy your updated docker-compose.yml through the dashboard. The first deployment takes a few minutes as it:- Configures DNS records
- Requests SSL certificate from Let’s Encrypt
- Sets up the reverse proxy
Step 5: Verify
After deployment, you can:- Access your domain: Visit
https://api.mycompany.com - Check certificate: Your browser should show a valid Let’s Encrypt certificate
- Verify evidence: Visit
https://api.mycompany.com/evidences/to see attestation data
Multiple Services with Custom Domains
You can use multiple custom domains in one deployment. Note that you need to explicitly set the listen port for each service.Why We Pin Infrastructure Images
The dstack-ingress image uses a SHA256 hash instead of a tag to ensure:- Auditability: Anyone can verify the exact infrastructure code handling domains
- Immutability: The ingress behavior never changes unexpectedly
- Security: Prevents infrastructure image substitution
- Reproducibility: Domain handling is consistent across all deployments
Security Features
WhenSET_CAA=true is enabled:
- CAA records restrict certificate issuance to the TEE managed Let’s Encrypt account
- Only certificates requested from within your TEE can be issued
- Certificate transparency logs can be monitored for unauthorized certificates
Cloudflare Users: Cloudflare automatically overrides CAA records at the apex domain (e.g., Should return the Let’s Encrypt account URI with
example.com). This prevents domain attestation from working correctly.Solution options:- Use a subdomain (recommended): Deploy to
app.example.cominstead ofexample.com - Disable Cloudflare’s CAA management: See Cloudflare CAA documentation
validationmethods=dns-01;accounturi=...Troubleshooting
Check Logs
Look for dstack-ingress container logs in the dashboard:Certbot Error: “too many certificates (5) already issued for this exact set of identifiers”
You may forget to attached the data volume.Other Common Issues
DNS not propagating: Wait 2-5 minutes for DNS changes to propagate globally. Certificate request failed: Verify your API token has permission to edit DNS records. Connection refused: EnsureTARGET_ENDPOINT points to the correct service:port.
CAA record conflicts: Some providers (like Linode) don’t allow CAA and CNAME on the same subdomain. The system will automatically use A records instead.

