Skip to content

WangYihang/Platypus

Repository files navigation

Platypus

GitHub stars GitHub license GitHub Release Downloads Sponsors

A host management hub for fleets of Linux machines. Install the Platypus agent on every host you own; the agent dials back to your Platypus server over TLS + protobuf; from the server you get an interactive shell, file management, and network tunnelling on every managed host — through one central control plane.

Screenshots

A Vercel-style flat-nav UI with a project dashboard, a host/listener/session browser, a multi-host dispatch console, and an admin user manager. See the full gallery at docs/screenshots/. Re-run make screenshots to regenerate them from the live app.

Project overview dashboard

Architecture

Platypus ships as two backend binaries plus a standalone desktop client:

Binary Role
platypus-server Daemon. Accepts inbound agent connections on TLS ingress ports; exposes a REST + WebSocket API for admin tooling; serves agent binaries for distribution.
platypus-agent The process that runs on each managed host. Dials back to the server over TLS + protobuf.
platypus-desktop Native (Wails v2) desktop GUI. Connect to any reachable server with URL + secret; tabbed UI for sessions, terminals, listeners, files, tunnels. See desktop/.

The server is purely an API — no embedded web UI. Multiple desktops can connect to the same server simultaneously.

Features

  • TLS + protobuf channel between agent and server
  • Multiple ingress ports so fleets in different networks share one hub
  • Interactive shell per host, streamed over WebSocket
  • File read / write / upload / download with chunked transfer
  • Network tunnels: local-port-forward, remote-port-forward, dynamic SOCKS5
  • Bearer-token-authenticated REST API
  • Python SDK
  • Auto-start listeners from config.yml
  • Graceful shutdown (drains connections on SIGINT/SIGTERM within 30s)

Documents

Quick start

One-Click Deployment (Recommended)

The fastest way to get a full Platypus system running (including the Server, Web UI, and a MinIO-backed Agent Distributor) is using Docker Compose:

git clone https://github.com/WangYihang/Platypus
cd Platypus
docker-compose up -d
  • Web UI: Open https://localhost:9443 in your browser (the container ships with a self-signed cert; your browser will prompt you to accept it on first visit).
  • Login: The bootstrap_secret is written to /app/data/bootstrap.secret inside the container on first boot (mode 0600). Read it with docker compose exec platypus-server cat /app/data/bootstrap.secret, use it once to create the first admin, then delete the file. After bootstrap completes the secret is no longer accepted.
  • Add Agents: Click "Add Agent" in the UI to get a one-line curl ... | sh command, signed and pinned to the project CA, to deploy agents to your fleet.

Build from source

Requires Go 1.24+ and protoc (only if you regenerate protobuf code).

git clone https://github.com/WangYihang/Platypus
cd Platypus
make build              # → ./build/{platypus-server,platypus-agent}

Other useful targets: make test, make lint, make snapshot (cross-platform via goreleaser), make help.

Development (pre-commit hooks)

Contributors should install the git hooks so gofmt / goimports / go vet / golangci-lint run before each commit:

pip install pre-commit   # or: pipx install pre-commit
make hooks               # one-time: wires .git/hooks/pre-commit
make pre-commit          # optional: run all hooks against every file now

Build the desktop app

Requires Node 22+, Wails CLI dependencies (wails doctor), and the platform's WebView libraries (webkit2gtk-4.1 on Linux, WebView2 on Windows, WKWebView on macOS).

make desktop-deps       # one-time: install Wails CLI + pnpm packages
make desktop-build      # → desktop/build/bin/platypus-desktop
make desktop-dev        # hot-reload dev mode

Or: use the standalone web UI (no install)

Same pages, same features (minus real-time event push), runs in any browser:

make web-ui             # → desktop/frontend/dist-web/ (static bundle)
make web-ui-serve       # preview at http://localhost:8080

dist-web/ is fully static; drop it on GitHub Pages / S3 / nginx. Point it at any platypus-server via the login form.

Full notes in desktop/README.md.

Install from release binaries

