Reach any service.
From anywhere.

Share one service — not your network. With your devices, your people, and other organizations.

Grant a service to a machine or a person, and it answers on localhost — over a post-quantum WireGuard mesh you run yourself. Link with a partner organization and share with them the same way, without merging networks. No account, no vendor cloud, no telemetry. One self-contained binary, every OS.

closed alpha · free · linux  macos  windows  ios  android  freebsd  openbsd

Three steps. One federation.

No accounts to create. No servers to provision. Run the binary, mint a code, paste it on the next device.

01  / run

Run the binary.

Drop the single sidehub executable on the device you want as the controller and run it. It opens a setup page on localhost — choose Controller, and point it at a relay: ours, a partner’s, or your own. No config file to hand-edit, no kernel module.

$ ./sidehub  # setup page on 127.0.0.1
02  / invite

Mint a bootstrap code.

In the controller’s dashboard, issue a one-time code bound to your federation. Hand it to whichever device should join — paste it, scan a QR, sneakernet it. Your call.

dashboard → new code  → bc_3f9…8a2
03  / join

Paste it to join.

Run sidehub on the new device and paste the code in its setup page. It joins the mesh — every link encrypted, direct when it can be, relayed when it can’t — and whatever you grant it appears on localhost.

$ ./sidehub + paste bc_…  # joined

Two devices that can't reach each other directly — behind a home router, a firewall, a carrier NAT — meet through a relay. The relay only forwards encrypted frames and sealed invitations; it never sees your traffic, your keys, or even which services exist. Because it can't read anything, it doesn't have to be yours: use our open relay (free, on request), a partner's, or run your own. It's never part of what you have to trust.

Four ways people use it.

One primitive — grant one service to one machine or person, deny everything else — covers problems that usually take four products. Nothing below opens a port, publishes a DNS name, or joins two networks together.

// partner exchange

Hand another organization one service.

Two organizations, two controllers, no merged network. Link once, then share a single service — and approve each of their people or machines who asks for it. They see what you share, not your network.

bob · partner-co → metrics · http → metrics.acme.sideservices.localhost
  • Scoped to one serviceCross-organization access is deny-by-default and per service. No shared address space, no site-to-site tunnel to decommission later.
  • Auditable on both endsEach side keeps its own record of the exchange: which person or machine, how many requests, how many bytes, over what period.
  • Withdrawn in one clickTake access back and their local address stops answering — no ticket to a network team, no firewall change.
// ot & industrial

Let a vendor reach one machine, not the plant.

Remote support for an HMI, a PLC or an instrument normally means a jump host, a VPN account and a route into the OT segment. Here the vendor is granted exactly one service on one device, for as long as you say.

vendor-laptop → hmi-3 · tcp → localhost:502
  • The device needs no softwarePlug it into the IoT appliance's protected port. It keeps its own address and its own firmware; the appliance is what joins the mesh.
  • The grant is the perimeterNothing else in the segment is reachable — there is no subnet to scan, because the vendor never receives a route, only a local port.
  • Time-boxed and revocableA service can carry an idle timeout and a deadline, and deleting it in the controller drops the live session on the device.
// private ai

Serve a self-hosted model to your people.

A GPU box running an inference server is the most sensitive thing to expose and the easiest to get wrong. Publish it as a service and grant it to people: it follows each of them to whichever device they sign in on, and never touches the internet.

alice · phone → llm · http → llm.acme.sideservices.localhost
  • Streaming worksToken streams and long-lived responses pass through unbuffered, so an OpenAI-compatible client behaves exactly as it would against localhost.
  • Prompts stay insideTraffic goes device-to-device over an encrypted tunnel. No inference provider, no vendor control plane, and no request contents are recorded — usage accounting stores counts, never payloads or query strings.
  • It knows who is askingThe model server is told which person is calling, and per-request accounting shows how much each one used — the basis for a chargeback, or for noticing a client that suddenly went loud.
// ci/cd

Give a build runner an internal dependency.

A hosted runner needs your private registry, a package proxy or a seeded database. The usual answers are a public endpoint behind a password, or a VPN credential sitting in CI secrets.

runner-07 → registry · http → registry.acme.sideservices.localhost
  • Nothing is publishedThe registry stays on its own machine. It is never resolvable by public DNS, never listening on a public port, never fronted by a public certificate.
  • One identity per runnerEach runner is its own peer with its own grant, so a compromised runner can be revoked on its own — and its traffic is separable in the usage log.
  • Same address everywhereThe service answers on the same local address on every runner, so the pipeline configuration does not change between environments.

A service is one thing you share.

A service is one thing you expose — a database, a web app, an SSH port, a SOCKS exit, even your mailbox. Grant it to a machine or a person and it shows up on a local address on their device. Nothing else on your network is visible: no subnet to scan, no flat address space to firewall.

TCP

Databases, SSH, Git, registries — anything on a port.

localhost:5432
UDP

DNS, syslog, game servers, custom protocols.

localhost:5353
HTTP / HTTPS the web naming

