Date: March 3, 2025 /  Author: Ralf Eichinger

Automated installation of Java with Ansible

In our previous post Automated administration with Ansible we installed Ansible for automated host administration.

Let’s use Ansible to install Java on the managed hosts.

We will write a playbook to use roles to install java on multiple managed host machines.

Prerequisites

First check setup of remote users on hosts:

$ cd mycompany-devops/ansible

$ ansible all -m command -a 'id' -i inventory.yml 
new_server | CHANGED | rc=0 >>
uid=1000(remote_username) gid=1000(remote_username) groups=1000(remote_username),27(sudo)
old_server | CHANGED | rc=0 >>
uid=1000(remote_username) gid=1000(remote_username) Gruppen=1000(remote_username),27(sudo)

So the user is in sudo group on all hosts. (As we see later this will not be sufficient …)

Check operating system on hosts:

$ ansible all -m setup -i inventory.yml | grep family
        "ansible_os_family": "Debian",
        "ansible_os_family": "Debian",

Write Playbook to install OpenJDK 21

As we manage Debian hosts we can use apt to install OpenJDK 21.

Playbook mycompany-devops/ansible/playbooks/openjdk-playbook.yaml:

- name: Install Java
  hosts: all
  tasks:
    - name: Install OpenJDK 21
      apt:
        name: openjdk-21-jdk
        state: present

Run the playbook:

$ ansible-playbook -i inventory.yml playbooks/openjdk-playbook.yaml

PLAY [Install Java] ************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************
ok: [old_server]
ok: [new_server]

TASK [Install OpenJDK 21] ******************************************************************************************************************************************
[WARNING]: Updating cache and auto-installing missing dependency: python3-apt
fatal: [old_server]: FAILED! => {"changed": false, "cmd": "/usr/bin/apt-get update", "msg": "E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)\nE: Unable to lock directory /var/lib/apt/lists/\nW: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)\nW: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)", "rc": 100, "stderr": "E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)\nE: Unable to lock directory /var/lib/apt/lists/\nW: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)\nW: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)\n", "stderr_lines": ["E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)", "E: Unable to lock directory /var/lib/apt/lists/", "W: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)", "W: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)"], "stdout": "Reading package lists...\n", "stdout_lines": ["Reading package lists..."]}
fatal: [new_server]: FAILED! => {"changed": false, "msg": "No package matching 'openjdk-21-jdk' is available"}

PLAY RECAP *********************************************************************************************************************************************************
new_server                 : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
old_server                 : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0  

The installation fails as the remote user lacks root privileges (“Permission denied”).

We configure the sudo password for the hosts in our inventory. Add ansible_become vars to each host (excerpt):

all:
  hosts:
    old_server:
      ansible_become: true
      ansible_become_method: sudo
      ansible_become_password: 'password'
    new_server:
      ansible_become: true
      ansible_become_method: sudo
      ansible_become_password: 'password'

We get error

fatal: [new_server]: FAILED! => {"changed": false, "msg": "No package matching 'openjdk-21-jdk' is available"}

So we change our playbook name to default-jre-playbook.yaml and to install package default-jre:

- name: Install Java Runtime Environment
  hosts: all
  tasks:
    - name: Install default JRE
      apt:
        name: default-jre
        state: present

Run playbook:

$ ansible-playbook -i inventory.yml playbooks/default-jre-playbook.yaml

PLAY [Install Java] ************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************
ok: [old_server]
ok: [new_server]

