From a9a97c8f7da9317fa10f832c2f0d255a1f382d91 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 10 Dec 2025 01:20:18 +0000
Subject: [PATCH 1/5] Initial plan
From 794814d251e28d133c51ef61cd37b21ea480f451 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 10 Dec 2025 01:27:10 +0000
Subject: [PATCH 2/5] Update BYOD docs with DNS management options and staging
workflow
Co-authored-by: lionello <591860+lionello@users.noreply.github.com>
---
docs/concepts/domains.mdx | 51 +++++++--
docs/tutorials/use-your-own-domain-name.mdx | 109 ++++++++++++++++++++
2 files changed, 154 insertions(+), 6 deletions(-)
diff --git a/docs/concepts/domains.mdx b/docs/concepts/domains.mdx
index 110bbc0d94..424f4e1708 100644
--- a/docs/concepts/domains.mdx
+++ b/docs/concepts/domains.mdx
@@ -15,22 +15,35 @@ To make your service accessible from the public internet with Defang-hosted doma
### Structure
-Defang-hosted domains use a structure that is based on your username and service name.
+When you deploy a publicly accessible service, Defang automatically provides you with domain names to access it.
-If you have a publicly accessible service, you will automatically receive a domain to access it. If you're deploying to the [Defang Playground](./defang-playground.md), your domain will be structured as follows:
+If you're deploying to the [Defang Playground](./defang-playground.md), you will receive:
+**Defang-hosted domain:**
```
https://---.defang.dev
```
-If you're using [Defang BYOC](./defang-byoc.md), your domain will be:
+If you're using [Defang BYOC](./defang-byoc.md), you will receive **both**:
+**Defang-hosted domain:**
```
https://--...defang.app
```
+
+**Cloud provider load balancer domain** (AWS example):
+```
+https://defang-xyz-b0f79bb-123456789012.ca-central-1.elb.amazonaws.com
+```
+
+:::tip Choosing Between Domains
+- Use the **Defang-hosted domain** (`defang.app`) for convenience and simplicity
+- Use the **cloud provider domain** (e.g., AWS ELB) if you want to avoid dependency on Defang infrastructure
+- Both domains point to the same service and work identically
+:::
@@ -72,18 +85,44 @@ const service = new defang.DefangService("serviceName", {
You can also bring your own domain to a Defang project. This allows you to use your own domain name to access your services, and varies a little bit depending on your setup.
-### BYOC or Defang Playground
+### DNS Management Options
+
+When bringing your own domain, you have two main approaches:
+
+#### Option 1: Using Your Existing DNS Provider (CloudFlare, Namecheap, etc.)
-If you are using [Defang BYOC](./defang-byoc.md) and *do not* have your domain's DNS hosted with your cloud provider, or if you are using the [Defang Playground](./defang-playground.md), you will need to follow this flow:
+If you are using [Defang BYOC](./defang-byoc.md) and *do not* have your domain's DNS hosted with your cloud provider, or if you are using the [Defang Playground](./defang-playground.md), you have two choices:
+**A. Point directly to your custom domain:**
1. Add the `domainname` to your service definition.
2. Run `defang compose up` to deploy your project.
3. Run `defang cert generate` to generate an SSL certificate. This command will provide instructions for where to point your domain's DNS before the certificate can be issued.
+4. **Note:** You will need to run `defang cert generate` again after each `defang compose up` to recreate SSL certificates.
-### BYOC
+**B. Use CNAME to Defang-hosted domain (Recommended for frequent deployments):**
+
+If you frequently deploy and tear down your services (e.g., for staging environments), you can avoid reconfiguring DNS each time by using a CNAME record:
+
+1. Don't add a `domainname` to your service definition.
+2. Run `defang compose up` to deploy your project.
+3. Defang will provide you with a `defang.app` domain (e.g., `service-name--port.project-name.username.defang.app`) and an AWS load balancer domain (e.g., `defang-xyz-b0f79bb-123456789012.ca-central-1.elb.amazonaws.com`).
+4. In your DNS provider, create a CNAME record pointing your custom domain to the `defang.app` domain or the AWS load balancer domain.
+5. You'll still need to run `defang cert generate` once to create the SSL certificate, but you won't need to update your DNS records on subsequent deployments.
+
+:::tip Managing Multiple Environments
+Use the `--project-name` flag or the `name:` field in your Compose file to create separate environments. For example, a project named "hello" with `--project-name hello-staging` would create a separate deployment, allowing you to maintain both production and staging environments simultaneously.
+:::
+
+#### Option 2: Using Route 53 (AWS) - Automatic DNS Management
If you are using [Defang BYOC](./defang-byoc.md) *and the DNS for your domain is hosted with your cloud provider* (i.e. a Hosted Zone in Route 53, if you're using AWS), all you need to do is specify the `domainname` in your service definition, as in the example below.
+**Benefits of Route 53:**
+- DNS records are automatically created and updated
+- SSL certificates are automatically provisioned and renewed
+- No need to run `defang cert generate` after each deployment
+- Ideal for environments that are frequently deployed and torn down
+
:::warning
For the time being, you can only use one domain per service.
If you need to use multiple domains, please vote on this [issue](https://github.com/DefangLabs/defang/issues/247).
diff --git a/docs/tutorials/use-your-own-domain-name.mdx b/docs/tutorials/use-your-own-domain-name.mdx
index 45daecf9ea..588e667be1 100644
--- a/docs/tutorials/use-your-own-domain-name.mdx
+++ b/docs/tutorials/use-your-own-domain-name.mdx
@@ -6,6 +6,10 @@ title: How to Use Your Own Domain
This tutorial will show you how to set up and use your own domain when deploying to AWS using Defang.
+There are two main approaches to using custom domains with Defang on AWS:
+1. **Using Route 53 for DNS management** (Recommended) - Automatic DNS and certificate management
+2. **Using your existing DNS provider** - Manual DNS configuration with CNAMEs
+
## Prerequisites
@@ -14,6 +18,16 @@ This tutorial will show you how to set up and use your own domain when deploying
* [The Defang CLI](/docs/intro/getting-started#install-the-defang-cli)
* [AWS Account Credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html)
+## Approach 1: Using Route 53 (Recommended)
+
+This approach is ideal if you want automatic DNS and certificate management, especially for frequently deployed environments like staging.
+
+**Benefits:**
+- No need to run `defang cert generate` after each deployment
+- DNS records are automatically created and updated
+- SSL certificates are automatically provisioned and renewed
+- Perfect for staging environments that are frequently deployed and torn down
+
## Step 1 - Set up a Hosted Zone in AWS Route 53
:::info
@@ -63,4 +77,99 @@ This will deploy your service and set up the necessary DNS records in Route 53 a
***
+## Approach 2: Using Your Existing DNS Provider (CloudFlare, Namecheap, etc.)
+
+If you prefer to keep your DNS with your current provider (like CloudFlare or Namecheap), you can use CNAME records to point to Defang-provided domains. This approach is particularly useful for frequently deployed environments.
+
+### Option A: Direct Custom Domain with Certificate Generation
+
+1. Add the `domainname` to your service definition in your Compose file:
+ ```yaml
+ services:
+ web:
+ domainname: staging.example.com
+ ports:
+ target: 3000
+ mode: ingress
+ ```
+
+2. Deploy your service:
+ ```bash
+ defang compose up
+ ```
+
+3. Generate an SSL certificate:
+ ```bash
+ defang cert generate
+ ```
+ This command will provide instructions for DNS configuration.
+
+4. **Important:** You'll need to run `defang cert generate` again after each `defang compose up` to recreate SSL certificates.
+
+### Option B: CNAME to Defang Domain (Recommended for Staging)
+
+This approach avoids having to reconfigure DNS and regenerate certificates for each deployment, making it ideal for staging environments that are frequently torn down and redeployed.
+
+1. **Don't** add a `domainname` to your service definition. Just expose the port:
+ ```yaml
+ services:
+ web:
+ ports:
+ target: 3000
+ mode: ingress
+ ```
+
+2. Deploy your service:
+ ```bash
+ defang compose up
+ ```
+
+3. After deployment, Defang provides you with two domains:
+ - **Defang-hosted domain**: `service-name--port.project-name.username.defang.app`
+ - **AWS load balancer domain**: `defang-xyz-b0f79bb-123456789012.ca-central-1.elb.amazonaws.com`
+
+4. In your DNS provider (CloudFlare, Namecheap, etc.), create a CNAME record:
+ - **Name**: `staging` (or your desired subdomain)
+ - **Target**: Either the `defang.app` domain or the AWS ELB domain
+ - **Example**: `staging.example.com` → `web--3000.myproject.myuser.defang.app`
+
+5. Run `defang cert generate` once to create the SSL certificate for your CNAME.
+
+6. For subsequent deployments, simply run `defang compose up`. Your CNAME record will continue to work without needing DNS changes.
+
+### Managing Multiple Environments
+
+To maintain separate staging and production environments simultaneously, use project names:
+
+**Using the `name` field in your Compose file:**
+```yaml
+name: myapp-staging
+
+services:
+ web:
+ ports:
+ target: 3000
+ mode: ingress
+```
+
+**Or using the `--project-name` flag:**
+```bash
+defang compose up --project-name myapp-staging
+defang compose up --project-name myapp-production
+```
+
+Each project name creates a separate deployment with its own domain:
+- Staging: `web--3000.myapp-staging.username.defang.app`
+- Production: `web--3000.myapp-production.username.defang.app`
+
+:::tip
+Create CNAMEs for both environments:
+- `staging.example.com` → `web--3000.myapp-staging.username.defang.app`
+- `app.example.com` → `web--3000.myapp-production.username.defang.app`
+
+Then you can deploy and tear down your staging environment as needed without touching DNS.
+:::
+
+***
+
For a deeper discussion of how to use a custom domain with Defang, see our [Domain](/docs/concepts/domains) concept docs.
From fe6ec8d4b068e0c9f6d0a6db714b8f8774bd88be Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 10 Dec 2025 01:29:29 +0000
Subject: [PATCH 3/5] Fix heading hierarchy in domains.mdx
Co-authored-by: lionello <591860+lionello@users.noreply.github.com>
---
docs/concepts/domains.mdx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/concepts/domains.mdx b/docs/concepts/domains.mdx
index 424f4e1708..79a31eb96d 100644
--- a/docs/concepts/domains.mdx
+++ b/docs/concepts/domains.mdx
@@ -85,11 +85,11 @@ const service = new defang.DefangService("serviceName", {
You can also bring your own domain to a Defang project. This allows you to use your own domain name to access your services, and varies a little bit depending on your setup.
-### DNS Management Options
+## DNS Management Options
When bringing your own domain, you have two main approaches:
-#### Option 1: Using Your Existing DNS Provider (CloudFlare, Namecheap, etc.)
+### Option 1: Using Your Existing DNS Provider (CloudFlare, Namecheap, etc.)
If you are using [Defang BYOC](./defang-byoc.md) and *do not* have your domain's DNS hosted with your cloud provider, or if you are using the [Defang Playground](./defang-playground.md), you have two choices:
@@ -113,7 +113,7 @@ If you frequently deploy and tear down your services (e.g., for staging environm
Use the `--project-name` flag or the `name:` field in your Compose file to create separate environments. For example, a project named "hello" with `--project-name hello-staging` would create a separate deployment, allowing you to maintain both production and staging environments simultaneously.
:::
-#### Option 2: Using Route 53 (AWS) - Automatic DNS Management
+### Option 2: Using Route 53 (AWS) - Automatic DNS Management
If you are using [Defang BYOC](./defang-byoc.md) *and the DNS for your domain is hosted with your cloud provider* (i.e. a Hosted Zone in Route 53, if you're using AWS), all you need to do is specify the `domainname` in your service definition, as in the example below.
From 03a6834aaa68df725b17ffcde5dc4c965c081e4b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 10 Dec 2025 01:32:07 +0000
Subject: [PATCH 4/5] Fix YAML syntax to use array format for ports
Co-authored-by: lionello <591860+lionello@users.noreply.github.com>
---
docs/tutorials/use-your-own-domain-name.mdx | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/docs/tutorials/use-your-own-domain-name.mdx b/docs/tutorials/use-your-own-domain-name.mdx
index 588e667be1..f80ccc7624 100644
--- a/docs/tutorials/use-your-own-domain-name.mdx
+++ b/docs/tutorials/use-your-own-domain-name.mdx
@@ -60,8 +60,8 @@ services:
context: ./web
dockerfile: Dockerfile
ports:
- target: 3000
- mode: ingress
+ - target: 3000
+ mode: ingress
```
@@ -89,8 +89,8 @@ If you prefer to keep your DNS with your current provider (like CloudFlare or Na
web:
domainname: staging.example.com
ports:
- target: 3000
- mode: ingress
+ - target: 3000
+ mode: ingress
```
2. Deploy your service:
@@ -115,8 +115,8 @@ This approach avoids having to reconfigure DNS and regenerate certificates for e
services:
web:
ports:
- target: 3000
- mode: ingress
+ - target: 3000
+ mode: ingress
```
2. Deploy your service:
@@ -148,8 +148,8 @@ name: myapp-staging
services:
web:
ports:
- target: 3000
- mode: ingress
+ - target: 3000
+ mode: ingress
```
**Or using the `--project-name` flag:**
From d88d00cb98adadcdbeca5abc12ff0682f72d84cf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 10 Dec 2025 01:34:34 +0000
Subject: [PATCH 5/5] Add protocol field to all port configurations for
consistency
Co-authored-by: lionello <591860+lionello@users.noreply.github.com>
---
docs/tutorials/use-your-own-domain-name.mdx | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/docs/tutorials/use-your-own-domain-name.mdx b/docs/tutorials/use-your-own-domain-name.mdx
index f80ccc7624..9ff6850857 100644
--- a/docs/tutorials/use-your-own-domain-name.mdx
+++ b/docs/tutorials/use-your-own-domain-name.mdx
@@ -60,8 +60,9 @@ services:
context: ./web
dockerfile: Dockerfile
ports:
- - target: 3000
- mode: ingress
+ - mode: ingress
+ target: 3000
+ protocol: http
```
@@ -89,8 +90,9 @@ If you prefer to keep your DNS with your current provider (like CloudFlare or Na
web:
domainname: staging.example.com
ports:
- - target: 3000
- mode: ingress
+ - mode: ingress
+ target: 3000
+ protocol: http
```
2. Deploy your service:
@@ -115,8 +117,9 @@ This approach avoids having to reconfigure DNS and regenerate certificates for e
services:
web:
ports:
- - target: 3000
- mode: ingress
+ - mode: ingress
+ target: 3000
+ protocol: http
```
2. Deploy your service:
@@ -148,8 +151,9 @@ name: myapp-staging
services:
web:
ports:
- - target: 3000
- mode: ingress
+ - mode: ingress
+ target: 3000
+ protocol: http
```
**Or using the `--project-name` flag:**