Skip to main content
Tensor9 can automatically generate publicly-accessible custom DNS hostnames and hosted zones for deployed appliances. This also enables the touch-free generation of SSL certificates. You can enable this feature by assigning a root vanity domain for your app during app creation. There are two ways to assign domains to appliances:
  1. Vendor-Supplied: Tensor9 automatically assigns subdomains of the app’s root vanity domain to customers (e.g., customer-a.ai-chat.playground.tensor9.app).
  2. Customer-Supplied: Your customer brings their own domain (e.g., app.internal.customer.com) and delegates it to the appliance.
In both cases, your Terraform origin stack remains exactly the same. The Tensor9 architectural model ensures that the hosted zone is created during appliance setup before the deployment stack is deployed. The deployment stack simply looks up the pre-existing zone to create records.

Enable Vanity Domains for Your Customers

To enable vanity domains, create your app with the -vanityDomain flag:
1

Specify a vanity domain during app creation

Specify the root domain:
tensor9 app create \
  -name ai-chat \
  -vanityDomain ai-chat.playground.tensor9.app
This triggers the Tensor9 Vendor Controller to create a hosted zone for this domain in your Tensor9 account.
2

One-time manual delegation

You must perform a one-time manual delegation from your DNS provider to the nameservers of the hosted zone created by Tensor9. This allows Tensor9 to manage subdomains on your behalf.

Vanity Domain Assignment

Once the app is created with a vanity domain, your customers can choose to use either the vendor-supplied or customer-supplied vanity domain option during appliance setup.

Vendor-Supplied Domains

In this model, Tensor9 automatically manages the assignment and delegation of a subdomain of your app’s root vanity domain to an appliance. When a customer installs your app, Tensor9 automatically:
1

Assigns a unique subdomain

Tensor9 assigns a unique subdomain to the appliance (e.g., customer-a.ai-chat.playground.tensor9.app).
2

Creates a hosted zone

The appliance setup process automatically creates a hosted zone for this subdomain within the customer’s cloud account.
3

Delegates the subdomain

Tensor9 automatically delegates the subdomain from your root hosted zone to the appliance hosted zone.

Customer-Supplied Domains

In this model, your customer brings their own domain name.
1

Customer provides domain

During appliance installation, the customer specifies their desired domain (e.g., portal.corp.com).
2

Zone Creation

The appliance setup process automatically creates a hosted zone for this domain within the customer’s cloud account.
3

Customer Delegation

The customer manually adds an NS record to their DNS provider to delegate the domain to their appliance hosted zone.

Origin Stack

To support both workflows, your Terraform code should be written to consume a hosted zone rather than create one.

1. Receive the Domain Name

Use the @vanity_domain_root() annotation on a variable. Tensor9 will inject the appliance’s assigned fully qualified domain name (FQDN) at deploy time.
# @vanity_domain_root()
variable "domain_root" {
  type        = string
  default     = "local.example.com"
}

2. Look Up the Hosted Zone

Reference the hosted zone using a Terraform data source instead of a resource. The zone will already exist (created by the appliance setup) by the time your stack is deployed.
data "aws_route53_zone" "app_zone" {
  name = var.domain_root
}

resource "aws_route53_record" "app" {
  zone_id = data.aws_route53_zone.app_zone.zone_id
  name    = "www.${var.domain_root}"
  type    = "CNAME"
  ttl     = 300
  records = [aws_lb.app.dns_name]
}

3. SSL Certificates

Since the domain is properly delegated to the appliance’s account, you can use automatic DNS validation for SSL certificates.
resource "aws_acm_certificate" "cert" {
  domain_name       = "www.${var.domain_root}"
  validation_method = "DNS"
}

resource "aws_route53_record" "cert_validation" {
  for_each = {
    for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = data.aws_route53_zone.app_zone.zone_id
}

resource "aws_acm_certificate_validation" "cert" {
  certificate_arn         = aws_acm_certificate.cert.arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}

Optional Annotations

@vanity_domain_provided()

Best Practice: We recommend defining your hosted zone in a separate infrastructure stack or allowing Tensor9 to manage it during appliance setup. This keeps your application origin stack focused on application resources. However, if you need to keep the hosted zone definition inside your origin stack (e.g., for self-contained single-file stacks or legacy architectures), you can use @vanity_domain_provided() to handle this conditionally. Annotate a boolean variable with @vanity_domain_provided(). Set it to true to allow the hosted zone to be created when you deploy the stack. During compiling of your deployment stack, Tensor9 will set the variable to false to skip hosted zone creation (since it was created during appliance setup) and allow the deployment stack to look up the zone.
# @vanity_domain_provided()
variable "zone_provided" {
  type    = bool
  default = false
}

# Conditionally create the zone ONLY if it wasn't provided
resource "aws_route53_zone" "created_zone" {
  count = var.zone_provided ? 0 : 1
  name  = var.domain_root
}

# Look up the zone if it WAS provided
data "aws_route53_zone" "lookup_zone" {
  count = var.zone_provided ? 1 : 0
  name  = var.domain_root
}

Best Practices

Please note the following best practices when defining a root vanity domain for your customers:
If your app is present at saas.com pick an alternative like saas-customers.com or saas.app. This ensures that the cookie space for your hosted offering is entirely separate from your customer’s installs. Your customers will have control over the appliance vanity domain hosted zone since they are created inside their environment.
The maximum length of the Common Name in a certificate is 64 characters. Vanity domains assigned to customers will include the appliance ID as well as any endpoints you have defined in your origin stack. The total length of the subdomain for which a certificate is requested cannot exceed the limit.

SSL

Since Tensor9 automatically delegates a vanity subdomain into the customer’s account, it is possible to generate certificates automatically and touch-free. If your origin stack defines SSL certificates, like AWS ACM certificates, make sure that the domain of the certificate refers to a record inside of your stack’s hosted zone and enable DNS validation. If you also provide a root vanity domain during app creation (as described above) then Tensor9’s automatic delegation of an assigned vanity subdomain into the customer’s account will allow the resource to be created at stack deploy time.