@@ -33,14 +33,26 @@ The dstack-ingress system provides a seamless way to set up custom domains for d
33333 . ** Certificate Management** :
3434
3535 - SSL certificates are automatically obtained during initial setup
36- - A scheduled task runs twice daily to check for certificate renewal
36+ - A simple background daemon checks for certificate renewal every 12 hours
3737 - When certificates are renewed, Nginx is automatically reloaded to use the new certificates
38+ - Uses a simple sleep loop instead of cron for reliability and easier debugging in containers
3839
39404 . ** Evidence Generation** :
4041 - The system generates evidence files for verification purposes
4142 - These include the ACME account information and certificate data
4243 - Evidence files are accessible through a dedicated endpoint
4344
45+ ## Features
46+
47+ ### Multi-Domain Support (New!)
48+
49+ The dstack-ingress now supports multiple domains in a single container:
50+
51+ - ** Single Domain Mode** (backward compatible): Use ` DOMAIN ` and ` TARGET_ENDPOINT ` environment variables
52+ - ** Multi-Domain Mode** : Use ` DOMAINS ` environment variable with custom nginx configurations in ` /etc/nginx/conf.d/ `
53+ - Each domain gets its own SSL certificate
54+ - Flexible nginx configuration per domain
55+
4456## Usage
4557
4658### Prerequisites
@@ -50,7 +62,7 @@ The dstack-ingress system provides a seamless way to set up custom domains for d
5062
5163### Deployment
5264
53- You can either build the ingress container and push it to docker hub, or use the prebuilt image at ` kvin /dstack-ingress` .
65+ You can either build the ingress container and push it to docker hub, or use the prebuilt image at ` dstacktee /dstack-ingress:20250924 ` .
5466
5567#### Option 1: Use the Pre-built Image
5668
@@ -59,7 +71,7 @@ The fastest way to get started is to use our pre-built image. Simply use the fol
5971``` yaml
6072services :
6173 dstack-ingress :
62- image : kvin /dstack-ingress@sha256:b61d50360c7a4e5ab7d22f5ce87677714f3f64a65db34ee5eebcc54683950c89
74+ image : dstacktee /dstack-ingress:20250924 @sha256:40429d78060ef3066b5f93676bf3ba7c2e9ac47d4648440febfdda558aed4b32
6375 ports :
6476 - " 443:443"
6577 environment :
@@ -87,15 +99,90 @@ volumes:
8799 cert-data : # Persistent volume for certificates
88100` ` `
89101
102+ ### Multi-Domain Configuration
103+
104+ ` ` ` yaml
105+ services :
106+ ingress :
107+ image : dstacktee/dstack-ingress:20250924@sha256:40429d78060ef3066b5f93676bf3ba7c2e9ac47d4648440febfdda558aed4b32
108+ ports :
109+ - " 443:443"
110+ environment :
111+ DNS_PROVIDER : cloudflare
112+ CLOUDFLARE_API_TOKEN : ${CLOUDFLARE_API_TOKEN}
113+ CERTBOT_EMAIL : ${CERTBOT_EMAIL}
114+ GATEWAY_DOMAIN : _.dstack-prod5.phala.network
115+ SET_CAA : true
116+ DOMAINS : |
117+ ${APP_DOMAIN}
118+ ${API_DOMAIN}
119+
120+ volumes :
121+ - /var/run/tappd.sock:/var/run/tappd.sock
122+ - letsencrypt:/etc/letsencrypt
123+
124+ configs :
125+ - source : app_conf
126+ target : /etc/nginx/conf.d/app.conf
127+ mode : 0444
128+ - source : api_conf
129+ target : /etc/nginx/conf.d/api.conf
130+ mode : 0444
131+
132+ restart : unless-stopped
133+
134+ app-main :
135+ image : nginx
136+ restart : unless-stopped
137+
138+ app-api :
139+ image : nginx
140+ restart : unless-stopped
141+
142+ volumes :
143+ letsencrypt :
144+
145+ configs :
146+ app_conf :
147+ content : |
148+ server {
149+ listen 443 ssl;
150+ server_name ${APP_DOMAIN};
151+ ssl_certificate /etc/letsencrypt/live/${APP_DOMAIN}/fullchain.pem;
152+ ssl_certificate_key /etc/letsencrypt/live/${APP_DOMAIN}/privkey.pem;
153+ location / {
154+ proxy_pass http://app-main:80;
155+ }
156+ }
157+ api_conf :
158+ content : |
159+ server {
160+ listen 443 ssl;
161+ server_name ${API_DOMAIN};
162+ ssl_certificate /etc/letsencrypt/live/${API_DOMAIN}/fullchain.pem;
163+ ssl_certificate_key /etc/letsencrypt/live/${API_DOMAIN}/privkey.pem;
164+ location / {
165+ proxy_pass http://app-api:80;
166+ }
167+ }
168+ ` ` `
169+
90170**Core Environment Variables:**
91171
92172- ` DNS_PROVIDER`: DNS provider to use (cloudflare, linode)
93- - `DOMAIN` : Your custom domain
173+ - `DOMAIN` : Your custom domain (for single domain mode)
174+ - `DOMAINS` : Multiple domains, one per line (supports environment variable substitution like `${APP_DOMAIN}`)
94175- `GATEWAY_DOMAIN` : The dstack gateway domain (e.g. `_.dstack-prod5.phala.network` for Phala Cloud)
95176- `CERTBOT_EMAIL` : Your email address used in Let's Encrypt certificate requests
96- - `TARGET_ENDPOINT` : The plain HTTP endpoint of your dstack application
177+ - `TARGET_ENDPOINT` : The plain HTTP endpoint of your dstack application (for single domain mode)
97178- `SET_CAA` : Set to `true` to enable CAA record setup
98179
180+ **Backward Compatibility:**
181+
182+ - If both `DOMAIN` and `TARGET_ENDPOINT` are set, the system operates in single-domain mode with auto-generated nginx config
183+ - If `DOMAINS` is set, the system operates in multi-domain mode and expects custom nginx configs in `/etc/nginx/conf.d/`
184+ - You can use both modes simultaneously
185+
99186For provider-specific configuration details, see [DNS Provider Configuration](DNS_PROVIDERS.md).
100187
101188# ### Option 2: Build Your Own Image
@@ -126,7 +213,6 @@ docker push yourusername/dstack-ingress:tag
126213
1272144. Update the docker-compose.yaml file with your image name and deploy
128215
129-
130216# ### gRPC Support
131217
132218If your dstack application uses gRPC, you can set `TARGET_ENDPOINT` to `grpc://app:50051`.
@@ -136,7 +222,7 @@ example:
136222` ` ` yaml
137223services:
138224 dstack-ingress:
139- image: kvin /dstack-ingress@sha256:b61d50360c7a4e5ab7d22f5ce87677714f3f64a65db34ee5eebcc54683950c89
225+ image: dstacktee /dstack-ingress:20250924 @sha256:40429d78060ef3066b5f93676bf3ba7c2e9ac47d4648440febfdda558aed4b32
140226 ports:
141227 - "443:443"
142228 environment:
0 commit comments