Red Hat Enterprise Linux 8.1


Just as I published last Unix Tutorial Digest on November 5th, RHEL 8.1 release got shipped – think this is a great incremental release bringing a number of key improvements to the Red Hat Enterprise Linux 8.

RHEL 8 Release Cadence

Red Hat announced that going forward Red Hat Enterprise Linux OS will be receiving regular updates every 6 months. Since RHEL 8 release was in May 2019, this current RHEL 8.1 update is right on time, 6 months after.

RHEL 8.1 Improvements I Want To Try

There’s a number of great improvements in this release:

  • Live Kernel Patching with kpatch
  • SELinux profiles for containers and tbolt for Thunderbolt devices – will be cool to try on my RHEL 8 PC
  • Perhaps try RHEL 7.6 in-place upgrade to RHEL 8.1
  • Review rhel-system-roles and specifically the new storage role added in RHEL 8.1
  • LUKS2 online re-encryption
  • RHEL 8 Web Console
    • firewall zones management
    • Virtual Machines configuration

I also want to try Red Hat Universal Base Image for RHEL 8 – it’s been around since initial release in May, I just never got the chance to have a look.

See Also

Ubuntu 19.10

Ubuntu 19.10
Ubuntu 19.10 Desktop Wallpaper

Ubuntu 19.10 was released on October 17th, which means it’s time to upgrade Ubuntu on my Dell XPS laptop. Please note this is NOT a long-term support (LTS) release, so 19.10 will only be supported until July 2020.

Ubuntu 19.10 – Eoan Ermine

Seems like a pretty solid upgrade:

  • WPA3 support for improved wireless security – need to check if I can upgrade my Ubiquiti equipment to support it
  • Linux Kernel upgraded to 5.3 – this is where I expect majority of improvements for my laptop
  • Dark Theme – in a very short space of just a few months I’m now using dark themes on my iPhone, desktop and laptop, plus in as many apps as support it properly
  • Ubuntu 19.10 is available for Raspberry Pi 4
  • lots of visual improvements in each of the Ubuntu editions – Xubuntu, Kubuntu, Ubuntu MATE

Download Ubuntu 19.10

As always, the best place to start with Ubuntu download is

Upgrading to Ubuntu 19.10

I did the usual sequence to get my laptop upgraded. Except the last step which needed the -d option to recognise that Ubuntu 19.10 is available. All of these commands were run through sudo.

  • apt update
  • apt upgrade
  • apt dist-upgrade
  • do-release-upgrade -d

Do you use Ubuntu? When are you planning to upgrade?

See Also

ZFS on root in Ubuntu 19.10

Ubuntu 19.10

Just read about ZFS making it into Ubuntu 19.10 installer as an experimental feature here, sounds pretty cool!

What is ZFS?

ZFS (originally called Zettabyte File System) is a revolutionary filesystem introduced by Sun Microsystems in 2005. ZFS took a few years to crystallise and was eventually shipped with Solaris 10 in 2009. It brought a number of fresh ideas to the world of enterprise storage and ZFS management of filesystems:

  • new parity checking modes, even more reliable than RAID5/RAID6
  • storage pool that can consist of different sized disks (typically you expect all disks to be of the same size and model)
  • self-healing
  • extra focus on the data consistency on disk – meaning ZFS caters for typical software and hardware errors
  • smart implementation and use of filesystem journaling
  • snapshots
  • data deduplication

ZFS in Ubuntu 19.10

To be clear, this is big deal not because ZFS is finally available in Ubuntu – it’s been around for quite some time thanks to the ZFS on Linux project. But this is the first time native support will be available in Ubuntu installer and also allow you to not just ZFS enable data disks but use it for root partition.

See Also

preserve-root flag for rm command

rm will warn you instead of removing everything in / recursively

rm command, the one used to delete files and directories, can be very dangerous if used with root privileges. It’s comforting to know that most modern rm implementations attempt to help you avoid a complete disaster (of deleting everything on your OS disk).

What preserve-root Flag Does

Default behaviour of rm command in Linux for quite some time, preserve-root flag means that if you attempt to recursively remove the root (/) directory you would get a warning:

greys@stream:/ $ rm -rf /
rm: it is dangerous to operate recursively on '/'
rm: use --no-preserve-root to override this failsafe

Why would this be dangerous? Because every directory and filesystem in Unix and Linux is mounted off root (/) path. So if you remove files/directories there recursively, you may wipe out your entire operating system (and quite a bit of mounted filesystems, if your’e really out of luck).

Now, I’m running this command as my own regular user in the example above. So even if rm wasn’t protecting me, I would still be unable to do any real harm to the OS due to core OS files being protected from accidental removal by regular users. But if I was running as root, it would have been really dangerous.

Why preserve-root is Really Useful

