DevOps Classroom notes 25/Jun/2026

Ansible Role: Tomcat 10 (Debian & RedHat Support)

This role installs and configures Apache Tomcat 10 on both Debian-based and RedHat-based Linux distributions using Ansible facts (ansible_os_family).


Role Structure

roles/
└── tomcat10/
    ├── defaults/
    │   └── main.yml
    ├── handlers/
    │   └── main.yml
    ├── tasks/
    │   ├── main.yml
    │   ├── install_debian.yml
    │   ├── install_redhat.yml
    │   └── configure.yml
    ├── templates/
    │   └── tomcat.service.j2
    ├── vars/
    │   ├── Debian.yml
    │   └── RedHat.yml
    └── meta/
        └── main.yml

defaults/main.yml

---
tomcat_version: "10.1.42"

tomcat_user: tomcat
tomcat_group: tomcat

tomcat_install_dir: /opt/tomcat

tomcat_url: "https://downloads.apache.org/tomcat/tomcat-10/v{{ tomcat_version }}/bin/apache-tomcat-{{ tomcat_version }}.tar.gz"

vars/Debian.yml

---
java_package: openjdk-17-jdk

vars/RedHat.yml

---
java_package: java-17-openjdk-devel

tasks/main.yml

---
- name: Load OS specific variables
  include_vars: "{{ ansible_os_family }}.yml"

- name: Install packages for Debian family
  include_tasks: install_debian.yml
  when: ansible_os_family == "Debian"

- name: Install packages for RedHat family
  include_tasks: install_redhat.yml
  when: ansible_os_family == "RedHat"

- name: Configure Tomcat
  include_tasks: configure.yml

tasks/install_debian.yml

---
- name: Update apt cache
  apt:
    update_cache: yes

- name: Install Java
  apt:
    name: "{{ java_package }}"
    state: present

tasks/install_redhat.yml

---
- name: Install Java
  dnf:
    name: "{{ java_package }}"
    state: present

For CentOS 7 replace dnf with yum.


tasks/configure.yml

---
- name: Create group
  group:
    name: "{{ tomcat_group }}"
    state: present

- name: Create user
  user:
    name: "{{ tomcat_user }}"
    group: "{{ tomcat_group }}"
    shell: /sbin/nologin
    home: "{{ tomcat_install_dir }}"
    state: present

- name: Download Tomcat
  get_url:
    url: "{{ tomcat_url }}"
    dest: /tmp/tomcat.tar.gz
    mode: "0644"

- name: Create installation directory
  file:
    path: "{{ tomcat_install_dir }}"
    state: directory
    owner: "{{ tomcat_user }}"
    group: "{{ tomcat_group }}"
    mode: "0755"

- name: Extract Tomcat archive
  unarchive:
    src: /tmp/tomcat.tar.gz
    dest: "{{ tomcat_install_dir }}"
    remote_src: yes
    extra_opts:
      - --strip-components=1
  notify: restart tomcat

- name: Set ownership
  file:
    path: "{{ tomcat_install_dir }}"
    owner: "{{ tomcat_user }}"
    group: "{{ tomcat_group }}"
    recurse: yes

- name: Deploy systemd service
  template:
    src: tomcat.service.j2
    dest: /etc/systemd/system/tomcat.service
    mode: "0644"
  notify: restart tomcat

- name: Enable and start Tomcat
  systemd:
    name: tomcat
    enabled: yes
    state: started
    daemon_reload: yes

templates/tomcat.service.j2

[Unit]
Description=Apache Tomcat 10
After=network.target

[Service]
Type=forking

User={{ tomcat_user }}
Group={{ tomcat_group }}

Environment=CATALINA_HOME={{ tomcat_install_dir }}
Environment=CATALINA_BASE={{ tomcat_install_dir }}

ExecStart={{ tomcat_install_dir }}/bin/startup.sh
ExecStop={{ tomcat_install_dir }}/bin/shutdown.sh

Restart=on-failure

[Install]
WantedBy=multi-user.target

handlers/main.yml

---
- name: restart tomcat
  systemd:
    name: tomcat
    state: restarted
    daemon_reload: yes

