Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs/concepts/core-features/networking.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ The Tenant and Admin gateways are deployed as separate Istio gateways with their

By default, gateways only support HTTP/HTTPS traffic. Non-HTTP TCP ingress (e.g., SSH) requires additional configuration. See [Set up non-HTTP ingress](/how-to-guides/networking/configure-non-http-ingress/).

## Domain-based vs path-based routing

UDS Core defaults to domain-based routing, where each exposed application uses a dedicated hostname. You can optionally enable path-based routing for built-in services when your ingress model needs fewer DNS entries and explicit path segmentation on shared hosts.

The routing models differ as follows:

| Model | URL pattern | Best fit | Notes |
|---|---|---|---|
| Domain-based (default) | `https://app.yourdomain.com` | Most platform and app deployments | Clear isolation by hostname and straightforward DNS ownership |
| Path-based (optional) | `https://yourdomain.com/<context>/<app-path>` | Environments that prefer shared hosts with path segmentation | In this release, built-in Keycloak and Grafana routes are path-aware |

When path routing is enabled with `pathRouting: true`, UDS Core builds built-in routes from `domain`, `adminDomain`, `contextPath`, and `adminContextPath` values in `ClusterConfig`.

For example, with `domain=example.mil`, `adminDomain=admin.example.mil`, `contextPath=/platform`, and `adminContextPath=/admin`:

- Keycloak SSO is exposed at `https://example.mil/platform/sso`
- Keycloak admin is exposed at `https://admin.example.mil/platform/admin/keycloak`
- Grafana is exposed at `https://admin.example.mil/platform/admin/grafana`

Application teams can still use `Package` route matching (`match.uri`) and rewrites (`advancedHTTP.rewrite`) to route multiple app paths on shared hosts. Reference [Use path-based routing](/how-to-guides/networking/use-path-based-routing/) for the end-to-end configuration flow.

## How application traffic flows

When a team deploys a UDS Package, they declare their networking intent in a `Package` CR.
Expand Down
32 changes: 30 additions & 2 deletions docs/getting-started/production/build-your-bundle.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ packages:
```yaml title="uds-config.yaml"
variables:
core:
keycloak_db_host: "your-db-host" # hostname or IP of your database server
keycloak_db_host: "your-db-host" # hostname or IP of your database server
keycloak_db_username: "keycloak" # database user created in provision-services step
keycloak_db_database: "keycloak" # database name created in provision-services step
keycloak_db_password: "your-db-password" # password for the database user
Expand Down Expand Up @@ -401,6 +401,35 @@ variables:
> [!NOTE]
> The `shared` section values (`domain`) are automatically available to all packages in the bundle. No bundle YAML overrides are needed for domain configuration; they flow through automatically.

## Configure path-based routing (optional)

UDS Core can route built-in services on shared hosts by URL path instead of subdomain. This is useful when your ingress model prefers one public host and one admin host with explicit path segmentation.

To enable this behavior, set the `ClusterConfig` expose fields through core overrides:

```yaml title="uds-bundle.yaml"
packages:
- name: core
overrides:
uds-operator-config:
uds-operator-config:
values:
- path: cluster.expose.pathRouting
value: true
- path: cluster.expose.contextPath
value: "/platform"
- path: cluster.expose.adminContextPath
value: "/admin"
```

With `shared.domain: yourdomain.com` and `shared.admin_domain: admin.yourdomain.com`, the built-in routes become:

- `https://yourdomain.com/platform/sso`
- `https://admin.yourdomain.com/platform/admin/keycloak`
- `https://admin.yourdomain.com/platform/admin/grafana`

Path-based routing in this release applies to built-in Keycloak and Grafana routes. Reference [Use path-based routing](/how-to-guides/networking/use-path-based-routing/) for the complete workflow, `Package` route matching, and troubleshooting.

## Build the bundle

Once your configuration files are ready, create the deployable bundle artifact.
Expand Down Expand Up @@ -432,4 +461,3 @@ Once your configuration files are ready, create the deployable bundle artifact.

> [!NOTE]
> The resulting bundle is self-contained (all images embedded, no internet needed at deploy time), versioned and reproducible, and transferable to airgapped environments or artifact registries.

36 changes: 35 additions & 1 deletion docs/how-to-guides/networking/expose-apps-on-gateways.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,40 @@ After completing this guide, your application will be accessible through one of

