Use cases

One shape of problem

Something in the cloud needs to reach something inside a network that will not accept an inbound connection — and a VPN, a port forward or a tunnel is unavailable, disallowed, or larger than the job.

It comes up more than "private network" suggests

The network is usually a stockroom, a plant floor, a branch shop or a customer's server cupboard. The reason there is no inbound path is rarely technical:

  • A consumer router nobody administers.
  • Carrier-grade NAT, with no address to forward.
  • An insurer's questionnaire, or a Cyber Essentials assessment.
  • A customer who will not put a supplier on their VLAN.

Three motions cover almost everything

  • Call in. Cloud code submits a task, an agent inside performs it, the result comes back. The agent is already parked on a long poll, so the cost is a round trip rather than a connection setup.
  • Be called. A forward gives an internal HTTP app a public URL. Nothing is published — the agent still makes the outbound connection.
  • On a schedule. Cron in a named timezone fires a task at each site, and one screen shows that fourteen sites ran last night and one did not.

Underneath all three: the agent's agent.config.json is the ceiling. A task payload can narrow what an agent will do and can never widen it. That file lives on the machine, written by whoever owns it, and the server cannot edit it — which is what most of these cases are actually buying.

What getting one in actually looks like

Three screens, in order. No port is opened at any step, and the two gates below are independent — one is held by whoever owns the machine, the other by whoever owns the account.

The Install the agent dialog, showing a one-time enrollment token and ready-made PowerShell, Linux and manual install commands.
1 You get a one-time enrollment token and a command to paste on the machine. The token is shown once and is worth treating as a password — it is what lets a machine join at all.
PowerShell output after installation: checksum verified, the agent installed as a Windows service, and a deny-by-default policy written to agent.config.json.
2 The installer registers a service and writes a deny-by-default agent.config.json. Out of the box it will do nothing — someone with access to that machine has to widen the policy and restart the service to grant anything. --print-policy shows exactly what it currently permits.
The OpenHook Agents page showing one machine listed under Waiting for authorisation, with Approve and Reject buttons.
3 Back in the cloud the machine appears under Waiting for authorisation and is refused every task until an admin approves it. So a leaked token alone still gets an attacker nothing. The originating address is masked in this screenshot.

Is this the right tool?

Worth settling early, because it decides whether the rest is worth reading.

Use a mesh VPN instead when…

  • The counterparty is a person who will install a client.
  • The traffic is interactive, large, or not HTTP.
  • Latency matters more than policy.
  • Someone needs a shell.

One engineer looking at one appliance for an afternoon is a Tailscale job. A static IP and someone competent with the firewall is a reverse proxy job.

OpenHook fits when…

  • There is nobody to install a client on. Stripe, Shopify, a marketplace webhook sender — SaaS counterparties who will never join your network.
  • The grant must be smaller than a host. A tunnel's unit of access is an address and a port; url_rules express "GET on this one path and nothing else".
  • The ceiling must be inspectable by whoever takes the risk. The customer's own administrator writes the policy file.
  • The credential must not leave the machine. Variables resolve on the agent; the server only ever stores a variable, like $ApiKey.
  • The far end is intermittent. Work submitted to a shop whose router is off queues until the machine next polls.

What people build

Grouped by who is building it. Each case names the constraint that decides whether it works.

AI assistants and retrieval

The MCP server is read-only by default, and agent restart and uninstall are unreachable through it at any setting.

Incident triage from an assistant

The assistant is pinned to named hosts, so the rest of the fleet is invisible. Every call becomes an ordinary task, so the agent's policy applies unchanged and the record lives in a server-side audit log rather than a client transcript.

For the human who needs a shell, a mesh VPN is the better answer. This is about putting a model on the problem.

Retrieval with the end user's own permissions

The standard RAG failure is a retrieval layer authenticating as one service account, so the assistant surfaces an HR document to anyone who phrases the question well. Passing the end user's own token lets the internal search API trim results itself.

Indexing without documents leaving the building

A scheduled script extracts text locally and returns paths, timestamps and extracted text — never the source bytes.

If you run the indexer yourself as containers, a mesh VPN node beside it is simpler. This wins when the indexer is managed or serverless.

A serverless app calling a self-hosted model

No sidecar can live next to a Lambda, so a call straight through to your GPU box works.

There is no streaming: token-by-token delivery is out, the generation must finish inside the task timeout, and the completion must fit the result ceiling.

Serving a web application from inside the network

The newest direction, and the one with the most prerequisites — read the limits below before committing to it.

A legacy app for remote and contract staff

An application that cannot be modernised, served at a hostname you own. A rule refusing the admin section applies on the machine, no matter what the server asks for.

A client review site or feature-branch preview

A build machine or workstation, hosts limited to localhost, one forward per project.

A tunnelling tool is simpler for a solo developer. This wins when preview URLs should be operator-created, pointed at approved machines, and revocable from one place.

Read-only admin for an external auditor

