ArticlesLinuxOpen Source Software

Ubuntu 20.04 Focal Fossa EOL: Beware these upgrade gotchas

In just two months (in April 2025), the widely used Linux distribution Ubuntu 20.04, code named Focal Fossa, will be end of life (EOL) and won't receive any public updates anymore. Time to upgrade!

Goodbye, Ubuntu Focal Fossa

Canonical, the company behind Ubuntu, continues to support Ubuntu 20.04 LTS for another 5 years for paying customers through the Extended Security Maintenance plan. See our list of LTS Linux distributions for more details.

RIP Ubuntu 20.04 Focal Fossa
RIP Ubuntu 20.04 Focal Fossa

Although an upgrade of Ubuntu to a newer LTS version, usually works very well, there are always some gotchas or configuration changes.

We've put together a list of applications to watch out for when upgrading your Ubuntu LTS version from 20.04 to 22.04 or the currently newest LTS release (24.04).

Note: Never jump across a major LTS release! Upgrade from one LTS version to the next. 20.04 -> 22.04 -> 24.04 etc.

sudoers

The /etc/sudoers file received some changes. However if you added entries to /etc/sudoers, these will be overwritten and be gone if you decide to not keep your existing configuration:

Configuration file '/etc/sudoers'
 ==> Modified (by you or by a script) since installation.
 ==> Package distributor has shipped an updated version.
   What would you like to do about it ?  Your options are:
    Y or I  : install the package maintainer's version
    N or O  : keep your currently-installed version
      D     : show the differences between the versions
      Z     : start a shell to examine the situation
 The default action is to keep your current version.
*** sudoers (Y/I/N/O/D/Z) [default=N] ? N

We recommend to keep the /etc/sudoers file as is and manually add the changes. Which are:

  • Added "Defaults use_pty"
  • Changed syntax from #include to @include

You can easily append these changes after the distribution upgrade with the following sed commands:

root@jammy:~# sed -i "/secure_path/ a\Defaults        use_pty" /etc/sudoers
root@jammy:~# sed -i "s/#include/@include/g" /etc/sudoers

Maybe now is also a good time to move all your custom added sudoers rules and entries into a separate file into the /etc/sudoers.d/ directory to prevent running into this problem again at the next distribution upgrade.

New APT repository key method

With the change from Ubuntu 20.04 to 22.04, the way apt repository keys is slightly different.

In the past releases, an APT repository key were added to the system by using the apt-key command. Here's an example using the PowerDNS APT repositories:

root@focal:~# curl -s https://repo.powerdns.com/CBC8B383-pub.asc | apt-key add -
OK

You then needed to add the repository in a .list file (without mentioning the key):

root@focal:~# cat /etc/apt/sources.list.d/powerdns.list 
deb http://repo.powerdns.com/ubuntu focal-auth-49 main

After a dist-upgrade to 22.04 (or newer), this apt-key method now leads to to a deprecation warning:

root@jammy:~# apt-get update
Hit:1 http://repo.powerdns.com/ubuntu jammy-auth-49 InRelease
[...]
Fetched 3755 kB in 1s (2569 kB/s)                        
Reading package lists... Done
W: http://repo.powerdns.com/ubuntu/dists/jammy-auth-49/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.

From now on, you need to download and save APT repository keys as separate "keyring" files and the repository needs to refer to this saved key:

root@jammy:~# curl -fsSL http://repo.powerdns.com/FD380FBB-pub.asc | sudo gpg --dearmor -o /usr/share/keyrings/powerdns.gpg

root@jammy:~# echo "deb [signed-by=/usr/share/keyrings/powerdns.gpg] http://repo.powerdns.com/ubuntu jammy-auth-49 main" | sudo tee /etc/apt/sources.list.d/powerdns.list
deb [signed-by=/usr/share/keyrings/powerdns.gpg] http://repo.powerdns.com/ubuntu jammy-auth-49 main

After this change, the output of apt update doesn't show the deprecation warning anymore:

