List multiple connections with the same name using nmcli NetworkManager under CentOS

When using the NetworkManager it is possible to create multiple connections with the same name, which may result in confusion how to list them all and how to delete the unneeded ones.

main menu
List network connections

It is simple to create a connection with a certain name, activate it and then deactivate it:

[root@srv ~]# nmcli con add type ethernet con-name eno2 ifname eno2 ipv4.method manual ipv4.addresses
Warning: There are 3 other connections with the name 'eno2'. Reference the connection by its uuid '47488136-83bf-4394-b2aa-3123886ca9a5'
Connection 'eno2' (47488136-83bf-4394-b2aa-3123886ca9a5) successfully added.
[root@srv ~]# nmcli con down eno2
Connection 'eno2' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/6)

So after deactivating the “eno2” connection (the real network interface is with the same name) it is possible to create another connection with the name “eno2” using the same (or even other network interface).
If there are multiple connections with the same name, when creating a new one, there is a warning as it is shown above. There is also a line in the nmcli output, which indicates how many connections there are with this name:

[root@srv ~]# nmcli
br0: connected to br0
        bridge, AC:1F:6B:F6:F6:3C, sw, mtu 1500
        ip4 default
        route4 default via metric 425
        route4 metric 425
        inet6 fe80::c1d5:b200:7259:7e4d/64
        route6 fe80::/64 metric 1024

eno1: connected to bridge-slave-eno1
        "Intel I210"
        ethernet (igb), AC:1F:6B:F6:F6:3C, hw, mtu 1500
        master br0

eno2: disconnected
        "Intel I210"
        3 connections available
        ethernet (igb), AC:1F:6B:F6:F6:3D, hw, mtu 1500

lo: unmanaged
        loopback (unknown), 00:00:00:00:00:00, sw, mtu 65536

DNS configuration:
        interface: br0

Use "nmcli device show" to get complete information about known devices and
"nmcli connection show" to get an overview on active connection profiles.

Consult nmcli(1) and nmcli-examples(7) manual pages for complete usage details.

Under the disconnected connection name “eno2”, there is a line informing there are 3 connections available under this section.

To list all network connections use the short syntax, which will show all the connections identified by their unique identifier (UUID):

main menu
3 connections with the same name

Keep on reading!

Automatically start zram swap device on boot with systemd zram-generator under CentOS Stream 9

zram-generator package will install necessary tools to automate the creation on boot the compressed RAM devices. This article focuses on compressed swap devices.

main menu

As of writing this article, the latest version in the package system under CentOS Stream 9 is 0.32. The the latest version on the original page of the software is much higher number 1.1.2 and many of the following configuration options are marked as OBSOLETE, but they work in the 0.32 version included in CentOS Stream 9 (and the new configuration options does not!). That’s why it is important to check the included sample configuration file.
The package installs no configuration file, just a sample configuration file – /usr/share/doc/zram-generator/zram-generator.conf.example.
zram in the kernel space –

STEP 1) Install the zram-generator

It is easy and straightforward, just a single package:

[root@srv) ~]# dnf install -y zram-generator
Last metadata expiration check: 3:42:20 ago on Fri 20 Oct 2023 05:18:32 AM UTC.
Dependencies resolved.
 Package                      Architecture         Version                      Repository               Size
 zram-generator               x86_64               0.3.2-7.el9                  appstream               409 k

Transaction Summary
Install  1 Package

Total download size: 409 k
Installed size: 983 k
Downloading Packages:
zram-generator-0.3.2-7.el9.x86_64.rpm                                         2.1 MB/s | 409 kB     00:00    
Total                                                                         1.3 MB/s | 409 kB     00:00     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                      1/1 
  Installing       : zram-generator-0.3.2-7.el9.x86_64                                                    1/1 
  Running scriptlet: zram-generator-0.3.2-7.el9.x86_64                                                    1/1 
  Verifying        : zram-generator-0.3.2-7.el9.x86_64                                                    1/1 



STEP 2) Create a configuration and start the service

