Skip to main content

Deploy your first app

This guide takes you from a fresh Vessl account to a running app on a server you own. The whole flow is: add a server → connect GitHub → create an app → deploy.

Before you begin

You'll need two things:

  1. A server (VPS) you control. Any Ubuntu server you can SSH into — from Hetzner, Contabo, DigitalOcean, Biznet Gio, etc. A small box (1–2 GB RAM) is enough to start. Vessl installs everything it needs (Docker, Traefik) for you.
  2. A GitHub repository with the app you want to deploy.

Sign in at dock.vessl.sh.

Step 1 — Add and provision a server

  1. Go to Servers → Add Server.
  2. Enter your server's IP address, SSH port (usually 22), and the SSH user. Add the SSH key Vessl shows you to the server (or let the wizard guide you).
  3. Vessl connects over SSH and provisions the box: installs Docker, sets up the Traefik gateway, configures the firewall, and hardens SSH.

When provisioning finishes the server shows Active. This is a one-time setup per server — all your apps can share it.

tip

You can reuse one server for many apps, or add several servers and deploy across them. Provisioning never touches your existing data.

Step 2 — Connect GitHub

So Vessl can pull your private code, connect the GitHub App on the account or organization that owns the repository:

  1. Go to Integrations → Connect GitHub.
  2. Pick the account/organization to install the Vessl app on. This must be the owner of your repo — if your repo is your-org/my-app, install it on your-org, not on a personal account that only has access to other repos.
  3. If the account you need isn't listed, click "Install Vessl on another account" and choose it on GitHub (you must be an admin of that org).
  4. Grant access to the repositories you'll deploy (or all repositories).
Org vs. account

A GitHub App installation is tied to the GitHub account that owns the repo — which can be a personal user or an organization. It is not tied to the email you used to sign in to Vessl. Always connect the account that owns the code.

Step 3 — Create an app

  1. Go to Projects → New Project (a project groups related apps).
  2. Inside the project, create an application and choose:
    • Repository and branch (e.g. main).
    • Server to deploy to (the one you provisioned in Step 1).
    • Build engine — Vessl auto-detects your stack and builds it (default Railpack, or Nixpacks). If your repo has a Dockerfile, Vessl uses that instead. You can switch engines anytime — see Build Engines.
  3. Optionally set:
    • Environment variables your app needs.
    • Start command, port (defaults to the framework's), and root directory (for monorepos).

Step 4 — Add a database (optional)

If your app needs a database, add a PostgreSQL, MySQL, or Redis add-on from the wizard or the app's add-ons tab. Vessl provisions it and injects the connection details into your app's environment — both Vessl-native variables and the common framework conventions (DATABASE_URL, DB_HOST, POSTGRES_*, etc.), so most frameworks connect on the first try.

Step 5 — Deploy

Hit Deploy. Vessl will:

  1. Clone your repo using the GitHub connection.
  2. Build the image (Railpack/Nixpacks, or your Dockerfile).
  3. Start a canary of the new version and health-check it.
  4. Swap traffic to the new version once it's healthy — your previous version keeps serving until then, so a failed deploy never takes you down.

Watch the live build & deploy logs stream in the deployment drawer. When it finishes, your app is reachable at its Vessl URL — a *.shipto.id subdomain assigned automatically. Add a custom domain later and Vessl issues a Let's Encrypt certificate automatically.

Step 6 — Auto-deploy on every push

Connected repos get auto-deploy by default: push to your deploy branch and Vessl ships the new commit automatically. You can toggle this per app.

Troubleshooting

Deploy fails at the git step (could not read Username / "Repository not found") Vessl can't authenticate to your repo. The GitHub App isn't installed on the repo's owning account, or its access was removed. Re-connect it under Integrations on the owner account (Step 2), then redeploy.

Health check fails with HTTP 500 (canary) Your app built and started, but returns an error on the health check — usually a missing environment variable, a database it can't reach, or a runtime crash on startup. Check the deployment logs for your app's own error; your previous version stays live in the meantime.

Build can't resolve your language/runtime version Make sure your lockfile and version files (package.json engines, composer.json require.php, .python-version, etc.) agree. The build engine reads them to pick the toolchain.


That's it — you've shipped your first app. Next, explore add-ons, custom domains, and environment management from your app's tabs in the dashboard.