Skip to content

Instantly share code, notes, and snippets.

@yorickdowne
Last active August 10, 2024 23:52
Show Gist options
  • Save yorickdowne/658ea3c79df5963e0829f152ba45db94 to your computer and use it in GitHub Desktop.
Save yorickdowne/658ea3c79df5963e0829f152ba45db94 to your computer and use it in GitHub Desktop.
Upgrade to Ubuntu Jammy Jellyfish

Ubuntu Jammy Jellyfish

To start, read the official release notes.

If your install fits into "vanilla Ubuntu plus maybe a handful of 3rd-party repos", then this guide for a simple upgrade to Ubuntu 22.04 "Jammy Jellyfish" from Ubuntu 20.04 "Focal Fossa" can be helpful. 3rd-party repos are handled with a find command.

Some Intel NUC10/11 with I225-LM or I225-V Ethernet chip may cause "freezing" of the OS after this update, if wired Ethernet is in use. There is no known fix; a workaround is to use a USB 3.0 to Ethernet dongle instead.

Note upgrade is only supported from Ubuntu 20.04 or later to Ubuntu 22.04. If you are on Ubuntu 18.04, upgrade to Ubuntu 20.04 first. Then once on Ubuntu 20.04, you can upgrade to Ubuntu 22.04.

  • Check free disk space

df -h

5 GiB free is a conservative amount. sudo apt clean and sudo apt autoremove can be used to free some disk space.

  • Identify any 3rd-party repos that may need to be updated. They'll be changed with a find command. ls /etc/apt/sources.list.d

  • Update current distribution

sudo apt-get update && sudo apt-get dist-upgrade --autoremove -y

If this brought in a new kernel, sudo reboot - otherwise continue

  • Update Ubuntu

For the following, keep existing config files when prompted.

sudo do-release-upgrade --allow-third-party

Reboot

sudo reboot

  • Change all 3rd-party repos

This is after the reboot so do-release-upgrade handles ubuntu.sources and third-party.sources.

The repos will have been disabled: They'll have a repo.list.distUpgrade file, but no repo.list file, ditto for repo.sources. Reenable them by copying their .list.distUpgrade file to .list, ditto for .sources.distUpgrade and .sources.

If you want to do this programatically:

find /etc/apt/sources.list.d -name "*.distUpgrade" | while IFS= read -r file; do
  base="${file%.distUpgrade}"
  if [ ! -e "$base" ]; then
    sudo cp "$file" "$base"
  fi
done

After that step, change focal to jammy.

sudo find /etc/apt/sources.list.d -type f \( -name '*.list' -o -name '*.sources' \) -exec sed -i 's/focal/jammy/g' {} \;

Run an apt update and if it fails on some repos because they haven't been updated to jammy, revert those to focal. Keep monitoring them and bring them to jammy when they are ready.

sudo apt-get update

Bring in the updated 3rd party repos

sudo apt-get dist-upgrade --autoremove

Automated by Ansible

Playbook jammy.yml:

---
- name: Upgrade to Ubuntu Jammy Jellyfish
  hosts: all
  serial: 1
  gather_facts: false
  roles:
    - base/upgrade_jammy

Role base/upgrade_jammy/tasks/main.yml:

---
- name: Get distribution version
  setup:
    filter: ansible_distribution*
- name: Skip if not Ubuntu 20.04
  meta: end_host
  when: ansible_distribution != 'Ubuntu' or ansible_distribution_version != '20.04'
- name: apt clean
  apt:
    clean: yes
  become: yes
- name: Get filesystem facts
  setup:
    filter: ansible_mounts
- name: Fail if free space on / is below 5 GiB
  ansible.builtin.assert:
    that:
      - item.size_available > (5 * 1024 * 1024 * 1024)
    fail_msg: "Free disk space on {{ item.mount }} is below 5 GiB"
  loop: "{{ ansible_mounts }}"
  when: item.mount == "/"
- name: All apt packages up to date
  apt:
    upgrade: dist
    update_cache: yes
  become: yes
- name: apt autoremove
  apt:
    autoremove: yes
  become: yes
- name: apt clean
  apt:
    clean: yes
  become: yes
- name: Check if reboot required
  ansible.builtin.stat:
    path: /run/reboot-required
  register: reboot_required_file
- name: Reboot if required
  ansible.builtin.reboot:
    msg: "Reboot initiated by Ansible"
    connect_timeout: 5
    reboot_timeout: 600
    pre_reboot_delay: 0
    post_reboot_delay: 60
    test_command: whoami
  when: reboot_required_file.stat.exists
  become: true
- name: Use do-release-upgrade to move to noble
  ansible.builtin.shell:
    cmd: do-release-upgrade -f DistUpgradeViewNonInteractive --allow-third-party
  become: yes
- name: Get distribution version
  setup:
    filter: ansible_distribution*
- name: Fail if not Ubuntu Jammy
  assert:
    that:
      - ansible_distribution_version == '22.04'
    fail_msg: "Upgrade to Ubuntu Jammy Jellyfish failed"
- name: Reboot on jammy
  ansible.builtin.reboot:
    msg: "Reboot initiated by Ansible"
    connect_timeout: 5
    reboot_timeout: 600
    pre_reboot_delay: 0
    post_reboot_delay: 60
    test_command: whoami
  become: yes
- name: Find all .distUpgrade files
  ansible.builtin.find:
    paths: /etc/apt/sources.list.d
    patterns: "*.distUpgrade"
  register: distupgrade_files
- name: Ensure corresponding file exists
  ansible.builtin.command: test -f "{{ item.path | regex_replace('.distUpgrade$', '') }}"
  ignore_errors: true
  register: check_file
  with_items: "{{ distupgrade_files.files }}"
  changed_when: false
- name: Copy .distUpgrade to the corresponding file if it does not exist
  ansible.builtin.command: cp "{{ item.item.path }}" "{{ item.item.path | regex_replace('.distUpgrade$', '') }}"
  when: item.rc != 0
  with_items: "{{ check_file.results }}"
  become: yes
- name: Find all repos
  ansible.builtin.find:
    paths: /etc/apt/sources.list.d
    patterns: ['*.list', '*.sources']
    recurse: no
  register: all_repos
- name: Switch repos from focal to jammy
  ansible.builtin.replace:
    path: "{{ item.path }}"
    regexp: 'focal'
    replace: 'jammy'
  loop: "{{ all_repos.files }}"
  loop_control:
    label: "{{ item.path }}"
  become: yes
- name: Bring in updated repos
  apt:
    upgrade: dist
    update_cache: yes
  become: yes
- name: apt autoremove
  apt:
    autoremove: yes
  become: yes
- name: Pause for 5 minutes for staggered upgrades
  pause:
    minutes: 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment