Back to Blog
deploymentdockerdevopsci-cd

Push-to-Deploy from Git, No CI Server Required

I

InfraPilot Team

May 16, 2026

The CI tax on a simple deploy

Turning a git push into a running container usually means standing up a CI pipeline: a runner, a registry login, a build job, credentials for your server, and a deploy step that SSHes in and restarts things. For a large team with dozens of services, that machinery earns its keep. For a side project or a small product on one or two servers, it is a lot of YAML to maintain for something conceptually simple.

Push-to-deploy removes the middle layer. The server that runs your app also builds it. You point InfraPilot at a repository, and a deploy becomes one command or one click.

What actually happens on a deploy

When you deploy from git, InfraPilot does the work a CI pipeline would normally coordinate, in one place:

  1. Clones the repository (a branch or a specific commit) onto the server.
  2. Builds an image, either from your Dockerfile or automatically with Nixpacks if there is no Dockerfile.
  3. Starts the new container, wires it into Nginx, and provisions SSL for its domain.
  4. Keeps the previous image so you can roll back in one step.

There is no external runner and no registry round-trip. The build artifact never leaves the machine it runs on.

Setting it up

From the CLI, a first deploy looks like this:

infrapilot connect --url https://infra.example.com --api-key ip_live_...
infrapilot deploy my-app \
  --git-repo https://github.com/me/my-app \
  --git-branch main \
  --wait

The --wait flag streams the build and start logs to your terminal, so you see the same output a CI job would give you without leaving the shell. You can also trigger the same deploy from the dashboard by pasting a repository URL and picking a branch.

Nixpacks or your own Dockerfile

If your repository has a Dockerfile, InfraPilot uses it. If it does not, Nixpacks inspects the project, detects the language and framework, and produces an image for you. That covers most Node, Python, Go, Ruby, and PHP apps without you writing any build config. When your build gets specific enough that the automatic path stops fitting, add a Dockerfile and InfraPilot switches to it on the next deploy. You are never locked into the magic.

When you still want a real CI

Push-to-deploy is not a replacement for testing. If you run a test suite, linting, or security gates before shipping, keep them. Two setups work well:

  • Run your tests in GitHub Actions (or any CI), and on green, call an InfraPilot deploy webhook. CI decides whether to ship; InfraPilot does the shipping.
  • Use InfraPilot deploy gates to run your tests and a SAST scan on the server during the build, so a failing gate blocks the deploy. This keeps everything on one machine and fits well when you do not already have CI.

The point is not to delete CI everywhere. It is to stop paying for a pipeline when a git push is all the workflow you actually need.

Rolling back

Because the previous image is kept, a rollback does not rebuild anything:

infrapilot rollback my-app

The container reverts to its previous image and comes back up in seconds. No git revert, no rebuild, no waiting on a runner. That safety net is what makes deploying straight from a branch comfortable rather than nerve-racking.