Session cookies relayed under names only that forward can produce, so a page on a neighbouring forward cannot plant a session for this one. Basic auth at the edge combines with it.

A public site from behind CGNAT

Reducing the method allowlist to GET and HEAD makes the public face read-only whatever the application would otherwise permit. Relaying no cookies means nobody can log in from outside at all.

If the only audience were the owner's own devices, WireGuard would be better outright.

Small and mid-size business with on-premise software

Sage 200, SAP Business One, Dynamics NAV, an EPOS back office, a dental or veterinary practice system — on a dynamic IP behind a consumer router, with no IT department. The other half of every integration is SaaS and cannot be put on the network.

Live stock and price in a storefront

The ERP has a LAN-only HTTP API; the storefront shows an overnight CSV and oversells between syncs. An agent on the ERP server, url_rules permitting GET on the item and price paths, and the service account password held locally.

Call live at add-to-cart and checkout, cache for listing pages — each in-flight call holds one server request open for its whole life.

Head office pushing prices to every shop

Instead of remote-desktopping into five back-office PCs after closing: write the price file into the till vendor's watched import folder, then run the vendor's import utility. A shop that was closed picks the work up when it opens.

"Which shops have this" becomes a screen rather than five phone calls.

Nightly extract from a school's MIS

A schedule runs the export locally on each school's server, with the SQL password referenced by name rather than sent. Replaces a per-school Windows scheduled task that fails silently when the export account's password expires.

Large extracts must be split or uploaded directly from the agent — reads are bounded and have no offset.

Despatch labels printed in the warehouse

The cloud OMS probes the printer's port as a pre-flight, so an unplugged printer fails with a message instead of a silent no-print, then writes into the label software's hot folder.

OpenHook is HTTP only — printing goes via a local utility, a watched folder, or the printer's own HTTP interface, never raw port 9100.

Software vendors, resellers and integrators

Here the driver is commercial rather than technical: onboarding stalls for weeks per customer on a single firewall change request, and the implementation calendar is the bottleneck on revenue.

One agent per customer, addressed by tag

Enrollment tokens stamp a tag at enrol time, so routing is configured before anyone touches the console. Writes carry an idempotency key, so a retried submission returns the original task rather than double-posting a sales order.

Never holding the customer's credential

The password lives on the customer's machine, written by their administrator; your cloud submits payloads that only reference it. Results and streamed output are scanned on the way back, so a task told to print the secret returns the placeholder.

This answers a security questionnaire rather than a technical objection — "encrypted at rest" stops being the claim being made.

Diagnosing a site without remote desktop

A read-only policy — system info, port checks, agent logs, health endpoints, the log directory — answers most tickets. A port check to SQL Server from that host distinguishes "the database is down" from "this machine cannot reach it".

Replaces the diagnostic call, not the interactive one. For watching a user reproduce a fault, remote desktop is still right.

Proving a site is ready before go-live

The customer runs one install command. The machine lands pending and is refused every task until approved, so the consultant checks hostname, platform, version and connecting address first, then probes the ERP and SQL hosts.

A VPN proves a tunnel is up; it does not prove this machine can reach that service through that TLS-inspecting proxy.

Industrial, OT and multi-site estates

Plant IT will not route from the corporate WAN into the cell VLAN, and three hundred inbound VPN tunnels is three hundred concentrator configurations for a flow that goes one way and carries a few kilobytes.

Cloud MES reading PLC tags

An agent on the existing historian box inside the cell VLAN, with hosts limited to that subnet and url_rules permitting GET on the read endpoint only — so every other path on the same PLC web server is refused.

Neither a site-to-site VPN nor a subnet router can express that restriction. If the MES needs OPC UA or a persistent subscription, none of this applies.

Meter and BMS polling across 300 sites

A quarter-hourly schedule in a named timezone polls each site's endpoint and delivers readings to your analytics ingest, signed. The cloud never polls anything.

Missed occurrences are never replayed and a run is skipped while the previous one is still going, so a site on slow 4G cannot accumulate a backlog.

Printing at a named store behind CGNAT

Behind carrier-grade NAT there is no port to forward — the option does not exist rather than being unwise. Printers that accept their job format over HTTP work directly, with method and path pinned to one endpoint.

The same rule refuses the printer's configuration pages on the same web server.

Time-boxed OEM access to a machine HMI

A forward with the OEM's office IP range allow-listed, methods limited, a credential of their own, and a toggle that ends it. No account in your directory, no firewall change, every request recorded.

A mesh VPN genuinely competes here, and is better if the OEM needs more than the HMI.

IT operations, MSPs and on-call

Customers pursuing Cyber Essentials, or answering an insurer's questionnaire, increasingly refuse standing remote access altogether.

Overnight sweeps with no site-to-site VPN

A collector enumerates the tagged agents and creates one schedule per agent. Each script emits a single JSON summary rather than raw command output.

There is no fan-out primitive, and if you already run a full RMM this duplicates its inventory function.

Pulling logs off a headless machine

Read roots set to exactly the log directory. For the last few thousand lines of a large log, run a script with a tail and filter on the machine.