Of course, most of us would never consciously attempt removing everything under /, but here’s a very typical scenario that is quite common with beginners: using unitialised variables (empty values).

greys@stream:/ $ MYDIR=mydir
greys@stream:/ $ echo rm -rf /${MYDIR}
rm -rf /mydir
greys@stream:/ $ rm -rf /${MYDIR}

In this example above, I have a variable called MYDIR, which points to a directory. I’m runnign echo command first to verify what rm command will look like – and it seems correct, so I attempt it.

But if I forget to initialise the MYDIR variable, its value will be empty, meaning my command will become much more dangerous:

greys@stream:/ $ MYDIR=
greys@stream:/ $ echo rm -rf /${MYDIR}
rm -rf /
greys@stream:/ $ rm -rf /${MYDIR}
rm: it is dangerous to operate recursively on '/'
rm: use --no-preserve-root to override this failsafe

See Also

Show Process Limits Using /proc Filesystem

Show process limits with /proc filesystem

I think I mentioned the special /proc filesystem before, it’s available in Linux distros and helps you obtain system and process information via normal files created in a special structure. Today I’d like to show you another cool trick /proc has.

Show Process Info Using /proc

Just to remind you, here’s what I mean: on my Red Hat PC I have this sshd daemon process running:

root@redhat:/ # ps -aef | grep [o]penssh
root 5130 1 0 Oct03 ? 00:00:00 /usr/sbin/sshd -D,,aes256-ctr,aes256-cbc,,aes128-ctr,aes128-cbc,,,,hmac-sha2-256,hmac-sha1,,hmac-sha2-512 -oGSSAPIKexAlgorithms=gss-gex-sha1-,gss-group14-sha1-,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1 -oHostKeyAlgorithms=rsa-sha2-256,ecdsa-sha2-nistp256,,ecdsa-sha2-nistp384,,rsa-sha2-512,ecdsa-sha2-nistp521,,ssh-ed25519,,ssh-rsa, -oPubkeyAcceptedKeyTypes=rsa-sha2-256,ecdsa-sha2-nistp256,,ecdsa-sha2-nistp384,,rsa-sha2-512,ecdsa-sha2-nistp521,,ssh-ed25519,,ssh-rsa,

So the sshd process ID (PID) is 5130. That means I can use /proc filesystem to learn quite a bit about the process:

root@redhat:/ # cd /proc/5130
root@redhat:/proc/5130 # ls
 attr        cmdline          environ  io         mem         ns             pagemap      sched      smaps_rollup  syscall        wchan
 autogroup   comm             exe      limits     mountinfo   numa_maps      patch_state  schedstat  stack         task
 auxv        coredump_filter  fd       loginuid   mounts      oom_adj        personality  sessionid  stat          timers
 cgroup      cpuset           fdinfo   map_files  mountstats  oom_score      projid_map   setgroups  statm         timerslack_ns
 clear_refs  cwd              gid_map  maps       net         oom_score_adj  root         smaps      status        uid_map

Each file or directory in this /proc/5130 location shows some information specific to this PID 5130.

For instance, if we list files in the fd directory there, we’ll see all the files and sockets open by sshd at the moment:

root@redhat:/proc/5130 # ls -al fd/*
lr-x------. 1 root root 64 Oct 3 14:10 fd/0 -> /dev/null
lrwx------. 1 root root 64 Oct 3 14:10 fd/1 -> 'socket:[39555]'
lrwx------. 1 root root 64 Oct 3 14:10 fd/2 -> 'socket:[39555]'
lr-x------. 1 root root 64 Oct 3 14:10 fd/3 -> /dev/urandom
lr-x------. 1 root root 64 Oct 3 14:10 fd/4 -> /var/lib/sss/mc/passwd
lrwx------. 1 root root 64 Oct 3 14:10 fd/5 -> 'socket:[45446]'
lrwx------. 1 root root 64 Oct 3 14:10 fd/6 -> 'socket:[45450]'
lr-x------. 1 root root 64 Oct 3 14:10 fd/7 -> /var/lib/sss/mc/group
lrwx------. 1 root root 64 Oct 3 14:10 fd/8 -> 'socket:[45452]'

TODO: I’ll be sure to write a separate post on the /proc filesystem with more thorough walkthrough.

Show Process Limits Using /proc

One of the files in /proc subdirectories is file called limits, and it’s super useful for confirming the current OS limits applied to the process in question.

So for the sshd process with PID 5130, here’s what we can see:

root@redhat:/proc/5130 # cat limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 127372 127372 processes
Max open files 1024 4096 files
Max locked memory 16777216 16777216 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 127372 127372 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us

Basically, this confirms that I haven’t fine-tuned anything on this new desktop just yet – open files count of 1024 is small cause it’s not a server that requires serving multiple files simultaneously.

