Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions custom-domain/dstack-ingress/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/.claude/
/CLAUDE.md
/test/
__pycache__
114 changes: 114 additions & 0 deletions custom-domain/dstack-ingress/DNS_PROVIDERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# DNS Provider Configuration Guide

This guide explains how to configure dstack-ingress to work with different DNS providers for managing custom domains and SSL certificates.

## Supported DNS Providers

- **Cloudflare** - The original and default provider
- **Linode DNS** - For Linode-hosted domains

## Environment Variables

### Common Variables (Required for all providers)

- `DOMAIN` - Your custom domain (e.g., `app.example.com`)
- `GATEWAY_DOMAIN` - dstack gateway domain (e.g., `_.dstack-prod5.phala.network`)
- `CERTBOT_EMAIL` - Email for Let's Encrypt registration
- `TARGET_ENDPOINT` - Backend application endpoint to proxy to
- `DNS_PROVIDER` - DNS provider to use (`cloudflare`, `linode`)

### Optional Variables

- `SET_CAA` - Enable CAA record setup (default: false)
- `PORT` - HTTPS port (default: 443)
- `TXT_PREFIX` - Prefix for TXT records (default: "_tapp-address")

## Provider-Specific Configuration

### Cloudflare

```bash
DNS_PROVIDER=cloudflare
CLOUDFLARE_API_TOKEN=your-api-token
```

**Required Permissions:**
- Zone:Read
- DNS:Edit

### Linode DNS

```bash
DNS_PROVIDER=linode
LINODE_API_TOKEN=your-api-token
```

**Required Permissions:**
- Domains: Read/Write access

