PageSourceSearch

https://bastio.com/assets/custom-domains-otiM2bd3.js

js bastio.com collected 2026-10-09 22:56:15 UTC 15,542 bytes, 158 lines download raw bytes

1import{j as e}from"./index-BkgFiefw.js";let a={title:"Custom domains",description:"Run Workspace on chat.yourcompany.com with full branding and TLS."},r=[{href:"/docs/cloud/workspace/for-admins"},{href:"/docs/cloud/billing"}],s={contents:[{heading:void 0,content:`By default your Workspace lives at workspace.bastio.com/c/<id>.
2Custom domains let you run the same chat product on
3chat.yourcompany.com (or anything else under your control) with
4your branding, no Bastio chrome, and a TLS cert managed for you.`},{heading:void 0,content:"Available on Business and Enterprise plans."},{heading:"how-it-works",content:"Two DNS records under your domain:"},{heading:"how-it-works",content:`The TXT record proves you control the domain. The CNAME routes
5traffic to Bastio's edge, which terminates TLS with a Let's
6Encrypt cert generated automatically once the TXT is verified.`},{heading:"how-it-works",content:`Verification is fully automated — no support ticket. The
7dashboard polls the TXT record on a backoff (~30s, 1m, 5m, 15m,
8hourly) until it sees the right value.`},{heading:"walkthrough",content:"Workspace → Settings → Domain → Add custom domain."},{heading:"walkthrough",content:`Enter the hostname you want — typically chat.yourcompany.com
9or ai.yourcompany.com. Bastio generates a verification
10token.`},{heading:"walkthrough",content:"Copy the TXT record into your DNS provider:"},{heading:"walkthrough",content:'Wait ~5 minutes. The dashboard shows "Verifying…" → "Verified".'},{heading:"walkthrough",content:"Add the CNAME:"},{heading:"walkthrough",content:`Wait another ~2 minutes. Bastio detects the CNAME, requests a
11Let's Encrypt cert, and flips the domain to "Active".`},{heading:"walkthrough",content:`Open https://chat.yourcompany.com — your Workspace, your
12brand.`},{heading:"branding",content:"Workspace → Settings → Branding lets you swap:"},{heading:"branding",content:"Workspace display name"},{heading:"branding",content:"Logo (top-left of the chat header)"},{heading:"branding",content:"Favicon"},{heading:"branding",content:"Primary accent color"},{heading:"branding",content:`These propagate to both the bastio.com fallback and your custom
13domain. The login page on your custom domain shows your branding;
14Bastio's name doesn't appear unless you put it there.`},{heading:"tls--cert-renewal",content:`Certs are issued by Let's Encrypt and auto-renew 30 days before
15expiry. If renewal fails (DNS changes, CNAME removed), the
16dashboard warns the workspace owner and falls back to the
17Bastio-issued domain until you fix the records.`},{heading:"multiple-domains-per-workspace",content:`You can add multiple domains — useful if you're rebranding
18("chat.acme.com" → "ai.acme.com") and want both live during the
19transition. Mark one as primary; that's the canonical URL the
20sidebar links use.`},{heading:"removing-a-domain",content:`Workspace → Settings → Domain → trash icon. The cert is revoked,
21the routing entry is removed, the workspace falls back to the
22default Bastio host. Existing chat URLs on the removed domain
23will 404 — bookmark the new domain before removing the old.
24Audited as domain.deleted.`},{heading:"apex-domains",content:`CNAMEs on the apex (yourcompany.com) aren't allowed by DNS
25spec. If you want the chat at the apex, use an ALIAS record
26(supported by Cloudflare, Route53, dnsimple) pointing to
27workspace.bastio.com. The TXT verification works the same
28way.`},{heading:"email",content:`If you set a support email in Settings → Branding, error
29pages on your custom domain show that email instead of
30Bastio's. The auth emails (welcome, password reset, invite)
31still come from [email protected] by default — Enterprise
32customers can set up custom-sender via DKIM-aligned SMTP
33records; talk to us.`},{heading:"common-pitfalls",content:`DNS propagation slower than 5 minutes. Some providers
34(especially registrar bundles like GoDaddy, Network Solutions)
35take 15-60 minutes to propagate TXT changes. Bastio polls for
36up to 6 hours before timing out.`},{heading:"common-pitfalls",content:`Conflicting CAA record. If your domain has a CAA record
37restricting cert issuers and Let's Encrypt isn't on it, cert
38generation fails. Add letsencrypt.org to your CAA record or
39remove the CAA restriction for the chat subdomain.`},{heading:"common-pitfalls",content:`CDN in front of the CNAME. Don't proxy
40chat.yourcompany.com through Cloudflare's "orange cloud"
41proxy unless you've configured Authenticated Origin Pulls.
42Plain DNS-only is fine; double TLS termination breaks WebSocket
43streaming for chat replies.`},{heading:"next",content:`For admins — the rest of
44the admin surface.`},{heading:"next",content:`Billing — custom domains require
45Business plan and above.`}],headings:[{id:"how-it-works",content:"How it works"},{id:"walkthrough",content:"Walkthrough"},{id:"branding",content:"Branding"},{id:"tls--cert-renewal",content:"TLS + cert renewal"},{id:"multiple-domains-per-workspace",content:"Multiple domains per workspace"},{id:"removing-a-domain",content:"Removing a domain"},{id:"apex-domains",content:"Apex domains"},{id:"email",content:"Email"},{id:"common-pitfalls",content:"Common pitfalls"},{id:"next",content:"Next"}]};const c=[{depth:2,url:"#how-it-works",title:e.jsx(e.Fragment,{children:"How it works"})},{depth:2,url:"#walkthrough",title:e.jsx(e.Fragment,{children:"Walkthrough"})},{depth:2,url:"#branding",title:e.jsx(e.Fragment,{children:"Branding"})},{depth:2,url:"#tls--cert-renewal",title:e.jsx(e.Fragment,{children:"TLS + cert renewal"})},{depth:2,url:"#multiple-domains-per-workspace",title:e.jsx(e.Fragment,{children:"Multiple domains per workspace"})},{depth:2,url:"#removing-a-domain",title:e.jsx(e.Fragment,{children:"Removing a domain"})},{depth:2,url:"#apex-domains",title:e.jsx(e.Fragment,{children:"Apex domains"})},{depth:2,url:"#email",title:e.jsx(e.Fragment,{children:"Email"})},{depth:2,url:"#common-pitfalls",title:e.jsx(e.Fragment,{children:"Common pitfalls"})},{depth:2,url:"#next",title:e.jsx(e.Fragment,{children:"Next"})}];function o(t){const n={a:"a",code:"code",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",span:"span",strong:"strong",ul:"ul",...t.components};return e.jsxs(e.Fragment,{children:[e.jsxs(n.p,{children:["By default your Workspace lives at ",e.jsx(n.co
45de,{children:"workspace.bastio.com/c/<id>"}),`.
46Custom domains let you run the same chat product on
47`,e.jsx(n.code,{children:"chat.yourcompany.com"}),` (or anything else under your control) with
48your branding, no Bastio chrome, and a TLS cert managed for you.`]}),`
49`,e.jsx(n.p,{children:"Available on Business and Enterprise plans."}),`
50`,e.jsx(n.h2,{id:"how-it-works",children:"How it works"}),`
51`,e.jsx(n.p,{children:"Two DNS records under your domain:"}),`
52`,e.jsx(e.Fragment,{children:e.jsx(n.pre,{className:"shiki shiki-themes github-light github-dark",style:{"--shiki-light":"#24292e","--shiki-dark":"#e1e4e8","--shiki-light-bg":"#fff","--shiki-dark-bg":"#24292e"},tabIndex:"0",icon:'<svg viewBox="0 0 24 24"><path d="M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z" fill="currentColor" /></svg>',children:e.jsxs(n.code,{children:[e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"TXT  _bastio.chat.yourcompany.com  →  bastio-verify=<token>"})}),`
53`,e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"CNAME chat.yourcompany.com         →  workspace.bastio.com"})})]})})}),`
54`,e.jsx(n.p,{children:`The TXT record proves you control the domain. The CNAME routes
55traffic to Bastio's edge, which terminates TLS with a Let's
56Encrypt cert generated automatically once the TXT is verified.`}),`
57`,e.jsx(n.p,{children:`Verification is fully automated — no support ticket. The
58dashboard polls the TXT record on a backoff (~30s, 1m, 5m, 15m,
59hourly) until it sees the right value.`}),`
60`,e.jsx(n.h2,{id:"walkthrough",children:"Walkthrough"}),`
61`,e.jsxs(n.ol,{children:[`
62`,e.jsxs(n.li,{children:[`
63`,e.jsx(n.p,{children:e.jsx(n.strong,{children:"Workspace → Settings → Domain → Add custom domain."})}),`
64`]}),`
65`,e.jsxs(n.li,{children:[`
66`,e.jsxs(n.p,{children:["Enter the hostname you want — typically ",e.jsx(n.code,{children:"chat.yourcompany.com"}),`
67or `,e.jsx(n.code,{children:"ai.yourcompany.com"}),`. Bastio generates a verification
68token.`]}),`
69`]}),`
70`,e.jsxs(n.li,{children:[`
71`,e.jsx(n.p,{children:"Copy the TXT record into your DNS provider:"}),`
72`,e.jsx(e.Fragment,{children:e.jsx(n.pre,{className:"shiki shiki-themes github-light github-dark",style:{"--shiki-light":"#24292e","--shiki-dark":"#e1e4e8","--shiki-light-bg":"#fff","--shiki-dark-bg":"#24292e"},tabIndex:"0",icon:'<svg viewBox="0 0 24 24"><path d="M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z" fill="currentColor" /></svg>',children:e.jsxs(n.code,{children:[e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"Type: TXT"})}),`
73`,e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"Name: _bastio.chat.yourcompany.com"})}),`
74`,e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"Value: bastio-verify=abc123…"})}),`
75`,e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"TTL:  300"})})]})})}),`
76`]}),`
77`,e.jsxs(n.li,{children:[`
78`,e.jsx(n.p,{children:'Wait ~5 minutes. The dashboard shows "Verifying…" → "Verified".'}),`
79`]}),`
80`,e.jsxs(n.li,{children:[`
81`,e.jsx(n.p,{children:"Add the CNAME:"}),`
82`,e.jsx(e.Fragment,{children:e.jsx(n.pre,{className:"shiki shiki-themes github-light github-dark",style:{"--shiki-light":"#24292e","--shiki-dark":"#e1e4e8","--shiki-light-bg":"#fff","--shiki-dark-bg":"#24292e"},tabIndex:"0",icon:'<svg viewBox="0 0 24 24"><path d="M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z" fill="currentColor" /></svg>',children:e.jsxs(n.code,{children:[e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"Type: CNAME"})}),`
83`,e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"Name: chat.yourcompany.com"})}),`
84`,e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"Value: workspace.bastio.com"})}),`
85`,e.jsx(n.span,{className:"line",children:e.jsx(n.span,{children:"TTL:  300"})})]})})}),`
86`]}),`
87`,e.jsxs(n.li,{children:[`
88`,e.jsx(n.p,{children:`Wait another ~2 minutes. Bastio detects the CNAME, requests a
89Let's Encrypt cert, and flips the domain to "Active".`}),`
90`]}),`
91`,e.jsxs(n.li,{children:[`
92`,e.jsxs(n.p,{children:["Open ",e.jsx(n.code,{children:"https://chat.yourcompany.com"}),` — your Workspace, your
93brand.`]}),`
94`]}),`
95`]}),`
96`,e.jsx(n.h2,{id:"branding",children:"Branding"}),`
97`,e.jsx(n.p,{children:"Workspace → Settings → Branding lets you swap:"}),`
98`,e.jsxs(n.ul,{children:[`
99`,e.jsx(n.li,{children:"Workspace display name"}),`
100`,e.jsx(n.li,{children:"Logo (top-left of the chat header)"}),`
101`,e.jsx(n.li,{children:"Favicon"}),`
102`,e.jsx(n.li,{children:"Primary accent color"}),`
103`]}),`
104`,e.jsx(n.p,{children:`These propagate to both the bastio.com fallback and your custom
105domain. The login page on your custom domain shows your branding;
106Bastio's name doesn't appear unless you put it there.`}),`
107`,e.jsx(n.h2,{id:"tls--cert-renewal",children:"TLS + cert renewal"}),`
108`,e.jsx(n.p,{children:`Certs are issued by Let's Encrypt and auto-renew 30 days before
109expiry. If renewal fails (DNS changes, CNAME removed), the
110dashboard warns the workspace owner and falls back to the
111Bastio-issued domain until you fix the records.`}),`
112`,e.jsx(n.h2,{id:"multiple-domains-per-workspace",children:"Multiple domains per workspace"}),`
113`,e.jsx(n.p,{children:`You can add multiple domains — useful if you're rebranding
114("chat.acme.com" → "ai.acme.com") and want both live during the
115transition. Mark one as primary; that's the canonical URL the
116sidebar links use.`}),`
117`,e.jsx(n.h2,{id:"removing-a-domain",children:"Removing a domain"}),`
118`,e.jsxs(n.p,{children:[`Workspace → Settings → Domain → trash icon. The cert is revoked,
119the routing entry is removed, the workspace falls back to the
120default Bastio host. Existing chat URLs on the removed domain
121will 404 — bookmark the new domain before removing the old.
122Audited as `,e.jsx(n.code,{children:"domain.deleted"}),"."]}),`
123`,e.jsx(n.h2,{id:"apex-domains",children:"Apex domains"}),`
124`,e.jsxs(n.p,{children:[`CNAMEs on the apex (yourcompany.com) aren't allowed by DNS
125spec. If you want the chat at the apex, use an ALIAS record
126(supported by Cloudflare, Route53, dnsimple) pointing to
127`,e.jsx(n.code,{children:"workspace.bastio.com"}),`. The TXT verification works the same
128way.`]}),`
129`,e.jsx(n.h2,{id:"email",children:"Email"}),`
130`,e.jsxs(n.p,{children:[`If you set a support email in Settings → Branding, error
131pages on your custom domain show that email instead of
132Bastio's. The auth emails (welcome, password reset, invite)
133still come from `,e.jsx(n.code,{children:"[email protected]"}),` by default — Enterprise
134customers can set up custom-sender via DKIM-aligned SMTP
135records; talk to us.`]}),`
136`,e.jsx(n.h2,{id:"common-pitfalls",children:"Common pitfalls"}),`
137`,e.jsxs(n.ul,{children:[`
138`,e.jsxs(n.li,{children:[e.jsx(n.strong,{children:"DNS propagation slower than 5 minutes."}),` Some providers
139(especially registrar bundles like GoDaddy, Network Solutions)
140take 15-60 minutes to propagate TXT changes. Bastio polls for
141up to 6 hours before timing out.`]}),`
142`,e.jsxs(n.li,{children:[e.jsx(n.strong,{children:"Conflicting CAA record."}),` If your domain has a CAA record
143restricting cert issuers and Let's Encrypt isn't on it, cert
144generation fails. Add `,e.jsx(n.code,{children:"letsencrypt.org"}),` to your CAA record or
145remove the CAA restriction for the chat subdomain.`]}),`
146`,e.jsxs(n.li,{children:[e.jsx(n.strong,{children:"CDN in front of the CNAME."}),` Don't proxy
147chat.yourcompany.com through Cloudflare's "orange cloud"
148proxy unless you've configured Authenticated Origin Pulls.
149Plain DNS-only is fine; double TLS termination breaks WebSocket
150streaming for chat replies.`]}),`
151`]}),`
152`,e.jsx(n.h2,{id:"next",children:"Next"}),`
153`,e.jsxs(n.ul,{children:[`
154`,e.jsxs(n.li,{children:[e.jsx(n.a,{href:"/docs/cloud/workspace/for-admins",children:"For admins"}),` — the rest of
155the admin surface.`]}),`
156`,e.jsxs(n.li,{children:[e.jsx(n.a,{href:"/docs/cloud/billing",children:"Billing"}),` — custom domains require
157Business plan and above.`]}),`
158`]})]})}function d(t={}){const{wrapper:n}=t.components||{};return n?e.jsx(n,{...t,children:e.jsx(o,{...t})}):o(t)}export{d as default,r as extractedReferences,a as frontmatter,s as structuredData,c as toc};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.