Download the appropriate archive for your OS/arch from the Releases page, extract, and run.

Run with Docker

docker build -t platypus-server .
docker run --rm -p 9443:9443 \
  -e PLATYPUS_DEV=1 \
  -v $(pwd)/config.yml:/config.yml \
  platypus-server

PLATYPUS_DEV=1 enables the on-disk KEK fallback so a fresh start "Just Works"; for production, drop that env var and set PLATYPUS_CA_KEK (32 bytes hex; openssl rand -hex 32) instead so the CA private-key encryption key is never written next to the encrypted database.

Run

./build/platypus-server                # foreground; Ctrl-C for graceful shutdown

For production, run the server under systemd rather than backgrounding it manually.

Production caveats

  • Single-instance only. The opaque-token verifier caches verified tokens in a per-process LRU. Revocation (logout, password change, AAT revoke, user delete) drops the entry on the same process synchronously — but a multi-replica deployment has no cross-process invalidation channel today, so a revoked token can keep working on other replicas for up to the cache TTL (30s). Don't run more than one platypus-server against the same DB until cross-process revocation lands. Vertical scale + an HA stand-by is the supported shape; horizontal load-balanced replicas are not.
  • PLATYPUS_CA_KEK in the environment. The CA private key is sealed with AES-256-GCM against this 32-byte hex value. Without it set, the server refuses to start unless PLATYPUS_DEV=1 is also present (which enables a dev-only on-disk fallback at <data-dir>/ca.kek — unsafe for production because the ciphertext and key end up on the same volume).
  • Desktop-class viewport, no mobile layout (yet). The Web UI targets ≥ 1280px viewports; the rail / sidebar / status-bar chrome takes ~300px, leaving the content body in the 80–100 character reading sweet spot. There is no responsive collapse for narrow windows today — sub-1024px viewports will show horizontal scrollers on tables. Tablet / phone support is on the backlog (P4 in the UX audit) but not blocking; admin work is desk work.
  • Object-store credentials. When the distributor is enabled (distributor.store.endpoint set), set PLATYPUS_DISTRIBUTOR_STORE_ACCESS_KEY_ID and PLATYPUS_DISTRIBUTOR_STORE_SECRET_ACCESS_KEY rather than baking them into config.yml. The bundled config.docker.yml ships with the YAML fields blank for that reason.

Usage

Topology

  • Server: 192.168.88.129
    • Unified TLS ingress (REST API + agent link + installer): 0.0.0.0:9443
  • Managed host: 192.168.88.130 (runs platypus-agent)

Quick tour

First, run ./platypus-server. A config.yml is generated from assets/config.example.yml if none exists. Defaults are sensible.

To enrol a new managed host:

  1. Open the Web UI / desktop app, navigate to the project, click Add Agent.
  2. Pick the target OS / arch and TTL, click Generate.
  3. Copy the one-liner the UI displays and run it on the managed host.

The server-rendered one-liner looks like:

curl -fsSL https://<server>:9443/api/v1/install/<one-shot-token> | sh

The single-use install token expires shortly after issuance and is burnt on the first successful hit. The script the server returns:

  • embeds the project CA so the agent binary download is verified with curl --cacert (no -k, no TOFU);
  • injects a single-use PAT so the agent can complete enrolment and obtain its mTLS client certificate;
  • refuses to run if the server has no project CA configured, unless the operator explicitly sets PLATYPUS_INSECURE_DOWNLOAD=1.

Do not hand-write curl http://... URLs against the legacy /agent/<host>:<port> path — that flow is removed. Always render the install command via the UI so it carries the trust anchor.

Desktop / Web

Open the desktop app (platypus-desktop) or the web UI (make web-ui-serve), fill in the server URL and secret, and you're in. Tabs: Sessions (every agent that's dialled in), Terminal, Files, Tunnels, Listeners.

Advanced usages

Other materials

Contributors

This project exists thanks to all the people who contribute.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

About

🔨 A modern, cross-platform machine manager

Resources

License

Security policy

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors