Skip to content

Feature License

SkimMail docs edited this page Sep 15, 2026 · 1 revision

English · Tiếng Việt · 中文

Plan and license

Since 1.6.0, SkimMail is free to self-host forever at the Community tier, with a small set of per-instance limits, and unlocks higher tiers through an offline, signed license key — no license server, no phone-home requirement to apply one, and no account of any kind on SkimMail's side.

What this solves

Self-hosted software that wants to fund itself usually picks one of two unpleasant options: cripple the free tier so hard it isn't really usable, or require a running license server that turns a self-hosted product into one more thing that can go down and lock you out of your own mail. SkimMail's entitlement system is neither: Community Edition is a complete, real mailbox reader with generous-enough limits for one person, and a key that unlocks more is a signed, offline token you paste in once — verified with cryptography already built into the binary, never checked against a remote server at apply-time.

Where it is

Settings ▸ Plan & License, owner only.

The three tiers

Resource Community Sponsor Pro
Accounts 10 25 Unlimited
Connections (egress proxies/tunnels) 3 5 Unlimited
Groups 2 5 Unlimited
Storage 5 GB (display only — see below) 15 GB (display only) Unlimited
Sign-ins (AUTH_MODE=users) 1 3 Unlimited

Community is the fallback whenever no license is applied, or an applied one has expired or been revoked. Sponsor's sign-in limit of 3 is the smallest number at which the owner/operator/viewer role model (see Users and roles) means anything at all — Community's other numbers describe one person with a real setup, not a team.

These limits are per instance, not per user. Counting them per user would let anyone lift the Community 10-account cap by creating a second sign-in; the counts behind every meter here are unscoped queries against the whole database on purpose.

Applying a key

Paste the license text, or drop the file it came in, and save. A key is a compact two-part token — a JSON payload and an Ed25519 signature, both base64url-encoded, joined by a . — verified against a public key baked into the binary at build time. Nothing is sent anywhere to apply it: the whole check happens locally, so it works on an air-gapped instance exactly as well as an internet-connected one.

A key with a bad or missing signature is refused outright (nothing is stored) and the screen reports it as invalid. A key that verifies but has already expired is still stored and shown — its tier, licensee name and dates are displayed for transparency — while every limit in effect falls back fully to Community until you apply a current one. Replacing an existing key, or removing it entirely to revert to Community, are both one click away on this screen.

What happens when a key expires or is revoked

Entitlement gates creation only — never recovery, never reading. If a Sponsor key lapses while you have 22 accounts configured, none of them disappear, stop syncing, or become read-only: all 22 keep working exactly as before. What changes is that you cannot add a 23rd account, connection or group until you either renew the key or delete down to the Community ceiling. The same instinct explains why storage is never enforced at all — see below.

The UI treats expired and revoked as related but distinct: a revoked key (one whose id appears on SkimMail's signed revocation list) is labelled as revoked rather than merely expired, so you know to ask about the license itself rather than assume your subscription simply ran out.

Revocation, and how it stays trustworthy without a phone-home requirement

Every SkimMail build carries a baked-in baseline of revoked license ids, which alone is enough to work forever on an offline instance. On top of that, an instance that has opted into the periodic self-update check (see Operations) piggybacks a fetch of the latest signed revocation list on the same cycle — never a separate network dependency of its own — and only accepts a fetched list if it is strictly newer than whatever is already cached, specifically to stop a network attacker from replaying an old, genuinely-signed list forever to hide a revocation you would otherwise have learned about. Any failure here — offline, update-checking turned off, a bad signature — is silently swallowed and simply leaves the baked-in baseline as the floor; it never blocks anything else in the product.

What is actually enforced, and what is only ever advisory

The four numbers above are not enforced identically:

  • Accounts, connections and groups are checked at the moment you try to create one more — adding an IMAP or OAuth account, adding an egress proxy/tunnel, or adding a group all refuse with "limit reached" once you are at the tier's ceiling.
  • Sign-ins are checked the same way, but only from the skimmail user add CLI (see Users and roles) — there is no self-serve "create a user" screen in the product for this to gate in the UI.
  • Storage is never enforced, on purpose. The number shown is a real filepath.Walk over your data directory, computed fresh each time you open this screen, but it is display-only: nothing in SkimMail refuses a write — a mail sync saving an attachment, a body being cached — because you are over a storage number. The alternative (a mailbox that stops accepting new mail because a disk got full according to a number on a settings screen) was judged worse than an honest, unenforced meter.

Limits

Available since 1.6.0
Role owner
Tiers Community · Sponsor · Pro
Enforcement point account/connection/group creation, and skimmail user add; never storage
Network required to apply a key No
Network required to check revocation No — best-effort, piggybacked on the opt-in update check

What it does not do

  • It gates no content. Message count, mailbox size, and cached body size are unaffected by tier — only the number of accounts, connections and groups you can create, and how many people can sign in.
  • It does not phone home to apply or verify a key. The signature check is entirely local; only the optional revocation-list refresh ever makes a network call, and it never blocks applying or using a key.
  • The verification key cannot be overridden by an environment variable, unlike the self-update key (UPDATE_PUBKEY). It is a build-time constant on purpose — an env override would let anyone generate their own keypair and self-sign an "unlimited" license in two commands, which would defeat the entire system.
  • It cannot restore something a limit is now blocking. Deleting down to the Community ceiling is manual, and — per Users and roles — deleting the wrong user account under a 1-seat limit can be a genuine bind; the CLI has a --reassign-to option for exactly that case.

See also

  • Users and roles — the sign-in limit, the skimmail user CLI, and what a 1-seat Community instance means for deleting a user
  • Operations — the opt-in update check the revocation-list refresh rides along with
  • LICENSE / COMMERCIAL-TERMS.md in the repository — the legal terms behind the tiers; this page describes only how the software behaves

SkimMail · skimmail@base101.app · 2026-09-15 · commit dffbb18

Clone this wiki locally