Skip to main content
awewarm-hub

awewarm-hub: Multi-tenant Hub Server

One always-on box keeps a whole team's subscription windows warm.

The multi-tenant hub server for awewarm: many users, one server, one-time invites — each user's secrets staying on their own machine.

English · 简体中文

Ko-fi

Version Python License

Status pip install Platform PyPI downloads GitHub stars

Real case: a five-person team on one $5 VPS. Everyone's subscription plans stay warm around the clock on the box that never sleeps — while every API key stays on each member's own laptop.

awewarm-hub splits the roles in two:

  • Operator (this machine, the 24/7 box): awewarm-hub serve + the admin commands below. You mint one-time invite codes and hand them out.
  • Users (their own machines, plain open-source awewarm only): awewarm remote connect <url> --invite awi_..., then awewarm config set <id> --remote. They never need this package.

Install

Requires Python ≥ 3.9:

pip install awewarm-hub          # brings awewarm with it

Quick Start

Let an AI agent set it up

Working in Claude Code, Codex, or another coding agent? Tell it:

Read https://github.com/wehuman01/awewarm-hub/blob/main/README.ai.md and follow it to set up your awewarm-hub server.

The agent installs the CLI, checks status and tenants read-only, and mints invite codes on your request. The resident serve process itself stays in your terminal (or systemd) — an agent never backgrounds it.

Manual setup

awewarm-hub serve                # listens on 127.0.0.1:8790, data at ~/.awewarm-server
awewarm-hub invite --note alice  # prints awi_... (one use, 48 h)
awewarm-hub status               # capacity, invite counts, tenants, serve liveness

awewarm and awewarm-hub

Two packages, two roles, same MPL-2.0 license and the same wehuman01 org:

