closedloop.email

How closedloop works

You give us a cloud API token. We provision a mail server in your account. You claim it, set your password, revoke our access. After that, we hold nothing.

1

Choose your cloud

We support Hetzner, DigitalOcean, Linode, and Vultr. You create an API token with read/write access — we have guides for each one on the blog. The server lives in your account, you pay the cloud provider directly.

2

We provision the server

We validate your token, upload our admin SSH key to your account, and run Terraform to create the server, firewall, and DNS records. The server boots with a self-generated admin password — we never choose one and never know it.

3

You claim it

Once the server is up, we give you a one-time claim token. You visit your loop's admin page, enter the token, and set your own admin password. The platform now has no mail credential.

4

Revoke our SSH key

We keep an SSH key on the server for support. You can revoke it from the dashboard at any time. After that, the platform has zero access to the server — no credential, no key, no path.

5

Use your loop

Sign in through the webmail interface on port 443. Every mailbox you create lives inside the loop. Mail never leaves, and no outside mail enters. When you are done, you can destroy the server from your cloud account dashboard.

What "airgapped" actually means

A closedloop is airgapped at two layers:

Network layer. The cloud firewall blocks inbound and outbound mail ports. tcp/25, 465, 587, 993, 995 — all closed. On Hetzner, DigitalOcean, and Linode this is enforced at the firewall. On Vultr it is enforced by Stalwart configuration (Vultr firewall groups are inbound-only).

Application layer. Stalwart's MtaStageRcpt.allowRelaying is set to false. Even an authenticated mailbox cannot relay mail to an external address. The server rejects the attempt immediately with a 5xx response.

The result: no email protocol can carry a message in or out. Webmail on port 443 is the only way to use the server.

What we hold (and what we don't)

We are explicit about this because most services are not:

  • Before claiming: we hold the cloud API token (in encrypted storage), an SSH key on the server, and the one-time claim token. We need these to provision the server.
  • After claiming: we drop the claim token, and the admin password you set is yours alone. We never see it.
  • After revoking SSH: we hold nothing. The only remaining credential is the cloud API token, which you provided and can delete from your cloud account at any time.

Most email providers choose not to read your mail. We cannot read it — there is no path.

Create your loop →