By default, there is no configuration file. The best place for it is /etc/systemd/zram-generator.conf.
Here is an example, which will fulfill the following:

  • Set the maximum RAM of the system, because it is a hard-coded 9G, by default. And if not redefined the device will be with 9G max memory no matter how much is tuned by the other options.
  • Set the RAM of the compressed device.
  • Set the fraction of the ram, which may be used by the device. Again as with the above configuration option, it is important, because it limits the maximum available memory to allocate for the compressed device.
  • Set the type of the device – filesystem or swap device.

There is the real world example configuration – /etc/systemd/zram-generator.conf

[root@srv ~]# cat /etc/systemd/zram-generator.conf
host-memory-limit = none
max-zram-size = 32768
zram-fraction = 1.0
compression-algorithm = zstd
swap-priority = 100
fs-type = swap

Keep on reading!

Edit with systemctl edit to add restart on fail to a service – nfs-ganesha

A quick tip how to edit a service unit file under a c system like CentOS Stream 9 or Ubuntu. The best way is to edit it with the the tool “systemctl edit [service_name]”, which will trigger the default editor to open a temporary copy of the systemd unit file with the service name used with it. The default editor in the console is controlled by “EDITOR” variable and may be changed prior using the systemctl edit. After a successful manipulation of the system unit file the new one will be installed and a reload of the systemd unit files will be triggered with “systemctl daemon-reload” automatically. Indeed, it is just a text edit of a text file, which will do several actions when using “systemctl edit” command.

main menu
systemctl cat service

systemd options ro restart a service on fail are:


Here, the example is to add a restart-on-fail functionality to the nfs-ganesha service (NFS service). The systemctl edit may be used for many other changes to the systemd unit file under the console and it is the easiest and proper way.

SCREENSHOT 1) Use “systemctl edit” to edit a copy of the systemd override unit file.

do not insert anything at the end of the comments or below the second red line comments – “### Lines below this comment will be discarded”. This temporary override file includes a systemd unit file of the service, which is opened for editing. The result override.conf file will only include the added lines, no other comments shown below the second red line.

main menu
systemctl edit opened

Keep on reading!

Change time zone for syslog messages in syslog-ng

When sending syslog packets to a remote server the time-zone of the current server may lead to problems because the syslog-ng program sets the time-zone with offset number according to the GMT. The remote server, especially if not a syslog-ng one, may interpret the offset as an offset to the UTC (Coordinated Universal Time), which leads times with an hour into the future.

main menu
configuration in syslog-ng

Note, this whole problem is because of the Daylight saving time and there are almost 6 months when the GMT is not equal to the UTC and it is an hour ahead. Probably it is not a good idea to offset according to the GMT, because of the Daylight saving time during the summer, but this is on the syslog-ng development side.
There is one option time-zone(“[time_zone_string]”), which allows to change the time-zone of the destination packets. To avoid misinterprets of the date and time in the message packets the best way is to use it with UTC, so the local system will do the all necessary to convert the local time to UTC properly.
The configuration below uses time-zone(“[time_zone_string]”) from the current local time to UTC, because the current local time zone is EEST (Eastern European Summer Time), which 3 hours ahead of UTC during the summer period and 2 during winter (Eastern European Time – EET).

Relay the local web server logs from the local UDP port to the remote server using reliable TCP connection and changing the local time to UTC of the packets.

