How to Manage Multiple Environments (Dev/Staging/Prod) on a VPS

Running distinct development, staging, and production environments prevents changes from reaching real users untested. This guide covers structuring multiple environments practically, whether on separate VPS instances or a shared one.

Why Separate Environments Matter

  • Test changes without risk to production data or users
  • Catch environment-specific bugs before they reach production
  • Give team members a safe space to experiment

Approach 1 — Separate VPS Per Environment (Recommended for Production Systems)

EnvironmentPurposeTypical Specs
DevelopmentActive feature work, frequent changesSmall, can be shared/ephemeral
StagingPre-production testing, mirrors prod closelySimilar to production, possibly smaller
ProductionLive, serving real usersFull production specs

Approach 2 — Multiple Environments on One VPS (Budget-Conscious)

Using different ports/subdomains and Docker isolation:

staging.yourdomain.com → :3001
yourdomain.com → :3000 (production)

Acceptable for smaller projects, but be aware that a resource-heavy staging test could theoretically impact production performance if truly co-located — weigh this trade-off against cost savings.

Environment-Specific Configuration

Use separate .env files per environment (see How to Manage Environment Variables and Secrets on a VPS):

.env.development
.env.staging
.env.production

Environment-Specific Database Isolation

Never let staging and production share a database — always fully separate databases, even if they run on the same database server:

CREATE DATABASE myapp_staging;
CREATE DATABASE myapp_production;

Restricting Access to Non-Production Environments

Staging and development environments shouldn't be publicly indexed or easily discoverable:

location / {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

See VPS Hosting for Developers: Setting Up a Dev/Staging Environment for full detail on this pattern.

Keeping Staging Representative of Production

Periodically refresh staging's database from a sanitized production backup, ensuring bugs that only appear with realistic data volume/shape are actually caught before reaching production.

Deployment Pipeline Across Environments

on:
  push:
    branches:
      - develop   # deploys to staging
      - main      # deploys to production

Configure your CI/CD pipeline (see How to Build a Simple CI/CD Pipeline with GitHub Actions) to deploy different branches to different environments automatically.

Promoting Code Between Environments

A typical flow: feature branches merge to develop (auto-deploys to staging) → after verification, develop merges to main (auto-deploys to production) — ensuring nothing reaches production without first passing through staging.

Environment Naming and Labeling

Make it visually obvious which environment someone is looking at — a banner, different color scheme, or clear labeling in staging/dev environments prevents costly mistakes (like someone believing they're testing safely in staging when actually in production).

Common Errors

Accidentally testing against production database — almost always caused by insufficiently distinct environment configuration; ensure connection strings are environment-specific and clearly different, ideally with a visual safeguard in the application itself.

Staging environment publicly indexed by search engines — add a noindex meta tag and restrict access as shown above.

Best Practices

  • Fully isolate databases between environments, always
  • Restrict access to non-production environments
  • Keep staging reasonably representative of production for meaningful testing

Continue Reading

Browse more articles in DevOps & CI/CD.

  • dev staging production, environment management, deployment pipeline, multiple environments
  • 0 brukere syntes dette svaret var til hjelp
Var dette svaret til hjelp?

Relaterte artikler

How to Set Up a Self-Hosted GitHub Actions Runner on a VPS

GitHub Actions' hosted runners work well for most projects, but a self-hosted runner on your own...

How to Deploy Automatically on Git Push (Webhook-Based Deployment)

Automating deployment whenever you push to a specific branch removes the manual "SSH in and pull"...

How to Set Up Blue-Green Deployment on a VPS

Blue-green deployment runs two identical production environments — only one live at a time...

How to Use Ansible for Server Configuration Management

Ansible automates server configuration through simple, human-readable YAML files — letting...

Infrastructure as Code Basics: Managing VPS Config with Terraform

Terraform lets you define infrastructure (VPS instances, networks, DNS records) as code, applied...