Skip to content

Hosting

Your host. Your cloud.

One container per workspace on your server. Each branch deploys to where you said it runs.

Runs on your server. Deploys to the cloud you already have.

One container per workspace, on a host you control. Connect AWS and switch on what it may build, with a preflight before anything is switched on. Or point it at a VPS you already rent.

Previews stay on DevBench compute, free and throwaway. Test, staging and production go wherever you point each branch, and a workspace can mix them: staging on a rented box, production in an AWS account.

Where should it run?

DevBench compute

Previews, free and throwaway.

The container preview, as a named environment. Free, and open to everybody, because it is the test loop the whole team works in.

What you need

  • The workspace's repos. Deploy a frontend and the rest of its App comes up too.

What DevBench does

  • Runs the workspace's whole repo set as containers you can click through.
  • The shared database and each repo's seed variables.
  • Replaced by the next deploy, stopped when idle, reaching nobody.

Who may press it

  • Anyone can deploy a preview.

  • An agent may deploy a preview and never an environment: devbench deploy in a box never names one.

devbench
  • $ devbench deploy

    Deploy this workspace's repos as live test containers. The same as the Deploy button.

What runs on your host.

DevBench is a control plane you run yourself, on a machine with Docker. Your code is cloned onto that host and leaves it only when you deploy it somewhere.

Outside

Your host · A machine with Docker

Leaves the host

Control plane · Django REST API

A Django REST API with token auth for the web, desktop and mobile clients, and Postgres behind it. Served over ASGI with Redis, so the chat's WebSockets are answered across workers; on WSGI everything still works, and every client quietly falls back to polling.

Memory is the constraint

Idle boxes are the largest single source of memory on the host, which is why a workspace outside the board's active column is stopped after half an hour of quiet, and why previews stop when idle.

No self-serve

The first organization is seeded by its owner; everyone after joins with an invite code. There is no sign-up path that creates an organization.

Model-agnostic

The agent login every workspace shares is one setting in the organization. Which model answers is your choice, and nothing else on the host depends on it.

A preview for every branch. Then the real thing.

The agent brings the whole repo set up as containers you can click through, with the shared database and each repo's seed variables. Throwaway, free, reaching nobody: replaced by the next deploy, stopped when idle.

Under it, one row per branch says where that branch really runs. Each repo gets a step timeline with elapsed times, and the log pane follows the build.

  • Throwaway
  • Free
  • Reaching nobody
  • Stopped when idle

Refused before it exists. Updated, not recreated. Stopped, not deleted.

The Deploy tab has two halves. Preview runs the workspace's whole repo set as containers on DevBench compute. Environments is one row per branch, saying where that branch actually runs.

Where a row can point

Deployed elsewhere, by default

DevBench does not deploy this. The row is the team's record of an environment somebody else's pipeline builds; its URL, login and notes are editable by anyone on the workspace.

DevBench compute

The container preview, as a named environment. The shared database and each repo's seed variables, replaced by the next deploy, stopped when idle, reaching nobody. Free, and open to everybody, because it is the test loop the whole team works in.

AWS or a provider

A static site in S3 behind CloudFront, an EC2 or Lightsail instance, a machine of your own over SSH. Staging on a rented box and production in an AWS account is two rows with different targets.

Three properties, each a failure that was easy to build instead

  1. Refusals happen before anything is created.

    A disconnected account, a capability nobody switched on, or an IAM policy missing a permission comes back as a sentence in the response to the button, not as a deployment that fails ninety seconds after you have walked away.

  2. A redeploy is an update.

    DevBench records what it made, bucket and prefix, distribution id, instance id, and the next deploy overwrites that site and reuses that distribution and that instance. Recreating a distribution means a new domain and a quarter-hour of propagation; recreating an instance doubles the bill and leaves the old one serving the old code.

  3. Stop does not delete.

    For a published site, a box you own or an instance, Stop marks the deployment stopped and touches nothing. A button in a list is not consent to take a production site off the internet.

An unknown target raises. It never falls back to DevBench compute; a deployment landing somewhere other than where its environment says is the thing this design removes. A failed deploy to an environment reaches the owners' Inbox, throttled per environment. A failed preview does not; you are looking at it.

DevBench does not guess how to restart your app.

Deploying to a machine, over SSH or onto an instance DevBench just created, runs an update script your team writes, on the environment. An environment without one is refused by name rather than guessed at.

DevBench did not build that box and cannot know whether the app is behind systemd, pm2, docker compose or a Makefile, and every wrong guess restarts something in production.

an environment's update script
set -euo pipefail                       # DevBench adds this line
cd /srv/app
git fetch origin "$DEVBENCH_BRANCH"
git checkout -q "$DEVBENCH_BRANCH"
git pull --ff-only
npm ci && npm run build
sudo systemctl restart app             # yours: systemd, pm2, compose, make…

What it brings that an SSH client does not

  • The host key is pinned. The first connection records the fingerprint; a changed one is refused.

  • The script runs under set -euo pipefail, so a failed git pull stops rather than restarting a service with the old code still on disk.

  • It is fed to bash on stdin rather than quoted into a command line.

  • $DEVBENCH_BRANCH, $DEVBENCH_REPO, $DEVBENCH_REPO_URL, $DEVBENCH_ENVIRONMENT, $DEVBENCH_PROJECT and $DEVBENCH_DEPLOYMENT are exported, so one script serves every environment.

AWS

