Expose OpenLakeForge publicly: client certificate or external gateway, with a Cloudflare Tunnel adapter in the profile
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- docker, python
- Domain
- cloud, infrastructure, security
Research direction
Start with roadmap issue #183, ADR 0013, and the role-enforcing perimeter in #176; then inspect the access configuration, ingress, CLI status output, and docs/testing/ entry points. Decide in the ADR whether the external gateway is needed for beta, then implement and document the client TLS and DNS responsibilities plus the test tunnel setup. Done means the listed HTTPS acceptance checks pass, including the #182 walkthrough through the tunnel.
Written by the indexing model from the issue text.
Description
Milestone: v0.6-alpha — Workloads, Sizing and Scale (moved from v0.8-beta)
Roadmap: #183 · Contract: #390 (spec.expose) · Decision update: 2026-10-23 (maintainer). Supersedes the 2026-10-16 decision that kept Cloudflare as test tooling only.
Decision
A small team must be able to expose a locally hosted OpenLakeForge on its own domain without a public IP, an open port, a reverse proxy or ACME. OpenLakeForge therefore supports two public exposure paths, both behind the role-enforcing perimeter (#176):
- Client-provided certificate. The client points their DNS at the ingress and supplies a TLS Secret for
*.<base_domain>. Unchanged from the earlier decision. - External gateway. TLS terminates outside the cluster (
spec.expose.gateway, #390). Cloudflare Tunnel is the first bundled adapter, optional and configured from the Deployment Profile. Free, no inbound port, public TLS at Cloudflare's edge.
Still true from the earlier decision:
- OpenLakeForge does not issue public certificates, run ACME, register domains, or create, change or check DNS records.
- OpenLakeForge never calls the Cloudflare API and holds no Cloudflare API key. The user creates the tunnel and its public hostnames once in the Cloudflare dashboard; OpenLakeForge only runs
cloudflaredwith the tunnel token. - Flat hostnames,
<service>-<stage>.<base_domain>and<service>.<base_domain>under one*.<base_domain>level (ADR 0013 decision 2). This is what Cloudflare's free Universal SSL certificate covers.
Profile shape
The fields belong to the spec.expose contract defined in #390; this issue implements its client-certificate path and its cloudflare_tunnel gateway adapter. Illustrative; final names are decided in #390 and ADR 0013:
spec:
expose:
visibility: public
domain: openlakeforge.dev
gateway:
provider: cloudflare_tunnel
token_secret_ref:
name: cloudflare-tunnel # created by the user; never a value in the profile
tls:
mode: external # TLS terminates at Cloudflare's edge
dns:
mode: existing # the user declares the tunnel hostnames
The client-certificate path is tls.mode: provided-secret with a TLS Secret reference for *.<domain>, behind the bundled Traefik ingress. The two paths are mutually exclusive. The token is a credential and lives only in a Kubernetes Secret, like the identity Secrets (ADR 0011: the profile holds no credentials).
The Cloudflare Tunnel adapter
User, once, in the Cloudflare dashboard (documented step by step):
- The domain uses Cloudflare nameservers (required for tunnel public hostnames on the free plan).
- Create a tunnel and copy its token into the Secret named in the profile.
- Add two public hostnames to the tunnel,
<base_domain>and*.<base_domain>, both pointing to the Traefik service in the cluster.
OpenLakeForge:
- Deploys
cloudflaredinolf-systemwith the token from the Secret, with resource requests and limits. - Sends everything to Traefik. Traefik serves only
user-facingroutes (ADR 0013 decision 4), all behind the perimeter except the identity route; internal services are never routed. Cloudflare's wildcard therefore exposes nothing Traefik doesn't already gate. olf access hosts(or the existing status output) lists the hostnames and the two tunnel public hostnames to declare, without checking them.
Origin TLS (cloudflared → Traefik). Traefik keeps terminating TLS with the local CA certificate for *.<base_domain>, and cloudflared trusts that CA for the origin leg. Pods keep reaching public URLs directly through the CoreDNS rewrite to Traefik (ADR 0013 decision 8), so token validation does not hairpin through the internet. If the tunnel token mode cannot carry the origin CA setting, record the chosen alternative in the ADR.
Identity. The GitHub App callback and Dex issuer use the public domain; olf github connect must produce them for a public base_domain.
Generic external gateway
cloudflare_tunnel is one value of spec.expose.gateway.provider (#390). The ADR defines what any external gateway relies on: which forwarded headers Traefik trusts and from where, that the perimeter cookie is Secure because the browser sees HTTPS, and the trust boundary between the gateway and the cluster. A client's own TLS-terminating proxy can use the same contract later; only the Cloudflare adapter ships in v0.6.
Fail-closed rules
- Public exposure (either path) is refused unless the #176 perimeter is enabled.
issuer: noneis refused for a public domain (ADR 0013 decision 9).local-caalone is refused for a public domain:spec.exposemust name a gateway or a provided TLS Secret.- A missing tunnel token Secret fails before mutation with an actionable message.
Scope
- Implement the
spec.exposeshapes from #390 fortls.mode: provided-secretandgateway.provider: cloudflare_tunnel(token Secret reference); the fail-closed rules above. - Client-provided TLS Secret path: the Secret serves
*.<base_domain>and the apex at the ingress, replicated or referenced per namespace as the ingress needs. - Cloudflare adapter:
cloudflareddeployment from the token Secret, sent to Traefik, origin trust of the local CA. -
olf access hostslists hostnames and the tunnel public hostnames to declare. - Rewrite ADR 0013: remove "test only" for Cloudflare, add the external gateway contract and both paths; History footer.
- Docs: a guide "Expose OpenLakeForge on your domain with Cloudflare Tunnel" (dashboard steps, Secret, profile, verification), and a page on what the client owns in each path.
Documented constraints (Cloudflare path)
- Cloudflare terminates public TLS and sees all traffic in clear, including tokens and query results. State this plainly so a team can decide.
- The domain must use Cloudflare nameservers.
- One wildcard level only on the free certificate (matches flat hostnames).
- Proxy limits: an origin response that takes longer than about 100 s fails with 524, and request bodies are capped at 100 MB on the free plan. Check Superset's long-running queries and uploads; Trino's polling client protocol should not be affected.
.devand other HSTS-preloaded TLDs require HTTPS everywhere; the tunnel provides it.
Acceptance
- On the maintainer's machine, the local stack is reachable at
https://openlakeforge.devand every enabledhttps://<route>.openlakeforge.devroute through the tunnel, with a valid public certificate, through the perimeter. - Sign-in through GitHub and Dex works end to end on the public domain, and roles are enforced (#182 walkthrough passes once on the public domain).
- Internal services (databases, object-store admin, catalog, registry) are unreachable through the tunnel.
- With a client-provided certificate for
*.<base_domain>, every enabled route answers over valid HTTPS through the perimeter. - Each fail-closed rule has a validator test; a profile without
spec.exposebehaves exactly as today. - Local
olf.localhost+local-cabehaviour and its e2e stay green. - Nothing in
tools/olfcalls the Cloudflare API.
Out of scope
ACME / Let's Encrypt issuance, DNS record management or validation, calls to the Cloudflare API, Cloudflare Access / Zero Trust policies, domain registration, external gateway adapters other than Cloudflare Tunnel, and cloud provider ingress (v0.9).
🤖 Generated with Claude Code
- Dominant language
- Python
- Stars
- 26
- Forks
- 6
- Avg merge
- 11h 46m
- Merged PRs (30d)
- 176
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from OpenLakeForge/openlakeforge
-
bug good first issue help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
OpenLakeForge/openlakeforge#498 ·
Maintainers usually reply within 1 day
-
feat(cli): export `olf query` output directly to a filePossibly taken @dbdefault claimed this 7 days ago. Openenhancement good first issue help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
OpenLakeForge/openlakeforge#494 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
good first issue help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
OpenLakeForge/openlakeforge#488 ·
Maintainers usually reply within 1 day
-
good first issue help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
OpenLakeForge/openlakeforge#487 ·
Maintainers usually reply within 1 day
-
good first issue help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
OpenLakeForge/openlakeforge#484 ·
Maintainers usually reply within 1 day
All issues in OpenLakeForge/openlakeforge
Similar issues
-
Context/namespace resources fail in-cluster: "Invalid kube-config file. No configuration found."Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
bug documentation
Difficulty 1/5 Under an hour Newbie friendliness 88/100
awslabs/visual-asset-management-system#880 ·
Maintainers usually reply within 1 day
-
netbox status: needs owner type: documentation
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
netbox-community/netbox#23533 ·
Maintainers usually reply within 1 day
-
app: scripts status: backlog type: documentation
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
netbox-community/netbox-scripts#68 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 91/100
marin-community/marin#10765 ·
Maintainers usually reply within 1 day