|
| 1 | +# **Certificate Management for Multi-Tenant Applications on Qovery** |
| 2 | + |
| 3 | +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. |
| 4 | + |
| 5 | +## **The Challenge** |
| 6 | + |
| 7 | +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: |
| 8 | + |
| 9 | +* **Certificate generation failures**: If validation fails for one domain, it can prevent certificate generation for all domains |
| 10 | +* **Deployment risks**: A single misconfigured domain can cause the entire deployment to fail |
| 11 | +* **Privacy concerns**: Customers can see other tenants' domains when inspecting the SSL certificate |
| 12 | +* **Certificate limits**: Let's Encrypt has rate limits that can be reached when managing many domains on a single certificate |
| 13 | + |
| 14 | +## **The Solution: Dedicated Ingresses Per Tenant** |
| 15 | + |
| 16 | +Instead of managing all domains through a single ingress, we'll create a dedicated ingress for each customer. This approach provides: |
| 17 | + |
| 18 | +* **Isolation**: Each tenant gets their own certificate and ingress configuration |
| 19 | +* **Reliability**: Issues with one tenant's domain won't affect others |
| 20 | +* **Privacy**: Certificates only contain the specific tenant's domain |
| 21 | +* **Scalability**: Easier to manage rate limits and certificate renewals |
| 22 | + |
| 23 | +## **Implementation Guide** |
| 24 | + |
| 25 | +### **Prerequisites** |
| 26 | + |
| 27 | +* A Qovery account with a configured cluster |
| 28 | +* DNS management access for your domains |
| 29 | + |
| 30 | +### **Step 1: Organize Your Infrastructure (Optional but Recommended)** |
| 31 | + |
| 32 | +While not mandatory, creating separate environments helps maintain a clean separation between your core infrastructure and tenant-specific configurations. |
| 33 | + |
| 34 | +1. **Create an Infrastructure Environment** |
| 35 | + |
| 36 | + This environment will host your main application components (frontend, API, database, etc.). |
| 37 | + |
| 38 | + * Navigate to your project dashboard |
| 39 | + * Click "Create new environment" |
| 40 | + * Name it "Infrastructure" or similar |
| 41 | + * Configure your environment settings |
| 42 | + |
| 43 | +2. **Create a Tenants Environment** |
| 44 | + |
| 45 | + This dedicated environment will contain all tenant-specific ingress configurations. |
| 46 | + |
| 47 | + * Create another environment |
| 48 | + * Name it "Tenants" or "Customers" |
| 49 | + * This provides logical separation and easier management |
| 50 | + |
| 51 | +### **Step 2: Deploy Your Main Application** |
| 52 | + |
| 53 | +If you haven't already deployed your application, follow the [Qovery deployment guide](https://hub.qovery.com/guides/getting-started/deploy-your-first-application/). |
| 54 | + |
| 55 | +For this example, we'll use a simple web application: |
| 56 | + |
| 57 | +1. **Deploy your container** |
| 58 | + |
| 59 | + * 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 |
| 60 | + * For testing, you can use a simple nginx container |
| 61 | + |
| 62 | +2. **Configure the application port** |
| 63 | + |
| 64 | + * Navigate to Settings → Ports |
| 65 | + * Click "Add port" |
| 66 | + * Configure: |
| 67 | + * Port: 80 (or your application's port exposed by your container) |
| 68 | + * Protocol: HTTP |
| 69 | + * Exposure: Publicly exposed |
| 70 | + |
| 71 | +3. **Add your main domain** (optional) |
| 72 | + |
| 73 | + * Go to Settings → Domains |
| 74 | + * Click "Add domain" |
| 75 | + * Enter your primary domain |
| 76 | + * Configure the required CNAME records in your DNS provider |
| 77 | + |
| 78 | +4. **Note important values** |
| 79 | + |
| 80 | + Before proceeding, save these values from your application's built-in environment variables: |
| 81 | + |
| 82 | + * `QOVERY_CONTAINER_XXXXXXX_HOST_INTERNAL`: The internal hostname of your application |
| 83 | + * `QOVERY_KUBERNETES_NAMESPACE_NAME`: Your environment's namespace |
| 84 | + |
| 85 | +5. You can find these in the Variables section of your application. |
| 86 | + |
| 87 | +### **Step 3: Create Tenant-Specific Ingresses** |
| 88 | + |
| 89 | +Now we'll create dedicated ingresses for each tenant using Helm charts. |
| 90 | + |
| 91 | +1. **Switch to your Tenants environment** (if you created one) |
| 92 | + |
| 93 | +2. **Create a new Helm service** |
| 94 | + |
| 95 | + 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. |
| 96 | + |
| 97 | + * Click "Create new service" |
| 98 | + * Select "Helm" |
| 99 | + * Name it after your tenant (e.g., "tenant-acme-corp") |
| 100 | + * Use the empty chart repository |
| 101 | + * Keep default values (no overrides needed) |
| 102 | + * Select only “Create” at the end of the create wizard |
| 103 | + |
| 104 | +3. **Configure the ingress** |
| 105 | + |
| 106 | + Navigate to Settings → Ports and add a port: |
| 107 | + |
| 108 | + * Service name: Use the `QOVERY_CONTAINER_XXXXXXX_HOST_INTERNAL` value |
| 109 | + * Namespace: Use `QOVERY_KUBERNETES_NAMESPACE_NAME` (if using separate environments) |
| 110 | + |
| 111 | + |
| 112 | +4. **Add the tenant's custom domain** |
| 113 | + |
| 114 | + * Go to Settings → Domains |
| 115 | + * Add the tenant's specific domain |
| 116 | + * Ensure the tenant configures their DNS records |
| 117 | + |
| 118 | +5. **Deploy the service** |
| 119 | + |
| 120 | + Deploy the Helm chart. Qovery will: |
| 121 | + |
| 122 | + * Create a dedicated ingress for this tenant |
| 123 | + * Generate a separate SSL certificate |
| 124 | + * Route traffic to your main application |
| 125 | + |
| 126 | +### **Step 4: Scale to Multiple Tenants** |
| 127 | + |
| 128 | +For additional tenants, you have two options: |
| 129 | + |
| 130 | +1. **Clone existing tenant configuration** |
| 131 | + |
| 132 | + * Clone an existing tenant service |
| 133 | + * Update the name and domain |
| 134 | + * Deploy |
| 135 | + |
| 136 | +2. **Create from scratch** |
| 137 | + |
| 138 | + * Repeat Step 3 for each new tenant |
| 139 | + |
| 140 | +## **Troubleshooting** |
| 141 | + |
| 142 | +### **Certificate Generation Issues** |
| 143 | + |
| 144 | +1. **Check DNS propagation** |
| 145 | + |
| 146 | +```shell |
| 147 | +dig _acme-challenge.tenant-domain.com CNAME |
| 148 | +``` |
| 149 | + |
| 150 | +2. **Verify ingress configuration** |
| 151 | + |
| 152 | + * Check the Qovery deployment logs |
| 153 | + * Ensure the domain is correctly configured |
| 154 | + |
| 155 | +3. **Monitor cert-manager logs** |
| 156 | + * Access your cluster logs to see certificate generation details |
| 157 | + |
| 158 | +### **Routing Issues** |
| 159 | + |
| 160 | +1. **Verify internal service name on the tenant port configuration** |
| 161 | + * Ensure the service name matches your application's internal hostname |
| 162 | +2. **Check namespace configuration** |
| 163 | + * Confirm the namespace is correct if using separate environments |
| 164 | + |
| 165 | +## **Conclusion** |
| 166 | + |
| 167 | +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. |
| 168 | + |
| 169 | +## **Related Resources** |
| 170 | + |
| 171 | +* [Qovery Custom Domain Documentation](https://hub.qovery.com/docs/using-qovery/configuration/application/#custom-domains) |
| 172 | +* [Deploying Applications with Qovery](https://hub.qovery.com/guides/getting-started/deploy-your-first-application/) |
| 173 | +* [Environment Management Guide](https://hub.qovery.com/docs/using-qovery/configuration/environment/) |
| 174 | +* [Qovery Helm Deployment](https://hub.qovery.com/docs/using-qovery/configuration/helm/) |
| 175 | + |
| 176 | +## **Next Steps** |
| 177 | + |
| 178 | +* Explore [Qovery's API](https://hub.qovery.com/docs/using-qovery/interface/rest-api/) to automate tenant provisioning |
| 179 | +* Consider implementing [auto-scaling](https://hub.qovery.com/docs/using-qovery/configuration/application/#auto-scaling) on the main service |
0 commit comments