TASK [Install OpenJDK 21] ******************************************************************************************************************************************
[WARNING]: Updating cache and auto-installing missing dependency: python3-apt
fatal: [old_server]: FAILED! => {"changed": false, "cmd": "/usr/bin/apt-get update", "msg": "E: The repository 'http://apt.postgresql.org/pub/repos/apt buster-pgdg Release' no longer has a Release file.\nW: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: https://nginx.org/packages/mainline/debian buster InRelease:********@nginx.com>\nE: Failed to fetch https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/dists/buster/InRelease  Clearsigned file isn't valid, got 'NOSPLIT' (does the network require authentication?)\nE: The repository 'https://adoptopenjdk.jfrog.io/adoptopenjdk/deb buster InRelease' is no longer signed.", "rc": 100, "stderr": "E: The repository 'http://apt.postgresql.org/pub/repos/apt buster-pgdg Release' no longer has a Release file.\nW: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: https://nginx.org/packages/mainline/debian buster InRelease: The following signatures were invalid: EXPKEYSIG ABF5BD827BD9BF62 nginx signing key <signing-key@nginx.com>\nE: Failed to fetch https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/dists/buster/InRelease  Clearsigned file isn't valid, got 'NOSPLIT' (does the network require authentication?)\nE: The repository 'https://adoptopenjdk.jfrog.io/adoptopenjdk/deb buster InRelease' is no longer signed.\n", "stderr_lines": ["E: The repository 'http://apt.postgresql.org/pub/repos/apt buster-pgdg Release' no longer has a Release file.", "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: https://nginx.org/packages/mainline/debian buster InRelease: The following signatures were invalid: EXPKEYSIG ABF5BD827BD9BF62 nginx signing key <signing-key@nginx.com>", "E: Failed to fetch https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/dists/buster/InRelease  Clearsigned file isn't valid, got 'NOSPLIT' (does the network require authentication?)", "E: The repository 'https://adoptopenjdk.jfrog.io/adoptopenjdk/deb buster InRelease' is no longer signed."], "stdout": "Hit:1 https://nginx.org/packages/mainline/debian buster InRelease\nHit:2 http://security.debian.org buster/updates InRelease\nIgn:3 http://apt.postgresql.org/pub/repos/apt buster-pgdg InRelease\nHit:4 http://ftp.debian.org/debian buster InRelease\nErr:5 http://apt.postgresql.org/pub/repos/apt buster-pgdg Release\n  404  Not Found [IP: 147.75.85.69 80]\nHit:6 http://ftp.debian.org/debian buster-updates InRelease\nErr:1 https://nginx.org/packages/mainline/debian buster InRelease\n  The following signatures were invalid: EXPKEYSIG ABF5BD827BD9BF62 nginx signing key <signing-key@nginx.com>\nGet:7 https://adoptopenjdk.jfrog.io/adoptopenjdk/deb buster InRelease [11.5 kB]\nErr:7 https://adoptopenjdk.jfrog.io/adoptopenjdk/deb buster InRelease\n  Clearsigned file isn't valid, got 'NOSPLIT' (does the network require authentication?)\nReading package lists...\n", "stdout_lines": ["Hit:1 https://nginx.org/packages/mainline/debian buster InRelease", "Hit:2 http://security.debian.org buster/updates InRelease", "Ign:3 http://apt.postgresql.org/pub/repos/apt buster-pgdg InRelease", "Hit:4 http://ftp.debian.org/debian buster InRelease", "Err:5 http://apt.postgresql.org/pub/repos/apt buster-pgdg Release", "  404  Not Found [IP: 147.75.85.69 80]", "Hit:6 http://ftp.debian.org/debian buster-updates InRelease", "Err:1 https://nginx.org/packages/mainline/debian buster InRelease", "  The following signatures were invalid: EXPKEYSIG ABF5BD827BD9BF62 nginx signing key <signing-key@nginx.com>", "Get:7 https://adoptopenjdk.jfrog.io/adoptopenjdk/deb buster InRelease [11.5 kB]", "Err:7 https://adoptopenjdk.jfrog.io/adoptopenjdk/deb buster InRelease", "  Clearsigned file isn't valid, got 'NOSPLIT' (does the network require authentication?)", "Reading package lists..."]}
changed: [new_server]

PLAY RECAP *********************************************************************************************************************************************************
new_server                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
old_server                 : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0 

The installation was successful on new_server but failed on old_server because of misconfiguration.

Let’s check the installed java:

$ ansible new_server -m command -a 'java --version' -i inventory.yml 
new_server | CHANGED | rc=0 >>
openjdk 17.0.14 2025-01-21
OpenJDK Runtime Environment (build 17.0.14+7-Debian-1deb12u1)
OpenJDK 64-Bit Server VM (build 17.0.14+7-Debian-1deb12u1, mixed mode, sharing)

So Java 17 is installed successfully on new_server.

 Tags:  topics devops

Previous
⏪ Automated administration with Ansible

Next
Deploy a Spring Boot Webapp to a VM with Ansible ⏩