diff --git a/.meta/team.toml b/.meta/team.toml index 1d25fb614c..8d7991ddaa 100644 --- a/.meta/team.toml +++ b/.meta/team.toml @@ -157,3 +157,14 @@ name = "Charles-Edouard Gagnaire" bio = """\ Charles-Edouard is Technical Account Manager at Qovery.\ """ + +[[team]] +id = "guillaume" +avatar = "https://github.com/guimove.png" +github = "https://github.com/guimove" +keybase = "https://keybase.io/guimove" +name = "Guillaume DA SILVA" +bio = """\ +Guillaume is a Senior Cloud Architect at Qovery with extensive experience \ +in cloud infrastructure and Kubernetes. He specializes in designing scalable architectures and enterprise-grade solutions.\ +""" diff --git a/website/docs/using-qovery/configuration/provider.md b/website/docs/using-qovery/configuration/provider.md index ce30549464..2b9e26d2b9 100644 --- a/website/docs/using-qovery/configuration/provider.md +++ b/website/docs/using-qovery/configuration/provider.md @@ -1,5 +1,5 @@ --- -last_modified_on: "2024-10-09" +last_modified_on: "2025-08-07" title: "Provider" description: "Learn how to install Qovery on your provider" sidebar_label: hidden diff --git a/website/guides/tutorial/certificate_management_for_multi_tenant_infrastructure.md b/website/guides/tutorial/certificate_management_for_multi_tenant_infrastructure.md new file mode 100644 index 0000000000..9e13560bb6 --- /dev/null +++ b/website/guides/tutorial/certificate_management_for_multi_tenant_infrastructure.md @@ -0,0 +1,234 @@ +--- +last_modified_on: "2025-08-08" +$schema: "/.meta/.schemas/guides.json" +title: Certificate Management for Multi-Tenant Applications on Qovery +description: Learn how to implement robust SSL/TLS certificate management for multi-tenant SaaS applications using dedicated ingresses per tenant on Qovery +author_github: https://github.com/guimove +tags: ["type: tutorial", "technology: qovery"] +hide_pagination: true +--- +import Alert from '@site/src/components/Alert'; +import Assumptions from '@site/src/components/Assumptions'; +import Jump from '@site/src/components/Jump'; + +Building multi-tenant applications where each customer has their own dedicated URL is a common pattern in SaaS platforms. While Qovery automatically handles TLS/SSL certificate creation and renewal for your custom domains, managing certificates at scale for multi-tenant architectures presents unique challenges. This guide will show you how to implement a robust certificate management strategy using dedicated ingresses for each tenant. + + + +## **The Challenge** + +When building multi-tenant applications on Qovery, the default approach uses a single ingress controller to manage all custom domains for the service. This creates several issues: + +* **Certificate generation failures**: If validation fails for one domain, it can prevent certificate generation for all domains +* **Deployment risks**: A single misconfigured domain can cause the entire deployment to fail +* **Privacy concerns**: Customers can see other tenants' domains when inspecting the SSL certificate +* **Certificate limits**: Let's Encrypt has rate limits that can be reached when managing many domains on a single certificate + +## **The Solution: Dedicated Ingresses Per Tenant** + +

+ Certificate Management Architecture Comparison +

+ +Instead of managing all domains through a single ingress, we'll create a dedicated ingress for each customer. This approach provides: + +* **Isolation**: Each tenant gets their own certificate and ingress configuration +* **Reliability**: Issues with one tenant's domain won't affect others +* **Privacy**: Certificates only contain the specific tenant's domain +* **Scalability**: Easier to manage rate limits and certificate renewals + +## **Implementation Guide** + +### **Prerequisites** + +* A Qovery account with a configured cluster +* DNS management access for your domains + +### **Step 1: Organize Your Infrastructure (Optional but Recommended)** + +

+ Qovery Platform +

