tech.guitarrapc.cóm

Technical updates

apt-key is deprecated. Manage keyring files in trusted.gpg.d insteadに対応する

AnsibleでGoをインストールするのにansible.builtin.apt_repositoryを使ってppaをインストールしていたのですが、Ubuntu 24.04からはエラーが出るようになりました。 ということで対処メモ。

Ansible処理変更前

当初はansible.builtin.apt_repositoryを使っていましたが、ここでエラーが出ます。

- name: "go - Add ppa:longsleep/golang-backports ppa repository"
  become: true
  ansible.builtin.apt_repository:
    repo: ppa:longsleep/golang-backports
    state: present

- name: "go - Install go"
  become: true
  ansible.builtin.apt:
    name: "golang-{{ go.version }}"
    state: latest
    update_cache: true
  register: apt
  until: "apt is not failed"
  retries: 2

エラーメッセージ

fatal: [localhost]: FAILED! => {"changed": false, "cmd": "/usr/bin/apt-key adv --recv-keys --no-tty --keyserver hkp://keyserver.ubuntu.com:80 876B22BA887CA91614B5323FC631127F87FA12D1", "msg": "Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).\ngpg: key C631127F87FA12D1: public key \"Launchpad PPA for Simon Eisenmann\" imported\ngpg: can't connect to the gpg-agent: IPC connect call failed\ngpg: Total number processed: 1\ngpg:               imported: 1", "rc": 2, "stderr": "Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).\ngpg: key C631127F87FA12D1: public key \"Launchpad PPA for Simon Eisenmann\" imported\ngpg: can't connect to the gpg-agent: IPC connect call failed\ngpg: Total number processed: 1\ngpg:               imported: 1\n", "stderr_lines": ["Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).", "gpg: key C631127F87FA12D1: public key \"Launchpad PPA for Simon Eisenmann\" imported", "gpg: can't connect to the gpg-agent: IPC connect call failed", "gpg: Total number processed: 1", "gpg:               imported: 1"], "stdout": "Executing: /tmp/apt-key-gpghome.swW3tIZwgo/gpg.1.sh --recv-keys --no-tty --keyserver hkp://keyserver.ubuntu.com:80 876B22BA887CA91614B5323FC631127F87FA12D1\n", "stdout_lines": ["Executing: /tmp/apt-key-gpghome.swW3tIZwgo/gpg.1.sh --recv-keys --no-tty --keyserver hkp://keyserver.ubuntu.com:80 876B22BA887CA91614B5323FC631127F87FA12D1"]}

Ansible処理変更後

ansible.builtin.apt_keyを使ってキーを管理して、リポジトリ定義をdeb形式に変更すれば解決です。なるほど、apt-keyが非推奨確定。

- name: "go - Add Golang PPA GPG key"
  become: true
  ansible.builtin.apt_key:
    id: "C631127F87FA12D1"
    keyserver: "keyserver.ubuntu.com"
    keyring: /etc/apt/trusted.gpg.d/longsleep.gpg
    state: present

- name: "go - Add Golang PPA repository with keyring"
  become: true
  ansible.builtin.apt_repository:
    repo: "deb [signed-by=/etc/apt/trusted.gpg.d/longsleep.gpg] http://ppa.launchpad.net/longsleep/golang-backports/ubuntu {{ ansible_distribution_release }} main"
    filename: "longsleep-golang-backports"
    state: present

- name: "go - Install go"
  become: true
  ansible.builtin.apt:
    name: "golang-{{ go.version }}"
    state: latest
    update_cache: true
  register: apt
  until: "apt is not failed"
  retries: 2

aptではなくバイナリインストールに切り替える

公式サイトでgoのインストールを見ると、aptからバイナリインストールに変わっています。 ということでAnsibleもそれに合わせましょう。

- name: "go - Create temporary directory for download"
  ansible.builtin.tempfile:
    state: directory
    prefix: golang_install
  register: temp_dir

- name: "go - Download Go tarball"
  ansible.builtin.get_url:
    url: "https://go.dev/dl/go{{ go.version }}.linux-amd64.tar.gz"
    dest: "{{ temp_dir.path }}/go.tar.gz"
    mode: "0644"
  register: download_result
  until: download_result is not failed
  retries: 3
  delay: 2

- name: "go - Remove previous Go installation if exists"
  become: true
  ansible.builtin.file:
    path: "/usr/local/go"
    state: absent
  when: default(false) # trueにすれば入れかえ

- name: "go - Extract Go tarball to /usr/local"
  become: true
  ansible.builtin.unarchive:
    src: "{{ temp_dir.path }}/go.tar.gz"
    dest: "/usr/local"
    remote_src: true
    creates: "/usr/local/go/bin/go"