Package Who installs it What it does
awewarm everyone (each user's own machine) schedules warm-up requests; awewarm serve covers one solo server
awewarm-hub (this package) the operator only (the 24/7 box) multi-tenant serving: tenants, one-time invites, quotas, revoke/restore

The engine underneath (WarmServer, schedule, transport, the HTTP handler core) comes from the awewarm pip dependency, pinned to its minor version so the wire protocol stays in lockstep with the open-source client. Expose the hub through a cloudflared tunnel (free TLS, no open inbound ports, your origin IP stays hidden) exactly like a solo awewarm server — see awewarm's README → Remote Server. A systemd user unit is the same shape, with ExecStart=awewarm-hub serve:

[Unit]
Description=awewarm-hub serve
After=network-online.target

[Service]
ExecStart=awewarm-hub serve
Restart=on-failure

[Install]
WantedBy=default.target

systemctl --user enable --now awewarm-hub (with loginctl enable-linger $USER on headless boxes).

Commands

awewarm-hub serve [--data-dir/--bind/--port]   # the resident hub server
                 [--max-tenants/--max-conns-per-tenant/--max-machines/--tick-seconds]
awewarm-hub status [--details]                 # capacity, invite counts, tenants, serve liveness
awewarm-hub invite [--note <who>] [--expires-hours N]
awewarm-hub list users [--api|--reveal|--json] # tenants: health, usage, machines, joining code
awewarm-hub list invites [--reveal|--json]     # every minted code: pending/used/revoked/expired
awewarm-hub revoke <t_...>|<awi_...>           # suspend a tenant / kill an invite (reversible)
awewarm-hub restore <t_...>|<awi_...>          # undo a revoke
awewarm-hub config [--data-dir /data|--unset]  # default data dir for this machine
awewarm-hub self-update [--check]              # upgrade from PyPI

How It Works

Each tenant gets a private workspace under tenants/<id>/ (connections, state, RAM keyring — invisible across tenants). tenants.json stores SHA-256 hashes of tenant tokens, so pairings survive a restart; invite codes are kept in the clear so the operator can recover one already sent (list invites --reveal) — anyone who can read the data dir can use a pending invite, so guard it. Revocation is suspension, not deletion: revoke + restore round-trips a tenant or an invite; a suspended tenant frees its capacity slot. A token serves one machine by default (--max-machines); revoke + restore clears its paired machines. A light per-tenant rate limit (60 requests/minute) stops a looping client.

One trust rule, stated plainly: the hub fires requests with its users' API keys, so their plaintext keys pass through its RAM. Hub for people who trust the machine's operator (and root); a shared VPS with strangers is not that.

Nothing secret is ever written to disk — API keys live in server RAM and are re-pushed by each user's machine after a restart.

Upgrading from pre-split awewarm serve --hub

The data dir (~/.awewarm-server, or whatever --data-dir/the old hub config --data-dir set) carries over unchanged — tenants, invites, and the persisted data-dir setting all keep working. Stop the old serve, install this package, start awewarm-hub serve. The old spellings (awewarm serve --hub, awewarm hub ...) die with a tombstone in awewarm naming their replacement here.

Config

awewarm-hub config [--data-dir /data] persists the default data dir on the hub machine (the flag overrides once; --unset clears it). The default is ~/.awewarm-server, shared with awewarm's solo server. Inside it: tenants.json (token hashes, invite codes, the serve record with caps/bind/version/start time) and one private tenants/<id>/ workspace per tenant. Serve stamps its caps into tenants.json at launch so one-shot CLI processes on the same box read the same numbers; a data dir whose serve never launched says "caps unknown" instead of guessing.

Self-Update

awewarm-hub self-update            # upgrade to the latest release
awewarm-hub self-update --check    # show versions only

Development

python3 -m venv .venv && source .venv/bin/activate
pip install -e ../awewarm -e .     # the open-source engine, editable, plus this package
python3 -m unittest discover -s tests

awewarm-hub -v says editable (with the git state) when running from this checkout; pip's recorded metadata freezes at pip install -e . time, so re-run it after a version bump to keep pip show in sync. awewarm-hub self-update refuses on a checkout — pull and re-install instead.

The source repository is wehuman01/awewarm-hub (open, MPL-2.0); releases are built and published to PyPI on tag push. See docs/CONTRIBUTING.md for the engineering doctrine and docs/CHANGELOG.md for release history.

Support

If awewarm-hub keeps your team's quotas warm, consider supporting it:

  • ⭐ Star the repo — it helps others find it.
  • Ko-fi — buy me a coffee.
  • 💬 WeChat — scan the QR code below.

WeChat Pay

awewarm-hub is free and open source. Sponsors keep it maintained — thank you.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

awewarm_hub-0.5.5.tar.gz (42.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

awewarm_hub-0.5.5-py3-none-any.whl (27.1 kB view details)

Uploaded Python 3

File details

Details for the file awewarm_hub-0.5.5.tar.gz.

File metadata

  • Download URL: awewarm_hub-0.5.5.tar.gz
  • Upload date:
  • Size: 42.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for awewarm_hub-0.5.5.tar.gz
Algorithm Hash digest
SHA256 e38ca67e276c00f60dca0598bdeb0a224f32fa15d80ff631b937d991268363b9
MD5 ad96fe1af5c805181c2260b92d57688d
BLAKE2b-256 04292e4df1a93d1f6d81cdcdc4336a1b0df068a0b2938fba2bbc37901bc2b15d

See more details on using hashes here.

File details

Details for the file awewarm_hub-0.5.5-py3-none-any.whl.

File metadata

  • Download URL: awewarm_hub-0.5.5-py3-none-any.whl
  • Upload date:
  • Size: 27.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for awewarm_hub-0.5.5-py3-none-any.whl
Algorithm Hash digest
SHA256 34bbf74f5b86012c9ff861868b84815682f79cfd7b2a0ecb1c336ca69606de66
MD5 8dd18b2094ebed5a65945b33025d53b8
BLAKE2b-256 1cf6571a45abdd63b79e453302391e42335c5af016247d3cfa93a04269047a13

See more details on using hashes here.

Release history Release notifications | RSS feed

0.6.0

2 files

0.5.8

2 files

0.5.7

2 files

0.5.6

2 files

This release

0.5.5 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page