Skip to main content
IMHCloud Logo
Back to support home

How to Configure Servers with Ansible

Automate server setup on InMotion Cloud with Ansible. This guide walks through installing Ansible, building an inventory from OpenStack instances, and writing reusable playbooks for repeatable, idempotent deployments.

5 min read

You have created your infrastructure on InMotion Cloud. The servers are running, the networks are in place, and the firewalls are configured. Now you need to install software on those servers, configure services, and deploy applications. Doing this by hand across multiple servers is slow, error-prone, and impossible to repeat reliably.

Ansible solves this by installing and configuring software on your servers automatically. You describe the desired state of a server in a simple text file, and Ansible makes every server match. This guide walks through a complete example that installs Docker and deploys WordPress on a freshly provisioned InMotion Cloud instance.

What Ansible Does in Plain Terms

Ansible is an automation tool. You tell it what you want a server to look like, and it makes the server look that way. That is the whole idea.

The instructions live in a file called a playbook. A playbook is a plain text YAML file that reads almost like a checklist:

  • Install the Docker package
  • Start the Docker service
  • Pull the WordPress image
  • Launch the container on port 80

Ansible reads the playbook, connects to each target server over SSH, and performs each step in order. If a step is already complete (Docker is already installed), Ansible skips it. If a step is missing (WordPress is not running), Ansible executes it. This property is called idempotency, and it is what makes Ansible safe to run repeatedly.

No agents are required on the target servers. Ansible uses SSH, which your InMotion Cloud instances already support.

Why Manual Setup Fails at Scale

Setting up one server by hand is fine. You log in, run apt install, edit a config file, and move on. Setting up ten servers by hand is where the problems start:

  • Commands get typed slightly differently each time
  • Config files drift as team members tweak them individually
  • Nobody remembers the exact sequence that got server three working
  • Onboarding a new team member means writing (and maintaining) a setup document

Ansible replaces that entire category of work with a file in your Git repository. The playbook is the source of truth. Anyone on the team can apply it. Every server ends up identical. Rebuilding a server after a failure takes one command instead of a day.

Prerequisites

Before starting, you need:

  • A running InMotion Cloud instance provisioned with Terraform or manually through Horizon. See Create Infrastructure with Terraform on OpenStack for the automated path.
  • An Ubuntu 24.04 LTS (Noble Numbat) image on the target instance. Ubuntu 24.04 is the current long-term support release and receives security updates through 2029.
  • A floating IP assigned to the instance
  • Your SSH private key on your local machine, matching the key pair attached to the instance
  • Ansible installed locally: sudo apt install ansible on Ubuntu, brew install ansible on macOS, or pip install ansible in a Python virtual environment

Verify your Ansible installation:

1ansible --version

You should see output similar to ansible [core 2.16.3].

Step 1: Create the Inventory File

The inventory file tells Ansible which servers to manage. Create a file named inventory.ini in a new project directory:

1[web]
2wordpress-01 ansible_host=203.0.113.45 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/inmotion_cloud_key

Replace 203.0.113.45 with your instance's floating IP and update the private key path to match your local SSH key.

Test the connection:

1ansible -i inventory.ini web -m ping

Expected output:

1wordpress-01 | SUCCESS => {
2 "ansible_facts": {
3 "discovered_interpreter_python": "/usr/bin/python3"
4 },
5 "changed": false,
6 "ping": "pong"
7}

A pong response confirms Ansible can reach the server over SSH.

Step 2: Write the Playbook

Create a file named deploy-wordpress.yml in the same directory:

1---
2- name: Install Docker and deploy WordPress
3 hosts: web
4 become: true
5
6 vars:
7 mariadb_root_password: "change-me-in-production"
8 mariadb_database: "wordpress"
9 mariadb_user: "wordpress"
10 mariadb_password: "change-me-too"
11
12 tasks:
13 - name: Update apt cache
14 apt:
15 update_cache: yes
16 cache_valid_time: 3600
17
18 - name: Install Docker prerequisites
19 apt:
20 name:
21 - ca-certificates
22 - curl
23 - gnupg
24 state: present
25
26 - name: Add Docker GPG key
27 apt_key:
28 url: https://download.docker.com/linux/ubuntu/gpg
29 state: present
30
31 - name: Add Docker apt repository
32 apt_repository:
33 repo: "deb https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
34 state: present
35
36 - name: Install Docker Engine
37 apt:
38 name:
39 - docker-ce
40 - docker-ce-cli
41 - containerd.io
42 state: present
43
44 - name: Ensure Docker service is running
45 systemd:
46 name: docker
47 state: started
48 enabled: yes
49
50 - name: Create Docker network for WordPress
51 community.docker.docker_network:
52 name: wordpress-net
53
54 - name: Run MariaDB container
55 community.docker.docker_container:
56 name: wordpress-db
57 image: mariadb:11.4
58 state: started
59 restart_policy: unless-stopped
60 networks:
61 - name: wordpress-net
62 env:
63 MARIADB_ROOT_PASSWORD: "{{ mariadb_root_password }}"
64 MARIADB_DATABASE: "{{ mariadb_database }}"
65 MARIADB_USER: "{{ mariadb_user }}"
66 MARIADB_PASSWORD: "{{ mariadb_password }}"
67
68 - name: Run WordPress container
69 community.docker.docker_container:
70 name: wordpress
71 image: wordpress:latest
72 state: started
73 restart_policy: unless-stopped
74 networks:
75 - name: wordpress-net
76 ports:
77 - "80:80"
78 env:
79 WORDPRESS_DB_HOST: "wordpress-db"
80 WORDPRESS_DB_USER: "{{ mariadb_user }}"
81 WORDPRESS_DB_PASSWORD: "{{ mariadb_password }}"
82 WORDPRESS_DB_NAME: "{{ mariadb_database }}"

