English · العربية · Español · Français · 日本語 · 한국어 · Tiếng Việt · 中文 (简体) · 中文(繁體) · Deutsch · Русский
A small, auditable, default-deny edge that lets a public server safely use private compute.
LazyEdge solves asymmetric reachability: your workstation can reach a cloud server, but the cloud server cannot dial back through home NAT. The worker opens an outbound OpenSSH reverse tunnel; the edge exposes only reviewed HTTPS host + method + path contracts through Caddy and two credential-separating guards. LocalLLM, Whisper, SoVITS, or another explicit HTTP service stays on local loopback.
Privacy promise: LazyEdge does not send telemetry, discover services, or expose an undeclared target. Only routes explicitly declared in the manifest can be generated. Request content travels only through the gateway and worker endpoints you configure, and LazyEdge does not persist request bodies. Your configured proxy, journal, upstream, or cloud provider can have its own logging policy; read the threat model.
| Donate | PayPal | Stripe |
|---|---|---|
flowchart LR
C[Authorized client] -->|HTTPS + client token| P[Caddy on public edge]
P --> E[edge guard]
E -->|separate relay token| R[127.0.0.1 reverse listener]
R ==>|worker-initiated SSH -R| W[worker guard]
W -->|separate upstream token| L[private service on 127.0.0.1]
- Outbound first: the private worker initiates the connection; no home router port-forward is required.
- Loopback throughout: raw model, tunnel, worker, CDP, VNC, and noVNC ports are never public targets.
- Exact policy: domain, method, and path are allowlisted; undeclared traffic is denied at edge and worker.
- Credential separation: client, relay, upstream, and SSH credentials are different and stay outside the manifest.
- Replaceable transport: OpenSSH first; the application contract remains decoupled from future WireGuard, rathole, or frp transport.
- Private service listeners: an application-neutral authenticated loopback seam lets edge-local callers reach explicitly selected services without DNS, Caddy, TLS, or NAT exposure.
- Bounded node admission: an opt-in LocalLLM profile authenticates two exact readiness/capability documents and rejects stale or release-mismatched canary evidence without turning LazyEdge into a fleet registry.
- Read-only rollout safety: a separate generic contract, journal, and one-shot stop authority can be embedded by an application-owned controller without giving the LazyEdge CLI deployment powers.
- Migratable edge: render the same reviewed project on a second cloud, connect it in parallel, test, then move DNS.
LazyEdge occupies the same problem space as an ngrok-style reverse tunnel, but it is intentionally narrower: the v0.4 preview exposes reviewed HTTP API routes, not arbitrary TCP ports or ad-hoc public URLs. See concepts at scale for the technology map.
Node.js 20+ is required. Start locally; do not apply generated production files until you have read the plan and security guide.
npx @lazyingart/lazyedge --help
mkdir my-edge
cd my-edge
npx @lazyingart/lazyedge init --output lazyedge.yaml
npx @lazyingart/lazyedge validate --config ./lazyedge.yaml
npx @lazyingart/lazyedge plan --config ./lazyedge.yamlThen render each artifact for review:
npx @lazyingart/lazyedge render caddy --config ./lazyedge.yaml
npx @lazyingart/lazyedge render openssh --config ./lazyedge.yaml \
--identity-file "$HOME/.config/lazyedge/ssh/id_ed25519" \
--known-hosts-file "$HOME/.config/lazyedge/ssh/known_hosts"
npx @lazyingart/lazyedge render accounts --config ./lazyedge.yaml \
--public-key-file "$HOME/.config/lazyedge/ssh/id_ed25519.pub"
npx @lazyingart/lazyedge render systemd --config ./lazyedge.yamlThe Caddy command above uses Automatic HTTPS. Add --manual-certificates only for an existing Certbot /etc/letsencrypt/live/<host>/ layout. The account renderer requires a dedicated Ed25519 public key; the OpenSSH paths refer to private worker files and do not copy their contents. The systemd command emits a labeled review bundle, or accepts --component edge|worker|tunnel|caddy|redirect|certbot for one section.
Keep runtime bindings split by trust boundary: copy the edge example only to the public gateway and the worker example only to private compute. The edge process reads the relay secret and external-client token store; the worker process reads the relay secret and private-upstream key. Neither role needs the other role's credential store.
After startup, run doctor --role edge on the cloud and doctor --role worker on private compute; use all only when both roles are genuinely co-located. Root-only render redirect-helper and render nat --direction apply|rollback commands print review artifacts with manifest-digest ownership tags—they never execute a firewall change. See operations.
The v1alpha1 interface is preview. Version 0.4 does not ship remote apply, rollback, or uninstall: renderers write reviewable artifacts, and an administrator installs them deliberately. See the complete quickstart.
An application-owned deployment controller can use the packaged EdgeRollout
contract, durable journal, and one-shot stop authority without moving its probes,
drain policy, service discovery, artifact installation, or rollback logic into
LazyEdge. The CLI surface is deliberately observational:
lazyedge rollout validate --rollout ./edge-rollout.yaml
lazyedge rollout plan --rollout ./edge-rollout.yaml --json
lazyedge rollout inspect --state /absolute/private/path/phase.json --jsonRollout input must be a non-empty regular UTF-8 YAML or JSON file no larger than
1 MiB. Symlinks, duplicate keys, YAML merges, aliases, custom tags, parser warnings,
unknown fields, and oversized input are rejected. validate and plan normalize
the declared artifact claims and compute a deterministic digest; they do not read
or verify the artifact paths and grant no write or stop authority. inspect reads
an existing owner-private journal without acquiring a lease.
There is no rollout executor, live-artifact verifier, or rollout systemd renderer.
A controller consuming a one-shot stop authorization must immediately couple the
exact PID and Linux process start ticks to the claimed systemd InvocationID
before performing the stop. See rollout safety and ownership.
| Path | Contents |
|---|---|
bin/ and src/ |
CLI, manifest validation, guards, token lifecycle, and renderers |
schemas/ |
machine-readable EdgeProject and read-only EdgeRollout contracts |
templates/ |
generated Caddy, OpenSSH, and systemd building blocks |
examples/ |
secret-free LocalLLM and generic HTTP examples, including separate edge and worker bindings |
docs/ |
architecture, security, operations, migration, and teaching guides |
i18n/ |
translated repository introductions |
references/private/ |
ignored, npm-excluded, secret-free machine notes—not a credential store |
- Architecture and request flow
- Configuration reference
- Security and threat model
- Operations and rollback
- Upgrade v0.2 to transport-only v0.3
- v0.4.0 release notes
- v0.3.1 release notes
- v0.3.0 release notes
- Alibaba → Huawei or dual-edge migration
- OpenAI-compatible client integration
- Application-neutral private service listeners
- Rollout safety and controller ownership
- Troubleshooting
- How larger multi-server systems relate
npm ci
npm test
npm run check
npm run pack:dry-run
git diff --checkInspect the npm dry-run file list. A release must not contain references/private/, .env, credentials, keys, tokens, logs, runtime state, browser profiles, or caches. Security-sensitive contributions should include a negative test; read CONTRIBUTING.md and SECURITY.md.
If you use LazyEdge in research, cite the repository. GitHub reads CITATION.cff and shows a Cite this repository panel on the repository page.
@software{chen_lazyedge_2026,
author = {Chen, Lachlan},
title = {LazyEdge: A default-deny edge for private compute},
year = {2026},
url = {https://github.com/lachlanchen/LazyEdge}
}v0.4 preview. The public interface may change. This repository describes the intended safe baseline; it does not claim that any particular domain, cloud server, tunnel, npm version, or LocalLLM deployment is live until that environment is independently verified. Do not use LazyEdge as the only control protecting sensitive or safety-critical systems.
MIT © Lachlan Chen