**Important Note for Linode:**
- Linode has a limitation where CAA and CNAME records cannot coexist on the same subdomain
- To work around this, the system will attempt to use A records instead of CNAME records
- If the gateway domain can be resolved to an IP, an A record will be created
- If resolution fails, it falls back to CNAME (but CAA records won't work on that subdomain)
- This is a Linode-specific limitation not present in other providers

## Docker Compose Example

```yaml
version: '3.8'

services:
ingress:
image: dstack-ingress:latest
ports:
- "443:443"
environment:
# Common configuration
- DNS_PROVIDER=linode
- DOMAIN=app.example.com
- GATEWAY_DOMAIN=_.dstack-prod5.phala.network
- [email protected]
- TARGET_ENDPOINT=http://backend:8080

# Linode specific
- LINODE_API_TOKEN=your-api-token
volumes:
- ./letsencrypt:/etc/letsencrypt
- ./evidences:/evidences
```

## Migration from Cloudflare-only Setup

If you're currently using the Cloudflare-only version:

1. **No changes needed for Cloudflare users** - The default behavior remains Cloudflare
2. **For other providers** - Add the `DNS_PROVIDER` environment variable and provider-specific credentials

## Troubleshooting

### DNS Provider Detection

If you see "Could not detect DNS provider type", ensure you have either:
- Set `DNS_PROVIDER` environment variable explicitly, OR
- Set provider-specific credential environment variables (e.g., `CLOUDFLARE_API_TOKEN`)

### Certificate Generation Issues

Different providers may have different propagation times. The default is 120 seconds, but you may need to adjust based on your provider's behavior.

### Permission Errors

Ensure your API tokens/credentials have the necessary permissions listed above for your provider.

## API Token Generation

### Cloudflare
1. Go to https://dash.cloudflare.com/profile/api-tokens
2. Create token with Zone:Read and DNS:Edit permissions
3. Scope to specific zones if desired

### Linode
1. Go to https://cloud.linode.com/profile/tokens
2. Create a Personal Access Token
3. Grant "Domains" Read/Write access
5 changes: 3 additions & 2 deletions custom-domain/dstack-ingress/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ RUN set -e; \

RUN mkdir -p /etc/letsencrypt /var/www/certbot /usr/share/nginx/html

COPY ./scripts/* /scripts/
RUN chmod +x /scripts/*
COPY ./scripts /scripts/
RUN chmod +x /scripts/*.sh /scripts/*.py
ENV PATH="/scripts:$PATH"
ENV PYTHONPATH="/scripts"
COPY .GIT_REV /etc/

ENTRYPOINT ["/scripts/entrypoint.sh"]
Expand Down
42 changes: 30 additions & 12 deletions custom-domain/dstack-ingress/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# Custom Domain Setup for dstack Applications

This repository provides a solution for setting up custom domains with automatic SSL certificate management for dstack applications using Cloudflare DNS and Let's Encrypt.
This repository provides a solution for setting up custom domains with automatic SSL certificate management for dstack applications using various DNS providers and Let's Encrypt.

## Overview

This project enables you to run dstack applications with your own custom domain, complete with:

- Automatic SSL certificate provisioning and renewal via Let's Encrypt
- Cloudflare DNS configuration for CNAME, TXT, and CAA records
- Multi-provider DNS support (Cloudflare, Linode DNS, more to come)
- Automatic DNS configuration for CNAME, TXT, and CAA records
- Nginx reverse proxy to route traffic to your application
- Certificate evidence generation for verification
- Strong SSL/TLS configuration with modern cipher suites (AES-GCM and ChaCha20-Poly1305)
Expand All @@ -17,16 +18,20 @@ This project enables you to run dstack applications with your own custom domain,
The dstack-ingress system provides a seamless way to set up custom domains for dstack applications with automatic SSL certificate management. Here's how it works:

1. **Initial Setup**:

- When first deployed, the container automatically obtains SSL certificates from Let's Encrypt using DNS validation
- It configures Cloudflare DNS by creating necessary CNAME, TXT, and optional CAA records
- It configures your DNS provider by creating necessary CNAME, TXT, and optional CAA records
- Nginx is configured to use the obtained certificates and proxy requests to your application

2. **DNS Configuration**:

- A CNAME record is created to point your custom domain to the dstack gateway domain
- A TXT record is added with application identification information to help dstack-gateway to route traffic to your application
- If enabled, CAA records are set to restrict which Certificate Authorities can issue certificates for your domain
- The system automatically detects your DNS provider based on environment variables

3. **Certificate Management**:

- SSL certificates are automatically obtained during initial setup
- A scheduled task runs twice daily to check for certificate renewal
- When certificates are renewed, Nginx is automatically reloaded to use the new certificates
Expand All @@ -40,7 +45,8 @@ The dstack-ingress system provides a seamless way to set up custom domains for d

### Prerequisites

- Host your domain on Cloudflare and have access to the Cloudflare account with API token
- Host your domain on one of the supported DNS providers
- Have appropriate API credentials for your DNS provider (see [DNS Provider Configuration](DNS_PROVIDERS.md) for details)

### Deployment

Expand All @@ -57,7 +63,13 @@ services:
ports:
- "443:443"
environment:
# DNS Provider
- DNS_PROVIDER=cloudflare

# Cloudflare example
- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}

# Common configuration
- DOMAIN=${DOMAIN}
- GATEWAY_DOMAIN=${GATEWAY_DOMAIN}
- CERTBOT_EMAIL=${CERTBOT_EMAIL}
Expand All @@ -68,21 +80,23 @@ services:
- cert-data:/etc/letsencrypt
restart: unless-stopped
app:
image: nginx # Replace with your application image
image: nginx # Replace with your application image
restart: unless-stopped
volumes:
cert-data: # Persistent volume for certificates
cert-data: # Persistent volume for certificates
```

Explanation of environment variables:
**Core Environment Variables:**

- `CLOUDFLARE_API_TOKEN`: Your Cloudflare API token
- `DNS_PROVIDER`: DNS provider to use (cloudflare, linode)
- `DOMAIN`: Your custom domain
- `GATEWAY_DOMAIN`: The dstack gateway domain. (e.g. `_.dstack-prod5.phala.network` for Phala Cloud)
- `GATEWAY_DOMAIN`: The dstack gateway domain (e.g. `_.dstack-prod5.phala.network` for Phala Cloud)
- `CERTBOT_EMAIL`: Your email address used in Let's Encrypt certificate requests
- `TARGET_ENDPOINT`: The plain HTTP endpoint of your dstack application
- `SET_CAA`: Set to `true` to enable CAA record setup

For provider-specific configuration details, see [DNS Provider Configuration](DNS_PROVIDERS.md).

#### Option 2: Build Your Own Image

If you prefer to build the image yourself:
Expand All @@ -95,6 +109,7 @@ If you prefer to build the image yourself:
```

**Important**: You must use the `build-image.sh` script to build the image. This script ensures reproducible builds with:

- Specific buildkit version (v0.20.2)
- Deterministic timestamps (`SOURCE_DATE_EPOCH=0`)
- Package pinning for consistency
Expand Down Expand Up @@ -150,10 +165,12 @@ The dstack-ingress system provides mechanisms to verify and attest that your cus
When certificates are issued or renewed, the system automatically generates a set of cryptographically linked evidence files:

1. **Access Evidence Files**:

- Evidence files are accessible at `https://your-domain.com/evidences/`
- Key files include `acme-account.json`, `cert.pem`, `sha256sum.txt`, and `quote.json`

2. **Verification Chain**:

- `quote.json` contains a TDX quote with the SHA-256 digest of `sha256sum.txt` embedded in the report_data field
- `sha256sum.txt` contains cryptographic checksums of both `acme-account.json` and `cert.pem`
- When the TDX quote is verified, it cryptographically proves the integrity of the entire evidence chain
Expand All @@ -178,9 +195,10 @@ The output will display CAA records that restrict certificate issuance exclusive
All Let's Encrypt certificates are logged in public Certificate Transparency (CT) logs, enabling independent verification:

**CT Log Verification**:
- Visit [crt.sh](https://crt.sh/) and search for your domain
- Confirm that the certificates match those issued by the dstack-ingress system
- This public logging ensures that all certificates are visible and can be monitored for unauthorized issuance

- Visit [crt.sh](https://crt.sh/) and search for your domain
- Confirm that the certificates match those issued by the dstack-ingress system
- This public logging ensures that all certificates are visible and can be monitored for unauthorized issuance

## License

Expand Down
Loading
Loading