Skip to content

Move your dev environment

Get an existing project — code, backing services, data and keys — onto a HostStack dev box. Everything here works today; where a path doesn't exist yet, the page says so.

The short version

Code comes in over git. Backing services are already in the box — you start them rather than move them. Data comes in over the network, pulled from somewhere the box can reach. Credentials go in through the dashboard or the terminal. There's no "upload my whole environment" button.

New to dev boxes? Start with AI dev environments.

Bring the code

Git is the transport. Push what you have locally to a remote, then point a box at it.

Where the repo livesHow to get it into a box
GitHub, connected to your teamPick it under GitHub repo when you create the box, or clone it from the terminal. No key needed: HTTPS clone and push go through your team's HostStack GitHub App, and git@github.com: remotes are rewritten to HTTPS so they use it too.
Any public http(s) URLPaste it under Clone URL. The box clones it into /workspace/<repo> on first boot. Only http(s) URLs are accepted there; ssh:// and git@ URLs have to be cloned from the terminal.
Private, on GitLab, Bitbucket, Codeberg or your own serverCreate a Blank box, add an SSH key and clone over SSH (below). The box's credential helper covers GitHub only, so an HTTPS clone from those hosts asks for credentials it can't supply.

In the box's terminal:

bash
# ~/.ssh points at /workspace/.ssh, so the key survives restarts.
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ''
cat ~/.ssh/id_ed25519.pub     # add this as a deploy key on the host

ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
git clone git@gitlab.com:acme/my-app.git /workspace/my-app

Generating the key in the box means the private half never leaves it. To use a key you already have instead, write it to ~/.ssh/id_ed25519 and chmod 600 it — there's no dashboard form for SSH keys.

Bring the backing services

You don't move these: the box already has them, as native processes rather than containers. There's no Docker daemon in a box, so a docker-compose.yml full of postgres, redis and friends is replaced, not run. Run it anyway — the box reads your compose file and tells you what to start instead:

bash
docker compose up        # prints which of YOUR services the box covers

dev-services up                 # postgres :5432 · redis :6379 · meilisearch :7700
dev-services up mysql mongodb   # MariaDB :3306 · MongoDB :27017, only when asked for
dev-services status

They listen on localhost only, and none of them needs a password:

Compose imageStart it withConnection URL
postgres, postgis, pgvector, timescaledbdev-services uppostgresql://dev@localhost:5432/dev
redis, valkey, redis-stackdev-services upredis://localhost:6379
meilisearchdev-services uphttp://localhost:7700 (no master key)
mysql, mariadb, perconadev-services up mysqlmysql://dev@127.0.0.1:3306/<db>
mongo, mongodbdev-services up mongodbmongodb://127.0.0.1:27017

A Postgres image's extensions (PostGIS, pgvector, TimescaleDB) are not part of the box's Postgres — the compose image maps to plain Postgres 17.

Your app's .env probably names a database and role that don't exist yet — postgres://postgres:postgres@localhost:5432/myapp is the classic. Create them rather than editing the config:

bash
dev-services createdb myapp            # database "myapp", owned by "dev"
dev-services createdb myapp postgres   # …or by a "postgres" role, created if missing

Anything with no in-box equivalent — Kafka, Elasticsearch, a vendor's sidecar — has to run as a HostStack service or point at a remote instance; the docker message lists which of your compose services those are. The engines keep their data on /workspace and come back by themselves after a restart.

Bring the data

The box can reach out, but nothing can reach in: there's no SSH server, so rsync, scp and sftp into a box don't work. Every import is a pull, run from the box's terminal.

Small files

Up to 16 MB each: drag, paste or Attach in the Terminal. The file lands in /workspace/.uploads/ and its path is pasted at your cursor.

Anything larger

Put it somewhere the box can fetch — object storage with a signed URL, a release asset, a server you own — and pull it with curl, wget, git or an outbound scp: scp you@your-server:/backups/db.dump /workspace/ works, from the box toward a host that accepts SSH.

A live database you can reach

Skip the file and stream it straight in.

dev-services up
dev-services createdb myapp

# Stream from a server you can reach…
pg_dump "postgresql://user:pw@old-host:5432/myapp" | psql -d myapp