Web apps and APIs answer at a name — no IP, no port to remember. Resolved on your own machine, never by public DNS.

wiki.acme.sideservices.localhost
SOCKS5

A proxy or exit on another node — route requests through where it sits.

localhost:1080
Mail

Private IMAP + SMTP for your federation, on the node you choose — mesh-only, and delivered to partner organizations over the mesh, never the public internet.

localhost:1143 · 1587

What's inside the binary.

Cross-platform, self-hosted, deny-by-default, post-quantum. No public DNS, no public TLS, no public anything.

// one binary

Every role, every OS.

Controller, hub, relay — the same self-contained sidehub executable, the same commands, on Linux, macOS, Windows, FreeBSD and OpenBSD. Apps for Android and iOS. No separate management or signal servers to run.

linuxmacoswindowsandroidiosfreebsdopenbsd
// access

Deny-by-default, per service.

Nothing is visible until the controller grants it — one service, to one machine or one person. A grant can end on a date, after idle time, or a fixed time after first use, and revoking it drops the live session.

postgres · tcp → build-runner
wiki · http → alice, on any device
redis · tcp → denied to all
// people

People, not just machines.

Grant a service to a person and it follows them to whichever device they sign in on. SideServices can sign them in to the app as well — telling it who is calling, or filling in a stored password — so there is no second login. One password per person, and it never reaches the controller.

alice wiki · signed in as alice
alice grafana · on laptop and phone
bob metrics · from partner-co, until Friday
// addressing

Localhost is the address.

TCP and UDP services bind to a stable local port. Web services answer at a name on your own machine — service.federation.sideservices.localhost — never published in public DNS.

postgres localhost:5432
redis localhost:6379
wiki wiki.acme.sideservices.localhost
grafana grafana.acme.sideservices.localhost
// transport

WireGuard mesh, post-quantum keys.

Every link between hubs is encrypted — direct when the network allows it, through a relay when it doesn’t. Identities and key exchange are hybrid post-quantum (Ed25519 + ML-DSA, X25519 + ML-KEM): harvest-now-decrypt-later doesn’t work here.

srv-01 laptop  wg · pq-sealed
laptop phone  wg · pq-sealed
edge-gw desktop  wg · pq-sealed
// federation

Share across organizations.

Link with another organization once, then share single services — you approve each of their people or machines, and take access back in seconds. The two networks never merge: they see the services you share, not your network. Mail flows between you over the same link.

metrics acme → partner-co
registry acme → lab-team
mail acme → partner-co, both ways
// accounting

Every request, attributed.

A service records who used it, how much moved and how long it took — per HTTP request and per TCP flow. Detail stays on the node that serves it; only counts roll up. Admin changes, sign-ins and partner decisions land in an audit log you can export.

alice registry · GET /v2/… · 412 KB
192.168.50.42 hmi-3 · tcp · 18 KB · 4m12s
partner-co metrics · 1,204 requests
// trust

A tiny trusted base.

No sign-up, no vendor control plane, no telemetry — you trust your own controller and nothing else. The relay can’t read your traffic, so it can be anyone’s. Device keys never leave the device, a person’s keys are stored only under their own password, and the whole federation backs up into one encrypted file.

vendor control plane / telemetry
a relay that can read your traffic
public CA · public DNS · public ports
trust only your own controller.

Every grant, in plain sight.

The controller is a small web app on your own machine: what needs you, every service and who can reach it. Each device sees only what it was granted, by name. Click a screenshot to enlarge.

The controller's Overview: one item needing attention — an access request waiting for approval — above cards for nodes online, services, people, partner federations, the relay and SideMail, and the federation's short fingerprint.
Overview — what needs you first, then the federation at a glance.
The controller's Services page: a partner's access request with Approve and Decline, then every service with who can reach it — people such as alice on her laptop and phone, machines such as a build runner, a partner organization's person on a lease, a service shared with partner-co, and redis granted to nobody.
Services — who can reach each one: people, machines, partner organizations. Or nobody yet.
Alice's laptop at sideservices.localhost, signed in as alice: the services granted to her grouped by the node that provides them with direct or relay paths, each web service opening at service.acme.sideservices.localhost, and a service from the partner-co federation.
Alice's laptop at sideservices.localhost — her services, by name, including one from a partner.
The controller's Services page, full size. The controller's Overview, full size. A node's service list at sideservices.localhost, full size.

Or run it as an appliance.

SideServices also ships as ready-to-flash appliances — the whole mesh baked into a small, self-updating image. No server to run, no operating system to install or patch.

// self-host a federation

Federation appliance

The easiest way to self-host an entire SideServices federation. Flash a Raspberry Pi, plug it in, and the controller, relay and your services come up as a single tiny image.

  • A whole federation in a boxController, relay and services on one Raspberry Pi — no Linux to install, harden or patch.
  • Atomic over-the-air updatesThe box updates itself in one step onto a second system partition, so the previous version is always one reboot away.
  • An extra-small trusted baseNo shell, no package manager, a read-only image — a tiny attack surface.

Built on the gokrazy appliance framework.

// protect any device