root@jammy:~# apt-get update
Hit:1 http://repo.powerdns.com/ubuntu jammy-auth-49 InRelease
Hit:2 http://eu-central-1.ec2.archive.ubuntu.com/ubuntu jammy InRelease                                  
Hit:3 http://eu-central-1.ec2.archive.ubuntu.com/ubuntu jammy-updates InRelease                          
Hit:4 http://security.ubuntu.com/ubuntu jammy-security InRelease                                         
Reading package lists... Done

libc6 service restart error

During the distribution upgrade process, you might run into a service restart error, triggered by the libc package upgrade:

Unpacking libc6:amd64 (2.35-0ubuntu3.9) over (2.31-0ubuntu9.17) ...
Setting up libc6:amd64 (2.35-0ubuntu3.9) ...
Checking for services that may need to be restarted...
Checking init scripts...
Restarting services possibly affected by the upgrade:
  cron: restarting...done.
  mysql: restarting...FAILED! (1)
  atd: restarting...done.

In this situation the mysql service failed to restart. Although this doesn't look nice in the output, this can be ignored and the upgrade process continues on.

MySQL or MariaDB will restart anyway once these packages are upgraded, too.

PostgreSQL Upgrade

In Ubuntu 20.04 the default PostgreSQL version is 12. A distribution upgrade to Ubuntu 22.04 upgrades PostgreSQL to version 14. Upgrades? The PostgreSQL upgrade is better described as new and secondary installation to the previous version.

After the Ubuntu upgrade two PostgreSQL clusters show up:

root@jammy:~# pg_lsclusters 
Ver Cluster Port Status Owner    Data directory              Log file
12  main    5432 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log
14  main    5433 online postgres /var/lib/postgresql/14/main /var/log/postgresql/postgresql-14-main.log

We can see that the older version (12) is still running under the default PostgreSQL port tcp/5432. The newly installed PostgreSQL 14 cluster is listening under tcp/5433. Both versions run alongside after the Ubuntu upgrade.

Does the newer version actually contain the application databases?

First connect to the original PostgreSQL server, running version 12:

root@jammy:~# su - postgres

postgres@jammy:~$ psql -p 5432
psql (14.15 (Ubuntu 14.15-0ubuntu0.22.04.1), server 12.22 (Ubuntu 12.22-0ubuntu0.20.04.1))
Type "help" for help.

postgres=# \l
                              List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  |   Access privileges   
-----------+----------+----------+---------+---------+-----------------------
 dnsui     | dnsui    | UTF8     | C.UTF-8 | C.UTF-8 | 
 postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 | 
 template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
 template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
(4 rows)

The application database ('dnsui' in this example) shows up. As expected.

What about the newly installed PostgreSQL 14? Let's verify:

postgres@jammy:~$ psql -p 5433
psql (14.15 (Ubuntu 14.15-0ubuntu0.22.04.1))
Type "help" for help.

postgres=# \l
                              List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  |   Access privileges   
-----------+----------+----------+---------+---------+-----------------------
 postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 | 
 template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
 template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
(3 rows)

The application database is missing here!

This means the Ubuntu distribution upgrade installed a new but empty PostgreSQL 14, but did not upgrade the existing databases to the new PostgreSQL version.

To do a proper database upgrade, you first need to shut down the new (and empty) PostgreSQL 14 server and delete the cluster:

root@jammy:~# pg_dropcluster --stop 14 main

root@jammy:~# pg_lsclusters 
Ver Cluster Port Status Owner    Data directory              Log file
12  main    5432 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log

Now run the pg_upgradecluster command to upgrade the PostgreSQL 12 instance to version 14:

root@jammy:~# pg_upgradecluster 12 main
Stopping old cluster...
Restarting old cluster with restricted connections...
[...]
Stopping target cluster...
Stopping old cluster...
Disabling automatic startup of old cluster...
Starting upgraded cluster on port 5432...