#NGINX - web logs
source udp_local {
    network(ip( port(514) transport("udp") so_rcvbuf(67108864) log_fetch_limit(1000) max-connections(1000) log-iw-size(1000000));

filter filter_nginx_access_log { program(nginx); };
destination d_tcp_syslog {
         port(10514) transport("tcp") disk-buffer(mem-buf-length(10000) mem-buf-size(128M) disk-buf-size(1024M) reliable(yes) dir("/var/lib/syslog-ng"))
log { source(udp_local); filter(filter_nginx_access_log); destination(d_tcp_syslog); };

the time_zone(“UTC”) in destination rule will ensure the packets have proper time related to the local server’s time in UTC and the mistake of misinterpreted date time is unlikely on a remote server.
More articles with syslog-ng

Firewalld and how to preserve the original source IP when forwarding to internal IP

Using firewalld and the forwarding options (IP or port forward) might work not as expected if the default setup is left on the system. Consider the simple example:

main menu
Internet <-> router <-> local network

The purpose is to forward a port to a server in the local network, which should be easy enough. Let the forwarding port be 80 and the server should receive the original source IP. To archive this task the system administrator should do the following on the router with firewalld service. Here is one of the simplest methods:

  • When the router’s external IP/interface and the router’s internal IP/interface are in the same firewalld zone. The zone is named “public” in the CentOS world.

The solution uses the masquerade rule added with a rich rule (–add-rich-rule), not the masquerade option of the zone (–add-masquerade).
The default configuration will assign the external interface and the internal interface, which may be a virtual one, in the same firewalld zone such as “public”. When this happens, activating the masquerade option will break the source IP and it will be replaced by the Netfilter with the internal IP address of the router and the internal server will see all incoming connections on the forwarded port as if they were coming from the internal router IP. All different IPs coming to this port will be replaced with the router’s internal IP and forwarded to the server’s internal.

The router’s external IP/interface and the router’s internal IP/interface are in the same firewalld zone.

This solution is demonstrated with a virtual interface – bridge br0, but it may be a network interface. By default, when the bridge is created, it will be added to the default zone, which is “public” in CentOS world. Use –get-active-zones to check the active zones and the assigned interfaces.

[root@srv ~]# firewall-cmd --get-active-zones
  interfaces: eth0 br0
[root@srv ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: br0 eth0
  services: cockpit dhcpv6-client http https ssh
  ports: 10022/tcp
  forward: yes
  masquerade: no
  rich rules:

If the options forward and masquerade are activated (i.e. yes on the above output) and a forward rule to an internal local IP (some server IP connected to the bridge br0) is introduced to the firewall, the local server will receive all connection attempts to the forwarded port, but the source IP will be overwritten with the gateway IP of the internal (local network). For example, the bridge br0 has IP and the eth0 has Internet IP Forwarding port to a server behind the bridge br0 with IP
Keep on reading!

Switch to a new master (primary) in MySQL InnoDB Cluster 8

Switching to a new master (or new primary if to use the new naming) in a MySQL 8 InnoDB Cluster is simple with the MySQL Shell console and the function of the cluster variable – setPrimaryInstance.

main menu
MySQL Shell with setPrimaryInstance

Why would someone need to do it manually? One of the reasons may be because one of the nodes is on the same physical server and thus suppose a smaller latency.

First, get a cluster object of the cluster by connecting to the cluster API with MySQL Shell:

[root@db-cluster-1 ~]# mysqlsh
MySQL Shell 8.0.28

Copyright (c) 2016, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates.
Other names may be trademarks of their respective owners.

Type '\help' or '\?' for help; '\quit' to exit.
 MySQL  JS > \connect clusteradmin@db-cluster-1
Creating a session to 'clusteradmin@db-cluster-1'
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 166928419 (X protocol)
Server version: 8.0.28 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.
 MySQL  db-cluster-1:33060+ ssl  JS > var cluster = dba.getCluster()

Second, show the status of the cluster to get the cluster topology and the exact nodes’ names, which will use as an argument of the setPrimaryInstance. Still, in the MySQL Shell Console:

 MySQL  db-cluster-1:33060+ ssl  JS > cluster.status()
    "clusterName": "mycluster1", 
    "defaultReplicaSet": {
        "name": "default", 
        "primary": "db-cluster-2:3306", 
        "ssl": "REQUIRED", 
        "status": "OK", 
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", 
        "topology": {
            "db-cluster-1:3306": {
                "address": "db-cluster-1:3306", 
                "memberRole": "SECONDARY", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "replicationLag": null, 
                "role": "HA", 
                "status": "ONLINE", 
                "version": "8.0.28"
            "db-cluster-2:3306": {
                "address": "db-cluster-2:3306", 
                "memberRole": "PRIMARY", 
                "mode": "R/W", 
                "readReplicas": {}, 
                "replicationLag": null, 
                "role": "HA", 
                "status": "ONLINE", 
                "version": "8.0.28"
            "db-cluster-3:3306": {
                "address": "db-cluster-3:3306", 
                "memberRole": "SECONDARY", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "replicationLag": null, 
                "role": "HA", 
                "status": "ONLINE", 
                "version": "8.0.28"
        "topologyMode": "Single-Primary"
    "groupInformationSourceMember": "db-cluster-2:3306"

Keep on reading!

Install CentOS Stream 9 booting VNC installer with kexec

Lately, dedicated servers come with Remote management consoles like IPMI KVM or iLO, or DRAC, but they are still slow to initiate the process of installing a system.

main menu
kexec execute

Consider a server (dedicated or not) should be installed in a remote colocation with the help of only the server’s network. The system administrator just receives an administrative shell access and nothing more and the server should be installed with the proper and secured software, in this case, the CentOS Stream 9. Using kexec the user can boot a new kernel from a different Linux Distribution and initiate automated network installation of the system and it is not needed any Remote management consoles. The only thing needed is the ability of the current system/kernel to be able to use kexec, which is pretty standard for 8 to 10 years old Linux systems. There is a good chance the colocations’ rescue CD/DVD/USB flash drives or the PXE rescue images support kexec, because they tend to upgrade their rescue systems, which the user may boot if he has problems.
Still, using kexec to initiate another kernel or Linux Distribution like CentOS Stream 9 with VNC installer, for example, it a powerful tool to safely replace a currently running system with only shell access.
This article has chosen to start the CentOS Stream 9 VNC installer just for demonstration purposes. Booting a downloaded kernel may be used for just anything from booting a system over the network, booting an installer, booting an unattended automation installation, and so on. There are a couple of simple things to check before booting the new kernel.
This article will show just one use case – reinstalling a system with CentOS Stream 9 over the network using the CentOS VNC Install. The purpose is to show how simple, fast, and easy is to install a modern Linux system only by having console access. No scripts are required if manual installation is performed.
To boot a CentOS Stream 9 VNC Installer the kexec command needs the following options.

The kexec commands need the following options:

  • Networkingdevice interface name, IP, netmask, gateway and DNS servers
  • Kernel options – these options will initiate scripts from the initramfs.
  • inst.vnc – a kernel option, which will start a VNC server with no password on the default port and network device. Using it with another inst.vncpassword=[PASSWORD] the VNC server will require the password – [PASSWORD]. The password should be a maximum of 8 characters because the VNC server will not start if it is with more!
  • inst.repo=[HTTP/HTTPS://repository] – a kernel option, which sets the CentOS HTTP/HTTPS repository.

The kexec command to boot the CentOS Stream 9 VNC Installer is:

kexec --initrd=./initrd.img -l ./vmlinuz --command-line="bootdev=eno1 nameserver= inst.vnc inst.vncpassword=cha3hae4ahZaqueev1ee inst.repo="

The kernel (i.e. vmlinuz) and the initramfs (i.e. initrd.img) should be downloaded in the current directory before executing the above command. The above line will order the kernel to load the new kernel, but to boot it another command must be executed:

kexec -e

Keep on reading!

List all rules and IPs when using firewalld under CentOS

CentOS 7, CentOS 8, CentOS Stream 8, CentOS Stream 9 use firewalld service for the firewall of the machine. Firewalld service is easily controlled by the command-line tool firewall-cmd, which has a relatively simple syntax. It imposes an abstraction layer over the much more complex Linux kernels backends like iptables, ip6tables, arptables, ebtables, ipsetand, and nftables. The Firewalld organizes the firewall rules with the help of policies and zones, but there is a catch – it is not possible to list all the firewall rules to check whether an IP, network, or ethernet interface takes part in some rule or policy.

main menu
nft list ruleset

Yes, it is possible to list all rules of a firewalld zone (firewall-cmd –list-all), but what if there are multiple zones? First, get all the zone names and then enumerate all the zones with a list command to check for an IP. It is not practical and fast.
There is the other trick, searching through the Firewalld configuration files in the directory /etc/firewalld/, which saves all the permanent rules. But what if there are temporary rules, which are not saved in the configuration?
From CentOS 8.2 (RHEL 8.2) firewalld backend defaults to nftables instead of “iptables”. By using the nftables tools we can list all the rules applied in text or JSON format. It is like a snapshot of all the running rules applied by the Linux kernel firewall infrastructure no matter in which zone and policy. There is no such command with the firewall-cmd tool.

CentOS 8.2 (RHEL 8.2) and above including CentOS Stream 9

There is an export command using the nfs command line tool.

nft list ruleset

Keep on reading!

Run a docker container with bigger storage

By default, the Docker command-line utility docker runs containers with 10G storage, which in most cases is enough, but if the user wants to just run a specific container with bigger storage there is an option for the docker command:

docker run --storage-opt size=50G

The option size=50G will set the docker container storage for the current only run command!

main menu
Root file system with 50G size.

Run a Ubuntu 22.04 Docker container with 50G root storage:

root@srv ~ # docker run --storage-opt size=50G -it ubuntu:22.04 bash
Unable to find image 'ubuntu:22.04' locally
22.04: Pulling from library/ubuntu
e96e057aae67: Pull complete 
Digest: sha256:4b1d0c4a2d2aaf63b37111f34eb9fa89fa1bf53dd6e4ca954d47caebca4005c2
Status: Downloaded newer image for ubuntu:22.04
root@4caab8c61157:/# df -h
Filesystem                                                                                          Size  Used Avail Use% Mounted on
/dev/mapper/docker-253:0-39459726-2f2d655687e5bd39620a2a083960ac969d8163b806152765a1fc166f0a82d3d9   50G  170M   50G   1% /
tmpfs                                                                                                64M     0   64M   0% /dev
tmpfs                                                                                               7.8G     0  7.8G   0% /sys/fs/cgroup
shm                                                                                                  64M     0   64M   0% /dev/shm
/dev/mapper/map-99f55d81-4132-42d4-9515-33d8cc11d3e2                                                3.6T  1.5T  2.2T  40% /etc/hosts
tmpfs                                                                                               7.8G     0  7.8G   0% /proc/asound
tmpfs                                                                                               7.8G     0  7.8G   0% /proc/acpi
tmpfs                                                                                               7.8G     0  7.8G   0% /proc/scsi

It’s worth mentioning this option “–storage-opt size=50G” is different from the “–storage-opt dm.basesize=50G“, the first one is used as a command argument to the docker command-line utility. The second one is used with the dockerd daemon to change the default Docker behavior from 10G to 50G storage. Note, either option cannot change the storage size of the already started container.

Migrate emails from GMail to another IMAP server with imapsync

It appears pretty easy to migrate an existing GMail account to another IMAP server, i.e. not GMail/Google server. There is an excellent synchronization tool – imapsync, which checks and downloads all the mails of an user account from one IMAP server to another IMAP server per user. The tool supports Google’s GMail accounts and their specific naming including the labels folders peculiarity (some folders in GMail may not have any physical emails, but just to show emails from another folders with specific labels). It’s worth mentioning that the imapsync works only only with GMail accounts, but it can be used to migrate from one IMAP server to another IMAP. The key here is the source and the destination server should support IMAP protocol.

Imapsync is an IMAP transfer tool. The purpose of imapsync is to migrate IMAP accounts or to backup IMAP accounts.

GMail will expose the labels as folders and in some early versions of the imapsync tool the emails with multiple labels may be shown in multiple folders and be duplicated. The version used here did not duplicate any email, even some emails were shown in multiple GMail folders.

There are two GMail settings to enable before proceeding with the migration:

  1. Enable “Less secure app access” or if 2-Step-Verification is enabled use App Passwords
  2. Enable IMAP, which is disabled by default.

SCREENSHOT 1) Manage the current Google account options by clicking on the top right corner as shown in the screenshot.

main menu
manage google account

Keep on reading!