Skip to content
Commitpedia
Log in Join & edit

Your first Ansible playbook: install nginx and publish a page

A complete beginner playbook that installs nginx on Debian or Ubuntu servers, starts it at boot and deploys a home page, with the commands to dry-run, apply and verify it.

Edit history of Your first Ansible playbook: install nginx and publish a page: 1 recorded edit
Edit history · 1 edit
Type
Script
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Language
yaml
Licence
CC0-1.0

This tutorial takes you from an empty folder to a web server configured by Ansible. It targets Debian or Ubuntu hosts (it uses the apt module). You need Ansible on your machine, SSH key access to the servers and a user that can use sudo.

Step 1: create the inventory

Make a project folder and an inventory file named inventory.ini. Replace the example names and addresses with your own servers.

[web]
web1.example.com ansible_host=192.0.2.10
web2.example.com ansible_host=192.0.2.11

[web:vars]
ansible_user=admin

ansible_host is the address to connect to, ansible_user the SSH login. Check that Ansible can reach every host:

ansible web -i inventory.ini -m ping

Each host should answer SUCCESS with "ping": "pong". If you see UNREACHABLE!, fix SSH first (see the separate fix entry for that error).

Step 2: write the playbook

Save this as site.yml:

---
- name: Install nginx and publish a home page
  hosts: web
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: true
        cache_valid_time: 3600

    - name: Make sure nginx is running and starts at boot
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true

    - name: Publish a simple home page
      ansible.builtin.copy:
        content: "<h1>Deployed by Ansible</h1>\n"
        dest: /var/www/html/index.html
        owner: root
        group: root
        mode: "0644"
  • hosts: web runs the play on the web group from the inventory.
  • become: true runs the tasks with sudo, because installing packages needs root.
  • update_cache with cache_valid_time: 3600 refreshes the apt index only if it is older than an hour.
  • enabled: true makes nginx start automatically after a reboot.
  • On Debian and Ubuntu the default nginx site serves /var/www/html, so the copied index.html becomes the home page.

Step 3: dry run, then apply

  1. Check the YAML: ansible-playbook -i inventory.ini site.yml --syntax-check
  2. Preview without changing anything: ansible-playbook -i inventory.ini site.yml --check. In check mode some tasks cannot know their final result (nginx is not installed yet, so the service task may fail); that is expected on a first run.
  3. Apply it: ansible-playbook -i inventory.ini site.yml. Add -K (--ask-become-pass) if sudo asks for a password on the servers.

At the end Ansible prints a PLAY RECAP line per host with counters such as ok, changed, unreachable and failed.

Step 4: verify and run it again

curl http://192.0.2.10/
ansible-playbook -i inventory.ini site.yml

The page should show “Deployed by Ansible”. The second playbook run should report changed=0 for every host: the package is present, the service is running and the file already has the right content, so nothing is touched. This is idempotency, and it is why you can safely re-run playbooks.

Where to go next

Move hard-coded values into variables, render the nginx configuration from a template and reload nginx only when it changes. Those are the next steps: variables, templates and handlers.

Official documentation

See also

  • 0181 Ansible concepts: inventory, modules, playbooks, idempotency and roles Ansible configures many servers over SSH from one control machine. Learn the core pieces: inventory, modules, tasks, playbooks, roles, and why runs… Beginner · Concept · Linux, macOS Article Ansible 15 Oct 2026
  • 0183 Ansible variables, templates and handlers: configure an nginx site Use group variables, Jinja2 templates and handlers together: render an nginx server block from variables, test the config and reload nginx only… Intermediate · How-to · Linux, macOS Script Ansible 15 Oct 2026
  • 0184 Ansible Vault: keep passwords and keys encrypted in your repo Ansible Vault encrypts variable files or single values so secrets can live in Git next to your playbooks. Create, edit and rekey… Advanced · How-to · Linux, macOS Article Ansible 15 Oct 2026
  • 0185 Ansible ad-hoc commands cheat sheet One-line ansible commands for quick jobs across many servers: ping hosts, run a command, copy files, manage packages, users and services, gather… Intermediate · Reference · Linux, macOS Article Ansible 15 Oct 2026
  • 0186 Fix: Ansible UNREACHABLE! Failed to connect to the host via ssh Ansible could not open an SSH session to the host, so no task ran. The text after the colon tells you why:… Intermediate · Fix · Linux, macOS Article Ansible · SSH & servers 15 Oct 2026
  • 0254 Automate three servers with Ansible: roles, templates, Vault and safe dry runs Build a real Ansible project for two web servers and one database server: inventory groups, SSH keys, roles, templates, handlers, an encrypted… Intermediate · Tutorial · Linux, macOS Article Ansible · Keys & config 15 Oct 2026

Repos in the wild

  • Ansible: agentless IT automation ansible/ansible The source repository of ansible-core, the engine behind Ansible playbooks, ad-hoc commands and the ansible-galaxy and ansible-vault tools. GitHub

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. commitpedia-admin +3,241 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?