Updated for nself v0.4.8
Configure custom domains, subdomains, and DNS settings for your nself deployment using the BASE_DOMAIN environment variable and automatic service routing.
# In .environments/dev/.env:
BASE_DOMAIN=local.nself.org
# In .environments/staging/.env:
BASE_DOMAIN=staging.yourdomain.com
# In .environments/prod/.env:
BASE_DOMAIN=yourdomain.com
# Rebuild and start
nself build && nself start# Primary domain
DOMAIN=yourdomain.com
# Additional domains (comma-separated)
ADDITIONAL_DOMAINS=www.yourdomain.com,app.yourdomain.com,api.yourdomain.com
# All domains will get SSL certificates automaticallySet up these DNS records with your domain provider:
# Point your domain to your server IP
yourdomain.com. A 203.0.113.1
www.yourdomain.com. A 203.0.113.1
api.yourdomain.com. A 203.0.113.1
app.yourdomain.com. A 203.0.113.1# If using a CNAME to point to another domain
www.yourdomain.com. CNAME yourdomain.com.
api.yourdomain.com. CNAME yourdomain.com.nself automatically creates subdomains based on BASE_DOMAIN:
# Core services (always enabled)
api.{BASE_DOMAIN} # Hasura GraphQL (HASURA_ROUTE=api)
auth.{BASE_DOMAIN} # Authentication (AUTH_ROUTE=auth)
# Optional services (when *_ENABLED=true)
admin.{BASE_DOMAIN} # nself-admin (NSELF_ADMIN_ROUTE=admin)
storage.{BASE_DOMAIN} # MinIO (MINIO_ROUTE=storage)
search.{BASE_DOMAIN} # MeiliSearch (MEILISEARCH_ROUTE=search)
mail.{BASE_DOMAIN} # MailPit (MAILPIT_ROUTE=mail)
grafana.{BASE_DOMAIN} # Grafana (GRAFANA_ROUTE=grafana)
# Custom services
CS_1=ping_api:express-ts:8001
CS_1_ROUTE=ping # ping.{BASE_DOMAIN}# Route external frontend apps through Nginx
FRONTEND_APP_1_NAME=web
FRONTEND_APP_1_PORT=3010
FRONTEND_APP_1_ROUTE=www # www.{BASE_DOMAIN}
FRONTEND_APP_2_NAME=docs
FRONTEND_APP_2_PORT=3011
FRONTEND_APP_2_ROUTE=docs # docs.{BASE_DOMAIN}
FRONTEND_APP_3_NAME=cloud
FRONTEND_APP_3_PORT=3013
FRONTEND_APP_3_ROUTE=cloud # cloud.{BASE_DOMAIN}# Use wildcard DNS for dynamic subdomains
*.yourdomain.com. A 203.0.113.1
# nself generates SSL certificates for all subdomains
# based on enabled services and frontend apps# Default local development domain
BASE_DOMAIN=local.nself.org
# *.local.nself.org resolves to 127.0.0.1 via Cloudflare DNS
# No /etc/hosts configuration needed!
# Services available at:
# - https://api.local.nself.org
# - https://auth.local.nself.org
# - https://admin.local.nself.org
# - https://storage.local.nself.org
# - https://mail.local.nself.org
# - https://search.local.nself.org
# Enable SSL trust for green lock
nself trust# Using a custom local domain
BASE_DOMAIN=myapp.local
# Add to /etc/hosts:
127.0.0.1 myapp.local
127.0.0.1 api.myapp.local
127.0.0.1 auth.myapp.local
127.0.0.1 admin.myapp.local
127.0.0.1 storage.myapp.local
# Generate self-signed certificate
nself prod ssl self-signed myapp.local# If running behind AWS ALB, CloudFlare, etc.
BEHIND_LOAD_BALANCER=true
TRUST_PROXY=true
PROXY_PROTOCOL_ENABLED=true
# Trust these proxy IPs
TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
# Forward headers
FORWARDED_HEADERS_ENABLED=true# When using a CDN (CloudFlare, AWS CloudFront)
CDN_ENABLED=true
CDN_PROVIDER=cloudflare
# Origin server settings
ORIGIN_ONLY_ACCESS=true
ORIGIN_SECRET=your-origin-secret
# Real visitor IP headers
REAL_IP_HEADER=CF-Connecting-IP
CLOUDFLARE_IPS_ENABLED=true# Route different services to different domains
HASURA_DOMAIN=api.yourdomain.com
MINIO_DOMAIN=storage.yourdomain.com
GRAFANA_DOMAIN=monitoring.yourdomain.com
FRONTEND_DOMAIN=app.yourdomain.com
# Custom routing rules
CUSTOM_ROUTES_ENABLED=true# Route by path instead of subdomain
# yourdomain.com/api -> Hasura
# yourdomain.com/storage -> MinIO
# yourdomain.com/monitoring -> Grafana
PATH_BASED_ROUTING=true
API_PATH=/api/v1
STORAGE_PATH=/storage
MONITORING_PATH=/monitoring# Check DNS propagation
dig yourdomain.com A
nslookup yourdomain.com
host yourdomain.com
# Test from multiple locations
dig @8.8.8.8 yourdomain.com
dig @1.1.1.1 yourdomain.com
# Check SSL certificate for domain
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com# nself domain validation
nself domain verify yourdomain.com
nself domain test-ssl yourdomain.com
nself domain check-dns yourdomain.com# Enable customer subdomains
MULTI_TENANT_ENABLED=true
TENANT_SUBDOMAIN_PATTERN=*.yourdomain.com
# Each tenant gets their own subdomain:
# customer1.yourdomain.com
# customer2.yourdomain.com
# etc.
# Database isolation per tenant
TENANT_DATABASE_STRATEGY=schema # or 'database'# Allow customers to use their own domains
CUSTOM_DOMAINS_ENABLED=true
CUSTOM_DOMAIN_VERIFICATION=dns # or 'file'
# Customer points customer.com -> your-server-ip
# You configure:
CUSTOM_DOMAIN_customer_com=customer123
# SSL certificates automatically provisioned# Prevent domain-related attacks
DOMAIN_SECURITY_ENABLED=true
# HSTS for all domains
HSTS_ALL_DOMAINS=true
HSTS_INCLUDE_SUBDOMAINS=true
# Content Security Policy
CSP_FRAME_ANCESTORS='self'
CSP_CONNECT_SRC='self https://*.yourdomain.com'
# Referrer policy
REFERRER_POLICY=strict-origin-when-cross-origin# Validate allowed domains
ALLOWED_DOMAINS=yourdomain.com,www.yourdomain.com
BLOCK_UNKNOWN_DOMAINS=true
# CORS configuration per domain
CORS_ORIGINS=https://yourdomain.com,https://www.yourdomain.com,https://app.yourdomain.com# Development (.environments/dev/.env)
ENV=dev
BASE_DOMAIN=local.nself.org
# SSL via nself trust
# Staging (.environments/staging/.env)
ENV=staging
BASE_DOMAIN=staging.yourdomain.com
# SSL via: nself prod ssl request staging.yourdomain.com --staging
# Production (.environments/prod/.env)
ENV=prod
BASE_DOMAIN=yourdomain.com
# SSL via: nself prod ssl request yourdomain.com# Switch to development
nself env switch dev
# Switch to staging
nself env switch staging
# Switch to production
nself env switch prod
# Compare domain configurations
nself env diff dev prod# Check DNS propagation globally
dig +trace yourdomain.com
# Test specific DNS servers
dig @8.8.8.8 yourdomain.com # Google
dig @1.1.1.1 yourdomain.com # Cloudflare
dig @208.67.222.222 yourdomain.com # OpenDNS
# Clear local DNS cache
sudo dscacheutil -flushcache # macOS
sudo systemctl restart systemd-resolved # Ubuntu# Check if domain is accessible
curl -I https://yourdomain.com
# Verify SSL certificate
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com
# Check certificate details
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null | openssl x509 -noout -dates# Verify subdomain DNS record
dig api.yourdomain.com
# Check nginx configuration
nself exec nginx nginx -t
# View nginx access logs
nself logs nginx | grep api.yourdomain.com
# Test subdomain directly
curl -H "Host: api.yourdomain.com" http://your-server-ip/# Update domain configuration
# 1. Update .env file
DOMAIN=newdomain.com
# 2. Update DNS records for new domain
# 3. Rebuild with new configuration
nself build
# 4. Update SSL certificates
nself ssl renew
# 5. Test new domain
curl -I https://newdomain.com# Redirect old domain to new domain
DOMAIN_REDIRECTS_ENABLED=true
REDIRECT_olddomain_com=https://newdomain.com
# Permanent redirects (301)
REDIRECT_TYPE=permanent
# Temporary redirects (302)
REDIRECT_TYPE=temporary