- name: "go - Add Go to system PATH in /etc/profile.d"
  become: true
  ansible.builtin.copy:
    dest: "/etc/profile.d/profile_andible_init_go.sh"
    content: |
      export PATH=$PATH:/usr/local/go/bin
      export GOPATH=$HOME/go
      export PATH=$PATH:$GOPATH/bin
    mode: "0644"
  register: go_path

- name: "go - Clean up temporary directory"
  ansible.builtin.file:
    path: "{{ temp_dir.path }}"
    state: absent

あるいは、次のように指定したgoがすでにインストールされているかで判定してもいいでしょう。

- name: "go - Check if Go is already installed"
  ansible.builtin.command: /usr/local/go/bin/go version
  register: go_version_result
  ignore_errors: true
  changed_when: false
  check_mode: false

- name: "go - Check if specified Go version is installed"
  ansible.builtin.shell: set -o pipefail && /usr/local/go/bin/go version | grep -q "go{{ go.version }}"
  register: go_version_check
  ignore_errors: true
  changed_when: false
  check_mode: false

- name: "go - Install Go tasks"
  when: go_version_check is failed
  block:
    - name: "go - Create temporary directory for download"
      ansible.builtin.tempfile:
        state: directory
        prefix: golang_install
      register: temp_dir

    - name: "go - Download Go tarball"
      ansible.builtin.get_url:
        url: "https://go.dev/dl/go{{ go.version }}.linux-amd64.tar.gz"
        dest: "{{ temp_dir.path }}/go.tar.gz"
        mode: "0644"
      register: download_result
      until: download_result is not failed
      retries: 3
      delay: 2

    - name: "go - Remove previous Go installation if exists"
      become: true
      ansible.builtin.file:
        path: "/usr/local/go"
        state: absent

    - name: "go - Extract Go tarball to /usr/local"
      become: true
      ansible.builtin.unarchive:
        src: "{{ temp_dir.path }}/go.tar.gz"
        dest: "/usr/local"
        remote_src: true

    - name: "go - Add Go to system PATH in /etc/profile.d"
      become: true
      ansible.builtin.copy:
        dest: "/etc/profile.d/profile_andible_init_go.sh"
        content: |
          export PATH=$PATH:/usr/local/go/bin
          export GOPATH=$HOME/go
          export PATH=$PATH:$GOPATH/bin
        mode: "0644"
      register: go_path

    - name: "go - Clean up temporary directory"
      ansible.builtin.file:
        path: "{{ temp_dir.path }}"
        state: absent

実行するときは変数だけ設定しておきます。

go:
  version: "1.24.1"

実行してみる

$ ansible-playbook

実行例です。

TASK [tools : Go - Install go] *********************************************************************
included: /mnt/d/github/guitarrapc/local-provisioner/envs/include_role/ubuntu/install_go.yaml for localhost => (item=version)

TASK [tools : go - Check if Go is already installed] ***********************************************
fatal: [localhost]: FAILED! => {"changed": false, "cmd": "/usr/local/go/bin/go version", "msg": "[Errno 2] No such file or directory: b'/usr/local/go/bin/go'", "rc": 2, "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [tools : go - Parse installed Go version] *****************************************************
skipping: [localhost]

TASK [tools : go - Check if specified Go version is installed] *************************************
fatal: [localhost]: FAILED! => {"changed": false, "cmd": "set -o pipefail && /usr/local/go/bin/go version | grep -q \"go1.24.1\"", "delta": "0:00:00.003985", "end": "2025-03-27 02:48:04.628278", "msg": "non-zero return code", "rc": 1, "start": "2025-03-27 02:48:04.624293", "stderr": "/bin/bash: line 1: /usr/local/go/bin/go: No such file or directory", "stderr_lines": ["/bin/bash: line 1: /usr/local/go/bin/go: No such file or directory"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [tools : go - Create temporary directory for download] ****************************************
changed: [localhost]

TASK [tools : go - Download Go tarball] ************************************************************
changed: [localhost]

TASK [tools : go - Remove previous Go installation if exists] **************************************
ok: [localhost]

TASK [tools : go - Extract Go tarball to /usr/local] ***********************************************
changed: [localhost]

TASK [tools : go - Add Go to system PATH in /etc/profile.d] ****************************************
changed: [localhost]

TASK [tools : go - Clean up temporary directory] ***************************************************
changed: [localhost]

うまく入っていますね。

$ go version
go version go1.24.1 linux/amd64

まとめ

原型が残らなくなったんですが、aptを使いたくない理由の1つだったりします。 Ansible飽きたので、そろそろ別の仕組みに乗せ換えてもいい気がしてきました。

参考