+ +While not mandatory, creating separate environments helps maintain a clean separation between your core infrastructure and tenant-specific configurations. + +1. **Create an Infrastructure Environment** + + This environment will host your main application components (frontend, API, database, etc.). + + * Navigate to your project dashboard + * Click "Create new environment" + * Name it "Infrastructure" or similar + * Configure your environment settings + +2. **Create a Tenants Environment** + + This dedicated environment will contain all tenant-specific ingress configurations. + + * Create another environment + * Name it "Tenants" or "Customers" + * This provides logical separation and easier management + +### **Step 2: Deploy Your Main Application** + +If you haven't already deployed your application, follow the [Qovery deployment guide](https://hub.qovery.com/guides/getting-started/deploy-your-first-application/). + +For this example, we'll use a simple web application: + +1. **Deploy your container** + + * Use the Qovery UI, our [CLI](https://hub.qovery.com/docs/using-qovery/interface/cli/), our [Terraform Provider](https://hub.qovery.com/docs/using-qovery/integration/terraform-provider/) or our [REST API](https://hub.qovery.com/docs/using-qovery/interface/rest-api/) to deploy your application + * For testing, you can use a simple nginx container + +2. **Configure the application port** + + * Navigate to Settings → Ports + * Click "Add port" + * Configure: + * Port: 80 (or your application's port exposed by your container) + * Protocol: HTTP + * Exposure: Publicly exposed + +

+ Add Port +

+ +3. **Add your main domain** (optional) + + * Go to Settings → Domains + * Click "Add domain" + * Enter your primary domain + * Configure the required CNAME records in your DNS provider + +4. **Note important values** + + Before proceeding, save these values from your application's built-in environment variables: + + * `QOVERY_CONTAINER_XXXXXXX_HOST_INTERNAL`: The internal hostname of your application + * `QOVERY_KUBERNETES_NAMESPACE_NAME`: Your environment's namespace + +

+ List Variables +

+ +5. You can find these in the Variables section of your application. + +### **Step 3: Create Tenant-Specific Ingresses** + +Now we'll create dedicated ingresses for each tenant using Helm charts. + +

+ Implementation Steps Flow +

+ +1. **Switch to your Tenants environment** (if you created one) + +2. **Create a new Helm service** + + We'll use an empty Helm chart, Qovery will create an ingress resource. You can use this [empty chart template](https://github.com/Guimove/empty-chart) or create your own. + + * Click "Create new service" + * Select "Helm" + * Name it after your tenant (e.g., "tenant-acme-corp") + * Use the empty chart repository + * Keep default values (no overrides needed) + * Select only “Create” at the end of the create wizard + +

+ Deploy Helm Chart +

+ +3. **Configure the ingress** + + Navigate to Settings → Ports and add a port: + + * Service name: Use the `QOVERY_CONTAINER_XXXXXXX_HOST_INTERNAL` value + * Namespace: Use `QOVERY_KUBERNETES_NAMESPACE_NAME` (if using separate environments) + +

+ Tenant Port +

+ +4. **Add the tenant's custom domain** + + * Go to Settings → Domains + * Add the tenant's specific domain + * Ensure the tenant configures their DNS records + +

+ Custom Domain +

