PKU harness
Cloud

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 returns protocol: 1, the services offered, limits, proof-of-work parameters, viewer pages, functions and the operator (name, contact, optional privacyURL).
  • 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, aud must 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 whose uses it doesn't fully cover are marked unavailable.
  • The common error body { error: { code, message, retryAfterS? } }, plus Retry-After and RateLimit-* headers.
  • Static viewer pages at /w/<plugin>/<page> with a strict Content Security Policy (CSP), and the GET /s/:id redirects.

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 dev

In the Android emulator, point Settings → Cloud → Self-hosted at http://10.0.2.2:8787.

The reference server is configured with environment variables:

VariableDefaultMeaning
PORT / HOST8787 / 0.0.0.0Listen address
CLOUD_PUBLIC_URLhttp://localhost:$PORTOrigin clients use; the aud of token challenges
CLOUD_DB./data/cloud.dbSQLite file (:memory: for throwaway runs)
CLOUD_TOKEN_SECRETgenerated, stored in the DBHMAC key for bearer tokens (≥ 32 chars)
CLOUD_POW_DIFFICULTY16Proof-of-work difficulty
CLOUD_POW_ROTATE_S21600Salt rotation period; the previous salt stays valid for one more period
CLOUD_OPERATOR_NAME / CLOUD_OPERATOR_CONTACT / CLOUD_PRIVACY_URLPKU harness Cloud (self-hosted) / emptyReturned by GET /v1/meta
CLOUD_PAGES_DIR<plugins repo>/pluginsFolder holding the <plugin>/web/dist viewer pages
CLOUD_TRUST_PROXYoff1 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.

On this page