VPS Configuration Management with Ansible: Automate Server Setup, Security, and Maintenance

Managing multiple VPS instances manually — SSHing into each one to install packages, push config files, and run updates — doesn’t scale. Ansible automates this without requiring any agent software on the target servers. This guide shows how to use Ansible to manage your entire VPS fleet from a single control node.

Why Ansible for VPS Management?

Unlike Puppet or Chef, Ansible is agentless — it connects via SSH and pushes configuration. This makes it ideal for VPS environments where you might have servers from different providers with different base images. Key benefits:

  • Agentless — No daemon to install or keep running on your VPS.
  • Idempotent — Running a playbook multiple times produces the same result.
  • YAML syntax — Easy to read, write, and version-control.
  • No database — No central server or database required, just a control machine with SSH access.

Installing Ansible

Set up a control node — typically your local machine or a small management VPS:

# Ubuntu/Debian control node
sudo apt update && sudo apt install ansible -y
ansible --version

For managing multiple VPS instances efficiently, choose a VPS plan with enough resources to run your control node.

Inventory: Defining Your VPS Fleet

Create an inventory file listing all your VPS instances:

# inventory/hosts.yml
all:
  children:
    web_servers:
      hosts:
        app-01:
          ansible_host: 192.168.1.10
          ansible_user: deploy
        app-02:
          ansible_host: 192.168.1.11
          ansible_user: deploy
    database_servers:
      hosts:
        db-01:
          ansible_host: 192.168.1.20
          ansible_user: deploy

Group servers by function (web_servers, database_servers, monitoring) so you can target specific groups in your playbooks. Test connectivity:

ansible all -i inventory/hosts.yml -m ping

Essential Playbooks for VPS Management

1. Security Hardening Playbook

# security-hardening.yml
---
- name: Apply security baseline to all VPS
  hosts: all
  become: yes
  tasks:
    - name: Disable SSH password authentication
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^#?PasswordAuthentication'
        line: 'PasswordAuthentication no'
      notify: restart sshd

    - name: Configure UFW defaults
      community.general.ufw:
        rule: deny
        direction: incoming

    - name: Allow SSH, HTTP, HTTPS
      community.general.ufw:
        rule: allow
        port: '{{ item }}'
      loop: [22, 80, 443]

    - name: Enable UFW
      community.general.ufw:
        state: enabled

    - name: Install fail2ban
      ansible.builtin.apt:
        name: fail2ban
        state: present

  handlers:
    - name: restart sshd
      ansible.builtin.service:
        name: sshd
        state: restarted

2. System Update Automation

# system-update.yml
---
- name: Apply system updates across all VPS
  hosts: all
  become: yes
  tasks:
    - name: Update apt cache
      ansible.builtin.apt:
        update_cache: yes
        cache_valid_time: 3600

    - name: Upgrade all packages
      ansible.builtin.apt:
        upgrade: dist
        autoremove: yes
        autoclean: yes

    - name: Check if reboot required
      ansible.builtin.stat:
        path: /var/run/reboot-required
      register: reboot_required

    - name: Reboot if needed
      ansible.builtin.reboot:
        reboot_timeout: 300
      when: reboot_required.stat.exists

Run this weekly via cron on your control node to keep all VPS instances patched:

0 3 * * 0 cd /home/deploy/ansible && ansible-playbook -i inventory/hosts.yml system-update.yml

3. Monitoring Agent Deployment

# monitoring.yml
---
- name: Deploy Prometheus Node Exporter
  hosts: all
  become: yes
  tasks:
    - name: Create prometheus user
      ansible.builtin.user:
        name: prometheus
        system: yes
        shell: /usr/sbin/nologin

    - name: Download node_exporter
      ansible.builtin.get_url:
        url: https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
        dest: /tmp/node_exporter.tar.gz

    - name: Extract and install
      ansible.builtin.unarchive:
        src: /tmp/node_exporter.tar.gz
        dest: /opt/
        remote_src: yes
      notify: restart node_exporter

Best Practices for Ansible on VPS

  • Use ansible-vault to encrypt sensitive variables (SSH keys, API tokens, database passwords): ansible-vault encrypt vars/secrets.yml
  • Structure your project with inventory/, playbooks/, roles/, and group_vars/ directories.
  • Test in dry-run mode first: ansible-playbook --check playbook.yml
  • Limit scope with --limit flag when testing on a single VPS before rolling out to all servers.
  • Keep playbooks in Git for change tracking and rollback capability.

Ansible transforms a chaotic collection of manually-configured VPS instances into a reproducible, auditable infrastructure. Start with the security hardening playbook, add system updates, then expand to application deployment. For reliable VPS instances to manage, explore VPS plans suitable for production workloads.

Leave a Reply