# …or restore a dump file you pulled in
pg_restore -d myapp /workspace/myapp.dump

If the data is the point — a staging dataset you want backed up and restorable — put it in a managed database instead of the box, and link it so its URL is injected. Managed databases are backed up daily and restorable from the dashboard; /workspace is not.

bash
hoststack db create --project prj_... --name app-db --engine postgres
hoststack db link db_... --service svc_... --alias APP
hoststack deploy trigger svc_...     # a link applies on the next deploy

# Then, in the box, DATABASE_URL is set:
psql "$DATABASE_URL" -c 'select 1'

Bring your credentials

Coding-agent logins

Save one per agent under Settings → Coding agents; it's stored encrypted on your account and seeded into every box, so you never do it per box. Already signed in inside a box? Save it from Development → All dev boxes → Shared setup → Agent logins with Capture.

API keys

ANTHROPIC_API_KEY, OPENAI_API_KEY and anything your app needs: set them in the box under Settings → Variables. The HostStack MCP key is provisioned for you.

SSH keys

No dashboard form: write them into /workspace/.ssh/ from the terminal, as above.

Git identity

A box starts with the name and email on your HostStack account as the commit author. Change it under Development → All dev boxes → Shared setup → Source control.

Bring your shell setup

Only /workspace persists. The rest of the filesystem — including $HOME and ~/.bashrc — is rebuilt from the image whenever the container is recreated: on power down and resume, a disk resize or an image update. So keep dotfiles on the volume and source them:

bash
git clone https://github.com/you/dotfiles /workspace/.dotfiles

# For this shell, and every new one until the next restart:
echo '. /workspace/.dotfiles/bashrc' >> ~/.bashrc
. /workspace/.dotfiles/bashrc

Global tools do persist, because the image points them at the volume:

  • bun add -g installs under /workspace/.bun, and pip install --user under /workspace/.local — both on PATH. npm install -g does not persist; use bun add -g.
  • Runtimes added with dev-runtime add land in /workspace/.mise.
  • node_modules, vendor and the like are in your repo, so they're on the volume already.
  • apt-get install can't work in a box. If the image is missing a system package you need, ask us to add it.

A one-line setup script in your repo is still the reliable answer for a box you might recreate.

First-run checklist

  1. See what's running

    hoststack-status shows the engines, the dev URL and the image build.

  2. Start the databases your app uses

    dev-services up, plus mysql or mongodb if your stack needs them, then dev-services createdb myapp to match your .env.

  3. Add a runtime, if yours isn't built in

    Node, Bun, Python and PHP are there already. For anything else, dev-runtime add go (or java, ruby, rust, erlang, elixir, dotnet).

  4. Install and start the app on port 3000

    cd /workspace/my-app && bun install && bun run dev — PORT=3000 and HOST=0.0.0.0 are already set.

  5. Open the dev URL

    Click Open app in the box's header. A "No app is listening on port 3000 yet" page (HTTP 503) means nothing is bound to port 3000; an invalid-host error means your framework needs .hoststack.dev in its allowed hosts — see Serve your app on the dev URL.

What has no path yet

These are real gaps, listed so you can plan around them rather than look for them:

No workspace import or restore

You can't upload a tarball of an existing environment, and there's no snapshot of a box's volume to restore from. Move code through git and data through a database.

No inbound SSH

So no rsync or scp into a box. Every transfer starts from inside it.

Uploads are small

The terminal upload is 16 MB per file — for screenshots and logs, not archives.

No dotfile seeding

See above.

GitHub is the only repo picker

GitLab, Bitbucket and Codeberg aren't sources in the create form, though HostStack deploys from them. Use a public clone URL, or a blank box and an SSH clone.

Companions are always new

The create form only makes fresh companion databases. Link an existing one afterwards with hoststack db link.

The CLI can't open a box

There's no dev shell, dev exec or dev open. Use the dashboard Terminal.

No team switcher in the CLI

There's no hoststack teams command. If you're on more than one team, set HOSTSTACK_TEAM_ID to choose which one CLI commands act on.

No MongoDB dump tools

mongodump and mongorestore aren't in the image.

Next steps