Success. Please check that the upgraded cluster works. If it does,
you can remove the old cluster with
    pg_dropcluster 12 main

Ver Cluster Port Status Owner    Data directory              Log file
12  main    5433 down   postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log
Ver Cluster Port Status Owner    Data directory              Log file
14  main    5432 online postgres /var/lib/postgresql/14/main /var/log/postgresql/postgresql-14-main.log

Now the databases were upgraded/migrated to the newer PostgreSQL version. The tcp listener has also changed now and the default PostgreSQL port tcp/5432 now points to PostgreSQL 14.

PostgreSQL server upgrade
PostgreSQL upgrade on Ubuntu

This is the time where you test your applications, using PostgreSQL databases. If all is successful, you can remove the now powered down old PostgreSQL version using pg_dropcluster.

Apache2 + PHP module

In Ubuntu 20.04 the onboard PHP version was 7.4. After the Ubuntu upgrade to 22.04, the new PHP version is 8.1 and php7.4 packages are removed by the upgrade process.

If you use an Apache2 web server and enabled the PHP module (libapache2-mod-php), Apache2 will run into a problem and will not start anymore. This can be seen in the apache2 service status:

Apache2 service failed to start after Ubuntu upgrade
Apache2 service failed to start after Ubuntu upgrade

The status output above doesn't show the reason though. To find out more, we can run apache2ctl:

root@jammy:~# apache2ctl configtest
apache2: Syntax error on line 146 of /etc/apache2/apache2.conf: Syntax error on line 3 of /etc/apache2/mods-enabled/php7.4.load: Cannot load /usr/lib/apache2/modules/libphp7.4.so into server: /usr/lib/apache2/modules/libphp7.4.so: cannot open shared object file: No such file or directory
Action 'configtest' failed.
The Apache error log may have more information.

The error shows that the libphp7.4so module cannot be loaded. The reason is, as mentioned before, that the php7.4 packages were removed and this needs to be switched to PHP 8.1.

Disable the php7.4 Apache2 module and enable the new php8.1 Apache2 module:

root@jammy:~# a2dismod php7.4
Module php7.4 disabled.
To activate the new configuration, you need to run:
  systemctl restart apache2

root@jammy:~# a2enmod php8.1
Considering dependency mpm_prefork for php8.1:
Considering conflict mpm_event for mpm_prefork:
Considering conflict mpm_worker for mpm_prefork:
Module mpm_prefork already enabled
Considering conflict php5 for php8.1:
Enabling module php8.1.
To activate the new configuration, you need to run:
  systemctl restart apache2

This has now resolved the configuration error and apache2 can be restarted:

root@jammy:~# apache2ctl configtest
Syntax OK

root@jammy:~# systemctl restart apache2

OpenSSH Server

There are a couple of configuration changes in the OpenSSH server configuration (/etc/ssh/sshd_config).

Changes to OpenSSH server configuration after Ubuntu upgrade

Besides adding or modifying some comments, the following changes are important to note:

  • The configuration option ChallengeResponseAuthentication was replaced by KbdInteractiveAuthentication
  • PID location was moved from /var/run/sshd.pid to /run/sshd.pid

Besides this, manually enabled options, such as PermitRootLogin, are removed if the maintainer's version is selected.

If you decide to keep your location configuration, you can use the following commands to change sshd_config to the new Ubuntu 22.04 options:

root@jammy:~# sed -i "s#/var/run/sshd.pid#/run/sshd.pid#" /etc/ssh/sshd_config
root@jammy:~# sed -i "s/ChallengeResponseAuthentication/KbdInteractiveAuthentication/g" /etc/ssh/sshd_config

Claudio Kuenzler
Claudio has been writing way over 1000 articles on his own blog since 2008 already. He is fascinated by technology, especially Open Source Software. As a Senior Systems Engineer he has seen and solved a lot of problems - and writes about them.

You may also like

Leave a reply

Your email address will not be published. Required fields are marked *

More in:Articles