+ +5. **Deploy the service** + + Deploy the Helm chart. Qovery will: + + * Create a dedicated ingress for this tenant + * Generate a separate SSL certificate + * Route traffic to your main application + +### **Step 4: Scale to Multiple Tenants** + +For additional tenants, you have two options: + +1. **Clone existing tenant configuration** + + * Clone an existing tenant service + * Update the name and domain + * Deploy + +2. **Create from scratch** + + * Repeat Step 3 for each new tenant + +## **Troubleshooting** + +### **Certificate Generation Issues** + +1. **Check DNS propagation** + +```shell +dig _acme-challenge.tenant-domain.com CNAME +``` + +2. **Verify ingress configuration** + + * Check the Qovery deployment logs + * Ensure the domain is correctly configured + +3. **Monitor cert-manager logs** + * Access your cluster logs to see certificate generation details + +### **Routing Issues** + +1. **Verify internal service name on the tenant port configuration** + * Ensure the service name matches your application's internal hostname +2. **Check namespace configuration** + * Confirm the namespace is correct if using separate environments + +## **Conclusion** + +By implementing dedicated ingresses for each tenant, you create a more robust, scalable, and secure multi-tenant architecture on Qovery. This approach provides better isolation, easier troubleshooting, and improved privacy for your customers. + +## **Related Resources** + +* [Qovery Custom Domain Documentation](https://hub.qovery.com/docs/using-qovery/configuration/application/#custom-domains) +* [Deploying Applications with Qovery](https://hub.qovery.com/guides/getting-started/deploy-your-first-application/) +* [Environment Management Guide](https://hub.qovery.com/docs/using-qovery/configuration/environment/) +* [Qovery Helm Deployment](https://hub.qovery.com/docs/using-qovery/configuration/helm/) + +## **Next Steps** + +* Explore [Qovery's API](https://hub.qovery.com/docs/using-qovery/interface/rest-api/) to automate tenant provisioning +* Consider implementing [auto-scaling](https://hub.qovery.com/docs/using-qovery/configuration/application/#auto-scaling) on the main service + +Tutorial + + + diff --git a/website/guides/tutorial/certificate_management_for_multi_tenant_infrastructure.md.erb b/website/guides/tutorial/certificate_management_for_multi_tenant_infrastructure.md.erb new file mode 100644 index 0000000000..6e2d86a3a2 --- /dev/null +++ b/website/guides/tutorial/certificate_management_for_multi_tenant_infrastructure.md.erb @@ -0,0 +1,222 @@ +--- +$schema: "/.meta/.schemas/guides.json" +title: Certificate Management for Multi-Tenant Applications on Qovery +description: Learn how to implement robust SSL/TLS certificate management for multi-tenant SaaS applications using dedicated ingresses per tenant on Qovery +author_github: https://github.com/guimove +tags: ["type: tutorial", "technology: qovery"] +hide_pagination: true +--- +import Alert from '@site/src/components/Alert'; +import Assumptions from '@site/src/components/Assumptions'; +import Jump from '@site/src/components/Jump'; + +Building multi-tenant applications where each customer has their own dedicated URL is a common pattern in SaaS platforms. While Qovery automatically handles TLS/SSL certificate creation and renewal for your custom domains, managing certificates at scale for multi-tenant architectures presents unique challenges. This guide will show you how to implement a robust certificate management strategy using dedicated ingresses for each tenant. + +## **The Challenge** + +When building multi-tenant applications on Qovery, the default approach uses a single ingress controller to manage all custom domains for the service. This creates several issues: + +* **Certificate generation failures**: If validation fails for one domain, it can prevent certificate generation for all domains +* **Deployment risks**: A single misconfigured domain can cause the entire deployment to fail +* **Privacy concerns**: Customers can see other tenants' domains when inspecting the SSL certificate +* **Certificate limits**: Let's Encrypt has rate limits that can be reached when managing many domains on a single certificate + +## **The Solution: Dedicated Ingresses Per Tenant** + +

+ Certificate Management Architecture Comparison +

+ +Instead of managing all domains through a single ingress, we'll create a dedicated ingress for each customer. This approach provides: + +* **Isolation**: Each tenant gets their own certificate and ingress configuration +* **Reliability**: Issues with one tenant's domain won't affect others +* **Privacy**: Certificates only contain the specific tenant's domain +* **Scalability**: Easier to manage rate limits and certificate renewals + +## **Implementation Guide** + +### **Prerequisites** + +* A Qovery account with a configured cluster +* DNS management access for your domains + +### **Step 1: Organize Your Infrastructure (Optional but Recommended)** + +

+ Qovery Platform +

+ +While not mandatory, creating separate environments helps maintain a clean separation between your core infrastructure and tenant-specific configurations. + +1. **Create an Infrastructure Environment** + + This environment will host your main application components (frontend, API, database, etc.). + + * Navigate to your project dashboard + * Click "Create new environment" + * Name it "Infrastructure" or similar + * Configure your environment settings + +2. **Create a Tenants Environment** + + This dedicated environment will contain all tenant-specific ingress configurations. + + * Create another environment + * Name it "Tenants" or "Customers" + * This provides logical separation and easier management + +### **Step 2: Deploy Your Main Application** + +If you haven't already deployed your application, follow the [Qovery deployment guide](https://hub.qovery.com/guides/getting-started/deploy-your-first-application/). + +For this example, we'll use a simple web application: + +1. **Deploy your container** + + * Use the Qovery UI, our [CLI](https://hub.qovery.com/docs/using-qovery/interface/cli/), our [Terraform Provider](https://hub.qovery.com/docs/using-qovery/integration/terraform-provider/) or our [REST API](https://hub.qovery.com/docs/using-qovery/interface/rest-api/) to deploy your application + * For testing, you can use a simple nginx container + +2. **Configure the application port** + + * Navigate to Settings → Ports + * Click "Add port" + * Configure: + * Port: 80 (or your application's port exposed by your container) + * Protocol: HTTP + * Exposure: Publicly exposed + +