All `advancedHTTP` options are composable; you can combine match conditions, headers, CORS, retries, and timeouts in a single expose entry. See the [`Package` CR reference](/reference/operator-and-crds/packages-v1alpha1-cr/) for the full list of supported fields.

4. **Deploy your application**
4. **(Optional) Route multiple applications on a single domain using paths**

If your ingress design uses shared hosts with URL path segmentation, use `match.uri` to route by path and `advancedHTTP.rewrite` to normalize requests for your backend.

```yaml title="uds-package.yaml"
apiVersion: uds.dev/v1alpha1
kind: Package
metadata:
name: app1
namespace: app1
spec:
network:
expose:
- service: app1
selector:
app.kubernetes.io/name: app1
host: "."
gateway: tenant
port: 8080
match:
- uri:
prefix: /app1
advancedHTTP:
rewrite:
# Strip /app1 before forwarding to the upstream application.
uri: /
```

Use this pattern for each application path (for example, `/app1`, `/app2`) to route multiple services on the same host.

> [!TIP]
> Reference [Use path-based routing](/how-to-guides/networking/use-path-based-routing/) for built-in service behavior (`pathRouting`, `contextPath`, and `adminContextPath`) and full configuration examples.

5. **Deploy your application**

**(Recommended)** Include the `Package` CR manifest in your [Zarf package](https://docs.zarf.dev/ref/create/) alongside your application's Helm chart and create/deploy. See [Packaging applications](/how-to-guides/packaging-applications/overview/) for general packaging guidance.

Expand Down Expand Up @@ -276,6 +309,7 @@ curl -v https://my-app.yourdomain.com

- [Networking & Service Mesh Concepts](/concepts/core-features/networking/) - how the service mesh, gateways, and network policies work together in UDS Core
- [`Package` CR Reference](/reference/operator-and-crds/packages-v1alpha1-cr/) - full CR schema and field reference for network, SSO, and monitoring configuration
- [Use path-based routing](/how-to-guides/networking/use-path-based-routing/) - Configure shared-host path routing and built-in service URL paths.
- [Enable the passthrough gateway](/how-to-guides/networking/enable-passthrough-gateway/) - Deploy the optional passthrough gateway for apps that handle their own TLS.
- [Define network access](/how-to-guides/networking/define-network-access/) - Configure intra-cluster and external network access for your application.
- [Create a custom gateway](/how-to-guides/networking/create-custom-gateways/) - Deploy a gateway with independent domain, TLS, and security controls.
Expand Down
5 changes: 5 additions & 0 deletions docs/how-to-guides/networking/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ For background on how the service mesh, gateways, and authorization model work,
description="Make applications accessible through the tenant or admin gateway."
href="/how-to-guides/networking/expose-apps-on-gateways/"
/>
<LinkCard
title="Use path-based routing"
description="Route built-in services and application endpoints on shared domains by URL path."
href="/how-to-guides/networking/use-path-based-routing/"
/>
<LinkCard
title="Enable the passthrough gateway"
description="Deploy the optional passthrough gateway for apps that handle their own TLS."
Expand Down
140 changes: 140 additions & 0 deletions docs/how-to-guides/networking/use-path-based-routing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
title: Use path-based routing
description: Configure UDS Core to route built-in services on shared domains by URL path, then use Package match rules for application path routing.
sidebar:
order: 2.012
---

import { Steps } from '@astrojs/starlight/components';

## What you'll accomplish

This guide shows you how to enable path-based routing in UDS Core and verify the resulting URLs. You will configure `ClusterConfig` expose fields for shared-domain routing and apply `Package` route matching so multiple apps can share one host.

## Prerequisites

- [UDS CLI](https://github.com/defenseunicorns/uds-cli/releases) installed
- [UDS Registry](https://registry.defenseunicorns.com) account created and authenticated locally with a read token
- Access to a Kubernetes cluster with UDS Core deployed
- Familiarity with [Expose applications on gateways](/how-to-guides/networking/expose-apps-on-gateways/)

## Before you begin

UDS Core defaults to domain and subdomain routing. If you do not set `pathRouting: true`, built-in services continue to use hostnames such as `sso.<domain>` and `<app>.<adminDomain>`.

With `pathRouting: true`, UDS Core uses shared hosts for exposed services. Use `Package` `match.uri` rules (and rewrites when needed) to route applications by path and avoid collisions.

## Steps

<Steps>

1. **Enable path routing in your core bundle overrides**

Set `pathRouting` and optional path prefixes in your core override. Use leading slashes and avoid trailing slashes.

```yaml title="uds-bundle.yaml"
packages:
- name: core
repository: registry.defenseunicorns.com/public/core
ref: x.x.x-upstream
overrides:
uds-operator-config:
uds-operator-config:
values:
- path: cluster.expose.pathRouting
value: true
- path: cluster.expose.contextPath
value: "/platform"
- path: cluster.expose.adminContextPath
value: "/admin"
```

> [!IMPORTANT]
> `contextPath` and `adminContextPath` must not collide after normalization. For example, using `/admin` for both fields is invalid.

2. **Set your shared domains**

Configure the public and admin domains in your deployment config.

```yaml title="uds-config.yaml"
shared:
domain: "example.mil"
admin_domain: "admin.example.mil"
```

With the example values above, built-in paths resolve as follows:
- SSO: `https://example.mil/platform/sso`
- Keycloak admin UI: `https://admin.example.mil/platform/admin/keycloak`
- Grafana: `https://admin.example.mil/platform/admin/grafana`

3. **Route application paths with `Package` match rules**

Use URI matching to pin requests to a service path, and rewrite when the backend expects `/` instead of the external path prefix.

```yaml title="uds-package.yaml"
apiVersion: uds.dev/v1alpha1
kind: Package
metadata:
name: app1
namespace: app1
spec:
network:
expose:
- service: app1
selector:
app: app1
host: "."
gateway: tenant
port: 8080
match:
- uri:
prefix: /app1
advancedHTTP:
rewrite:
# Strip the external path prefix before forwarding to the app service.
uri: /
```

If your backend already handles the prefixed path, omit the rewrite.

4. **Create and deploy your bundle**

Build and deploy the updated configuration.

```bash
uds create --confirm
uds deploy uds-bundle-*.tar.zst --confirm
```

</Steps>

## Verification

Verify the cluster routing configuration and test the built-in endpoints.

```bash
uds zarf tools kubectl get clusterconfig uds-cluster-config -o yaml | grep -A6 "expose:"
curl -I https://example.mil/platform/sso
curl -I https://admin.example.mil/platform/admin/grafana
```

## Troubleshooting

### Problem: Requests return 404 after enabling path routing

**Symptom:** Built-in service URLs return `404` or route to the wrong app.

**Solution:** Confirm `contextPath` and `adminContextPath` include a leading `/`, do not include a trailing `/`, and do not normalize to the same value.

### Problem: Backend receives an unexpected prefixed path

**Symptom:** Your app logs show requests such as `/app1/healthz` when it expects `/healthz`.

**Solution:** Add `advancedHTTP.rewrite.uri: /` to the matching expose entry, then redeploy.

## Related documentation

- [Expose applications on gateways](/how-to-guides/networking/expose-apps-on-gateways/) - Configure gateway exposure and route behavior with `Package` resources.
- [Build your bundle](/getting-started/production/build-your-bundle/) - Set core bundle overrides and deploy production-ready bundles.
- [Clusterconfig CR (v1alpha1)](/reference/operator-and-crds/clusterconfig-v1alpha1-cr/) - Field-level reference for `pathRouting`, `contextPath`, and `adminContextPath`.
- [Packages CR (v1alpha1)](/reference/operator-and-crds/packages-v1alpha1-cr/) - Full schema for `match` and `advancedHTTP` route controls.
5 changes: 5 additions & 0 deletions docs/operations/troubleshooting-and-runbooks/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ If you're setting up UDS Core for the first time, see [How-To Guides](/how-to-gu
description="Diagnose and fix admission failures, unexpected mutations, and stuck deployments caused by UDS policies."
href="/operations/troubleshooting-and-runbooks/policy-violations/"
/>
<LinkCard
title="Path Routing Issues"
description="Diagnose path-based routing failures for built-in services and application routes."
href="/operations/troubleshooting-and-runbooks/path-routing-issues/"
/>
<LinkCard
title="Too Many Open Files"
description="Resolve <code>too many open files</code> / <code>watcher create</code> errors caused by low inotify or open file limits on the host."
Expand Down
Loading