Skip to main content

Configuring Previews

Overview

Preview URLs work out of the box: every endpoint declared on a sandbox or route group gets a URL on Signadot's domain, authenticated and served for you.

Starting with Operator v1.4.0, previews are also configurable per cluster, in the operator's Helm values:

  • Preview URLs on your own domain. By pointing an ingress you control at the operator's preview server, previews can be served on a domain of yours (for example *.preview.example.com) with your own TLS certificates and your own access controls.
  • Turning previews off for a cluster entirely, so that Signadot serves no preview traffic for it.

Both are set in the chart — the API and the Dashboard report them, read-only.

Declaring preview endpoints

Nothing changes in how endpoints are declared. They are defined on a sandbox's defaultRouteGroup or on a standalone Route Group, exactly as before:

name: my-sandbox
spec:
cluster: my-cluster
forks:
- forkOf:
kind: Deployment
namespace: hotrod
name: frontend
customizations:
images:
- image: my-registry/frontend:pr-42
defaultRouteGroup:
endpoints:
- name: frontend
target: http://frontend.hotrod.svc:8080

The configuration below only changes what domain the resulting URL is on and whether it is served.

Configuring previews

Previews are configured per cluster, in the operator's Helm values:

previewServer:
enabled: true # serve previews for this cluster
customDomain: preview.example.com # optional; your own base domain
helm upgrade signadot-operator signadot/operator \
--namespace signadot --reuse-values \
--set previewServer.customDomain=preview.example.com
ValueBehavior
previewServer.enabled: true (default)Previews are served for this cluster.
previewServer.enabled: falsePreview traffic is refused for this cluster — including through your own ingress (see warnings below).
previewServer.customDomainThe base domain used in the Preview URLs reported for the cluster's endpoints. You serve that domain yourself (see setup).

The chart validates the values when it renders: customDomain must be a bare domain of at least two labels (no scheme, port, path, wildcard or trailing dot, at most 255 characters), and setting it with enabled: false is rejected — with previews off there is nothing behind the domain to serve it.

Changing the values is a helm upgrade; the Signadot Control Plane picks them up from the cluster's cluster-config ConfigMap.

Checking what a cluster is doing

The API reports each cluster's previews, and is read-only — the chart values above are where previews are configured:

curl -H "signadot-api-key: $SIGNADOT_API_KEY" \
"https://api.signadot.com/api/v2/orgs/${ORG}/clusters/${CLUSTER}/preview"

The report has three fields, plus notes when they do not speak for themselves:

  • previews — whether previews are served: in-cluster (operator v1.4.0+), control-plane (an older operator, or a cluster that has never connected), or off.
  • customDomain — the cluster's custom domain, when one is set.
  • configured — whether the chart carries previewServer values at all. false means the chart predates them; such a cluster behaves as it always has.

The same report backs the Previews card on the cluster's page in the Dashboard.

Version requirements and effect on existing setups

  • Operator v1.4.0 or later is required for custom domains and for turning previews off. Nothing else needs to be installed.
  • Clusters on older operators are unaffected. They keep the behavior they have always had; upgrading the operator is what makes the configuration available.
  • Existing Preview URLs keep working. A custom domain changes which URL is reported for an endpoint, not which URLs resolve.
  • The traffic source inside your cluster changes on upgrade. From v1.4.0 the operator serves previews with a component of its own, previewserver, so preview requests reach your workloads from the previewserver Pod (label app=previewserver, in the operator's namespace) rather than from the Signadot tunnel agent. If you use NetworkPolicies, a service mesh with strict mTLS, or source-IP-based controls that restrict which Pods may call your services, allow traffic from previewserver before upgrading, or hold the cluster on its current operator version until you have. A blocked hop surfaces as 502 responses on preview URLs.

Serving previews on your own domain

To serve previews through your own ingress:

  1. Upgrade the operator to v1.4.0 or later.

  2. Choose a base domain (for example preview.example.com) and provision a wildcard TLS certificate for *.preview.example.com. TLS terminates at your ingress; previewserver speaks plain HTTP behind it.

  3. Point your ingress at previewserver: the previewserver Service, port 8080, in the operator's namespace. See the per-controller examples below.

  4. Set previewServer.customDomain to your base domain and helm upgrade. Preview URLs reported by the API and Dashboard then use it, in the form https://<endpoint-id>.preview.example.com — the leading DNS label is the endpoint's opaque ID — and can be called like any other URL you serve:

    curl https://ep2fbmvlpr9zw.preview.example.com/api/status

Your ingress configuration must satisfy two requirements, and both matter:

  1. Forward the original Host header unchanged. previewserver resolves each request from the leading DNS label of Host. Most controllers (ingress-nginx, Gateway API) preserve Host by default.
  2. Strip any client-supplied X-Forwarded-Host header before setting your own. X-Forwarded-Host is used as a fallback identity source, so an ingress that blindly forwards a client's value turns it into a forgeable input.

Ingress configuration by controller

All of the examples below satisfy both requirements when applied as written. Use the one matching the controller you already run; each tab notes the controller-specific settings that must hold for the example to stay correct.

Each example addresses the previewserver Service by port number (8080) rather than by port name. That is deliberate: the single listener carries both HTTP/1.1 and cleartext HTTP/2 (gRPC previews arrive on it too), and a service mesh selects the protocol it speaks to a backend from the port's name, so the name is a protocol declaration rather than a stable address.

Both requirements are covered by nginx's default proxy template with no annotations needed:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: previewserver
namespace: signadot
spec:
ingressClassName: nginx
tls:
- hosts:
- "*.preview.example.com"
secretName: preview-wildcard-tls
rules:
- host: "*.preview.example.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: previewserver
port:
number: 8080
warning

This is safe only while the controller's use-forwarded-headers setting is false (nginx's default). With use-forwarded-headers: true, common when nginx sits behind another L7 proxy or cloud load balancer, nginx substitutes a client-supplied X-Forwarded-Host into its own routing decisions, which breaks both requirements at once: a request could be served another endpoint's content by forging a single header. This is a controller-wide setting that cannot be fixed per-Ingress; if your main controller needs it enabled, run a separate dedicated controller instance for previews with the setting left at its default. Confirm your controller's actual setting before relying on this example.

Requests arriving through your ingress are served by previewserver directly and are not authenticated by Signadot. Access control for your domain is yours, at your ingress. Preview URLs on Signadot's domain remain authenticated by the Signadot Control Plane as before.

Turning previews off and on

Setting previewServer.enabled: false makes Signadot refuse preview traffic for the cluster (and uninstalls the previewserver component). Things to know before flipping it:

  • Preview requests are refused with 404 (gRPC: NOT_FOUND) for every endpoint on the cluster, including previously shared links.
  • Reported URLs do not change. Endpoints keep listing their addresses in the API, the Dashboard and pull request comments — links to them are already in circulation — they just stop working.
  • Your own domain stops working too. Uninstalling previewserver removes the backend your ingress points at.
  • Re-enabling restores serving. Endpoint IDs are stable, so links that existed before the toggle work again after it.

Both directions take a helm upgrade and take effect once the Signadot Control Plane picks up the cluster's updated configuration.

Effect on sandboxes and route groups

  • The configuration is per cluster, per endpoint. Each endpoint follows the configuration of the cluster its target lives in, so a route group that spans clusters can mix URLs on different domains, and endpoints Signadot serves with endpoints it does not.
  • Status is unchanged. An endpoint that cannot be resolved in the cluster is reported on the sandbox's and route group's readiness status, and a preview URL returns 503 until the sandbox's routing is ready — the same readiness that has always gated sandbox traffic. See Sandbox Status.

Use cases

  • Previews behind your own access controls: serve preview URLs on your domain behind your SSO/VPN/ingress policies, keeping preview traffic off shared external infrastructure.
  • Custom-branded preview links: PR comments and notifications carry https://<id>.preview.your-domain.com links that live entirely within your DNS and certificates.
  • Compliance and network isolation: serve previews through your own ingress, on your own domain. Note this governs what is advertised, not a closed path: while previews are enabled, the same endpoints stay reachable on Signadot's domain as well.

See also