BenchPress Documentation

BenchPress Documentation

Open in ChatGPT
Ask ChatGPT about this page
Open in Claude
Ask Claude about this page

Production safety

Production safety

What BenchPress is and is not ready to carry — the alpha verdict, the container privilege boundary, what is backed up, and the endpoint-by-endpoint release checklist.

Whether BenchPress is safe to run on your host, and what has to be true first.

Who this is for. Whoever is deciding what this box will carry.

Before you start. Read the verdict before the tables. It has not changed
and it is not hedged.

The verdict

BenchPress is alpha software. Do not run it on a host you cannot afford to
lose.

It is built for developers and small teams spinning up disposable Frappe and
ERPNext environments. It is not built to host customer data. Concretely:

  • It takes host-level privilege. setup.sh adds your user to the docker
    group, starts the shared MariaDB and Redis containers, and enables IP
    forwarding under /etc/sysctl.d. These are real, persistent changes to the
    host.
  • A lab user gets root inside their bench. That is by design and it is why
    the runtime matters. See
    The container privilege boundary.
  • Database backups are automatic. Restore is manual. The shared MariaDB is
    dumped nightly to host disk outside its data volume, and the restore path is
    documented and verified. Other bench data in Docker volumes is not backed
    up. See Backup and restore.
  • Single-tenant assumption. Quotas, rate limits and audit trails are still
    in progress. Run BenchPress for people you trust, on a host dedicated to it.

Use it on a dedicated dev box, a VM, or a cloud instance you can rebuild. Not
on your daily-driver workstation, and not on a shared production server.

The container privilege boundary

This is the one item on the checklist that reads not ready without a
deployment precondition.

create_bench_container deliberately avoids privileged. A bench gets
NET_ADMIN and /dev/net/tun, and nothing else. But a lab user holds root
inside the container, and without a user namespace, in-container UID 0 is
host UID 0.

Close it one of two ways before you ship anything real:

Option How Status here
Sysbox default_bench_runtime = sysbox, with sysbox-runc registered with Docker the default, and what this host runs
Docker userns-remap {"userns-remap": "default"} in /etc/docker/daemon.json see WireGuard and the VPN plane

Running the daemon rootless is an accepted third option.

Prove it, do not assume it:

bash apps/benchpress/setup.sh <site> --strict

--strict exits non-zero rather than warning. Use it on any host that matters.

Steps

  1. Read the verdict and decide what this host will carry.
  2. Close the container privilege boundary.
  3. Confirm the platform and versions on
    Prerequisites.
  4. Confirm backups are landing. See
    Backup and restore.
  5. Run the diagnostics and fix every failing row. See
    Diagnostics.
  6. Work through the release checklist and decide
    which follow-ups you are accepting.

Verify

bash apps/benchpress/setup.sh <site> --strict          # exits 0
bench --site <site> execute benchpress.diagnostics.run_diagnostics
ls -lh sites/<site>/private/backups/mariadb/ | tail -3

All three must pass on a host carrying anything you would miss.

The release checklist

Last reviewed 2026-07-02, from the authorization suite, the contract and
timing suite, a branch security review, and a sweep of every
ignore_permissions=True and secret-handling path.

Read as: Ready, Ready with a follow-up, Not ready.

Whitelisted endpoints

Endpoint Guard Verdict Note
get_labs login only Ready A shared admin-curated catalog. No per-user data
get_lab login only Ready One catalog row
get_lab_templates login only Ready A static list
create_lab_from_template require_admin Ready Admin-only, proven by test
build_lab_image require_admin Ready Admin-only, proven by test
get_benches owner filter Follow-up Returns decrypted SSH, admin and code-server passwords in the list payload. Owner-scoped, but secrets belong in an on-demand call
create_bench login, own deterministic id Ready The id embeds the caller, so a user can only create their own
bench_action require_bench_access, delete admin-only Ready Start, stop and restart are owner-scoped. Delete is admin-gated
get_deploy_logs require_bench_access Ready Cross-user access denied by test
add_device login, peer owned by caller Ready Creates only the caller's peer
remove_device owner or admin Ready Ownership enforced before delete
list_devices owner filter Ready Bench peers excluded
get_device_wg_config owner or admin Follow-up The guard exists. The cross-user negative test does not
create_site require_bench_access only when bench is set Follow-up A bench-less call skips the guard and creates an orphan Bench Site
get_user_context login, own session Ready Returns only the caller's identity and roles
get_code_server_credentials require_bench_access Ready Decrypted only after the ownership check
restart_code_server require_bench_access Ready Cross-user denied by test

Whitelisted controller methods

Method Guard Verdict Note
Bench Instance.enqueue_deploy document read permission, owner-limited Ready The framework enforces it on call
Bench Instance.enqueue_redeploy same Ready
Bench Instance.enqueue_stop same Ready
Bench Instance.enqueue_start same Ready
Database Server.setup_mariadb read permission, admin-only doctype Follow-up A state-changing operation should check write, and it has no authorization test
Database Server.start_mariadb same Follow-up As above
Database Server.stop_mariadb same Follow-up As above
Database Server.retry_setup same Follow-up As above
Database Server.get_logs read permission Ready A read, checked as a read. Add a test

Cross-cutting

Component Verdict Note
Permission model Ready Guest, wrong role and cross-user are all rejected. only_for raises for non-administrators
Secret handling Ready Decryption only behind an owner or admin guard. The database root password is never logged
ignore_permissions=True, 39 uses Ready Confined to enqueued and system flows. Ownership is tracked on owner and owner_user
SQL construction Ready Identifiers are hashed and SQL is base64-wrapped before shelling. Not injectable
Container isolation Not ready without a precondition Non-privileged, but a lab user holds in-container root. Ship only on a host with sysbox, userns-remap or a rootless daemon

What to fix, in order

  1. The container privilege boundary. Ship only on a host that closes it.
    This is a deployment precondition, not an app default.
  2. create_site with no bench. Make bench mandatory, or guard the empty
    case, so the endpoint cannot create an orphan Bench Site that bypasses
    the access check.
  3. Database Server state-changing methods. Move them to a write
    permission check and add authorization tests.
  4. get_benches secret exposure. Move SSH, admin and code-server password
    retrieval out of the bulk list payload into an on-demand per-bench call.
  5. get_device_wg_config test gap. Add an explicit cross-user negative
    test. The guard exists. The coverage does not.

Troubleshooting

Symptom Cause Fix
setup.sh --strict refuses to continue Neither userns-remap nor rootless is on Enable sysbox or userns-remap, then re-run
A bench container will not start after enabling userns-remap The remapped daemon cannot see the old storage Everything must be redeployed. Nothing was deleted
Volumes are not in the nightly dump Only the shared MariaDB is backed up Take your own copies of anything else
A user reached another user's bench This should not happen and is a security finding Capture the request and open an issue

Reference

Item Value
Readiness alpha
Strict setup bash apps/benchpress/setup.sh <site> --strict
Container capabilities NET_ADMIN, /dev/net/tun. Not privileged
Default runtime sysbox
Backed up the shared MariaDB, nightly, 7 dumps
Not backed up bench Docker volumes
Checklist last reviewed 2026-07-02
Last updated 4 hours ago
Was this helpful?
Thanks!