Configure app hostnames
Learn how to serve apps and the app builder preview on their own hostnames on a self-hosted Retool instance deployed with Helm.
By default, a self-hosted Retool instance serves each published app in a sandboxed iframe. Since this iframe lacks an origin, browsers actively enforce strict security boundaries that block access to localStorage, IndexedDB, cookies, the camera, and the microphone. Many third-party scripts cannot load, and an identity-aware proxy behind which Retool operates can drop its cookie on the app's requests.
If you need access to these features, you can configure your self-hosted instance to serve apps using their own hostnames instead. This enables an app to run as a normal web page instead of an iframe, allowing access to those browser features.
After you configure app hostnames, each app gets its own hostname under an apps domain that's either a subdomain, such as apps.retool.example.com, or a separate domain entirely, such as example-apps.com. For example, with the apps domain apps.retool.example.com:
- Published app
- App builder preview
- App in a space
https://retool.example.com/rr/app/claims
https://claims.apps.retool.example.com/
https://retool.example.com/sandbox/<id>/...
https://sandbox-<id>.sandboxes.apps.retool.example.com/
https://finance.example.com/rr/app/claims
https://finance--claims.apps.retool.example.com/
Before you begin
Use this checklist as you prepare to configure app hostnames to ensure you have everything ready.
This guide requires Retool Helm chart 6.13.2 or later.
Process overview
Configuring app hostnames involves changes to the Retool instance and to each space hosted on it, including the Admin Space and every other space.
- Once for the instance: You update the Helm configuration, and add DNS records and a certificate.
- For each space: You turn on app hostnames in the space's settings, and choose which browser features the space supports in the app builder preview.
The configuration happens in two stages, each with its own helm upgrade. This lets you confirm that apps are served correctly from their hostnames before you change the app builder preview.
- First upgrade: You set up the apps domain, the domain that apps are served from, such as
apps.retool.example.com. Published apps then move to their own hostnames one space at a time. They stay in the sandboxed iframe until you turn on app hostnames in the space's settings. - Second upgrade: After you verify the apps domain, you move the app builder preview to its own origin. This applies to every space at once. Choose the browser features each space supports before this upgrade.
Choose the apps domain
Apps are served from an apps domain. Retool recommends using a subdomain of your Retool instance. You can also use a separate domain, such as when your security policy requires the browser to separate the Retool instance from the apps your users build.
| Instance subdomain | Separate domain | |
|---|---|---|
| Example | apps.retool.example.com | example-apps.com |
| Separation between Retool and apps | Retool enforces it with host checks, __Host- cookies, and Sec-Fetch-Site checks | The browser enforces it, because the apps are on a different site |
| Setup | One more wildcard DNS record and certificate under your existing domain | A second domain with its own DNS zone and certificates |
This guide uses retool.example.com as a placeholder Retool instance and apps as the chosen instance subdomain. For a separate domain, it uses example-apps.com. Replace these values with your own during configuration. The tabs in this guide show the steps for each option, and your selection applies to every tab on the page.
- Instance subdomain
- Separate domain
The instance subdomain can't match, be under, or be above the domain of any space. For example, with apps at apps.retool.example.com, a space whose domain is finance.apps.retool.example.com or example.com is rejected, but a space whose domain is finance.example.com is accepted.
Only names under the instance subdomain are served, so apps.retool.example.com itself needs no DNS record or certificate.
The app builder preview is served from a sandboxes subdomain of the instance subdomain, such as sandboxes.apps.retool.example.com. Each preview gets its own hostname under it, such as sandbox-<id>.sandboxes.apps.retool.example.com.
The separate domain can't match, be under, or be above the domain of any space. For example, with apps at example-apps.com, a space whose domain is finance.example-apps.com is rejected.
Only names under the separate domain are served, so example-apps.com itself needs no DNS record or certificate.
The app builder preview is served from a sandboxes subdomain of the separate domain, such as sandboxes.example-apps.com. Each preview gets its own hostname under it, such as sandbox-<id>.sandboxes.example-apps.com.
Configure DNS records
App and app builder preview hostnames must resolve to the load balancer used by the Retool instance. This is usually the load balancer in front of your Kubernetes ingress controller.
- Instance subdomain
- Separate domain
If you already have a wildcard record for your Retool instance, such as *.retool.example.com, it may already cover these hostnames. A wildcard record is typically configured when spaces are enabled. You can check whether a wildcard DNS record covers them by running dig with an example fully qualified domain name (FQDN):
dig +short test.apps.retool.example.com
dig +short test.sandboxes.apps.retool.example.com
If dig returns your load balancer's address for both names, no change is needed. If either command returns no value or a different address, add a record for each name that failed: *.apps.retool.example.com or *.sandboxes.apps.retool.example.com.
An existing wildcard stops covering these names once any record exists at or under apps.retool.example.com. Certificate validation records are the usual cause. For example, AWS Certificate Manager validates *.apps.retool.example.com with a permanent CNAME at _<hash>.apps.retool.example.com. Run the dig checks again after you issue the certificate.
Because the separate domain is in its own DNS zone, an existing wildcard record for your Retool instance doesn't cover it. In the DNS zone for the separate domain, add wildcard records that point to the load balancer's address: *.example-apps.com and *.sandboxes.example-apps.com.
To check the records, run dig with an example name for each:
dig +short test.example-apps.com
dig +short test.sandboxes.example-apps.com
If dig returns your load balancer's address for both names, the records are configured correctly. Run the dig checks again after you issue the certificate.
Add a wildcard certificate
Unlike a DNS wildcard record, a certificate wildcard matches one label only.
- Instance subdomain
- Separate domain
For example, a *.retool.example.com certificate would not cover *.apps.retool.example.com. You must add a wildcard certificate for the instance subdomain, such as *.apps.retool.example.com, and one for the app builder preview, *.sandboxes.apps.retool.example.com. A single certificate can include both names.
Add a wildcard certificate for the separate domain, *.example-apps.com, and one for the app builder preview, *.sandboxes.example-apps.com. A single certificate can include both names. A certificate for your Retool domain doesn't cover either of them.
If you use cert-manager, you must use an issuer that solves DNS-01 challenges, as HTTP-01 challenges cannot issue wildcard certificates. Annotate the Ingress in the next section. Otherwise, create the certificate yourself and store it in a TLS secret.
Update Helm configuration
The next step is to update your instance's configuration so it can support app hostnames. Add the following to your Helm values. Keep the values for the app builder preview commented out so that only published app hostnames are applied first. Once you verify that published apps are being served correctly, you can then move the app builder preview.
- Instance subdomain
- Separate domain
rr:
appServingLayer:
enabled: true
domain: apps.retool.example.com
separate:
enabled: false # Set to true to run the app serving layer as its own deployment.
ingress:
enabled: true
ingressClassName: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-dns # If you use cert-manager.
# The app builder keeps WebSocket connections open to the sandbox.
# nginx.ingress.kubernetes.io/proxy-read-timeout: '3600'
# nginx.ingress.kubernetes.io/proxy-send-timeout: '3600'
tls:
- secretName: retool-apps-tls
hosts:
- '*.apps.retool.example.com'
- '*.sandboxes.apps.retool.example.com' # For the app builder preview.
# agentSandbox:
# wildcardSandboxes: true
rr:
appServingLayer:
enabled: true
domain: example-apps.com
separate:
enabled: false # Set to true to run the app serving layer as its own deployment.
ingress:
enabled: true
ingressClassName: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-dns # If you use cert-manager. Use an issuer for the DNS zone of the separate domain.
# The app builder keeps WebSocket connections open to the sandbox.
# nginx.ingress.kubernetes.io/proxy-read-timeout: '3600'
# nginx.ingress.kubernetes.io/proxy-send-timeout: '3600'
tls:
- secretName: retool-apps-tls
hosts:
- '*.example-apps.com'
- '*.sandboxes.example-apps.com' # For the app builder preview.
# agentSandbox:
# wildcardSandboxes: true
These values configure your Retool instance to:
- Set
RR_APP_DOMAINon the Retool backend. - Run the app serving layer inside the existing backend pods on port 3010, behind a service named
<release>-app-serving-layer. - Create an ingress that routes all hostnames under the apps domain to the app serving layer only.
If you want to keep the app serving layer separate from the main backend pods, set rr.appServingLayer.separate.enabled to true. Pod settings such as replicaCount, resources, and affinity go under separate.
Don't add the apps domain to the top-level ingress.hosts as this ingress adds other Retool paths to every host it serves.
Once you update the configuration, run helm upgrade to apply the changes. Apps stay in the sandboxed iframe and the app builder preview is unchanged until you make the rest of the changes.
Allow network access
If Retool sits behind a VPN, an IP allowlist, or an identity-aware proxy such as Google IAP or Cloudflare Access, you must also apply the same protection to *.apps.retool.example.com, or to *.example-apps.com if you use a separate domain. This is necessary to prevent external access to your apps.
When a user signs in from an app, they are redirected from the app's hostname to the Retool instance, after which they're returned to the app's hostname. An identity-aware proxy must allow that round trip and accept wildcard hostnames.
Verify the setup
To check DNS, the certificate, and routing in one request, run the following command. Any name works in place of test. If you use a separate domain, use test.example-apps.com.
curl https://test.apps.retool.example.com/api/checkHealth
A response of {"message":"serving layer is healthy"} with a valid certificate confirms that the changes were successfully applied.
Enable app hostnames for a space
Once you've verified that apps are served from their hostnames correctly, you are ready to enable app hostnames for a space. Navigate to Settings > Beta and turn on Enable app hostnames.
The setting only applies to the current space and has no effect unless the instance has an apps domain configured. Repeat this in each space whose apps you want to serve from their hostnames, including the Admin Space. You can do this in any order, so you can verify the changes using one space first.
User-facing changes
After you enable app hostnames for a space, the following changes take effect:
- Existing apps work at their own hostnames without being republished.
- Old links such as
https://retool.example.com/rr/app/claims/page2?x=1redirect tohttps://claims.apps.retool.example.com/page2?x=1, keeping the path and any URL parameters. - Shareable preview links are served from a hostname under the apps domain, such as
a1b2c3d4e5f6.apps.retool.example.com. Older preview links continue to work. - The View button, share links, and preview links in the app builder show the hostname URLs.
- Users only need to sign in to Retool to open apps in a space to which they have access. Each app's hostname keeps its own session which Retool automatically creates. On the first visit, the browser initially redirects the user through Retool and then returns with no sign-in prompt. Users who aren't signed in to Retool arrive at the sign-in page, as expected.
Move the app builder preview
After you verify the apps domain and enable app hostnames for at least one space, you then move the app builder preview to its own origin. This preview then runs at sandbox-<id>.sandboxes.apps.retool.example.com for every space at once. There's no per-space configuration.
If you use a separate domain, replace sandboxes.apps.retool.example.com with sandboxes.example-apps.com in this section. The app builder preview then runs on a different site from the app builder, so its sandbox cookie is a third-party cookie that Retool sets as a partitioned cookie (Partitioned).
Before you continue:
- Confirm that each space's domain matches
rr.agentSandbox.proxy.backendDomainSuffixes. A space's app builder preview calls the space's own domain, and this setting lists the hosts the sandbox proxy treats as Retool. If your space domains sit under your Retool host, one suffix covers all of them. - If Retool sits behind a VPN, an IP allowlist, or a firewall, allow traffic to
*.sandboxes.apps.retool.example.com.
Choose browser features
The iframe allows some browser features by default, such as clipboard-write and geolocation. After the app builder preview moves to its own origin, the browser blocks these and other permission-gated features unless the space explicitly allows them. Enable the features your apps use so that nothing stops working when the preview moves.
To specify which browser features to support in the app builder:
- Navigate to Settings > Beta and enable Permissions Policy settings.
- Navigate to Settings > App security > Permissions Policy.
- Enable each feature you want to support.
- Repeat these steps in every space, including the Admin Space.
These settings only apply to the app builder preview, and only once the preview moves to its own origin. Until then, the permissions already allowed by the iframe remain in place. After that, when a user grants a browser permission such as camera access in the app builder, every app in that space can use it without asking again. Published apps aren't affected by these settings. They run as separate web pages, so the browser asks for permission for each one independently.
Enable the preview in Helm
In your Helm values, uncomment the preview values that were added earlier.
rr:
appServingLayer:
ingress:
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: '3600'
nginx.ingress.kubernetes.io/proxy-send-timeout: '3600'
agentSandbox:
wildcardSandboxes: true
These values configure your Retool instance to:
- Serve the app builder preview from
sandboxes.apps.retool.example.com, behind a service named<release>-agent-sandbox-proxyon port 3019. - Route
*.sandboxes.apps.retool.example.comto the sandbox proxy through the same ingress as the apps domain. - Keep the WebSocket connections that the app builder holds open to the sandbox from timing out.
If rr.agentSandbox.networkPolicy.enabled is on, allow the ingress controller to reach the sandbox proxy:
rr:
agentSandbox:
networkPolicy:
extraIngressFrom:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
Run helm upgrade to apply the changes. The preview then moves to its own origin for every space. Sandboxes that are already running keep their old address until they shut down, and the next sandbox for that branch starts at an address under sandboxes.apps.retool.example.com.
Verify the preview
To check DNS, the certificate, and routing for the preview domain in one request, run the following command. Any name works in place of test.
curl https://test.sandboxes.apps.retool.example.com/livez
The command returns {"status":"ok"} with a valid certificate.
Manage spaces
Apps in a space are served at <hostname ID>--<app>.<apps domain>. For example:
finance--claims.apps.retool.example.com
Each space has a hostname ID that appears in every app URL in the space:
- When you create a space in Settings > Spaces, a Hostname ID field appears once the instance serves apps on hostnames. Leave it blank to use the first label of the space's domain. For example,
finance.example.comgivesfinance. If that ID is taken, the space getsfinance2, and so on. - Existing spaces get an ID automatically the first time the instance starts with an apps domain. The ID is derived the same way, and the oldest space keeps the plain name when two would clash.
- An ID is 1 to 40 lowercase letters, digits, and single hyphens.
apps,sandboxes, andretool-probeare reserved. - You can't change an ID after it's set, because it's part of every app URL in the space.
A hostname label is at most 63 characters, so <hostname ID>--<app> must fit. When a space gets its ID, Retool shortens any published app name that no longer fits. In the Admin Space, Retool renames apps that use a reserved name, such as apps to apps2.
- Old links with the old name, such as
https://finance.example.com/rr/app/<old name>, keep working and redirect to the app's hostname. - An app created later can't take another app's old name.
- If the app is connected to Source Control, sync keeps working with the old name in
package.json.