How can I manage keyring files in trusted.gpg.d with ansible playbook since apt-key is deprecated?

In short, you need to put the GPG key with the correct extension into a separate directory that is not searched by default, and point your repository configuration at that specific file.

For more info on why you need a separate directory, see this answer to “Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead”.

Warning: apt will not accept ASCII GPG keys saved with .gpg extension.

You can verify whether you have the old ASCII GPG format(.asc) or the newer binary GPG format(.gpg) via file:

# file elastic-old.gpg
elastic-old.gpg: PGP public key block Public-Key (old)

# file elastic.gpg    
elastic.gpg: PGP/GPG key public ring (v4) created Mon Sep 16 17:07:54 2013 RSA (Encrypt or Sign) 2048 bits MPI=0xd70ed6cd267c5b3e...

If your key is the old format, you can either use the .asc extension, or you can optionally de-armor it via gpg --dearmor elastic.gpg into the new binary format and use the .gpg extension.

The de-armor step is annoying for ansible automation, so I suggest you just use whatever format upstream provides as is.

On Ubuntu 22.04, there’s a folder you’re expected to use that is not preloaded – /etc/apt/keyrings – or you can create your own directory and use that.

As for the Ansible part, you can use get_url or file to push the GPG key onto the system, and then use apt_repository like before to add the repo, with the addition of specifying the keyring.

Using the binary GPG format with .gpg

- name: Add Example GPG key
  ansible.builtin.get_url:
    url: https://example.com/example.gpg
    dest: /etc/apt/keyrings/example.gpg
    mode: '0644'
    force: true

Or using the .asc extension if upstream still hasn’t switched over yet

- name: Add Example GPG key
  ansible.builtin.get_url:
    url: https://example.com/example.gpg
    dest: /etc/apt/keyrings/example.asc
    mode: '0644'
    force: true

Then you can define your repository via apt_repository module like before.

- name: Add Example repo
  ansible.builtin.apt_repository:
    filename: example-repo
    repo: 'deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com/packages/8.x/apt stable main'

Keep in mind that apt_repository uses the old .list format instead of the new DEB822 compliant .sources format.

If you want/need to use the newer DEB822 format and you happen to be running Ansible 2.15 or newer, you should use the deb822_repository module.

If you are stuck using older Ansible core, you can template it yourself similarly to this:

tasks/main.yaml

- name: Add Elastic repo
  notify: apt update force
  ansible.builtin.template:
    src: repo.j2
    dest: /etc/apt/sources.list.d/elastic-8.x.sources
    mode: '0644'
  vars:
    repo_name: Example PPA
    repo_uris: https://example.com/packages/8.x/apt
    repo_suites: stable
    repo_components: main
    repo_signed_by: /etc/apt/keyrings/example.gpg

templates/repo.j2

X-Repolib-Name: {{ repo_name }}
Types: deb
URIs: {{ repo_uris }}
Suites: {{ repo_suites }}
{% if repo_components is defined %}
Components: {{ repo_components }}
{% endif %}
Signed-By: {{ repo_signed_by }}

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)