Monday, 22 December 2025

Ansible 29. roles - example using nginx depployment

We can create ansible role using any of the below command:

ansible-galaxy role init demo-role 

or

ansible-galaxy init demo-role

The ansible-galaxy role init command is the modern, more explicit way to structure the command, while ansible-galaxy init is the older, shorthand version.

[oracle@oel01db ansible-role]$ ansible-galaxy role init nginx_role_demo

- Role nginx_role_demo was created successfully

[oracle@oel01db ansible-role]$ ls -lrt

total 0

drwxr-xr-x 10 oracle oinstall 154 Dec 22 14:24 nginx_role_demo

[oracle@oel01db ansible-role]$ cd nginx_role_demo

[oracle@oel01db nginx_role_demo]$ ls -lt

total 4

drwxr-xr-x 2 oracle oinstall   39 Dec 22 14:24 tests

drwxr-xr-x 2 oracle oinstall   22 Dec 22 14:24 vars

drwxr-xr-x 2 oracle oinstall   22 Dec 22 14:24 defaults

drwxr-xr-x 2 oracle oinstall   22 Dec 22 14:24 handlers

drwxr-xr-x 2 oracle oinstall   22 Dec 22 14:24 meta

drwxr-xr-x 2 oracle oinstall   22 Dec 22 14:24 tasks

drwxr-xr-x 2 oracle oinstall    6 Dec 22 14:24 files

-rw-r--r-- 1 oracle oinstall 1328 Dec 22 14:24 README.md

drwxr-xr-x 2 oracle oinstall    6 Dec 22 14:24 templates

[oracle@oel01db nginx_role_demo]$


list the role:

[oracle@oel01db ansible-role]$ ansible-galaxy list -p .
# /home/oracle/ansible-project/ansible-role
- nginx_role_demo, (unknown version)
# /usr/share/ansible/roles
# /etc/ansible/roles
[WARNING]: - the configured path /home/oracle/.ansible/roles does not exist.
[oracle@oel01db ansible-role]$

-p stands for roles path.

Above command tells , it found ansible role named "nginx_role_demo" in the /home/oracle/ansible-project/ansible-role path.

Please note, list command should run Ansible commands from the project directory that is outside the role root directory.

Why this warning appears (important)

[WARNING]: - the configured path /home/oracle/.ansible/roles does not exist.

Explanation:

Even though you specifically told it where to look using -p ., Ansible always tries to check its default system paths as well. The warning is simply telling you that one of its "built-in" search locations doesn't exist on your disk yet.

Ansible checks default paths in this order:

  1. roles_path (from ansible.cfg, if set)

  2. ~/.ansible/roles

  3. /usr/share/ansible/roles

  4. /etc/ansible/roles


The easiest way to stop the "nagging" alert is to just create the empty directory Ansible is looking for:

oracle@oel01db ansible-role]$ mkdir -p ~/.ansible/roles

[oracle@oel01db ansible-role]$  ansible-galaxy list -p .
# /home/oracle/ansible-project/ansible-role
- nginx_role_demo, (unknown version)
# /home/oracle/.ansible/roles
# /usr/share/ansible/roles
# /etc/ansible/roles
[oracle@oel01db ansible-role]$

If you want ansible-galaxy list to list the role without -p , you needs to define ansible.cfg and the mention the roles_path.

Where I need to define ansible.cfg ? and what path I need to mention for roles_path ?

To make ansible-galaxy list work without the -p flag, you should place the ansible.cfg file in the root of your project directory, not inside the role itself.

So place it in /home/oracle/ansible-project/ansible-role/.

This is your "Project Root." Ansible looks for an ansible.cfg in the current directory from which you run your commands. If you put it here, you can run your playbooks and galaxy commands from this folder easily.

What path to mention?

Since your role (nginx_role_demo) is sitting directly inside your current folder, tell Ansible to look "here":

roles_path = ./

or

roles_path = /home/oracle/ansible-project/ansible-role

[oracle@oel01db ansible-role]$ pwd
/home/oracle/ansible-project/ansible-role
[oracle@oel01db ansible-role]$ 

[oracle@oel01db ansible-role]$ cat ansible.cfg
[defaults]
roles_path = ./
[oracle@oel01db ansible-role]$

[oracle@oel01db ansible-role]$ ansible-galaxy list
# /home/oracle/ansible-project/ansible-role
- nginx_role_demo, (unknown version)
[oracle@oel01db ansible-role]$


The structure of Ansible Role

roles/nginx_role_demo/
├── defaults/
│   └── main.yml        # Configurable values
├── vars/
│   └── main.yml        # Fixed/internal values
├── tasks/
│   ├── install.yml     # Install nginx
│   ├── config.yml      # Config files
│   ├── service.yml    # Start/enable service
│   └── main.yml       # Entry point
├── handlers/
│   └── main.yml       # Restart nginx
├── templates/
│   └── nginx.conf.j2  # Jinja2 template
├── files/
│   └── index.html     # Static file
├── meta/
│   └── main.yml       # Role metadata
└── README.md          # Documentation

Typical project layout


project/
├── inventory/
│   └── hosts
├── <my-playbook>.yml              👈 MAIN playbook (goes here)
├── roles/
│   └── nginx_server/
│       ├── tasks/
│       ├── defaults/
│       ├── vars/
│       ├── handlers/
│       ├── templates/
│       ├── files/
│       ├── tests/
│       └── meta/


My Project setup:

[oracle@oel01db ansible-role]$ pwd
/home/oracle/ansible-project/ansible-role <-- is my role project directory.
[oracle@oel01db ansible-role]$
[oracle@oel01db ansible-role]$ ls -lrt
total 8
-rw-r--r--  1 oracle oinstall  86 Dec 22 17:22 configure_nginx_via_role.yml
drwxr-xr-x  2 oracle oinstall  19 Dec 22 17:23 inventory
drwxr-xr-x 10 oracle oinstall 154 Dec 22 17:23 nginx_role_demo
-rw-r--r--  1 oracle oinstall  27 Dec 22 20:01 ansible.cfg
[oracle@oel01db ansible-role]$ cat ./inventory/hosts
[db_servers]
oelggvm01
[oracle@oel01db ansible-role]$ cat configure_nginx_via_role.yml
- name: Setup Nginx server
  hosts: all
  become: yes
  roles:
    - nginx_role_demo

[oracle@oel01db ansible-role]$ cd nginx_role_demo
[oracle@oel01db nginx_role_demo]$ ls -lrt
total 4
-rw-r--r-- 1 oracle oinstall 1328 Dec 22 14:24 README.md
drwxr-xr-x 2 oracle oinstall   22 Dec 22 15:03 defaults
drwxr-xr-x 2 oracle oinstall   78 Dec 22 15:05 tasks
drwxr-xr-x 2 oracle oinstall   27 Dec 22 15:05 templates
drwxr-xr-x 2 oracle oinstall   24 Dec 22 15:06 files
drwxr-xr-x 2 oracle oinstall   39 Dec 22 15:09 tests
drwxr-xr-x 2 oracle oinstall   22 Dec 22 17:29 vars
drwxr-xr-x 2 oracle oinstall   22 Dec 22 17:34 handlers
drwxr-xr-x 2 oracle oinstall   22 Dec 22 17:35 meta
[oracle@oel01db nginx_role_demo]$

defaults:

[oracle@oel01db nginx_role_demo]$ cat ./defaults/main.yml
---
# defaults file for nginx_role_demo
nginx_port: 80
nginx_server_name: localhost
nginx_root: /usr/share/nginx/html
[oracle@oel01db nginx_role_demo]$


The default provides ansible default values, but the caller (playbook / inventory / group_vars) can change them without editing the role.

For example , here the default nginx_port is defined as 80, but you can have a different port number on the playbook.

for example:

- name: Setup Nginx server
  hosts: all
  become: yes
  roles:
    - role: nginx_role_demo
      vars:
        nginx_port: 8080

