CI/CD for VM Deployments: Pipelines, Secrets, Rollbacks & Releases

Serdar Tekin
Serdar Tekin
Co-Founder & CTO
Updated Oct 17, 202613 min read
Written for: Developers and small teams automating releases to Linux VMs
CI/CDDevOpsVM DeploymentGitHub ActionsRelease Automation
Last reviewed:
Guide
CI/CD for VM Deployments: Pipelines, Secrets, Rollbacks & Releases
rafftechnologies.com/learn
On this page

Key Takeaways

Build once, deploy versioned artifacts, separate deployment credentials from runtime secrets, protect production environments, verify health, and keep a tested rollback path.

Don't have a server yet? Deploy a Raff VM in 60 seconds.

CI/CD for VM deployments is the process of turning a code change into a repeatable build, test, release, verification, and rollback workflow for one or more virtual machines.

The useful boundary is simple:

Text
commit → CI checks → build versioned artifact/image → approve release → deploy to VM → restart/reload safely → verify health → keep rollback target

Raff Technologies VMs can be automated through normal Linux tooling, APIs, cloud-init, and infrastructure-as-code workflows. The CI/CD system should treat the VM as a controlled deployment target, not as a terminal that someone manually edits after every merge.

Start with a Raff Linux VM, then use a versioned deployment pipeline instead of manual production changes.

CI and CD solve different parts of VM delivery

Continuous integration (CI) validates the change before production.

Typical CI steps include:

  • checkout;
  • dependency installation;
  • linting;
  • unit/integration tests;
  • security or dependency checks;
  • build/package;
  • artifact publication.

Continuous delivery/deployment (CD) moves a validated release toward a target environment.

Typical CD steps include:

  • environment approval;
  • secret retrieval;
  • deployment;
  • service restart/reload;
  • migrations;
  • health checks;
  • rollback on failure.

A team can have CI without automated production deployment. That is often a sensible intermediate stage.

Build once, deploy the same artifact

The safest pipeline creates a versioned artifact once and promotes that exact artifact.

Examples:

  • tar/zip release bundle;
  • compiled binary;
  • Docker image;
  • framework build output.

Avoid rebuilding production independently after tests passed elsewhere. A second build can produce a different dependency graph or output.

A release identifier should map back to a commit SHA, tag, or immutable image digest.

Choose the deployment transport deliberately

Common VM deployment methods include:

MethodGood fitMain concern
SSH + rsync/scpSmall teams and simple artifactsCredential scope and imperative scripts
SSH + remote release scriptRepeatable VM release directoriesScript quality and rollback handling
Pull from artifact/object storageLarger artifactsAccess control and artifact retention
Pull container imageContainer workloadsRegistry and image lifecycle
Config-management/IaC workflowLarger fleetsMore operational tooling

SSH is not inherently wrong. A narrowly scoped, audited deployment credential can be appropriate for a small VM fleet.

The pipeline should not use a developer's personal SSH key.

Separate deployment credentials from runtime secrets

CI/CD needs credentials to reach the target environment, but those credentials should be scoped to deployment.

Examples:

  • deploy-only SSH key;
  • short-lived cloud credentials;
  • environment-scoped CI secret;
  • registry read token.

Runtime secrets such as database passwords or application API keys should not automatically become visible to every CI job.

Use environment-specific protection and approval controls for production credentials.

Use deployment environments and approvals

A practical workflow often separates:

Text
development → staging → production

Production can require:

  • branch/tag rules;
  • manual approval;
  • protected environment;
  • limited secret access;
  • restricted deployment actor.

This reduces the chance that every successful CI run automatically becomes a production release.

For environment architecture, see Staging vs Production vs Development Environments.

Keep VM state predictable

A pipeline should know where the application lives and how releases are activated.

One common layout:

Text
/opt/app/releases/<release-id>/ /opt/app/current -> /opt/app/releases/<release-id>/

The deploy job:

  1. uploads/extracts the new release;
  2. installs only required production dependencies if necessary;
  3. validates configuration;
  4. switches the active release;
  5. restarts or reloads the service;
  6. checks health;
  7. retains previous releases for rollback.

This is easier to recover than overwriting one directory in place.

Service restarts should be controlled

The release step should use the production supervisor:

  • systemctl restart or reload for systemd services;
  • PM2 reload/restart for Node.js where PM2 is used;
  • Docker Compose update/recreate for Compose workloads.

Do not deploy by killing arbitrary PIDs or starting a new process in an interactive shell.

The Application Deployment on a Linux VM guide owns the broader runtime architecture.

Database migrations need their own failure plan

Database migrations are one of the hardest parts of automated deployment.

A useful rule is to prefer backward-compatible changes when possible.

For example:

  1. add a new nullable column;
  2. deploy code that can use old/new state;
  3. backfill;
  4. switch reads/writes;
  5. remove old schema in a later release.

That is safer than a deployment that makes the previous application version immediately incompatible with the database.

A pipeline should not automatically run destructive migrations without a recovery plan.

Verify health after deployment

A successful SSH command is not a successful deployment.

The pipeline should verify:

  • process/service state;
  • local readiness endpoint;
  • public HTTPS endpoint;
  • expected version where possible;
  • basic critical-path request.

If health fails, stop promotion and roll back or leave the previous release active.

Rollback should be faster than debugging

Production incidents are not the right time to design rollback.

For artifact-based deployments, keep at least one previous known-good release.

For containers, keep the previous image digest/tag.

Rollback should ideally be:

Text
select previous release → switch active version → restart → verify

Database changes may make rollback more complicated, which is why migration compatibility matters.

Blue-green and rolling deployments are later-stage options

A single VM deployment usually has a short restart/reload window unless the runtime supports graceful reload.

As availability requirements increase, teams may use:

  • blue-green deployment;
  • rolling deployment across multiple VMs;
  • canary releases;
  • app-platform deployment primitives.

These require extra capacity and traffic-routing control.

Use Blue-Green vs Rolling Deployments for that decision rather than implementing complexity before the workload needs it.

GitHub-hosted vs self-hosted runners

Where CI runs is a separate decision from where the application runs.

A GitHub-hosted runner is simpler operationally. A self-hosted runner can provide custom software, network access, caching, or resource control but becomes infrastructure that the team must patch, isolate, monitor, and scale.

Use GitHub Actions Self-Hosted Runners vs GitHub-Hosted for that decision.

Do not place an untrusted public-repository workflow on a privileged self-hosted runner that can reach production secrets or networks.

CI/CD pipeline security checklist

For production VM deployment:

  • use least-privilege deploy credentials;
  • separate production secrets from general CI secrets;
  • protect deployment environments;
  • pin or review third-party actions/tools;
  • restrict who can modify deployment workflows;
  • avoid printing secrets;
  • keep build artifacts immutable/versioned;
  • log deployment identity and release ID;
  • rotate deployment credentials;
  • limit network access where practical.

What to automate first

A small team does not need to automate everything at once.

A useful progression is:

Stage 1

  • tests on push;
  • manual production deployment using a documented script.

Stage 2

  • build/version artifact in CI;
  • protected manual deployment job.

Stage 3

  • automated staging deploy;
  • production approval;
  • health verification;
  • one-command rollback.

Stage 4

  • multi-VM rolling/blue-green release if availability requirements justify it.

This sequence adds safety before sophistication.

For Linux server deployments, Raff Linux VMs are one self-managed compute option for the deployment target. Keep the same approvals, secret boundaries, health checks, and rollback process regardless of provider.

When an app platform is simpler

A VM pipeline is valuable when the team wants OS/runtime control.

An app platform may be simpler when you primarily want:

  • Git-connected builds;
  • environment-variable management;
  • managed release lifecycle;
  • automatic runtime restart;
  • platform-level deployment history;
  • less server administration.

Use Cloud VM vs App Platform to compare the responsibility models.

Use Raff VM for server-level control, or Raff Apps when managed application deployment fits the team better.

Frequently asked questions

What is CI/CD for a VPS?

It is an automated or semi-automated workflow that tests, builds, releases, verifies, and rolls back application versions deployed to a virtual private server or cloud VM.

Can GitHub Actions deploy directly to a VPS?

Yes. A common approach uses a protected deployment job with a scoped SSH credential, versioned artifact, remote release script, health check, and rollback path.

Should I run a self-hosted CI runner on the production VM?

Usually not. It increases the blast radius because workflow execution and production runtime share the same trust boundary. Separate runners or hosted runners are easier to isolate.

Should production deploy automatically after every merge?

Not necessarily. Small teams often benefit from automatic CI plus a protected production approval until the release process and test coverage are mature.

How do I roll back a VM deployment?

Keep the previous artifact or image, switch the active release back, restart the service, and verify health. Database compatibility must be considered separately.

Do I need Kubernetes for CI/CD?

No. CI/CD works with a single VM, multiple VMs, containers, Kubernetes, and app platforms. The deployment target changes the release mechanics, not the need for repeatable delivery.

Sources

Was this article helpful?
Serdar Tekin
Serdar Tekin
Co-Founder & CTO

Co-Founder & CTO at Raff, focused on cloud infrastructure, systems architecture, security, reliability, and production operations.

Put it into practice

Spin up a Raff server, follow the steps above on real infrastructure, and you are live. Linux or Windows, backed by a 14-day money-back guarantee.

Frequently asked questions

What is CI/CD for a VPS?
It is a workflow that tests, builds, releases, verifies, and rolls back application versions deployed to a VPS or cloud VM.
Can GitHub Actions deploy directly to a VPS?
Yes. Use a protected deployment job with a scoped SSH credential, versioned artifact, remote release script, health check, and rollback path.
Should I run a self-hosted CI runner on the production VM?
Usually not. It combines workflow execution and production runtime in the same trust boundary.
Should production deploy automatically after every merge?
Not necessarily. Automatic CI plus a protected production approval is often a safer starting point.
How do I roll back a VM deployment?
Keep the previous artifact or image, switch the active release back, restart the service, and verify health.
Do I need Kubernetes for CI/CD?
No. CI/CD works with single VMs, multi-VM systems, containers, Kubernetes, and app platforms.