Skip to content

Docs › Plugins

Running a store

Deploy a plugin store, claim it, and look after it.

A store is yours. You choose its plugins and its members, and you are responsible for what it lists and for the sources those plugins reach. List only plugins for sources you and your members are entitled to use. Kaeri makes the store’s software and does not run, list or review stores.

A store is one small program, and it is the same program wherever it runs. Run it on what you already have: an account on a hosting platform, a server, or a computer that stays on.

Where How What it costs
Cloudflare Workers Deploy button Fits the free plan. R2 may ask for a payment method on file
Vercel Deploy button Fits the Hobby plan and Neon’s free plan
Netlify Deploy button Fits the Free plan
Render Deploy button The smallest paid instance, because the store needs a disk
Heroku Deploy button A Basic dyno and Postgres Essential 0
Fly.io fly launch Billed by use. The machine stops while nobody uses the store
Railway A template Billed by use
A server or a computer of yours kaeri store serve, or Docker Nothing more

Each link has the details for that host: what the deploy creates and where it keeps the store’s records and plugin files. Updating a store covers new releases on every host.

A new store has no owner. The templates for hosting platforms ask for, or generate, a setup code. Open https://<your store>/admin/ in a browser, enter the code, and the page answers with an owner invite link. On a platform that generates the code, it is listed with the service’s environment variables.

Paste the link into Kaeri the way anyone joins a store: Sources, Enter, Join a store. The device that joins with it owns the store. The setup code stops working once the store has an owner.

A store also prints a one-time owner invite in its log when it starts without an owner, which is the easier way on your own machine or wherever the log is in front of you.

kaeri store serve ./my-store --url https://plugins.example --name "Our plugins"

The first run creates ./my-store and prints the owner invite. --url is the address people will reach the store at, and invite links are built from it. The server listens on 127.0.0.1:7878 unless --listen says otherwise.

Kaeri joins stores over HTTPS only, apart from stores on the same machine. Either pass --tls-cert and --tls-key, or put the server behind something that serves HTTPS already, such as Caddy, a Cloudflare Tunnel or Tailscale. The Docker templates come with Caddy for a machine with a domain, and with Tailscale Funnel for one without.

The server also comes as a small program of its own, kaeri-store, in the container image ghcr.io/bitknox/kaeri-store. It takes the same commands as kaeri store.

The store’s page in Kaeri has what an owner needs day to day: Invite someone, Members, where you can remove someone’s access, and Publish a plugin from your plugin directory. Choose a plugin you published to stop offering it.

Choose Open the admin page to open the store in your browser, already signed in. It has the same controls and a few more: rename people, make someone an owner, revoke one lost device without removing its owner, and publish by dropping .wasm files onto the page. A sign-in link works once, for ten minutes, and a session lasts twelve hours.

On the store’s own machine, a few things work from the shell:

kaeri store invite ./my-store --name Alex # print an invite link
kaeri store publish ./my-store --plugin plugin.wasm # publish or update a plugin
kaeri store admin ./my-store # print a sign-in link for the admin page

In a container, the same commands run as kaeri-store, for example docker compose exec store kaeri-store invite --name Alex.

Publishing to Cloudflare, Vercel or Netlify

Section titled “Publishing to Cloudflare, Vercel or Netlify”

A store there cannot run a plugin to ask what it is, so the plugin has to carry the answer. Publish from Kaeri and it is added for you. To publish a file through the admin page instead, add it first:

kaeri plugin stamp plugin.wasm

Members’ copies of Kaeri check every plugin against what it says when they install it, so a plugin cannot get in under someone else’s name this way.

The templates set these for you. Every option of kaeri store serve can also come from the environment:

Variable Meaning
KAERI_STORE_URL The address people reach the store at. Found on its own on Render, Railway, Fly and Heroku
KAERI_STORE_NAME The store’s name, as members see it
KAERI_STORE_SETUP_CODE Claims the store from its admin page while nobody owns it
KAERI_STORE_DIR The directory holding the store’s records and plugin files
DATABASE_URL A Postgres database to keep everything in instead
KAERI_STORE_TRUST_PROXY true behind a proxy that is the only way in

The full list is in the protocol document.

Everything a store has is in one place: its directory, its volume or its database. That includes the key that signs its plugin list, so keep backups as private as the store itself. Someone with that key, or with control of the server, could sign a list your members would accept.