task:

[oracle@oel01db nginx_role_demo]$ cat ./tasks/config.yml
---
- name: Deploy nginx config
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: Restart nginx

- name: Copy index.html
  ansible.builtin.copy:
    src: index.html
    dest: "{{ nginx_root }}/index.html"
[oracle@oel01db nginx_role_demo]$
[oracle@oel01db nginx_role_demo]$ cat ./tasks/service.yml
---
- name: Restart nginx
  ansible.builtin.service:
    name: "{{ nginx_service }}"
    state: restarted
[oracle@oel01db nginx_role_demo]$
[oracle@oel01db nginx_role_demo]$ cat ./tasks/main.yml
---
# tasks file for nginx_role_demo
- import_tasks: install.yml
- import_tasks: config.yml
- import_tasks: service.yml
[oracle@oel01db nginx_role_demo]$


template:

[oracle@oel01db nginx_role_demo]$ cat ./templates/nginx.conf.j2
user nginx;
worker_processes auto;

events {
  worker_connections 1024;
}

http {
  server {
    listen {{ nginx_port }};
    server_name {{ nginx_server_name }};

    location / {
      root {{ nginx_root }};
      index index.html;
    }
  }
}
[oracle@oel01db nginx_role_demo]$

files:

[oracle@oel01db nginx_role_demo]$ cat ./files/index.html
<h1>Welcome to Nginx managed by Ansible</h1>

[oracle@oel01db nginx_role_demo]$

vars:

[oracle@oel01db nginx_role_demo]$ cat ./vars/main.yml
---
# vars file for nginx_role_demo
nginx_package: nginx
nginx_service: nginx
[oracle@oel01db nginx_role_demo]$

These variables can not be changed:

handlers:

[oracle@oel01db nginx_role_demo]$ cat ./handlers/main.yml
# handlers file for nginx_role_demo
---
- name: Restart nginx
  ansible.builtin.service:
    name: "{{ nginx_service }}"
    state: restarted

[oracle@oel01db nginx_role_demo]$

Main playbook file is kept OUTSIDE the role root directory.

[oracle@oel01db ansible-role]$ cat configure_nginx_via_role.yml
- name: Setup Nginx server
  hosts: all
  become: yes
  roles:
    - nginx_role_demo

[oracle@oel01db ansible-role]$
























Let's confirm the changes applied by the playbook.

Files are copied as expected: 

[oracle@oelggvm01 ~]$ cd /usr/share/nginx/html
[oracle@oelggvm01 html]$
[oracle@oelggvm01 html]$ ls -lrt
total 16
-rw-r--r-- 1 root root  368 Jun 26 19:04 nginx-logo.png
lrwxrwxrwx 1 root root   37 Jun 26 19:06 system_noindex_logo.png -> ../../pixmaps/system-noindex-logo.png
lrwxrwxrwx 1 root root   14 Jun 26 19:06 poweredby.png -> nginx-logo.png
-rw-r--r-- 1 root root 3996 Jun 26 19:06 50x.html
-rw-r--r-- 1 root root 3940 Jun 26 19:06 404.html
drwxr-xr-x 2 root root   27 Dec 23 03:38 icons
-rw-r--r-- 1 root root   46 Dec 23 03:39 index.html
[oracle@oelggvm01 html]$ cat index.html
<h1>Welcome to Nginx managed by Ansible</h1>

[oracle@oelggvm01 html]$

[oracle@oelggvm01 html]$ cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;

events {
  worker_connections 1024;
}

http {
  server {
    listen 80;
    server_name localhost;

    location / {
      root /usr/share/nginx/html;
      index index.html;
    }
  }
}
[oracle@oelggvm01 html]$



No comments:

Post a Comment

Building a Safer PostgreSQL CI/CD Pipeline with GitHub Actions: Dev → PR Review → Test Promotion

In my previous post, we explored a simple push-to-main deployment strategy . While functional, that model is not considered an industry best...