Serve your published vault content on your own domain — DNS configuration, TXT verification, and TLS certificate activation.
Lifestream Vault lets you serve your published vault content on a domain you own — for example, docs.yourcompany.com — instead of the default *.lifestreamdynamics.com subdomain. The platform handles domain verification and TLS activation automatically.
By the end of this guide you will have:
Custom domain support requires a Business tier subscription. Upgrade in Settings → Subscription. Published vaults on free and pro tiers are served from the default lifestreamdynamics.com domain.
Prerequisites
The first step is to register your domain with Lifestream Vault. The API creates a domain record and returns a verification token — a unique string you must add to your DNS as a TXT record to prove ownership.
You can add a domain via the UI (Vault Settings → Custom Domains → Add Domain), the SDK, or the REST API.
import { LifestreamVaultClient } from '@lifestreamdynamics/vault-sdk';
const { client } = await LifestreamVaultClient.login(
'https://vault.lifestreamdynamics.com',
'you@example.com',
'your-password',
);
const domain = await client.customDomains.create({
domain: 'docs.yourcompany.com',
});
console.log('Domain ID:', domain.id);
console.log('Verification token:', domain.verificationToken);
// lsvault-verify=abc123...
// You will add this value to a DNS TXT record in the next step.Add two DNS records at your registrar or DNS provider. Log in to your DNS management console and create the following records:
| Record | Name | Value |
|---|---|---|
| TXT | _lsv-verify.docs.yourcompany.com | lsvault-verify=<token> |
| CNAME | docs.yourcompany.com | your-vault-server.lifestreamdynamics.com |
Replace <token> with the verificationToken value returned when you added the domain. Replace your-vault-server.lifestreamdynamics.com with the actual CNAME target shown in Vault Settings → Custom Domains.
Cloudflare users: add both records as DNS-only (grey cloud) initially. You can enable the orange cloud (proxy) after verification completes, but be aware that Cloudflare's proxy terminates TLS — see the TLS section below.
DNS propagation can take anywhere from a few minutes to 48 hours depending on your registrar and TTL settings. The domain-verification BullMQ worker checks automatically with exponential backoff — starting at 5-minute intervals and backing off up to 4 hours between checks. You do not need to manually trigger re-verification.
After you add the DNS TXT record, the domain-verification BullMQ worker runs in the background and queries _lsv-verify.<yourdomain> via DNS. When it finds the correct TXT value, the domain status changes from pending to verified.
Poll the domain status to track progress:
const DOMAIN_ID = 'domain-uuid'; // from the create() response
// Poll until verified (in practice, set up a webhook or check the UI)
async function waitForVerification(maxAttempts = 10) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const domain = await client.customDomains.get(DOMAIN_ID);
console.log(`Attempt ${attempt + 1}: status = ${domain.status}`);
if (domain.status === 'verified') {
console.log('Domain verified! SSL status:', domain.sslStatus);
return domain;
}
if (domain.status === 'failed') {
throw new Error('Domain verification failed — check your DNS records.');
}
// Wait 60 seconds before next poll
await new Promise((resolve) => setTimeout(resolve, 60_000));
}
throw new Error('Verification did not complete within the polling window.');
}
const verified = await waitForVerification();
console.log('Custom domain active:', verified.domain);Verification typically completes within 15 minutes if your DNS records are correct and TTLs are low. If verification has not completed after approximately 48 hours (the maximum number of worker retry attempts), you will receive an email notification and the domain status will change to failed. Check your DNS records with dig TXT _lsv-verify.docs.yourcompany.com and re-add the domain if needed.
After domain verification succeeds, the domain sslStatus changes to active automatically on cloud-hosted deployments. Your custom domain is then fully operational over HTTPS.
Self-hosted deployments require additional reverse proxy configuration:
Caddy (recommended for automatic HTTPS):
docs.yourcompany.com {
reverse_proxy localhost:4100
}
Caddy handles ACME certificate issuance and renewal automatically.
Nginx + Certbot:
server {
listen 443 ssl;
server_name docs.yourcompany.com;
ssl_certificate /etc/letsencrypt/live/docs.yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/docs.yourcompany.com/privkey.pem;
location / {
proxy_pass http://localhost:4100;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Run certbot --nginx -d docs.yourcompany.com to obtain and install the certificate.
Cloudflare proxy (orange cloud): If you are proxying through Cloudflare, TLS termination happens at Cloudflare's edge. Ensure the SSL/TLS mode in your Cloudflare dashboard is set to Full (strict) — Flexible mode sends traffic to the origin over plain HTTP and can cause redirect loops.
| Problem | Solution |
|---|---|
Verification stuck in pending | Check the TXT record with dig TXT _lsv-verify.docs.yourcompany.com +short — the value must exactly match the verificationToken |
CNAME conflict error | Remove any existing A or AAAA records for the subdomain before adding the CNAME; a subdomain cannot have both a CNAME and an address record |
| SSL not activating | Verify the CNAME resolves to the correct target (dig CNAME docs.yourcompany.com); for self-hosted, check reverse proxy TLS configuration |
| Custom domain returns 404 | Verify the vault is published (PUT /api/v1/vaults/:vaultId/publish with { "published": true }) and the domain is linked to the correct vault |
| Mixed content warnings | Ensure all assets referenced in your published content use HTTPS URLs; check for hardcoded http:// links in document frontmatter or embedded HTML |
| Cloudflare redirect loop | Set Cloudflare SSL/TLS mode to Full (strict) — Flexible mode causes an infinite HTTP↔HTTPS redirect loop with some reverse proxy configurations |
CUSTOM_DOMAINS_ENABLED, DOCS_DOMAIN, etc.)