This playbook reads top to bottom:

  1. Update the package cache so the server knows what is available
  2. Install the prerequisites Docker needs
  3. Add the official Docker repository and its GPG key
  4. Install the Docker Engine
  5. Make sure Docker starts on boot
  6. Create a private Docker network so the containers can talk to each other
  7. Launch a MariaDB container for the database
  8. Launch a WordPress container that uses the MariaDB container

Every step is declarative. You are describing the final state, not writing a shell script.

Step 3: Install the Docker Collection

The Docker-specific Ansible modules live in a separate collection. Install it once:

1ansible-galaxy collection install community.docker

Step 4: Run the Playbook

From your project directory:

1ansible-playbook -i inventory.ini deploy-wordpress.yml

Ansible connects over SSH and runs the playbook. You should see output similar to:

1PLAY [Install Docker and deploy WordPress] ***********************************
2
3TASK [Gathering Facts] *******************************************************
4ok: [wordpress-01]
5
6TASK [Update apt cache] ******************************************************
7changed: [wordpress-01]
8
9TASK [Install Docker prerequisites] ******************************************
10changed: [wordpress-01]
11
12TASK [Add Docker GPG key] ****************************************************
13changed: [wordpress-01]
14
15TASK [Add Docker apt repository] *********************************************
16changed: [wordpress-01]
17
18TASK [Install Docker Engine] *************************************************
19changed: [wordpress-01]
20
21TASK [Ensure Docker service is running] **************************************
22ok: [wordpress-01]
23
24TASK [Create Docker network for WordPress] ***********************************
25changed: [wordpress-01]
26
27TASK [Run MariaDB container] *************************************************
28changed: [wordpress-01]
29
30TASK [Run WordPress container] ***********************************************
31changed: [wordpress-01]
32
33PLAY RECAP *******************************************************************
34wordpress-01 : ok=10 changed=8 unreachable=0 failed=0

A changed status means the task modified the server. ok means the server already matched the desired state. failed=0 is the line that matters most.

Step 5: Verify WordPress Is Running

Open your instance's floating IP in a web browser:

1http://203.0.113.45

You should see the WordPress installation wizard, ready to configure a site title, admin user, and database connection.

You can also verify from the command line that both containers are running:

1ssh ubuntu@203.0.113.45 "sudo docker ps"

Expected output:

1CONTAINER ID IMAGE STATUS PORTS
2a1b2c3d4e5f6 wordpress:latest Up 2 minutes 0.0.0.0:80->80/tcp
3f6e5d4c3b2a1 mariadb:11.4 Up 2 minutes 3306/tcp

What You Replaced

Without Ansible, the same outcome would have required:

  1. SSH into the server
  2. Run apt update && apt install for each prerequisite
  3. Manually add the Docker GPG key and repository
  4. Install Docker and enable the service
  5. Write docker run commands for MariaDB and WordPress, remembering every environment variable
  6. Document every step so the next team member can reproduce it

Repeat that for each additional server. Every manual step is a chance to introduce a difference between environments.

With Ansible, you run ansible-playbook once. Run it against five servers and you get five identical WordPress deployments. Run it again next month when the original server fails and the replacement is configured in minutes.

How This Fits the Bigger Picture

Server configuration is the second stage of the modern cloud workflow. Terraform builds the infrastructure, Ansible configures it, Docker packages applications, and Kubernetes runs them at scale. See How Modern Applications Run on Cloud Infrastructure for the full picture of how these tools connect.

Your Ansible playbook is typically the second command in a deployment pipeline:

1terraform apply # Build the servers
2ansible-playbook ... # Configure them

Storing both files in the same Git repository gives you a complete, version-controlled definition of your environment from bare infrastructure to running application.

Where to Go from Here

When your team is ready to adopt this workflow on infrastructure with transparent, predictable pricing, contact the InMotion Cloud team.

Related Articles

Read article

How to Create Cloud Infrastructure with Terraform

Learn how Terraform automates cloud infrastructure creation on InMotion Cloud. This guide walks through a real example that provisions a network, security group, and virtual machine with a single command.