Example Playbook

---
- hosts: appservers
  become: yes

  roles:
    - tomcat10

Supported Operating Systems

Distribution ansible_os_family
Ubuntu Debian
Debian Debian
RHEL RedHat
Rocky Linux RedHat
AlmaLinux RedHat
CentOS RedHat

Facts Used

The role automatically determines the operating system family using:

ansible_os_family

This allows a single role to support both Debian and RedHat families without hardcoding package managers or distribution names.

Task:

  • Create a Java role
  • Create a Tomcat role
  • Support Ubuntu and Red Hat-based systems

Prompt:

Create an Ansible role for installing Java and another role for installing and configuring Tomcat. Both roles should support Ubuntu (Debian family) and Red Hat-based systems (RHEL, CentOS, Rocky, AlmaLinux) using Ansible facts (ansible_os_family) for OS detection.

2. Ansible Galaxy Roles

Ansible Galaxy is the public hub for sharing Ansible roles and collections.

2.1 Install a Role from Galaxy

ansible-galaxy role install geerlingguy.nginx

Installed to ~/.ansible/roles/ by default.

2.2 Install to a Custom Path

ansible-galaxy role install geerlingguy.nginx -p roles/

2.3 Install Specific Version

ansible-galaxy role install geerlingguy.nginx,3.2.0

2.4 Install from requirements.yml

Create requirements.yml:

---
roles:
  - name: geerlingguy.nginx
    version: "3.2.0"
  - name: geerlingguy.java
    version: "2.1.0"

collections:
  - name: community.general
    version: ">=7.0.0"
  - name: ansible.posix

Install all at once:

ansible-galaxy install -r requirements.yml
ansible-galaxy collection install -r requirements.yml

2.5 Create a New Role Skeleton

ansible-galaxy role init myrole

Generated structure:

myrole/
├── defaults/
│   └── main.yml        # default variables (lowest priority)
├── files/              # static files to copy
├── handlers/
│   └── main.yml        # handlers (e.g., restart nginx)
├── meta/
│   └── main.yml        # role metadata, dependencies
├── tasks/
│   └── main.yml        # main task list
├── templates/          # Jinja2 templates (.j2)
├── tests/
│   ├── inventory
│   └── test.yml
└── vars/
    └── main.yml        # variables (higher priority than defaults)

2.6 Using a Role in a Playbook

- name: Setup Web Server
  hosts: webservers
  roles:
    - geerlingguy.nginx
    - geerlingguy.java

2.7 Pass Variables to a Role

- name: Setup Web Server
  hosts: webservers
  roles:
    - role: geerlingguy.nginx
      vars:
        nginx_listen_port: 8080

2.8 Include Role in Tasks (Dynamic)

tasks:
  - name: Apply nginx role
    include_role:
      name: geerlingguy.nginx

2.9 Role Dependencies (meta/main.yml)

# roles/myapp/meta/main.yml
dependencies:
  - role: geerlingguy.java
    vars:
      java_packages:
        - java-17-openjdk
  - role: geerlingguy.nginx

2.10 List Installed Roles

ansible-galaxy role list

2.11 Remove a Role

ansible-galaxy role remove geerlingguy.nginx

2.12 Install & Use a Collection

# Install collection
ansible-galaxy collection install community.general

# Use a module from the collection in a playbook
- name: Use community.general module
  community.general.ini_file:
    path: /etc/app.conf
    section: database
    option: host
    value: "localhost"

Galaxy CLI Quick-Reference

Command Purpose
ansible-galaxy role install <name> Install role
ansible-galaxy role init <name> Scaffold new role
ansible-galaxy role list List installed roles
ansible-galaxy role remove <name> Remove role
ansible-galaxy install -r requirements.yml Bulk install from file
ansible-galaxy collection install <ns.col> Install collection

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Please turn AdBlock off
Animated Social Media Icons by Acurax Responsive Web Designing Company

Discover more from Direct DevOps from Quality Thought

Subscribe now to keep reading and get access to the full archive.

Continue reading

Visit Us On FacebookVisit Us On LinkedinVisit Us On Youtube