Skip to content

Access, hostnames, and TLS

An application becomes publicly reachable when it has at least one access entry. An access entry connects a port on a workload to a hostname on the internet, and chooses the protocol and the TLS strategy that bridges the two.

spec:
access:
- name: public
type: https
target: { workload: web, port: http }
hostname: { generated: true }
tls: { managedBy: edgible }
policies:
auth: { mode: none }

This page walks through each piece.

Edgible supports three access protocols:

typeWhat it doesWhen to use
httpsTLS terminated at Caddy on the device; HTTP forwarded to the workload.The default for any web app or HTTP API.
tcpRaw TCP byte stream forwarded over the tunnel — bytes are not inspected or modified by the platform.Databases, custom protocols, anything non-HTTP.
udpRaw UDP datagrams forwarded over the tunnel.Game servers, DNS, anything UDP-native.

For https, the platform handles TLS. For tcp and udp, your workload is responsible for any encryption it wants — the platform is a transparent pipe.

A hostname tells the platform which traffic belongs to this access entry. There are two kinds.

hostname: { generated: true }

Edgible mints a hostname under a platform-owned domain (something like <app-slug>-<short-id>.edgible.app). The hostname is stable for the lifetime of the application — it doesn’t change on redeploy. Use this for quick prototypes, internal services, anywhere you don’t need a custom name.

hostname: { custom: api.example.com }

Use any hostname you control. You’re responsible for pointing DNS at Edgible (the platform will give you the target record at deploy time). The deploy stays in a pending_dns-style state until DNS verification succeeds, then the certificate is issued and traffic starts flowing.

A single access entry can have multiple hostnames — list them as { custom: [api.example.com, api.example.net] } — and they’ll route to the same workload port under a single SAN certificate.

For https access, you choose how the certificate is obtained.

tls: { managedBy: edgible } # default — platform manages cert lifecycle
tls: { managedBy: passthrough } # workload handles TLS itself

With managedBy: edgible, the platform orders the certificate, validates the domain, installs it on the device’s Caddy, and rotates it before expiry. You don’t see the cert; the platform handles its lifecycle. This is the default.

With managedBy: passthrough, the platform forwards TLS bytes directly to the workload — your workload terminates TLS itself. Use this when you have a specific reason to control the certificate (for example, mTLS terminated by your application).

Every access entry can specify an authentication mode that runs before the request reaches your workload:

policies:
auth: { mode: none }

Four modes are supported:

  • none — anyone with the URL can reach the service. Use for genuinely public endpoints.
  • edgible-login — the requester must present a valid Edgible session for a member of your organization. Use for internal tools.
  • api-key — the requester must present a bearer token issued by edgible application api-keys create. Use for programmatic access.
  • short-code — the requester must present a short-code token (rotating, time-bounded, optionally usage-capped). Use for short-lived shareable access.

The check happens at Caddy on the device, before the request reaches your workload. A missing or invalid credential returns 401 without your code seeing the request at all. See Authentication modes for the details of each.

Beyond auth, an access entry’s policies block can include ipRules (CIDR allow/deny), rateLimit, and waf — see the YAML reference for the full set. Enforcement of WAF and rate-limiting is delivered by the platform edge and may evolve over time.

Multiple access entries on one application

Section titled “Multiple access entries on one application”

An application can have several access entries — for example, a public read API and an internal admin UI on the same workload, with different policies:

spec:
workloads:
- name: app
type: compose
composeFile: ./compose.yml
ports:
- { name: public, containerPort: 8080, protocol: tcp }
- { name: admin, containerPort: 9090, protocol: tcp }
access:
- name: api
type: https
target: { workload: app, port: public }
hostname: { custom: api.example.com }
tls: { managedBy: edgible }
policies: { auth: { mode: api-key } }
- name: admin
type: https
target: { workload: app, port: admin }
hostname: { custom: admin.example.com }
tls: { managedBy: edgible }
policies: { auth: { mode: edgible-login } }

Each access entry gets its own hostname, certificate, and policy.