IoT appliance

Put a SideServices appliance in front of an industrial machine or IoT device and expose only the specific services you choose — with no web traffic reaching the device by default.

  • SecurityPassword-authenticated over-the-air updates and a minimal trusted computing base keep the box secure and up to date.
  • Devices that can't run softwareA PLC, a camera, a lab instrument: plug it into the protected port and it reaches its granted service with nothing installed — still attributed by its own address.
  • Ease of useToken-based enrollment — as simple as plugging in a USB stick. No console, no config files.
Contact us about appliances Federation & IoT appliances are in alpha — tell us your use case.

How it compares.

Same WireGuard primitive as a mesh VPN. A different idea of who's in charge — and what's reachable.

Hosted mesh VPNs

A vendor runs the control plane you have to trust. You sign up; your coordination lives in their cloud.

SideServices

Your own controller is the only thing you trust — no account, no vendor in the loop. The relay is untrusted, so it can be ours, a partner's, or yours.

Self-hosted meshes

Every node gets a flat address, gated by network ACLs, plus a separate management or signal server to operate.

SideServices

Deny-by-default at the service level, and federation across organizations. One binary is every role — nothing extra to run.

Partner-access portals

Your partner becomes a guest in your system — a one-time code, a guest account, an identity in your tenant.

SideServices

Two organizations, each with its own network, identity and controller, link once and share single services. Neither becomes the other's tenant.

Public meshes & ad-hoc relays

A global network anyone can join, or a shared relay for one-off shells — you firewall on top.

SideServices

Each federation is private and controller-signed, on infrastructure you own, with structured, revocable access per service.

Across all of them: end-to-end post-quantum identity and key exchange, and services that answer on localhost — no public DNS, no public CA.

Questions, answered.

Short version: one binary, a post-quantum WireGuard mesh, deny-by-default service access, and a localhost addressing trick. Everything stays on devices you own.

Request alpha access →
What's a federation?

The devices (hubs) you’ve enrolled together, plus the people who use them. One hub is the controller — it signs enrollment and holds the federation’s identity. Hubs connect directly over encrypted WireGuard links, with a relay fallback behind NAT. There’s no central data plane and no shared address space — just the services you grant.

How is this different from a mesh VPN?

A mesh VPN drops every device onto one flat network and gates it with ACLs. SideServices is deny-by-default at the service level: a service is invisible until the controller grants it to a specific machine or person. The WireGuard transport is the same proven primitive — the access model isn’t.

Can I grant access to a person rather than a device?

Yes. A person signs in on any of their devices with one password, and the services granted to them appear there — and go when they sign out. SideServices can also sign them in to the app itself, so a granted wiki opens already logged in as them.

Can I share a service with another organization?

Yes — that is what federation links are for. Link with the other organization once (both admins confirm each other’s fingerprint), then share single services. You approve each of their people or machines, and can take access back at any time. The networks never merge, and mail between the two federations works over the same link.

Is it quantum-safe?

Yes. Identities are hybrid Ed25519 + ML-DSA-65 signatures; enrollment and key exchange are hybrid X25519 + ML-KEM-768, and every tunnel’s key is protected by them. A future quantum computer that records today’s traffic still can’t read it or forge an identity.

Why no public TLS and no public DNS?

Because both already happen, privately, elsewhere in the stack. Traffic between hubs is encrypted by WireGuard; the few control channels use fingerprint-pinned certificates and signed payloads, not the public PKI. Names resolve on your own machine. Nothing about your services leaks to certificate-transparency logs or open resolvers.

Who runs the relay, and do I have to trust it?

No — and that’s the point. The relay (the same binary, in its rendezvous role) only forwards encrypted frames and sealed invitations between devices that can’t connect directly. It can’t read your traffic, your keys, or your service map, so it’s never part of what you trust. Use our open relay (free, on request), a partner’s, or run your own.

Does it work on phones?

Yes. The Android and iOS apps run a node while you use them and open your services inside the app, signed in as you. On Android it can also keep running in the background, for a phone that hosts a service.

What if the controller's machine dies?

Take a backup from the controller: one file, encrypted with a passphrase you choose, holding the federation’s identity and its whole registry. Restore it on a new machine and every node carries on — no re-enrollment.

Can a device only consume — never host anything?

Yes. Deploy it without a relay and it’s consume-only: it uses services others share with it and exposes nothing. Attach a relay later, with no redeploy, if you ever want it to host services.

Do I need an account?

No. No sign-up, no vendor control plane, no telemetry. The controller is a device you own running the same binary, and codes travel between devices by whatever means you choose.

How do I get it?

It’s in closed alpha right now, and free. Request access at info@sidephone.io. Public builds and source are coming soon. (sidehub is the name of the binary; SideServices is the product.)

Coming soon.

SideServices (the sidehub binary) is in closed alpha — free, but builds and source aren't public yet. Want in? Email us and we'll get you set up.

linux · amd64 linux · arm64 macos · universal windows · x64 ios · testflight android · apk freebsd openbsd source

one binary — every OS, every role · all builds coming soon