+ Add Port +

+ +3. **Add your main domain** (optional) + + * Go to Settings → Domains + * Click "Add domain" + * Enter your primary domain + * Configure the required CNAME records in your DNS provider + +4. **Note important values** + + Before proceeding, save these values from your application's built-in environment variables: + + * `QOVERY_CONTAINER_XXXXXXX_HOST_INTERNAL`: The internal hostname of your application + * `QOVERY_KUBERNETES_NAMESPACE_NAME`: Your environment's namespace + +

+ List Variables +

+ +5. You can find these in the Variables section of your application. + +### **Step 3: Create Tenant-Specific Ingresses** + +Now we'll create dedicated ingresses for each tenant using Helm charts. + +

+ Implementation Steps Flow +

+ +1. **Switch to your Tenants environment** (if you created one) + +2. **Create a new Helm service** + + We'll use an empty Helm chart, Qovery will create an ingress resource. You can use this [empty chart template](https://github.com/Guimove/empty-chart) or create your own. + + * Click "Create new service" + * Select "Helm" + * Name it after your tenant (e.g., "tenant-acme-corp") + * Use the empty chart repository + * Keep default values (no overrides needed) + * Select only “Create” at the end of the create wizard + +

+ Deploy Helm Chart +

+ +3. **Configure the ingress** + + Navigate to Settings → Ports and add a port: + + * Service name: Use the `QOVERY_CONTAINER_XXXXXXX_HOST_INTERNAL` value + * Namespace: Use `QOVERY_KUBERNETES_NAMESPACE_NAME` (if using separate environments) + +

+ Tenant Port +

+ +4. **Add the tenant's custom domain** + + * Go to Settings → Domains + * Add the tenant's specific domain + * Ensure the tenant configures their DNS records + +

+ Custom Domain +