File reads start at the beginning of the file and have no offset or tail option — this changes the workflow, not just the size.

Allow-listed remediation instead of a shell

The customer's own administrator names specific executables — in practice small wrapper scripts, not general interpreters. Output streams back incrementally, so a 90-second job is observable, and cancelling kills the process tree.

An RMM reaches the same machine, but its model is "run arbitrary code as SYSTEM" with a boundary the customer cannot inspect.

Knowing what each machine permits

The agents API returns what a machine's policy currently permits, so "on which endpoints can the console execute anything" is a query rather than one engineer's memory.

Not a reason to deploy anything on its own — a by-product of having agents installed for the cases above.

What it is not for

Longer than a marketing page would normally make it, because every one of these gets asked for — and most would not be discovered until after the build starts.

  • Anything that is not HTTP. No raw sockets: SQL over 1433, RDP, SMB, Modbus TCP, BACnet/IP, OPC UA, RTSP and raw JetDirect are all out of scope. A port check reports that a port accepts a connection and nothing more — it is a probe, not a channel.
  • Anything interactive. No shell, no remote desktop, no free-form troubleshooting. Every step is a long-poll round trip, so it is a question-and-answer loop and never a session.
  • WebSockets, SSE, or any streamed response. The relay is strictly complete-request to complete-response. That rules out live dashboards, hot reload in a dev server, chat and notification channels, and streamed model output.
  • Large files in one shot. A single response is capped well under a megabyte by default, and an overrun is refused rather than truncated — so a PDF invoice or an SPA bundle fetched plainly still fails. A client that speaks Range is a different matter: the range is carried inward and narrowed to what the relay can hold, so a download manager or curl -C - walks a multi-gigabyte file in pieces. What stays out is anything that must arrive whole in one request.
  • Bulk data movement or replication. Paging a catalogue turns a 200k-row sync into thousands of sequential round trips, each a stored task row. Have the script upload directly to object storage and let OpenHook carry the schedule and the exit code.
  • High-frequency telemetry. Every poll is a durable row with a payload and a result. One-second reads across 300 sites is roughly 26 million rows a day.
  • A multi-tenant isolation boundary. There is still no tenant object, though a key can now carry a reach — a set of tags or named machines outside which it can neither send work, read a result, nor discover anything exists. Reading anything out of reach answers 404 rather than 403, so the estate cannot be mapped by trying names, and work aimed at a machine outside the reach is refused. What a reach does not give you: one shared database, process, queue, retention setting and backup underneath; no per-customer noisy-neighbour control, since the rate limit is per key but the queue is not; and no customer-facing login — anyone signed in to the console, and every forward and schedule configured there, addresses the whole fleet. Authorisation also happens at submission rather than delivery, so retagging a machine does not redirect work already queued for it by name. A reach makes one instance defensible for a vendor serving many customers. Where the customer is the one who must be assured, or their data must not sit beside anyone else's, still run an instance each.
  • A user directory at the edge. A forward carries one shared secret, not an identity layer: no SSO, no per-user revocation, and no answer to "which of the partner's staff ran that report".
  • An RMM, or any network without egress. It does not image machines, deploy software or inventory applications, and the whole design assumes outbound HTTPS works.

Two that surprise people. The secret scrub is literal text matching — a script that encodes or chunks a secret before printing it defeats it entirely, so treat it as defence in depth and nothing more. And the scheduler is not a system of record: a site that was powered off produces no task row at all, so alert on the absence of a success rather than on failed tasks.

Sharp edges that decide a design

Not bugs, not obvious, and they change what you build.

🧾

Request headers are opt-in, and empty by default

A forward always sends content type, accept and a synthesised forwarded-for. Anything else has to be named in relay_headersstripe-signature, or a wildcard like x-shopify-*. Name them and webhook signatures verify normally; forget to, and the signature never arrives, so the only way to accept the webhook is to stop checking it.

🔀

A page load is a dozen concurrent relays

Each in-flight relay holds one server request open for its whole life, and a browser opens 12–30 connections for a single page. On a small host that deadlocks rather than merely being slow — check headroom before promising anyone a web UI.

📏

The response ceiling decides feasibility

Well under a megabyte by default. A modern app's main bundle routinely exceeds it, so raise the limit before the first page render rather than after.

🚦

The rate limit is a capacity ceiling

One bucket is shared by every caller of a forward, so one aggressive client exhausts it for everyone. Size it to protect the machine behind it — it is not per-caller abuse control.

🧱

The agent policy is the only real boundary

Everything the console expresses is a narrowing of what the agent already permits. Network calls made from inside a script are not governed by the host allowlist — enabling scripts widens the ceiling to whatever that machine can reach.

💳

Task payloads are stored

Only forwards relaying a session seal the exchange. An ordinary task's payload and result sit on the server for the retention period — fine when self-hosted with short retention and recorded, indefensible by accident.

Recognise one of these?

Register and we'll provision your instance at your own subdomain.