CI/CD turns “it works on my machine” into an automated, repeatable path from a code change to production. Every push is built and tested automatically; every successful build can be deployed with confidence — often without anyone logging into a server.

The terms

  • Continuous Integration (CI) — every change is merged frequently into a shared branch and automatically built and tested. Problems surface within minutes, not at release time.
  • Continuous Delivery — every change that passes CI is ready to deploy; a human clicks the button for production.
  • Continuous Deployment — every change that passes is deployed to production automatically.

Most small teams aim for continuous delivery: automatic deploys to staging, one click (or merge) for production.

A typical pipeline

push / pull request
   │
   ▼
1. Checkout & install dependencies (cached)
2. Lint & static checks (formatting, types, security scanning)
3. Unit tests
4. Build artifact (bundle, binary, Docker image)
5. Integration / end-to-end tests
6. Publish artifact (registry, artifact store)
   │
   ▼ (main branch)
7. Deploy to staging → smoke tests
8. Deploy to production (manual approval or automatic)
9. Post-deploy checks, notifications

Build once, deploy many: the same artifact (e.g. a Docker image tagged with the commit SHA) moves from staging to production. Rebuilding for each environment risks shipping something you didn’t test.

Tools

Tool Hosting Notes
GitHub Actions GitHub, self-hosted runners Huge marketplace of actions
GitLab CI/CD GitLab.com or self-hosted Integrated with GitLab
Gitea / Forgejo Actions Self-hosted GitHub Actions–compatible syntax
Jenkins Self-hosted Extremely flexible, more maintenance
Woodpecker / Drone Self-hosted Lightweight, container-based

Guides: GitHub Actions deploy to VPS, GitLab CI over SSH, Jenkins, Gitea Actions, Woodpecker CI.

Deploying to a VPS

Common patterns, from simplest to most robust:

  1. SSH + git pull — the pipeline SSHes in and runs a deploy script. Simple; the server needs build tools.
  2. Build in CI, rsync artifacts — the server only receives built files. See deploying a React app.
  3. Build a Docker image, push to a registry, pull on the server — consistent environments; easy rollbacks by image tag.
  4. GitOps — the pipeline updates manifests in Git; an agent in the cluster applies them. See Argo CD.

Make deployments atomic and reversible: release directories with symlink switches, image tags per commit, and a documented rollback command. See deployment strategies and zero-downtime Node.js deploys.

Secrets in pipelines

  • Store credentials in the CI system’s secret store, scoped to protected branches/environments.
  • Use dedicated, least-privilege deploy users and keys — see sudo for automation.
  • Never print secrets in logs; mask them.
  • Verify SSH host keys (known_hosts) instead of disabling checks.

Keeping pipelines fast

Slow pipelines get skipped. Keep feedback under ~10 minutes:

  • Cache dependencies (npm, pip, Composer, Go modules) and Docker layers — see Docker build cache.
  • Run jobs in parallel (lint, unit tests, build).
  • Only run what changed in monorepos (path filters).
  • Use faster runners: a self-hosted runner on a VPS with warm caches often beats shared cloud runners. See self-hosted GitHub runner and GitLab Runner.
  • Fail fast: cheap checks first.

Good practices

  • Protect the main branch: required checks must pass before merging.
  • Small, frequent changes — easier to test, review and roll back.
  • Tests you trust: flaky tests erode confidence in the whole pipeline.
  • Deploy outside peak hours until you trust the process; then deploy any time.
  • Monitor after deploys and alert on errors — see Uptime Kuma.

Getting started

  1. Add a CI workflow that installs dependencies and runs tests on every push.
  2. Add a build step that produces an artifact.
  3. Add a manual deploy job for staging, then production.
  4. Automate staging deploys; keep a manual gate for production until you’re comfortable.

A small KVM VPS makes a capable self-hosted runner, keeping build caches warm and builds fast.

  • CI/CD
  • DevOps
  • Deployment