Connect the account. Switch on what it may build. Preflight first.

Credentials say who DevBench is in an account; feature toggles say what it may build there. The two halves are kept deliberately separate, and a connection belongs to the organization, not to the person who pasted it.

What it may build

S3 static site
One bucket per site, behind CloudFront.
S3 shared site
Several sites pooled in one bucket, a key prefix and a CloudFront distribution each.
Lightsail
Fixed-price instances and managed databases.
RDS
Postgres, MySQL and MariaDB run by AWS, with backups and optional multi-AZ.
EC2
Plain VMs: a Django app under gunicorn, a Node server, anything wanting a box.
Elastic Beanstalk
Load-balanced, auto-scaling environments AWS keeps healthy.

Credentials can be a plain IAM user's keys, or keys whose only right is to assume a role in the target account, the usual arrangement when one management account fans out to several. A capability whose required settings are still blank cannot be switched on at all.

Switching a capability on checks the account first

  1. 1

    IAM simulates the required actions

    That capability's declared actions are evaluated against the calling principal's actual policies, performing none of them.

  2. 2

    A probe, if simulation is not allowed

    Normal for a tightly scoped deploy user. A read-only probe runs instead and the result is recorded as a warning, never as ok. “The service answered” is a weaker claim than “the account is allowed”.

  3. 3

    A denial names the missing actions

    The page turns them into a pasteable IAM policy for whoever has the access, who is usually not the person looking at the screen.

Re-checked on a schedule

A failure marks the account and reaches the owners' Inbox, throttled per account, with the throttle cleared the moment it recovers. Keys that start authenticating as a different AWS account bypass the throttle entirely. An account whose last check failed contributes no deploy targets, so a picker never offers something that cannot be reached.

Resources

Resources lists what already exists in the account. Linking a resource to the part of a repo it serves is how DevBench knows this Amplify app serves web/ and that EC2 box houses services/api.

devbench cloud
  • $ devbench cloud can

    What this workspace may do in the cloud, and how far.

  • $ devbench cloud list

    Deployments that already exist in the organization's cloud accounts.

  • $ devbench cloud link <id> <repo>[/<dir>]

    Record which part a resource serves.

  • $ devbench cloud call <service> <Operation>

    One AWS call through DevBench. No credentials are ever given to a box.

A VPS you already rent, and the accounts machines come from.

A machine at Hetzner or Contabo with two cores and 4 GB costs a few euros a month, less than an EC2 instance a third its size. DevBench deploys onto it the same way it deploys onto an instance it created.

  • SSH

    Any machine you can reach over SSH

    Connecting asks forHost, port, user, a key or a password

  • Hetzner Cloud

    The account machines come from

    Connecting asks forA workspace API token

  • DigitalOcean

    The account machines come from

    Connecting asks forA personal access token

  • Vultr

    The account machines come from

    Connecting asks forAn API key

  • Supabase

    A Supabase workspace

    Connecting asks forWorkspace URL, service role key, anon key

  • MongoDB

    Atlas or your own mongod

    Connecting asks forA connection string

A capability is “is the software actually installed”

Verifying an SSH connection opens a session and reads the distribution, kernel, CPU count, memory and free disk. Each capability is checked by running the tool and asking for its version.

Every capability also needs systemd, because that is how services are installed and restarted. A missing package refuses the toggle and returns what is absent with the command that installs it, which the app turns into a shell script: the counterpart of the generated IAM policy, for the same reason. Whoever has root on the box is usually not the person looking at the screen.

capabilities
docker
A Docker Engine this user can talk to
nodejs
Node and npm
python_app
Python 3 and the venv module, a separate package on Debian
static_site
nginx, and certbot for automatic HTTPS
postgres
The Postgres client, and a server answering locally

The SSH provider takes a machine that already exists. The vendor-API providers take the account machines come from, which is what makes choosing a size and a region at deploy time possible. Every connection is re-verified on a schedule, and a failure reaches the owners.

Apps

The repos that make up one application, and how each part runs.

An App is the set of repositories that make up one application. It is the unit a person picks when creating a workspace, and the unit a deployment resolves: deploy a frontend and the rest of its App comes up too. A repo belongs to at most one App.

A recipe per part

Each part of an App, a repo or a directory inside a monorepo, carries its own recipe: the install, build and start commands, a port, what kind of thing it is (frontend, backend, worker), a Dockerfile path or a static output directory, and which secrets it needs. Write these by hand, or have DevBench read the repo in a throwaway box and propose them. Nothing is written until you apply the proposal.

Databases and seed SQL

Apps also own databases and their seed SQL, the data a preview boots with. The seed editor loads the stored SQL before showing you a box, because an empty box saved over a real dump is unrecoverable. A schema change belongs in a migration, not in the seed.

devbench deploy
  • $ devbench deploy

    Deploy this workspace's repos as live test containers. The same as the Deploy button.

  • $ devbench deploy config list

    Every deployable part of this workspace and where it goes.

  • $ devbench deploy config generate

    Read a repo in a throwaway box and propose how each part builds and runs.

  • $ devbench deploy config apply <id>

    Turn a proposal into real deploy configs.

  • $ devbench deploy config set <repo>[/<dir>] --start … --build …

    Create or edit one part's recipe.

  • $ devbench deploy seed set --file <path>

    Replace a deploy database's seed. For schema changes, add a migration instead.

Invite only

We set your organization up with you.

Tell us about your team and the repositories you would bring; we reply within a working day.