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. (Optional) Enable root domain support

    By default, UDS Core gateways use wildcard hosts (e.g., *.yourdomain.com), which match subdomains but not the root domain itself. If you need to serve traffic at https://yourdomain.com, enable root domain support in your UDS Core 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"

    Create and deploy the bundle:

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

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

  2. 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.

    Expose on the tenant gateway for 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.

  3. Deploy your application

    (Recommended) Include the Package CR manifest in your Zarf package alongside your application’s Helm chart and create/deploy. See Packaging applications for general packaging guidance.

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

    Or apply the Package CR directly for quick testing:

    Terminal window
    uds zarf tools kubectl apply -f uds-package.yaml

    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

Symptom: 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

Symptom: 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

Symptom: 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: