How to Version Control Your Server Configuration

Treating server configuration as code — tracked in Git, reviewed, and deployed like any application — brings the same reliability benefits to infrastructure that version control brings to software.

Why Version Control Configuration

  • Full history of every change, who made it, and why
  • Ability to review changes before applying (pull requests)
  • Rollback capability if a configuration change causes problems
  • Documentation by nature — the repository itself describes the intended server state

What to Version Control

CategoryExamples
Web server configsNginx/Apache virtual host files
Application deployment configsdocker-compose.yml, systemd unit files
Infrastructure definitionsTerraform files, Ansible playbooks, cloud-init templates
CI/CD pipeline definitionsGitHub Actions workflows, Jenkinsfiles

What NOT to Commit Directly

  • Secrets, passwords, API keys — use environment variables or a secrets manager instead (see How to Manage Environment Variables and Secrets on a VPS)
  • SSL private keys
  • Anything containing customer/personal data

Setting Up a Basic Infrastructure Repository

mkdir infrastructure && cd infrastructure
git init
infrastructure/
├── nginx/
│   ├── sites/
│   │   └── myapp.conf
├── systemd/
│   └── myapp.service
├── ansible/
│   ├── inventory.ini
│   └── playbook.yml
└── README.md

Deploying Configuration Changes from the Repository

Rather than editing config files directly on the server, edit them in the repository, then deploy:

scp nginx/sites/myapp.conf deploy@YOUR_SERVER_IP:/tmp/
ssh deploy@YOUR_SERVER_IP "sudo cp /tmp/myapp.conf /etc/nginx/sites-available/ && sudo nginx -t && sudo systemctl reload nginx"

Or, more robustly, use Ansible to apply changes consistently (see How to Use Ansible for Server Configuration Management).

Using Pull Requests for Configuration Changes

Even for infrastructure, requiring a pull request/review before merging configuration changes catches mistakes before they reach a live server — the same discipline applied to application code.

Detecting Configuration Drift

Over time, manual fixes made directly on a server (during an incident, for example) can cause the live server to diverge from what's in version control. Periodically audit for this:

diff /etc/nginx/sites-available/myapp.conf infrastructure/nginx/sites/myapp.conf

Tools like Ansible naturally help prevent drift, since re-applying a playbook enforces the defined state, correcting any manual deviations.

Documenting the "Why" Alongside the "What"

Use commit messages and a README to explain non-obvious configuration decisions — a future administrator (including yourself, months later) benefits enormously from understanding why a particular setting exists, not just what it is.

Example Commit Message Practice

git commit -m "Increase Nginx client_max_body_size to 50m

Required for the new bulk file upload feature added in
the main application (see app repo commit abc123).
Without this, uploads over 1MB were rejected with 413."

Handling Server-Specific Variations

For configuration that legitimately differs between servers (different domains, different resource limits), use templating (Ansible Jinja2 templates, or environment-specific variable files) rather than maintaining entirely separate, drifting copies of similar configs.

Common Errors

Committed a secret accidentally — treat it as compromised and rotate immediately; Git history retains it even after a subsequent removal commit.

Best Practices

  • Never commit secrets directly; use environment variables or a dedicated secrets manager
  • Require review for infrastructure changes, same as application code
  • Periodically check for configuration drift between the repository and live servers

Continue Reading

Browse more articles in DevOps & CI/CD.

  • infrastructure as code, version control configuration, configuration drift, gitops
  • 0 Users Found This Useful
Was this answer helpful?

Related Articles

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...