Hope you find this useful!

See Also

Run Ansible Tasks Based on OS Distribution

Skipping Tasks Based on Ansible Conditionals

I’m actively refreshing my Ansible setup for both servers and desktops, running mostly Red Hat Enterprise Linux and CentOS Linux. Today’s quick tip is about the functionality that Ansible has for precise control of configuration management in such closely related distros.

How To Run Ansible Task In Specific OS Distribution

Ansible has quite a few facts it collects about each managed system, they are usually established (collected) at the very start of running any playbook (unless you decide to skip gathering facts).

A whole group of Ansible facts talks about OS distribution. Here they are as confirmed form the freshly deployed CentOS 8 Stream VM:

One of these facts is ansible_distribution:

greys@maverick:~/proj/ansible $ ansible stream -m setup| grep distribution
"ansible_distribution": "CentOS",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/redhat-release",
"ansible_distribution_file_variety": "RedHat",
"ansible_distribution_major_version": "8",
"ansible_distribution_release": "Core",
"ansible_distribution_version": "8.0",

We can use the very first one, called ansible_distribution. For CentOS, it says “CentOS”, but for Red Hat Enterprise Linux, it will be “RedHat”.

Example of using ansible_distribution

I have the following task below. It’s activating RHEL 8 subscription using my account, but obviously should only be doing this for Red Hat systems. For CentOS, I simply want to skip this task.

That’s why I’m checking for ansible_distribution, and as per below – the code will only run if and when the distribution is speficially RedHat, and not CentOS as my “stream” VM:

- name: Register RHEL 8 against Tech Stack
  shell: "subscription-manager register --activationkey=rhel8 --org=100XXXXX --force"
    - rhel
    ansible_distribution == "RedHat" 

That’s it! Even if I specify the tags=rhel filter, ansible-playbook will skip this task based on the collected facts (stream is the VM hostname):

greys@maverick:~/proj/ansible $ ansible-playbook --tags=rhel vm.yaml
PLAY [Tech Stack baseline] ***
TASK [Gathering Facts] *
ok: [stream]
TASK [techstack : Register RHEL 8 against Tech Stack] 
skipping: [stream]
stream                     : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

See Also

CentOS 8 and CentOS Stream Released

Great news, CentOS 8 is released now. Even better – there’s now a step in between Fedora and RHEL, called CentOS Stream.

Have you tried them yet? I’ll be upgrading to CentOS 8 this week and am also thinking of downloading and installing CentOS Stream in a KVM VM.

Let me know what you think!

See Also

Attach Interface to Specific Firewall Zone in RHEL 8


One of the first things I had to do on my recently built RHEL 8 PC was to move the primary network interface from public (default) zone to home zone – to make sure any firewall ports I open stay private enough.

How To List Which Zones and Interfaces are Active

Using the get-active-zones option of the firewall-cmd command, it’s possible to confirm where eno1 interface is at the moment. It’s already in the home zone cause I made the update earlier:

root@redhat:~ # firewall-cmd --get-active-zones
  interfaces: eno1
  interfaces: virbr0

Attach Interface to a Firewall Zone

Here’s how one can move specified interface into a zone we want:

root@redhat:~ # firewall-cmd --zone=home --change-interface=eno1

Just to show how it works, I’m going to move eno1 into public zone and back to home one:

root@redhat:~ # firewall-cmd --zone=public --change-interface=eno1
root@redhat:~ # firewall-cmd --get-active-zones
  interfaces: virbr0
  interfaces: eno1

Making Sure Firewall Changes Are Permanent

Don’t forget that after confirming a working firewall configuration, you need to re-run the same command with permanent option – this will update necessary files to make sure your firewall changes can survive a reboot:

root@redhat:~ # firewall-cmd --zone=home --change-interface=eno1 --permanent
The interface is under control of NetworkManager, setting zone to 'home'.

That’s it for today. Am really enjoying RHEL 8 configuration and still have this feeling I barely scratch the surface with all the new improvements this Red Hat Enterprise Linux brings.

See Also

Hello, World in podman


Turns out it’s not that easy to install Docker CE in RHEL 8 just yet. Well, maybe there’s no immediate need since RHEL 8 comes with its own containerization stack based on podman?

Hello, World in podman

podman provides comprehensive compatibility with docker command, most non-Docker specific options are supported.

If you are familiar with docker command syntax, give it a try by just replacing docker with podman command. 

Let’s do the hello world exercise:

greys@redhat:~ $ podman run hello-world
Trying to pull…Failed
Trying to pull…Failed
Trying to pull…Getting image source signatures
Copying blob 1b930d010525: 977 B / 977 B [==================================] 0s
Copying config fce289e99eb9: 1.47 KiB / 1.47 KiB [==========================] 0s
Writing manifest to image destination
Storing signatures

