Skip to content

Keep .env values out of the browser safe and securely

One Go binary serves your static site and injects .env secrets server-side — invisible to DevTools and the Network tab.

  • Single binary ~2–12 MB — no Node, no node_modules
  • Secrets never reach the browser — {VAR} replaced server-side
  • Local & public gateways, hot-reload, dashboard & PHP support
  • Cross-platform • MIT • No telemetry
Get Started

View raw prompt View on GitHub Works with Cursor, Kilo Code, Copilot, Claude

Why envGo

fetch() calls written in front-end JavaScript ship your API key to every visitor. A conventional backend fixes that but brings a runtime, a dependency tree, and a deployment to maintain.

envGo is the narrow alternative: a single static binary that serves your HTML and holds the key. No Node.js, no node_modules, no runtime to install — roughly 2–8 MB depending on platform. See how it compares → Comparison.

Core features

Single binary

Static file server, proxy, and gateway in one executable. Zero third-party Go dependencies — the standard library only.

Secrets never reach the browser

{NAME} placeholders are substituted inside the Go process. DevTools, the Network tab, and browser memory only ever see placeholders and boolean flags.

Fixed-route gateway

Public mode serves /api/<name> from a JSON config, with per-route variable allow-sets, rate limiting, and optional bearer auth.

Hot reload

Edit .env while running — changes are picked up within about 1.5 seconds, no restart.

Cross-platform

macOS, Linux, and Windows on amd64 and arm64, all from one codebase.

Built-in diagnostics

A metadata-only dashboard, typo detection for env keys, and warnings when PHP code would expose a secret.

Quick start

1. Install

⬇ envgo-windows-amd64.exe · ARM64 build

Terminal window
mkdir C:\envgo
copy $env:USERPROFILE\Downloads\envgo-windows-amd64.exe C:\envgo\envgo.exe
[Environment]::SetEnvironmentVariable(
"Path",
[Environment]::GetEnvironmentVariable("Path", "User") + ";C:\envgo",
"User"
)
# Open a NEW terminal, then:
envgo -v

Need a different build, or a checksum to verify one? Download.

2. Create a project and run it

The next two commands are identical on every platform:

Terminal window
mkdir myapp && cd myapp
envgo init # writes .env, .env.example, index.html, .gitignore, README.md
# put a real key in .env, then:
envgo run dev # opens http://127.0.0.1:8080/

Your page uses the key without ever seeing it:

<div id="MY_SECRET"></div>
<script src="/__env.js"></script>
// The browser sends the literal text {OPENAI_API_KEY};
// the Go process substitutes the real value before forwarding.
await fetch("/proxy", {
method: "POST",
headers: { "Content-Type": "application/json", "X-EnvGo-Token": token },
body: JSON.stringify({
target_url: "https://api.openai.com/v1/chat/completions",
headers: { Authorization: "Bearer {OPENAI_API_KEY}" },
}),
});

The page above pairs with this .env — the <div id="…"> elements and every {…} placeholder must match a key in the file:

.env
MY_SECRET=some-real-value
OPENAI_API_KEY=sk-your-real-key-here
HOST=127.0.0.1
PORT=8080
MODE_PUBLIC=false
# CONFIG=envgo.routes.json

HOST/PORT/MODE_PUBLIC/CONFIG are not secrets — they control where and how envGo runs:

  • HOST/PORT choose where envgo run dev listens (PORT=3000http://127.0.0.1:3000/). Only for envgo run.
  • MODE_PUBLIC=true (or MODE=public, ENVGO_MODE, CONFIG=envgo.routes.json) switches to public mode without flagsenvgo run dev alone serves /api/<name> with envgo.routes.json. false/local keeps local /proxy mode. Flag --config always wins. See CLI Commands.

Choose a mode

Local modePublic mode
Enable with(default) or MODE_PUBLIC=false in .env--config envgo.routes.json or MODE_PUBLIC=true / CONFIG=envgo.routes.json in .env
Browser calls/proxy with a session token/api/<name>, no token
Target URL comes fromThe browser, restricted by --allowThe config file
Rate limitingNonePer-route, per-IP
Use forDevelopment and private toolsAnything publicly reachable

Documentation map

Free, and open source

envGo is MIT licensed. Free for personal and commercial use, with no paid tier, no licence key, no usage limit, and no telemetry — the binary makes no outbound connections of its own, only the upstream calls you ask it to proxy.

Feedback is genuinely welcome, and a confusing error message is as useful to hear about as a bug. See License & feedback for where to report an issue, ask a question, or propose a change.

Known limitations

envGo is deliberately small, and it is worth knowing what that costs:

  • Streaming responses are not redacted. SSE passthrough skips scrubbing, so an upstream that echoes a key inside a stream will leak it to the browser.
  • default_rate_limit is empty by default, which means unlimited. Rate limiting must be opted into explicitly.
  • If PHP is unavailable or fails, the .php source is served as a file rather than producing an error.
  • Rate limiting is per process. Multiple instances each enforce their own limit, and behind a proxy without trust_proxy: true all clients share one bucket.
  • The session token is not user authentication. It is per process, has no expiry, and any page on your own origin can fetch it.

The full list is in the Threat Model.