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.

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 ansibleon Ubuntu,brew install ansibleon macOS, orpip install ansiblein 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 WordPress3 hosts: web4 become: true56 vars:7 mariadb_root_password: "change-me-in-production"8 mariadb_database: "wordpress"9 mariadb_user: "wordpress"10 mariadb_password: "change-me-too"1112 tasks:13 - name: Update apt cache14 apt:15 update_cache: yes16 cache_valid_time: 36001718 - name: Install Docker prerequisites19 apt:20 name:21 - ca-certificates22 - curl23 - gnupg24 state: present2526 - name: Add Docker GPG key27 apt_key:28 url: https://download.docker.com/linux/ubuntu/gpg29 state: present3031 - name: Add Docker apt repository32 apt_repository:33 repo: "deb https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"34 state: present3536 - name: Install Docker Engine37 apt:38 name:39 - docker-ce40 - docker-ce-cli41 - containerd.io42 state: present4344 - name: Ensure Docker service is running45 systemd:46 name: docker47 state: started48 enabled: yes4950 - name: Create Docker network for WordPress51 community.docker.docker_network:52 name: wordpress-net5354 - name: Run MariaDB container55 community.docker.docker_container:56 name: wordpress-db57 image: mariadb:11.458 state: started59 restart_policy: unless-stopped60 networks:61 - name: wordpress-net62 env:63 MARIADB_ROOT_PASSWORD: "{{ mariadb_root_password }}"64 MARIADB_DATABASE: "{{ mariadb_database }}"65 MARIADB_USER: "{{ mariadb_user }}"66 MARIADB_PASSWORD: "{{ mariadb_password }}"6768 - name: Run WordPress container69 community.docker.docker_container:70 name: wordpress71 image: wordpress:latest72 state: started73 restart_policy: unless-stopped74 networks:75 - name: wordpress-net76 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:
- Update the package cache so the server knows what is available
- Install the prerequisites Docker needs
- Add the official Docker repository and its GPG key
- Install the Docker Engine
- Make sure Docker starts on boot
- Create a private Docker network so the containers can talk to each other
- Launch a MariaDB container for the database
- 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] ***********************************23TASK [Gathering Facts] *******************************************************4ok: [wordpress-01]56TASK [Update apt cache] ******************************************************7changed: [wordpress-01]89TASK [Install Docker prerequisites] ******************************************10changed: [wordpress-01]1112TASK [Add Docker GPG key] ****************************************************13changed: [wordpress-01]1415TASK [Add Docker apt repository] *********************************************16changed: [wordpress-01]1718TASK [Install Docker Engine] *************************************************19changed: [wordpress-01]2021TASK [Ensure Docker service is running] **************************************22ok: [wordpress-01]2324TASK [Create Docker network for WordPress] ***********************************25changed: [wordpress-01]2627TASK [Run MariaDB container] *************************************************28changed: [wordpress-01]2930TASK [Run WordPress container] ***********************************************31changed: [wordpress-01]3233PLAY 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 PORTS2a1b2c3d4e5f6 wordpress:latest Up 2 minutes 0.0.0.0:80->80/tcp3f6e5d4c3b2a1 mariadb:11.4 Up 2 minutes 3306/tcp
What You Replaced
Without Ansible, the same outcome would have required:
- SSH into the server
- Run
apt update && apt installfor each prerequisite - Manually add the Docker GPG key and repository
- Install Docker and enable the service
- Write
docker runcommands for MariaDB and WordPress, remembering every environment variable - 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 servers2ansible-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
- Review the full workflow overview to see how Ansible connects to Docker, Kubernetes, and Terraform
- Automate the previous stage with Create Infrastructure with Terraform on OpenStack
- Explore additional Ansible modules at the official Ansible documentation
When your team is ready to adopt this workflow on infrastructure with transparent, predictable pricing, contact the InMotion Cloud team.
Related Articles
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.