← All posts
August 15, 2026·4 min read·Guides

Deploying from GitHub to a VPS: A Step-by-Step Guide for Indie Hackers

Connect a repo once, then never think about the deploy step again. The full path from git push to a live app, including what happens when you push again.

DeployOS Team · Engineering

Most "deploy from GitHub" guides stop at the first successful deploy. The part that actually matters for a side project you're going to keep shipping to is what happens on push number two, and number fifty. This covers both.

The one-time setup

You need a VPS you can SSH into (a $5/month box is enough to start) and the DeployOS desktop app free tier works with no card.

Servers → Add Server, paste the host and credentials, test the connection, then run Bootstrap from the server card. That installs Docker, the firewall rules, and a reverse proxy in one pass the parts of "deploying to a VPS" that have nothing to do with your actual app and that you don't want to redo by hand every time you spin up a new box.

Connect GitHub once

From Settings, click Continue with GitHub. This is a device-authorization flow the same mechanism the gh CLI uses: DeployOS shows you a short code, opens github.com, and waits for you to approve it there. No personal access token to generate, copy, and eventually leak in a screenshot.

Once connected, every future New App form shows a repo picker instead of a bare URL field, and private repos work the same way public ones do.

First deploy

Applications → New App, pick your repo, name the app, and click Create, then Deploy. If your repo has a Dockerfile, DeployOS builds it as-is. If it doesn't, Railpack detects the framework and builds it for you Node, Python, Go, static sites, and more, no config required for the common case. Either way you get a live streamed log: build, start, attach to the network, publish the route, health check.

If your app lives in a subfolder of a monorepo rather than the repo root, set Root directory in Advanced options and DeployOS builds from there instead.

The part that matters after push number two

Flip Auto-deploy on from the app's Overview tab. From then on, DeployOS watches your branch in the background and redeploys automatically when it moves no git push followed by alt-tabbing to click Deploy by hand. Because a desktop app doesn't have a stable public URL for GitHub to send a webhook to, this works by polling instead: DeployOS periodically checks the branch and catches up the moment it's moved, including catching up in one sweep the next time you open the app if it was closed when you pushed.

If you cut releases deliberately rather than deploying every commit, turn on Track tags instead and it'll redeploy on new git tags (v1.2.0) rather than every push to main.

When a deploy goes wrong

Every successful Railpack build keeps the last 3 images cached, so rolling back to the previous version is instant no rebuild, no redeploying an old commit from scratch. And if the app just won't come up, the built-in Doctor runs a 9-step diagnostic (DNS, ports, proxy, container, health check, and more) and explains in plain English what's actually broken, rather than leaving you to grep logs at midnight.

Testing a branch before it hits main

If you want feedback on a pull request before merging it, DeployOS can spin up a preview environment per branch or PR on the same poll-based approach as auto-deploy a real, separate deployment you can promote to production once it looks right, or tear down without touching your main app.

What you end up with

A repo connected once, a server that redeploys itself on every push you care about, and rollback that doesn't require redoing a build. That's the actual deploy step for an indie project solved once, not per-project.

Your own deploy platform, on a $5 server.

Deploy from GitHub to your own server in one click free download, no account needed.

Download DeployOS