Hello from Docker!

This message shows that your installation appears to be working correctly.

To try something more ambitious, you can run an Ubuntu container with:

$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:

For more examples and ideas, visit:

As you can see, podman searches in Red Hat and Quay image repositories before moving on to Docker registry, but finally gets the hello-world image there.

Run Ubuntu image in podman

And if we want to follow Docker’s advice and try running the Ubuntu Docker image, we’ll replace

docker run -it ubuntu bash


podman run -it ubuntu bash

… It just works:

greys@redhat:~ $ podman run -it ubuntu bash
Trying to pull…Failed
Trying to pull…Failed
Trying to pull…Getting image source signatures
Copying blob 5667fdb72017: 25.45 MiB / 25.45 MiB [==========================] 3s
Copying blob d83811f270d5: 34.53 KiB / 34.53 KiB [==========================] 3s
Copying blob ee671aafb583: 850 B / 850 B [==================================] 3s
Copying blob 7fc152dfb3a6: 163 B / 163 B [==================================] 3s
Copying config 2ca708c1c9cc: 3.33 KiB / 3.33 KiB [==========================] 0s
Writing manifest to image destination
Storing signatures
root@686f0d85b4ad:/# uname -a
Linux 686f0d85b4ad 4.18.0-80.el8.x86_64 #1 SMP Wed Mar 13 12:02:46 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
root@686f0d85b4ad:/# cat /etc/lsb-release 

I think it’s pretty cool. Will definitely read up and post more about podman and containerization in Red Hat in the following weeks.

See Also

Upgrading to CentOS 7.7


CentOS 7.7 has just been released a few days ago and with any luck CentOS 8 will be released next week. I decided to quickly upgrade one of my dedicated servers from CentOS 7.6 to CentOS 7.7.

Confirm CentOS Version

Just a couple of steps to check what CentOS release we’re running:

root@s2:~ # cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)

There should also be a package reflecting CentOS release already installed on your system. This package will be upgraded along with the rest of the OS when we’re stepping up to CentOS 7.7:

root@s2:~ # rpm -qa | grep centos-release

Check Available CentOS Upgrades

yum command has the check-update option for verifying if any packages are available for updating:

root@s2:~ # yum check-update

This will return a rather long list. To be super-sure we’ll actually get the CentOS 7.7 upgrade, look for the same centos-release package:

root@s2:~ # yum check-update | grep centos-release
 centos-release.x86_64                    7-7.1908.0.el7.centos           base

Upgrade CentOS 7.6 to CentOS 7.7

We need the yum update command here. After you run it it will resolve dependencies and report something like this, prompting for your confirmation:

Transaction Summary
Install    3 Packages (+25 Dependent packages)
Upgrade  406 Packages
Total download size: 577 M
Is this ok [y/d/N]:

Sounds about right! We’ll press Y and let the server download and apply all the updates…

On my hosting it took about 1min to download all the packages!

Transaction Summary
Install    3 Packages (+25 Dependent packages)
Upgrade  406 Packages
Total download size: 577 M
Is this ok [y/d/N]:
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
 Updating   : libgcc-4.8.5-39.el7.x86_64                                                                                                       1/841
 Installing : urw-base35-fonts-common-20170801-10.el7.noarch                                                                                   2/841
 Updating   : 1:grub2-common-2.02-0.80.el7.centos.noarch                                                                                       3/841
 Updating   : centos-release-7-7.1908.0.el7.centos.x86_64                                                                                      4/841
 Updating   : langtable-0.0.31-4.el7.noarch                                                                                                    5/841
 Updating   : libreport-filesystem-2.1.11-43.el7.centos.x86_64                                                                                 6/841
yum-plugin-fastestmirror.noarch 0:1.1.31-52.el7                           yum-utils.noarch 0:1.1.31-52.el7
   urw-fonts.noarch 0:2.4-16.el7

It took less than 10 min to apply all the package updates, so the only things left are to capture current kernel version before and after the reboot:

root@s2:/ # uname -a
Linux s2 3.10.0-957.5.1.el7.x86_64 #1 SMP Fri Feb 1 14:54:57 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Now let’s reboot:

root@s2:/ # shutdown -r now

… and confirm that we’re running newer Linux Kernel and sporting the CentOS 7.7 release now:

greys@s2:~ $ uname -a
Linux s2 3.10.0-1062.1.1.el7.x86_64 #1 SMP Fri Sep 13 22:55:44 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Hmmm. This does look a bit conservative! It’s 3.10 branch of Linux kernel whereby desktop releases are sporting Linux Kernel 5.x already.

Anyway, that’s server s2 upgraded to CentOS 7.7 successfully!

We’re certainly running the CentOS 7.7 release now:

greys@s2:~ $ cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)

See Also