Guides

Box: a dev environment in the browser

Install a Box to get VS Code in the browser on your own server, with the runtimes you pick, git and build tools, your code on persistent volumes, and a domain for any dev server in one step.

A Box is a development environment you install from the Apps catalog: VS Code in the browser (code-server, the official image from Coder), the runtimes you pick (Node.js, Bun, Python, Go), git, curl and build tools, and your code on persistent volumes. It runs on your server as an ordinary one-click app, so logs, backups, domains and redeploys work as for any project.

What you need first

  • A server with at least 2 GB of memory. The install wizard checks it. To cap what the Box and your builds can use, set limits under Resources like for any app.
  • A domain for the editor, so VS Code opens over HTTPS. A free subdomain works if your panel offers one.

Create a Box

Open the app

Click New Project in the sidebar, stay on the Apps tab, and choose Box (search for box or vscode).

Pick the runtimes

Runtimes lists Node.js (LTS), Bun, Python 3 and Go. Node.js and Python are selected by default. git, curl and build tools (gcc, make, pkg-config) are always there, whatever you pick.

Optionally, a repository

Git repository to clone takes a public https:// URL, and Branch a branch name (empty means the repository's default branch). The Box clones it once, on its first start. See Clone a repository for private repositories.

Choose the editor's address and install

Give the VS Code endpoint a domain, then install. The first deploy builds the Box image (the code-server image plus build tools and the start script) and starts the editor.

Sign in

Open the project. The Overview shows the connection details:

  • VS Code: the editor's address. Open opens it in a new tab.
  • Password: generated at install, 24 letters and digits. Reveal or copy it and sign in.

The editor opens ~/workspace. Where things live:

PathVolumeWhat is there
/home/coder/workspacebox_workspaceYour code, and the cloned repository.
/home/coderbox_homeEverything else in your home directory: runtimes, VS Code extensions and settings, shell history.

Both volumes survive restarts and redeploys, and you can back them up like any other volume (Volumes and volume backups).

Runtimes

The Box installs the runtimes with mise into the home volume, in the background on the first start. The editor is usable right away; a runtime appears in new terminals when its install finishes.

RuntimeSettingDefault version
Node.jsBOX_NODE_VERSION24.21.0 (LTS)
BunBOX_BUN_VERSION1.4.2
PythonBOX_PYTHON_VERSION3.14.7
GoBOX_GO_VERSION1.27.1
  • Progress: the service logs show lines starting with [box], and cat ~/.local/share/box/status in the terminal prints installing, ready or failed. A runtime that failed is retried on the next restart.
  • Idempotent: every start runs the same install, and a runtime that is already installed is left alone.
  • Add one later: open Configuration, then App settings, change Runtimes, press Save changes and Apply now. The Box restarts and installs the new one.
  • Pin other versions: the version fields are under the advanced settings. An exact version keeps a Box reproducible; a major version (24) or lts makes mise install the newest match.
  • Remove one: unticking a runtime does not delete it. Run mise unuse -g node (for example) in the terminal to drop it.
  • Other tools: mise is always installed, so mise use -g java@21 or mise use -g rust adds more.

Every download is HTTPS only. The mise archive is checked against its published SHA-256 before it runs, and mise checks the checksums of the runtimes it downloads. Debian packages for the build tools are installed over HTTPS when the image is built.

Clone a repository

A public repository set in Git repository to clone is cloned into ~/workspace/<name> on the first start, once. Changing the URL later clones the new repository on the next restart, next to the first one; a folder that already exists is never overwritten.

The URL must be a plain https:// address, with no user name or token in it. Synq does not hand its own Git credentials (GitHub App, tokens, deploy keys) to a Box: anyone with the Box password has a shell in the container and could read them. For a private repository, clone it from the Box's terminal after signing in to your Git host there, for example:

  • over HTTPS, with a fine-grained, read-only token that git asks for when you run git clone;
  • over SSH, with a key you create in the Box (ssh-keygen -t ed25519) and add to the repository as a deploy key.

The Box panel

The Box panel is on the project's Overview, under the connection details, and on the service's own Overview (Apps & Services, then the box service), where it also has Open VS Code and Show password. It shows:

  • a reminder that the password opens a shell (see Security);
  • the runtimes the Box installs and the repository it clones;
  • Regenerate password;
  • Exposed ports, with a form to expose another one.

Regenerate the password

Press Regenerate password in the Box panel and confirm. Synq generates a new password, saves it as the service's encrypted PASSWORD variable and restarts the editor with it. Everyone signed in is signed out and the old password stops working; files and runtimes are kept. The new password is shown once in the panel, and the connection details show it from then on.

If the Box cannot restart (a deployment is running, for example), the old password is put back and still works. A Box that has not been deployed yet just saves the new password for its first start.

Expose a port

Run a dev server in the Box's terminal, then give it a domain:

Listen on all interfaces

The dev server must listen on 0.0.0.0, not only on localhost. For example npm run dev -- --host 0.0.0.0 for Vite, or python -m http.server 8000 --bind 0.0.0.0.

Enter the port

In the Box panel, type the port in Container port and press Expose a port. Port 8080 is the editor itself and is refused.

Choose the address

The service's Domains tab opens with the Add route form filled in for that port. Pick a free subdomain or your own domain and press Add, as in Custom domains. The Box keeps running: the route is applied like any other domain, and the port is then listed under Exposed ports.

To stop exposing a port, remove its route on the service's Domains tab.

An exposed port is public

Anyone with the address reaches the dev server, without the Box password. For a private preview, open /proxy/3000/ on the editor's address instead (replace 3000 with your port): code-server forwards it to the port and it stays behind the password. /proxy/ strips the prefix, so the dev server sees /; a dev server configured with that path as its base (for example Vite's --base) uses /absproxy/3000/, which keeps it.

Security

  • The password is a shell. Anyone who has it can run commands in the container and read every file in it, including the workspace. Share it only with people you trust, and regenerate it when someone should lose access. code-server limits sign-in attempts (2 a minute, 12 an hour).
  • No root. The editor runs as the coder user (uid 1000). The Box image removes code-server's password-less sudo, so the editor user can't become root. That is also why system packages can't be added from inside; use mise, npm, pip or go for tools.
  • No Docker access. The Docker socket is not mounted and the container is not privileged, so the Box cannot start containers or reach the host.
  • Exposed ports are public. See Expose a port.

From the API

services.getBox returns the editor's address, the exposed ports, the runtimes and the repository (never the password), and services.regenerateBoxPassword sets a new password, restarts the editor and returns the password once. Exposing a port is an ordinary route: add an entry to the service's publicEndpoints with services.update. See Services.

Limits

  • Private repositories are not cloned automatically; see Clone a repository.
  • There is no root in the Box, so system packages beyond the build tools can't be installed.
  • A runtime removed from the settings stays installed until you run mise unuse -g <name>.
  • On Synq Cloud, a regenerated password is saved and takes effect on the next redeploy, because the running container can't be restarted with a new environment in place. The old password works until then.

On this page