Skip to content

Expose applications on gateways

After completing this guide, your application will be accessible through one of UDS Core’s ingress gateways — either the tenant gateway (for end-user applications) or the admin gateway (for admin-facing interfaces).

  • UDS CLI installed
  • Access to a Kubernetes cluster with UDS Core deployed and TLS configured — see Configure TLS certificates
  • A domain configured in your uds-config.yaml:
    uds-config.yaml
    shared:
    domain: yourdomain.com
    admin_domain: admin.yourdomain.com # optional, defaults to admin.<domain>
  • Wildcard DNS records for *.yourdomain.com and *.admin.yourdomain.com pointing to the tenant and admin gateway load balancer IPs
  • Familiarity with Zarf packages
  1. Define a Package CR for your application

    Add an expose entry to route traffic through a gateway. The UDS Operator creates the necessary VirtualService and AuthorizationPolicy resources automatically.

    To expose on the tenant gateway (end-user traffic):

    uds-package.yaml
    apiVersion: uds.dev/v1alpha1
    kind: Package
    metadata:
    name: my-app
    namespace: my-app
    spec:
    network:
    expose:
    - service: my-app-service
    selector:
    app.kubernetes.io/name: my-app
    host: my-app
    gateway: tenant
    port: 8080

    This exposes the application at https://my-app.yourdomain.com, routing traffic to port 8080 on pods matching the selector.

    To expose on the admin gateway (admin-facing interfaces), use gateway: admin:

    uds-package.yaml
    apiVersion: uds.dev/v1alpha1
    kind: Package
    metadata:
    name: my-app
    namespace: my-app
    spec:
    network:
    expose:
    - service: my-app-admin
    selector:
    app.kubernetes.io/name: my-app
    host: my-app
    gateway: admin
    port: 9090

    This exposes the application at https://my-app.admin.yourdomain.com. Since the admin and tenant gateways are logically separated, you can apply different security controls to each (IP allowlisting, mTLS client certificates, etc.).

  2. Build and deploy your Zarf package

    Include the Package CR manifest in your Zarf package alongside your application’s Helm chart. Then build and deploy:

    Terminal window
    uds zarf package create --confirm && uds zarf package deploy zarf-package-*.tar.zst --confirm

    If your application is part of a UDS Bundle, include the Zarf package in your bundle and deploy it with uds create and uds deploy instead.

Check that the Package CR was reconciled and shows the expected endpoints:

Terminal window
uds zarf tools kubectl get package my-app -n my-app

The ENDPOINTS column should show your application’s URL(s). Test access:

Terminal window
curl -v https://my-app.yourdomain.com

Expose a service on the root (apex) domain

Section titled “Expose a service on the root (apex) domain”

By default, UDS Core gateways use wildcard hosts (e.g., *.yourdomain.com), which match subdomains but not the root domain itself. To serve traffic at https://yourdomain.com, enable root domain support.

  1. Enable the root domain in your bundle

    uds-bundle.yaml
    packages:
    - name: core
    repository: registry.defenseunicorns.com/public/core
    ref: x.x.x-upstream
    overrides:
    istio-tenant-gateway:
    uds-istio-config:
    values:
    - path: rootDomain.enabled
    value: true
    - path: rootDomain.tls.mode
    value: SIMPLE
    - path: rootDomain.tls.credentialName
    value: "" # Leave blank to auto-create the secret from cert data
    - path: rootDomain.tls.supportTLSV1_2
    value: true
    variables:
    - path: rootDomain.tls.cert
    name: "ROOT_TLS_CERT"
    - path: rootDomain.tls.key
    name: "ROOT_TLS_KEY"
    sensitive: true
    - path: rootDomain.tls.cacert
    name: "ROOT_TLS_CACERT"
  2. Expose your service using the . host

    uds-package.yaml
    apiVersion: uds.dev/v1alpha1
    kind: Package
    metadata:
    name: my-app
    namespace: my-namespace
    spec:
    network:
    expose:
    - service: my-app-service
    selector:
    app.kubernetes.io/name: my-app
    host: "."
    gateway: tenant
    port: 80

    Ensure your DNS has an A record for the root domain pointing to your ingress gateway.

  3. Create and deploy your bundle and application

    Deploy the UDS Core bundle with the root domain overrides:

    Terminal window
    uds create --confirm && uds deploy uds-bundle-*.tar.zst --confirm

    Then build and deploy your application’s Zarf package (which includes the Package CR):

    Terminal window
    uds zarf package create --confirm && uds zarf package deploy zarf-package-*.tar.zst --confirm

Symptoms: Browser or curl returns connection refused or timeout.

Solution:

  • Verify the Package CR was reconciled: uds zarf tools kubectl get package my-app -n my-app — check the STATUS column
  • Ensure your DNS resolves the hostname to the gateway load balancer IP

Symptoms: Application accessible on an unexpected URL or not at all.

Solution:

  • Check the gateway field in your Package CR matches your intent (tenant or admin)
  • Verify the host field — it becomes the subdomain prefix (e.g., host: my-appmy-app.yourdomain.com)
  • Check shared.domain in your uds-config.yaml

Symptoms: Subdomains work but https://yourdomain.com does not.

Solution:

  • Confirm rootDomain.enabled is set to true in your bundle overrides
  • Verify DNS has an A record for the root domain (not just a wildcard)
  • Check that TLS certificates are provided for the root domain configuration

These guides and concepts may be useful to explore next: