Skip to main content

erun expose

Expose an in-namespace Service at a stable public hostname under the platform's services zone. erun expose is for platform deployments — installations that run the PowerDNS singleton and declare a platform: block. It does two things: it ensures a per-environment wildcard DNS record points at the env's ingress IP, and it applies a Host-routing Ingress for the Service.

A hosted platform already runs this for you against its runtime environments' MCP edge as part of their server-side deploy — see Hosted platform · Automatic exposure. Run this command by hand for any other service you want to expose, or on a platform that predates automatic exposure.

erun expose team dev api --ip 203.0.113.10
erun expose team dev api --ip 203.0.113.10 --port 8080
erun expose team dev api --ip 127.0.0.1 --dry-run # preview, no side effects

What it does

For erun expose <tenant> <env> <service>, <service> is the logical service name: it becomes the DNS label in the public hostname <service>.<tenant>-<env>.<servicesZone> (the services zone comes from the platform config — e.g. api.team-dev.services.erunpaas.com) and the Ingress routes it to the tenant-scoped in-namespace Service <tenant>-<service> — the name that service's component chart renders (e.g. apiteam-api). The public host stays a clean label while the Ingress targets the real Service. The flow:

  1. Per-env wildcard A record. It upserts *.<tenant>-<env>.<servicesZone>--ip (TTL 60) in the platform's authoritative zone by exec'ing pdnsutil inside the platform's PowerDNS pod. The wildcard covers every service in that env, so exposing additional services later only adds an Ingress — the DNS record is written once.
  2. Host-routing Ingress. It applies an Ingress named expose-<service> into the env's namespace, routing the hostname to the tenant-scoped Service <tenant>-<service> on --port (default 80).

The DNS write targets the platform environment's cluster (where PowerDNS runs); the Ingress is applied to the target env's cluster. These can be different clusters — expose resolves each context independently.

HTTPS is requested by default, but it only takes effect when something will actually populate the env's per-env wildcard cert Secret (<tenant>-<env>-wildcard-tls): the Ingress carries a tls: block referencing it and sets ingressClassName only once --dns01-token-file, --dns01-broker-url, and --acme-email are all set, provisioning that Secret through erun's DNS-01 broker — see Networking spec · Platform service exposure for the exact mechanism. On a hosted platform these three flags are supplied automatically as part of the environment's server-side deploy; running expose by hand for it needs nothing extra. Without them, expose resolves to the same plain http:// Ingress --no-tls asks for explicitly, rather than referencing a Secret nothing will ever populate. Pass --ingress-class / --tls-secret to override the defaults.

Removing exposure

erun unexpose <tenant> <env> removes the per-env wildcard DNS record expose created. A hosted platform's environment deletion already runs this for you — see Hosted platform · Automatic exposure. Run it by hand only if you exposed an environment manually and are tearing it down outside the normal delete flow.

Flags

FlagDescription
--ip <ip>Required. The env's ingress IP the per-env wildcard record points at — 127.0.0.1 for a VM-backed local cluster, a node/LAN IP, or the public LB IP for a remote cluster.
--port <int>Service port the Ingress routes to. Default 80.
--skip-if-unconfiguredSucceed as a no-op instead of the "no platform block" error below, for a script that calls expose after another command without knowing whether the target project is a platform deployment.
--dry-runResolve and print the full plan — the hostname, the pdnsutil exec, and the Ingress apply — without touching DNS or the cluster.

Error behaviour

ConditionWhat happensRecover
No platform: block (or no base domain) in .erun/config.yamlAborts: a platform block with a base domain is required in .erun/config.yaml; exit 1.Add a platform: block.
Malformed platform: blockAborts with the specific validation error (bad base domain, services zone not under it, unparseable authoritative IP, …); exit 1.Fix the offending field.
platform: block has no envAborts: platform.env is required in .erun/config.yaml …; exit 1. expose derives the PowerDNS pod's namespace from platform.env, so it cannot run without it.Set platform.env to the platform environment that runs PowerDNS.
--ip omittedAborts: a target IP is required …; exit 1.Pass --ip <env ingress IP>.
Service name is not a DNS-1035 labelAborts before any DNS write: service name "…" must be a DNS-1035 label …; exit 1.Use a lowercase letters/digits/hyphen name.
pdnsutil exec or Ingress apply fails (live run)Surfaces the underlying kubectl error; the wildcard record and the Ingress are applied in that order, so a later failure can leave the DNS record written.Re-run once the cluster issue is resolved — both operations are idempotent (record replace, Ingress apply).

See also