+ +5. **Deploy the service** + + Deploy the Helm chart. Qovery will: + + * Create a dedicated ingress for this tenant + * Generate a separate SSL certificate + * Route traffic to your main application + +### **Step 4: Scale to Multiple Tenants** + +For additional tenants, you have two options: + +1. **Clone existing tenant configuration** + + * Clone an existing tenant service + * Update the name and domain + * Deploy + +2. **Create from scratch** + + * Repeat Step 3 for each new tenant + +## **Troubleshooting** + +### **Certificate Generation Issues** + +1. **Check DNS propagation** + +```shell +dig _acme-challenge.tenant-domain.com CNAME +``` + +2. **Verify ingress configuration** + + * Check the Qovery deployment logs + * Ensure the domain is correctly configured + +3. **Monitor cert-manager logs** + * Access your cluster logs to see certificate generation details + +### **Routing Issues** + +1. **Verify internal service name on the tenant port configuration** + * Ensure the service name matches your application's internal hostname +2. **Check namespace configuration** + * Confirm the namespace is correct if using separate environments + +## **Conclusion** + +By implementing dedicated ingresses for each tenant, you create a more robust, scalable, and secure multi-tenant architecture on Qovery. This approach provides better isolation, easier troubleshooting, and improved privacy for your customers. + +## **Related Resources** + +* [Qovery Custom Domain Documentation](https://hub.qovery.com/docs/using-qovery/configuration/application/#custom-domains) +* [Deploying Applications with Qovery](https://hub.qovery.com/guides/getting-started/deploy-your-first-application/) +* [Environment Management Guide](https://hub.qovery.com/docs/using-qovery/configuration/environment/) +* [Qovery Helm Deployment](https://hub.qovery.com/docs/using-qovery/configuration/helm/) + +## **Next Steps** + +* Explore [Qovery's API](https://hub.qovery.com/docs/using-qovery/interface/rest-api/) to automate tenant provisioning +* Consider implementing [auto-scaling](https://hub.qovery.com/docs/using-qovery/configuration/application/#auto-scaling) on the main service + +Tutorial diff --git a/website/metadata.js b/website/metadata.js index b1d696ad4c..87d69accf9 100644 --- a/website/metadata.js +++ b/website/metadata.js @@ -411,6 +411,15 @@ module.exports = { "series_position": null, "title": "Build E2E Testing Ephemeral Environments with GitHub Actions and Qovery" }, + { + "author_github": "https://github.com/guimove", + "description": null, + "id": "/tutorial/certificate_management_for_multi_tenant_infrastructure", + "last_modified_on": null, + "path": "website/guides/tutorial/certificate_management_for_multi_tenant_infrastructure.md", + "series_position": null, + "title": "Certificate Management for Multi-Tenant Applications on Qovery" + }, { "author_github": "https://github.com/evoxmusic", "description": null, @@ -1028,6 +1037,14 @@ module.exports = { "id": "cegagnaire", "keybase": "https://keybase.io/baalooos", "name": "Charles-Edouard Gagnaire" + }, + { + "avatar": "https://github.com/guimove.png", + "bio": "Guillaume is a Senior Cloud Architect at Qovery with extensive experience in cloud infrastructure and Kubernetes.He specializes in designing scalable architectures and enterprise-grade solutions.", + "github": "https://github.com/guimove", + "id": "guillaume", + "keybase": "https://keybase.io/guimove", + "name": "Guillaume DA SILVA" } ], "technologies": [ diff --git a/website/static/img/certificate_management_for_multi_tenant_infrastructure/archi_overview.png b/website/static/img/certificate_management_for_multi_tenant_infrastructure/archi_overview.png new file mode 100644 index 0000000000..1180ee806a Binary files /dev/null and b/website/static/img/certificate_management_for_multi_tenant_infrastructure/archi_overview.png differ diff --git a/website/static/img/certificate_management_for_multi_tenant_infrastructure/custom_domain.png b/website/static/img/certificate_management_for_multi_tenant_infrastructure/custom_domain.png new file mode 100644 index 0000000000..3717e97557 Binary files /dev/null and b/website/static/img/certificate_management_for_multi_tenant_infrastructure/custom_domain.png differ diff --git a/website/static/img/certificate_management_for_multi_tenant_infrastructure/deploy_helm_chart.png b/website/static/img/certificate_management_for_multi_tenant_infrastructure/deploy_helm_chart.png new file mode 100644 index 0000000000..8cc35d1a59 Binary files /dev/null and b/website/static/img/certificate_management_for_multi_tenant_infrastructure/deploy_helm_chart.png differ diff --git a/website/static/img/certificate_management_for_multi_tenant_infrastructure/edit_port.png b/website/static/img/certificate_management_for_multi_tenant_infrastructure/edit_port.png new file mode 100644 index 0000000000..f9ccdfb7d1 Binary files /dev/null and b/website/static/img/certificate_management_for_multi_tenant_infrastructure/edit_port.png differ diff --git a/website/static/img/certificate_management_for_multi_tenant_infrastructure/environment_structure.png b/website/static/img/certificate_management_for_multi_tenant_infrastructure/environment_structure.png new file mode 100644 index 0000000000..a7031ac0c0 Binary files /dev/null and b/website/static/img/certificate_management_for_multi_tenant_infrastructure/environment_structure.png differ diff --git a/website/static/img/certificate_management_for_multi_tenant_infrastructure/implementation_flow.png b/website/static/img/certificate_management_for_multi_tenant_infrastructure/implementation_flow.png new file mode 100644 index 0000000000..41a3b03509 Binary files /dev/null and b/website/static/img/certificate_management_for_multi_tenant_infrastructure/implementation_flow.png differ diff --git a/website/static/img/certificate_management_for_multi_tenant_infrastructure/list_variables.png b/website/static/img/certificate_management_for_multi_tenant_infrastructure/list_variables.png new file mode 100644 index 0000000000..e2b84b134c Binary files /dev/null and b/website/static/img/certificate_management_for_multi_tenant_infrastructure/list_variables.png differ diff --git a/website/static/img/certificate_management_for_multi_tenant_infrastructure/tenant_port.png b/website/static/img/certificate_management_for_multi_tenant_infrastructure/tenant_port.png new file mode 100644 index 0000000000..9ed3248ef7 Binary files /dev/null and b/website/static/img/certificate_management_for_multi_tenant_infrastructure/tenant_port.png differ