(: June 26, 2019)
Apache Tomcat is a free and open-source HTTP server designed to serve Java web pages. Tomcat is an implementation of the Java Servlet, JavaServer Pages, Java Expression Language, and Java WebSocket technologies. It is widely deployed and powers various mission-critical web applications around the world.
The standard way of installing Tomcat on a Linux system such as Ubuntu/CentOS/Debian is manual and time-consuming. This guide will discuss a better way, which is automated and can be reproduced easily.
Environment Setup
I assume you have a CentOS 7+, Ubuntu 16.04+ system with Systemd service manager. This Ansible installation won’t work for Upstart or Sysvinit.
Step 1: Install Ansible
The main dependency on your Workstation is Ansible. Install Ansible on your Linux system using the commands shared below.
###### CentOS / Fedora / RHEL ###### sudo yum install ansible sudo dnf install ansible ###### Ubuntu/Debian/Linux Mint ###### sudo apt-get install -y software-properties-common sudo apt-add-repository --yes --update ppa:ansible/ansible sudo apt-get update sudo apt-get install -y ansible ###### Arch/Manjaro ###### $ sudo pacman -S ansible ###### macOS ###### sudo easy_install pip sudo pip install ansible
Step 2: Create Ansible folders
Let’s create a directory for our project.
mkdir -p ~/projects/ansible/roles
cd ~/projects/ansible/roles
Our Ansible YAML files will be located in this parent directory.
Step 3: Create Ansible playbook files
We now need to create ansible role and tasks as YAML files to orchestrate steps of the manual ordered processes.
cd ~/projects/ansible/roles
mkdir -p tomcat/{tasks,handlers,defaults,vars,templates}
The tomcat role has the following folders:
- tasks – contain task files
- handlers – contain handlers file
- defaults – the default lower priority variables for this role
- vars – has variables associated with the role
- templates – holds files for use with the template resource
You should have something like this.
$ tree
.
├── roles
│ └── tomcat
│ ├── defaults
│ ├── handlers
│ ├── tasks
│ └── vars
└── tomcat
7 directories, 0 files
3.1 Create setup tasks
Let’s create tasks which will setup complete Tomcat environment.
3.11 – For Debian family.
$ vim tomcat/tasks/tomcat-setup-Debian.yml
Add:
- name: Ensure the system can use the HTTPS transport for APT.
stat:
path: /usr/lib/apt/methods/https
register: apt_https_transport
- name: Install APT HTTPS transport.
apt:
name: "apt-transport-https"
state: present
update_cache: yes
when: not apt_https_transport.stat.exists
- name: Install basic packages
package:
name: ['vim','aptitude','bash-completion','tmux','tree','htop','wget','unzip','curl','git']
state: present
update_cache: yes
- name: Install Default Java (Debian/Ubuntu)
apt:
name: default-jdk
state: present
- name: Add tomcat group
group:
name: tomcat
- name: Add "tomcat" user
user:
name: tomcat
group: tomcat
home: /usr/share/tomcat
createhome: no
system: yes
- name: Download Tomcat
get_url:
url: "{{ tomcat_archive_url }}"
dest: "{{ tomcat_archive_dest }}"
- name: Create a tomcat directory
file:
path: /usr/share/tomcat
state: directory
owner: tomcat
group: tomcat
- name: Extract tomcat archive
unarchive:
src: "{{ tomcat_archive_dest }}"
dest: /usr/share/tomcat
owner: tomcat
group: tomcat
remote_src: yes
extra_opts: "--strip-components=1"
creates: /usr/share/tomcat/bin
- name: Copy tomcat service file
template:
src: templates/tomcat.service.j2
dest: /etc/systemd/system/tomcat.service
when: ansible_service_mgr == "systemd"
- name: Start and enable tomcat
service:
daemon_reload: yes
name: tomcat
state: started
enabled: yes
when: ansible_service_mgr == "systemd"
3.12 – For RedHat family.
$ vim tomcat/tasks/tomcat-setup-RedHat.yml
with:
- name: Add EPEL repository
yum:
name: epel-release
state: present
- name: Install basic packages
package:
name: ['vim','bash-completion','tmux','tree','htop','wget','unzip','curl','git']
state: present
- name: Install Java 8 CentOS
yum:
name: java-1.8.0-openjdk
state: present
- name: Add tomcat group
group:
name: tomcat
- name: Add "tomcat" user
user:
name: tomcat
group: tomcat
home: /usr/share/tomcat
createhome: no
system: yes
- name: Download Tomcat
get_url:
url: "{{ tomcat_archive_url }}"
dest: "{{ tomcat_archive_dest }}"
- name: Create a tomcat directory
file:
path: /usr/share/tomcat
state: directory
owner: tomcat
group: tomcat
- name: Extract tomcat archive
unarchive:
src: "{{ tomcat_archive_dest }}"
dest: /usr/share/tomcat
owner: tomcat
group: tomcat
remote_src: yes
extra_opts: "--strip-components=1"
creates: /usr/share/tomcat/bin
- name: Copy tomcat service file
template:
src: templates/tomcat.service.j2
dest: /etc/systemd/system/tomcat.service
when: ansible_service_mgr == "systemd"
- name: Start and enable tomcat
service:
daemon_reload: yes
name: tomcat
state: started
enabled: yes
when: ansible_service_mgr == "systemd"
- name: Start and enable firewalld
service:
name: firewalld
state: started
enabled: yes
when: ansible_service_mgr == "systemd"
- name: Open tomcat port on the firewall
firewalld:
port: 8080/tcp
permanent: true
state: enabled
immediate: yes
when: ansible_service_mgr == "systemd"
Create main.yml file.
$ vim tasks/main.yml
---
- name: Add the OS specific variables
include_vars: "{{ item }}"
with_first_found:
- "{{ ansible_distribution }}{{ ansible_distribution_major_version }}.yml"
- "{{ ansible_os_family }}.yml"
- include_tasks: "tomcat-{{ ansible_os_family }}.yml"
3.2 – Create vars file.
$ vim defaults/main.yml
---
tomcat_ver: 9.0.21
tomcat_archive_url: https://archive.apache.org/dist/tomcat/tomcat-9/v{{ tomcat_ver }}/bin/apache-tomcat-{{ tomcat_ver }}.tar.gz
tomcat_archive_dest: /tmp/apache-tomcat-{{ tomcat_ver }}.tar.gz
Check tomcat releases page for latest Tomcat 9.x.
Then add OS family specific variables.
$ vim tomcat/vars/Debian.yml --- JAVA_HOME: /usr/lib/jvm/default-java $ vim tomcat/vars/RedHat.yml JAVA_HOME: /usr/lib/jvm/jre
3.3 – Create service systemd template
We also need to add Tomcat systemd service as a template.
vim templates/tomcat.service.j2
Add:
[Unit]
Description=Tomcat
After=syslog.target network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment=JAVA_HOME={{ JAVA_HOME }}
Environment='JAVA_OPTS=-Djava.awt.headless=true'
Environment=CATALINA_HOME=/usr/share/tomcat
Environment=CATALINA_BASE=/usr/share/tomcat
Environment=CATALINA_PID=/usr/share/tomcat/temp/tomcat.pid
ExecStart=/usr/share/tomcat/bin/catalina.sh start
ExecStop=/usr/share/tomcat/bin/catalina.sh stop
[Install]
WantedBy=multi-user.target
3.4 – Add handler.
$ vim handlers/main.yml
- name: restart tomcat
service:
name: tomcat
state: restarted
3.5 – Define playbook execution file.
Playbook file defines roles to be executed, and on which instances.
cd ~/ansible/
vim tomcat-setup.yml
Paste:
- name: Tomcat deployment playbook
hosts: app-servers
become: yes
become_method: sudo
remote_user: vagrant
roles:
- tomcat
Replace app-servers with the server IP address or hostname or server group defined in the inventory file. This can be a custom file such as hosts in the project directory, or global inventory file – /etc/ansible/hosts.
$ sudo vim /etc/ansible/hosts
Example:
$ cat /etc/ansible/hosts
192.168.10.11
servera.example.com
[app-servers]
server1
server2
Where there is a DNS mapping for names used on /etc/hosts or records resolvable via DNS server in the network.
$ cat /etc/hosts
192.168.121.52 server1
192.168.121.108 server2
server1 is CentOS 7 machine and server2 runs Ubuntu 18.04.
This is the final folder structure:
$ cd ~/projects/ansible
$ tree
.
├── roles
│ └── tomcat
│ ├── defaults
│ │ └── main.yml
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ ├── main.yml
│ │ ├── tomcat-Debian.yml
│ │ └── tomcat-RedHat.yml
│ ├── templates
│ │ └── tomcat.service.j2
│ └── vars
│ ├── Debian.yml
│ └── RedHat.yml
├── setup-tomcat.yml
└── tomcat
Step 4: Execute Playbook
We are ready to run tomcat playbook for the action to begin.
$ cd ~/projects/ansible
$ ansible-playbook setup-tomcat.yml
My execution output sample:
PLAY [Tomcat deployment playbook] *****************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************
ok: [server1]
ok: [server2]
TASK [tomcat : include_tasks] *********************************************************************************************************************
included: /home/jmutai/projects/ansible/roles/tomcat/tasks/tomcat-RedHat.yml for server1
included: /home/jmutai/projects/ansible/roles/tomcat/tasks/tomcat-Debian.yml for server2
TASK [tomcat : Set Server timezone] ***************************************************************************************************************
changed: [server1]
TASK [tomcat : Add EPEL repository to CentOS] *****************************************************************************************************
changed: [server1]
TASK [tomcat : Install basic packages] ************************************************************************************************************
changed: [server1]
TASK [tomcat : Install Java 8 CentOS] *************************************************************************************************************
changed: [server1]
TASK [tomcat : Add tomcat group] ******************************************************************************************************************
changed: [server1]
TASK [tomcat : Add "tomcat" user] *****************************************************************************************************************
changed: [server1]
TASK [tomcat : Download Tomcat] *******************************************************************************************************************
changed: [server1]
TASK [tomcat : Create a tomcat directory] *********************************************************************************************************
changed: [server1]
TASK [tomcat : Extract tomcat archive] ************************************************************************************************************
changed: [server1]
TASK [tomcat : Copy tomcat service file] **********************************************************************************************************
changed: [server1]
TASK [tomcat : Start and enable tomcat] ***********************************************************************************************************
changed: [server1]
TASK [tomcat : Start and enable firewalld] ********************************************************************************************************
changed: [server1]
TASK [tomcat : Open tomcat port on the firewall] **************************************************************************************************
changed: [server1]
TASK [tomcat : Set Server timezone] ***************************************************************************************************************
changed: [server2]
TASK [tomcat : Ensure the system can use the HTTPS transport for APT.] ****************************************************************************
ok: [server2]
TASK [tomcat : Install APT HTTPS transport.] ******************************************************************************************************
skipping: [server2]
TASK [tomcat : Install basic packages] ************************************************************************************************************
[WARNING]: Could not find aptitude. Using apt-get instead
changed: [server2]
TASK [tomcat : Install Default Java (Debian/Ubuntu)] **********************************************************************************************
changed: [server2]
TASK [tomcat : Add tomcat group] ******************************************************************************************************************
changed: [server2]
TASK [tomcat : Add "tomcat" user] *****************************************************************************************************************
changed: [server2]
TASK [tomcat : Download Tomcat] *******************************************************************************************************************
changed: [server2]
TASK [tomcat : Create a tomcat directory] *********************************************************************************************************
changed: [server2]
TASK [tomcat : Extract tomcat archive] ************************************************************************************************************
changed: [server2]
TASK [tomcat : Copy tomcat service file] **********************************************************************************************************
changed: [server2]
TASK [tomcat : Start and enable tomcat] ***********************************************************************************************************
changed: [server2]
PLAY RECAP ****************************************************************************************************************************************
server1 : ok=14 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
server2 : ok=13 changed=5 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Test your installation and configuration by visiting server URL on port 8080.

This is a green light for a successful installation of Tomcat on Ubuntu/Debian/CentOS using Ansible.
Related articles:
Build AWS EC2 Machine Images (AMI) With Packer and Ansible
Configure Jenkins behind Nginx reverse proxy and Let’s Encrypt SSL
How to Install Semaphore Ansible Web UI on CentOS 7 & Ubuntu 18.04