Providers and self-hosting
How to pick the official instance, a self-hosted reference server or any conforming URL, what a provider must implement, and how to run and configure the reference server.
A server that offers the cloud is called a provider. PKU harness isn't tied to one provider: the app can use any server that implements the cloud protocol. The first part of this page is for users and explains how to choose a provider. The rest is for operators and explains what a provider must implement and how to run the open-source reference server.
Choosing a provider (users)
Settings → Cloud has three options.
Official is the instance run by pkuinfo. It is not deployed yet. Once it launches, it will stay small and offer only the relay for live shares, a small end-to-end encrypted store and the viewer pages. It stays off until you turn it on.
Self-hosted asks for a base URL. When you tap Test connection, the app shows the
operator, services and limits that the provider returns from /v1/meta.
Off means no cloud. Plugins that require cloud become unavailable. Plugins for which the
cloud is optional keep working locally.
URLs must use HTTPS. Development builds also accept http://10.0.2.2:*, http://localhost:*
and http://127.0.0.1:*. Switching provider doesn't move any data, because each provider has its
own device identity and its own store.
What a provider implements
A provider implements everything in the API reference and validates
data with the schemas from @pku-harness/cloud-protocol. In
detail:
GET /v1/meta. It returnsprotocol: 1, the services offered, limits, proof-of-work parameters, viewer pages, functions and the operator (name,contact, optionalprivacyURL).- Device registration and token minting. A device must solve a proof of work to register. When
a device signs a challenge to get a token,
audmust be your own origin, clocks may differ by up to 5 minutes, and nonces must not be replayed. Tokens are valid for 10 minutes. - The services you list in
services. A provider may offer only some of them. Plugins whoseusesit doesn't fully cover are marked unavailable. - The common error body
{ error: { code, message, retryAfterS? } }, plusRetry-AfterandRateLimit-*headers. - Static viewer pages at
/w/<plugin>/<page>with a strict Content Security Policy (CSP), and theGET /s/:idredirects.
Reference server
The open-source reference server is the packages/cloud-server folder in the
pku-harness-plugins
repository. It runs on Bun, Hono and bun:sqlite (in WAL mode), and it validates every request
and response with the @pku-harness/cloud-protocol schemas.
The reference server advertises store, channels and functions. push answers
501 unsupported for now. Plugin server functions (/v1/fn, /v1/p) are governed by
CLOUD_FN_POLICY. In production (NODE_ENV=production) it defaults to allowlist with an empty
list. Server functions are off on the official server.
To run the reference server locally:
cd pku-harness-plugins/packages/cloud-server
bun run dev # http://localhost:8787, reloads on change, data in ./data/cloud.db
bun test # route tests + real WebSocket/SSE tests
# or from the repo root: bun run --filter @pku-harness/cloud-server devIn the Android emulator, point Settings → Cloud → Self-hosted at http://10.0.2.2:8787.
The reference server is configured with environment variables:
| Variable | Default | Meaning |
|---|---|---|
PORT / HOST | 8787 / 0.0.0.0 | Listen address |
CLOUD_PUBLIC_URL | http://localhost:$PORT | Origin clients use; the aud of token challenges |
CLOUD_DB | ./data/cloud.db | SQLite file (:memory: for throwaway runs) |
CLOUD_TOKEN_SECRET | generated, stored in the DB | HMAC key for bearer tokens (≥ 32 chars) |
CLOUD_POW_DIFFICULTY | 16 | Proof-of-work difficulty |
CLOUD_POW_ROTATE_S | 21600 | Salt rotation period; the previous salt stays valid for one more period |
CLOUD_OPERATOR_NAME / CLOUD_OPERATOR_CONTACT / CLOUD_PRIVACY_URL | PKU harness Cloud (self-hosted) / empty | Returned by GET /v1/meta |
CLOUD_PAGES_DIR | <plugins repo>/plugins | Folder holding the <plugin>/web/dist viewer pages |
CLOUD_TRUST_PROXY | off | 1 takes the client IP from the last X-Forwarded-For hop (use behind Caddy) |
deploy/ holds a Dockerfile, a Caddyfile and a Litestream config; its README.md explains how
to use them. The server's own README.md documents the server-function variables
(CLOUD_FN_POLICY, CLOUD_FN_ALLOW, CLOUD_FN_VERIFIED, CLOUD_FN_LOCAL,
CLOUD_SECRET_<PLUGIN>__<NAME>).
Operating an instance
If you plan to run an instance for other people, keep these points in mind:
- Say who you are (
operator.name,contact) and publish a privacy statement (privacyURL). - Keep payloads and tokens out of your logs. Payloads are ciphertext, but IP addresses and request times are still personal data.
- Hosting in mainland China requires ICP filing. The official instance is planned outside the mainland, with a short dedicated domain for share links. WeChat may show a warning page for unknown domains, so the app always offers both a QR code and a copy-link button.
Security
How PKU harness Cloud keeps user data unreadable to the server. Device keypairs, proof-of-work registration, short-lived signed plugin tokens, XChaCha20-Poly1305 envelopes, share-link secrets in the URL fragment, claim-once channels and share-link redaction.
cloud-protocol package
@pku-harness/cloud-protocol: the zod wire schemas, path builders, envelope crypto, share-link helpers, proof of work and token challenge that the app, providers and viewer pages share.