Managing KVM on AlmaLinux 9 using the virsh Command-Line Tool

In previous chapters, we have covered the installation and configuration of KVM-based guest operating systems on AlmaLinux 9. This chapter explores additional areas of the virsh tool that have not been covered in previous chapters and how it may be used to manage KVM-based guest operating systems from the command line.

The virsh Shell and Command-Line

The virsh tool is both a command-line tool and an interactive shell environment. When used in the command-line mode, the command is issued at the command prompt with sets of arguments appropriate to the task.

To use the options as command-line arguments, use them at a terminal command prompt, as shown in the following example:

# virsh <option>Code language: plaintext (plaintext)

The virsh tool, when used in shell mode, provides an interactive environment from which to issue sequences of commands.

To run commands in the virsh shell, run the following command:

# virsh
Welcome to virsh, the virtualization interactive terminal.
Type:  'help' for help with commands
       'quit' to quit
virsh #Code language: plaintext (plaintext)

At the virsh # prompt, enter the options you wish to run. The following virsh session, for example, lists the current virtual machines, starts a virtual machine named FedoraVM, and then obtains another listing to verify the VM is running:

# virsh 
Welcome to virsh, the virtualization interactive terminal.
Type:  'help' for help with commands
       'quit' to quit
virsh # list
 Id    Name                           State
 8     AlmaLinux9VM                   running
 9     Rocky9VM                      running
virsh # start FedoraVM
Domain FedoraVM started
virsh # list
 Id    Name                           State
 8     AlmaLinux9VM                   running
 9     Rocky9VM                       running
10     FedoraVM                       running
virsh#Code language: plaintext (plaintext)

The virsh tool supports a wide range of commands, a complete listing of which may be obtained using the help option:

# virsh help restore
    restore - restore a domain from a saved state in a file
    restore <file> [--bypass-cache] [--xml <string>] [--running] [--paused]
    Restore a domain.
    [--file] <string>  the state to restore
    --bypass-cache   avoid file system cache when restoring
    --xml <string>   filename containing updated XML for the target
    --running        restore domain into running state
    --paused         restore domain into paused stateCode language: plaintext (plaintext)

In the remainder of this chapter, we will look at some of these commands in more detail.

Listing Guest System Status

The status of the guest systems on an AlmaLinux 9 virtualization host may be viewed at any time using the list option of the virsh tool. For example:

# virsh listCode language: plaintext (plaintext)

The above command will display output containing a line for each guest similar to the following:

virsh # list
 Id    Name                           State
 8     AlmaLinux9VM                   running
 9     Rocky9VM                       running
10     FedoraVM                       running
Code language: plaintext (plaintext)

Starting a Guest System

A guest operating system can be started using the virsh tool combined with the start option followed by the name of the guest operating system to be launched. For example:

# virsh start myGuestOSCode language: plaintext (plaintext)

Shutting Down a Guest System

The shutdown option of the virsh tool, as the name suggests, is used to shut down a guest operating system:

# virsh shutdown guestNameCode language: plaintext (plaintext)

Note that the shutdown option allows the guest operating system to perform an orderly shutdown when it receives the instruction. To instantly stop a guest operating system, the destroy option may be used (with the risk of file system damage and data loss):

# virsh destroy guestNameCode language: plaintext (plaintext)

Suspending and Resuming a Guest System

A guest system can be suspended and resumed using the virsh tool’s suspend and resume options. For example, to suspend a specific system:

# virsh suspend guestNameCode language: plaintext (plaintext)

Similarly, to resume the paused system:

# virsh resume guestNameCode language: plaintext (plaintext)

A suspended session will be lost if the host system is rebooted. Also, be aware that a suspended system continues to reside in memory. Therefore, to save a session such that it no longer takes up memory and can be restored to its exact state (even after a reboot), it is necessary to save and restore the guest.

Saving and Restoring Guest Systems

A running guest operating system can be saved and restored using the virsh utility. When saved, the current status of the guest operating system is written to disk and removed from system memory. A saved system may subsequently be restored at any time (including after a host system reboot).

To save a guest:

# virsh save guestName path_to_save_fileCode language: plaintext (plaintext)

To restore a saved guest operating system session:

# virsh restore path_to_save_fileCode language: plaintext (plaintext)

Rebooting a Guest System

To reboot a guest operating system:

# virsh reboot guestNameCode language: plaintext (plaintext)

Configuring the Memory Assigned to a Guest OS

To configure the memory assigned to a guest OS, use the setmem option of the virsh command. For example, the following command reduces the memory allocated to a guest system to 256MB:

# virsh setmem guestName 256Code language: plaintext (plaintext)

Note that acceptable memory settings must fall within the memory available to the current Domain. This may be increased using the setmaxmem option.


The virsh tool provides various options for creating, monitoring, and managing guest virtual machines. As outlined in this chapter, the tool can be used in either command-line or interactive modes.

Creating KVM Virtual Machines on AlmaLinux 9 with virt-install and virsh

In the previous chapters, we explored the creation of KVM guest operating systems on an AlmaLinux 9 host using Cockpit and the virt-manager graphical tool. This chapter will focus on creating KVM-based virtual machines using the virt-install and virsh command-line tools. These tools provide all the capabilities of the virt-manager and Cockpit options with the added advantage of being used within scripts to automate virtual machine creation. In addition, the virsh command allows virtual machines to be created based on a specification contained within a configuration file.

The virt-install tool is supplied to allow new virtual machines to be created by providing a list of command-line options. This chapter assumes that the necessary KVM tools are installed. Read the chapter Installing KVM Virtualization on AlmaLinux for details on these requirements.

Running virt-install to build a KVM Guest System

The virt-install utility accepts a wide range of command-line arguments that provide configuration information related to the virtual machine being created. Some command-line options are mandatory (expressly, name, memory, and disk storage must be provided), while others are optional.

At a minimum, a virt-install command will typically need the following arguments:

  • –name – The name to be assigned to the virtual machine.
  • –memory – The amount of memory allocated to the virtual machine.
  • –disk – The name and location of an image file for storage for the virtual machine. This file will be created by virt-install during the virtual machine creation unless the –import option is specified to indicate an existing image file is to be used.
  • -cdrom or –location – Specifies the local path or the URL of a remote ISO image containing the installation media for the guest operating system.

A summary of all the arguments available for use when using virt-install can be found in the man page:

$ man virt-installCode language: plaintext (plaintext)

An Example AlmaLinux 9 virt-install Command

With reference to the above command-line argument list, we can now look at an example command-line construct using the virt-install tool.

Note that to display the virtual machine and complete the installation, a virt-viewer instance must be connected to the virtual machine after the virt-install utility starts it. By default, virt-install will attempt to launch virt-viewer automatically once the virtual machine starts running. However, if virt-viewer is unavailable, virt-install will wait until a virt-viewer connection is established. For example, the virt-viewer session may be running locally on the host system if it has a graphical desktop or a connection may be established from a remote client as outlined in the chapter entitled Creating KVM Virtual Machines on AlmaLinux 9 using virt-manager.

The following command creates a new KVM virtual machine configured to run an AlmaLinux 9 guest using KVM para-virtualization. It creates a new 10GB disk image, assigns 2048MB of RAM to the virtual machine, and configures a virtual CD device for the installation media ISO image:

# virt-install --name demo_vm_guest2 --memory 2048 --disk path=/tmp/demo_vm_guest.img,size=10 --network network=default --cdrom ./AlmaLinux-9.2-x86_64-minimal.isoCode language: plaintext (plaintext)

As the creation process runs, the virt-install command will display status updates of the creation progress:

Starting install...
Allocating 'demo_vm_guest2.img'                                |  10 GB  00:00:01     
Running graphical console command: virt-viewer --connect qemu:///system --wait demo_vm_guestCode language: JavaScript (javascript)

Once the guest system has been created, the virt-viewer screen will appear containing the guest operating system installer loaded from the specified installation media:

Figure 24-1

From this point, follow the standard installation procedure for the guest operating system.

Starting and Stopping a Virtual Machine from the Command-Line

Having created the virtual machine from the command line, it stands to reason that you may also need to start it from the command line in the future. This can be achieved using the virsh command-line utility, referencing the name assigned to the virtual machine during creation. For example:

# virsh start demo_vm_guestCode language: plaintext (plaintext)

Similarly, the virtual machine may be sent a shutdown signal as follows:

# virsh shutdown demo_vm_guestCode language: plaintext (plaintext)

Suppose the virtual machine fails to respond to the shutdown signal and does not begin a graceful shutdown. In that case, the virtual machine may be destroyed (with the attendant risks of data loss) using the destroy directive:

# virsh destroy demo_vm_guestCode language: plaintext (plaintext)

Creating a Virtual Machine from a Configuration File

The virsh create command can take as an argument the name of a configuration file on which to base the creation of a new virtual machine. The configuration file uses XML format. The easiest way to create a configuration file is to dump out the configuration of an existing virtual machine and modify it for the new one. This can be achieved using the virsh dumpxml command. For example, the following command outputs the configuration data for a virtual machine domain named demo_vm_guest to a file named demo_vm_guest.xml:

# virsh dumpxml demo_vm_guest > demo_vm_guest.xmlCode language: plaintext (plaintext)

Once the file has been generated, load it into an editor to review and change the settings for the new virtual machine.

At the very least, the <name>, <uuid>, and image file path <source file> must be changed to avoid conflict with the virtual machine from which the configuration was taken. In the case of the UUID, this line can be deleted from the file.

The virtualization type, memory allocation, and number of CPUs, to name but a few options, may also be changed if required. Once the file has been modified, the new virtual machine may be created as follows:

# virsh create demo_vm_guest.xmlCode language: plaintext (plaintext)


KVM provides the virt-install and virsh command-line tools as a quick and efficient alternative to using the Cockpit and virt-manager tools to create and manage virtual machine instances. These tools have the advantage that they can be used from within scripts to automate the creation and management of virtual machines. The virsh command also includes the option to create VM instances from XML-based configuration files.

Creating KVM Virtual Machines on AlmaLinux 9 using virt-manager

The previous chapter explored how to create KVM virtual machines on AlmaLinux 9 using the Cockpit web tool. With the caveat that virt-manager may one day be discontinued once the Virtual Machines Cockpit extension is fully implemented, this chapter will cover using this tool to create new virtual machines.

Starting the Virtual Machine Manager

If you have not already done so, install the virt-manager package as follows:

# dnf install virt-managerCode language: plaintext (plaintext)

Next, launch Virtual Machine Manager from the command line in a terminal window by running virt-manager. Once loaded, the virtual machine manager will prompt for the password of the currently active user before displaying the following screen:

Figure 23-1

The main screen lists the current virtual machines running on the system.

By default, the manager should be connected to the system libvirtd instance. If it is not, connect to the host system by right-clicking on the entry in the list and selecting Connect from the popup menu.

To manage session-based virtual machines, select the File -> Add Connection… menu option to display the dialog shown in Figure 23-1:

Figure 23-2

Select QEMU/KVM user session from the Hypervisor menu and click the Connect button within this dialog. On returning to the main virt-manager screen, the QEMU/KVM session should now be listed as shown in above.

To create a virtual system, click on the new virtual machine button (the far left button in the toolbar) to display the first screen of the New VM wizard. In the Name field, enter a suitably descriptive name for the virtual system. On this screen, also select the location of the media from which the guest operating system will be installed. This can either be a CD or DVD drive, an ISO image file accessible to the local host, a network install using HTTP, FTP, NFS, or PXE, or the disk image from an existing virtual machine:

Figure 23-3

Configuring the KVM Virtual System

Clicking Forward will display a screen seeking additional information about the installation process. The displayed screen and information required will depend on selections made on the initial screen. For example, if a CD, DVD, or ISO is selected, this screen will ask for the specific location of the ISO file or physical media device. This screen also attempts to identify the type and version of the guest operating system (for example, the Windows version or Linux distribution) based on the specified installation media. If it is unable to do so, turn off the Automatically detect from installation media/source option, type in the first few characters of the operating system name, and select an option from the list of possible matches:

Figure 23-4

Once these settings are complete, click the Forward button to configure CPU and memory settings. The optimal settings will depend on the number of CPUs and amount of physical memory present in the host, together with the requirements of other applications and virtual machines that will run in parallel with the new virtual machine:

Figure 23-5

On the next screen, options are available to create an image disk of a specified size, select a preexisting volume, or create a storage volume of a specified format (raw, vmdk, ISO, etc.). Unless you have a specific need to use a particular format (for example, you might need to use vmdk to migrate to a VMware-based virtualization environment at a later date) or need to use a dedicated disk or partition, it is generally adequate to specify a size on this screen:

Figure 23-6

If the default settings are used here, the virtual machine will use a storage volume within the default storage pool for the virtual disk drive. To use the custom “MyPool” storage pool created in the preceding chapter, enable the Select or create custom storage option before clicking the Manage… button.

In the storage volume dialog, select the MyPool entry in the left-hand panel, followed by the + button in the main panel to create a new storage volume:

Figure 23-7

Note that the + button in the bottom left-hand corner of the dialog may also be used to create new storage pools as an alternative to using the Cockpit interface.

In the configuration screen (Figure 23-7), name the storage volume, select the volume size, and click on the Finish button to create the volume and assign it to the virtual machine:

Figure 23-8

Once these settings are configured, select the new volume and click the Choose Volume button. Then, click the Forward button once more. The final screen displays a summary of the configuration. Review the information displayed. Advanced options are also available to change the virtual network configuration for the guest, as shown in Figure 23-8:

Figure 23-9

Starting the KVM Virtual Machine

Click on the Finish button to begin the creation process. The virtualization manager will create the disk and configure the virtual machine before starting the guest system. Finally, the new virtual machine will appear in the main virt-manager window with the status set to Running as illustrated in Figure 23-9:

Figure 23-10

By default, the console for the virtual machine should appear in the virtual machine viewer window. To view the console of the running machine at any future time, ensure that it is selected in the virtual machine list and select the Open button from the toolbar. The virtual machine viewer should be ready for the installation process to begin:

Figure 23-11

From now on, follow the installation instructions to install the guest OS in the KVM virtual machine.


There are several ways to create new KVM-based virtual machines on an AlmaLinux 9 host system. This chapter uses the virt-manager graphical tool to create, configure, and run a guest operating system, including creating a new storage volume. With these basics covered, the next chapter will cover the creation of virtual machines from the command line.

Creating KVM Virtual Machines on AlmaLinux 9 using Cockpit

KVM-based virtual machines can easily be configured on AlmaLinux 9 using the virt-install command-line tool, the virt-manager GUI tool, or the Virtual Machines module of the Cockpit web console. This chapter will use Cockpit to install an operating system as a KVM guest on an AlmaLinux 9 host. The chapter titled “Creating KVM Virtual Machines on AlmaLinux 9 using virt-manager” will cover using the virt-manager tool to create new virtual machines.

The next chapter, “Creating KVM Virtual Machines with virt-install and virsh” will cover the command-line approach to virtual machine creation.

Installing the Cockpit Virtual Machines Module

The virtual machines module may not be included in a standard Cockpit installation by default. Assuming that Cockpit is installed and configured, the virtual machines module may be installed as follows:

# dnf install cockpit-machinesCode language: plaintext (plaintext)

Once installed, the Virtual Machines option (marked A in Figure 22-1) will appear in the navigation panel the next time you log into the Cockpit interface:

Figure 22-1

Creating a Virtual Machine in Cockpit

To create a virtual machine in Cockpit, click the Create VM button marked B in Figure 22-1 to display the creation dialog.

Within the dialog, enter a name for the machine and choose whether the installation media is in the form of an ISO accessible via a URL or a local filesystem path, or select the operating system information for the guest and choose the Download an OS option to have the installation image downloaded automatically during the installation process.

Also, specify the size of the virtual disk drive to be used for the operating system installation and the amount of memory to be allocated to the virtual machine:

Figure 22-2

KVM provides a choice of System or User session virtual machines. System virtual machines run with root privileges and full access to hardware devices and networks but are prevented from storing disk images in user folders. User sessions, on the other hand, are restricted to the user’s privileges with restricted network and device access. Disk images, however, can be stored in the user’s home directory. For this tutorial, select the System option.

Click on the Create and Edit button to build the virtual machine. After the creation process is complete, select the new VM from the list to display the configuration details, as shown in Figure 22-3:

Figure 22-3

As described in “An Overview of Virtualization Techniques” KVM provides virtual machines with several options in terms of network configuration. To view and change the network settings of a virtual machine, scroll down to the Network interfaces section of the guest overview screen and click the Edit button:

Figure 22-4

In the resulting dialog, the Network Type menu may be used to change the type of network connection, for example, from Virtual network (NAT) to direct attachment (MacVTap) or Bridge to LAN.

Starting the Installation

To start the new virtual machine and install the guest operating system from the designated installation media, click the Install button at the top of the overview page. Cockpit will start the virtual machine and update the Console view where the guest OS screen will appear:

Figure 22-5

If the installation fails, check the message to see if an error occurred when opening the installation image. This usually occurs because the QEMU emulator runs as a user named qemu, which does not have access to the directory in which the ISO installation image is located. To resolve this issue, open a terminal window (or connect with SSH if the system is remote), change directory to the location of the ISO image file, and add the qemu user to the access control list (ACL) of the parent directory as follows:

# cd /path/to/iso/directory 
# setfacl --modify u:qemu:x ..Code language: plaintext (plaintext)

After making this change, check the settings as follows:

# getfacl ..
# file: ..
# owner: demo
# group: demo
Code language: plaintext (plaintext)

Once these changes have been made, click the Install button again to complete the installation.

To complete the installation, interact with the screen in the Consoles view just as you would if you were installing the operating system on physical hardware. If the console is too small to accommodate the entire guest operating system screen, click the Expand button in the top right-hand corner.

It is also possible to connect with and display the graphical console for the VM from outside the Cockpit browser session using the virt-viewer tool. To install virt-viewer on an AlmaLinux 9 system, run the following command:

# dnf install virt-viewerCode language: plaintext (plaintext)

The virt-viewer tool is also available for Windows systems and can be downloaded from the following URL:

Run virt-viewer as follows to connect with a system-based virtual machine running on the local host:

$ sudo virt-viewerCode language: plaintext (plaintext)

After virt-viewer has started, select the virtual machine you wish to connect to from the resulting dialog:

Figure 22-6

To list and access session-based guests, launch virt-viewer as follows:

$ virt-viewer --connect qemu:///sessionCode language: plaintext (plaintext)

Alternatively, it is also possible to specify the virtual machine name and bypass the selection dialog entirely, for example:

$ sudo virt-viewer demo-vm-guestCode language: plaintext (plaintext)

To connect a virt-viewer instance to a virtual machine running on a remote host using SSH, the following command can be used:

$ virt-viewer --connect qemu+ssh://<user>@<host>/system <guest name>Code language: plaintext (plaintext)

For example:

$ virt-viewer --connect qemu+ssh://[email protected]/system demo_vm_guestCode language: plaintext (plaintext)

When using this technique, it is important to note that you will be prompted twice for the user password before the connection is fully established.

Once the virtual machine has been created, the Cockpit interface can monitor the machine and perform tasks such as rebooting, shutting down, or deleting the guest system. An option is also included on the Disks panel to add disks to the virtual machine configuration.

Working with Storage Volumes and Storage Pools

When a virtual machine is created, it will usually have at least one virtual disk drive. The images that represent these virtual disk drives are stored in storage pools. A storage pool can be an existing directory on a local filesystem, a filesystem partition, a physical disk device, Logical Volume Management (LVM) volume group, or even a remote network file system (NFS).

Each storage pool is divided into one or more storage volumes. Storage volumes are typically individual image files, each representing a single virtual disk drive, but they can also take the form of physical disk partitions, entire disk drives, or LVM volume groups.

When a virtual machine was created using the previous steps, a default storage pool was created to store virtual machine images. This default storage pool occupies space on the root filesystem and can be reviewed from within the Cockpit Virtual Machine interface by selecting the Storage Pools option at the top of the panel marked C in Figure 22-1 above.

When selected, the screen shown in Figure 22-7 below will appear containing a list of storage pools currently configured on the system:

Figure 22-7

In the above example, the default storage pool is located on the root filesystem and stores the virtual machine image in the /var/lib/libvirtd/images directory. To view the storage volumes contained within the pool, select the Storage Volumes tab highlighted in Figure 22-8:

Figure 22-8

In the case of the demo guest, the storage volume takes the form of an image file named demovm-guest.qcow2. Depending on the selections made when the VM was created, the pool may also include a storage volume containing the installation ISO image. To find out which storage volume a particular virtual machine uses, return to the main Virtual machines screen, select the virtual machine, and scroll to the Disks panel, as shown in Figure 22-9:

Figure 22-9

Although using the default storage pool is acceptable for testing purposes and early experimentation, it is recommended that additional pools be created for general virtualization use. To create a new storage pool, display the Storage Pools screen within Cockpit and click on the Create storage pool button to display the dialog shown in Figure 22-10:

Figure 22-10

In the above example, a new storage pool is being created named MyPool using a file system partition mounted as /MyPool within the local filesystem (the topic of disk drives, partitions, and mount points is covered later in the chapter entitled “Adding a New Disk Drive to an AlmaLinux 9 System”). Once created, the pool will be listed within the Cockpit storage pool screen and can contain storage volumes as new virtual machines are created.


This chapter has outlined using the Cockpit web-based interface to create and manage KVM-based virtual machines. The Cockpit interface has the advantage of not requiring access to a desktop environment running on the host system. An alternative option is using the virt-manager graphical tool outlined in the next chapter.

Installing KVM Virtualization on AlmaLinux

Earlier versions of Red Hat Enterprise Linux (on which AlmaLinux is based) provided two virtualization platforms: Kernel-based Virtual Machine (KVM) and Xen. In recent releases, support for Xen has been removed, leaving KVM as the only bundled virtualization option supplied with AlmaLinux 9. In addition to KVM, third-party solutions are available in products such as VMware and Oracle VirtualBox. Since KVM is supplied with AlmaLinux 9, however, this virtualization solution will be covered in this and subsequent chapters.

Before plunging into installing and running KVM, it is worth discussing how it fits into the various types of virtualization outlined in the previous chapter.

An Overview of KVM

KVM is categorized as a Type-1 hypervisor virtualization solution that implements full virtualization with support for unmodified guest operating systems using Intel VT and AMD-V hardware virtualization support.

KVM differs from many other Type-1 solutions in that it turns the host Linux operating system into the hypervisor, allowing bare metal virtualization to be implemented while running a complete, enterprise-level host operating system.

KVM Hardware Requirements

Before proceeding with this chapter, we must discuss the hardware requirements for running virtual machines within a KVM environment. First and foremost, KVM virtualization is only available on certain processor types. As previously discussed, these processors must include either Intel VT or AMD-V technology.

To check for virtualization support, run the lscpu command in a terminal window:

# lscpu | grep Virtualization:Code language: plaintext (plaintext)

If the system contains a CPU with Intel VT support, the above command will provide the following output:

Virtualization: VT-xCode language: plaintext (plaintext)

Alternatively, the following output will be displayed when a CPU with AMD-V support is detected:

Virtualization: AMD-VCode language: plaintext (plaintext)

If the CPU does not support virtualization, no output will be displayed by the above lscpu command.

Note that while the above commands only report whether the processor supports the respective feature, it does not indicate whether it is currently enabled in the BIOS. This is because, in practice, virtualization support is typically disabled by default in the BIOS of most systems. Therefore, you should check your BIOS settings to ensure the appropriate virtualization technology is enabled before proceeding with this tutorial.

Unlike a dual-booting environment, a virtualized environment involves running two or more complete operating systems concurrently on a single computer system. This means the system must have enough physical memory, disk space, and CPU processing power to comfortably accommodate all these systems in parallel. Therefore, before beginning the configuration and installation process, check on the minimum system requirements for both AlmaLinux 9 and your chosen guest operating systems and verify that your host system has sufficient resources to handle the requirements of both systems.

Preparing AlmaLinux 9 for KVM Virtualization

Unlike Xen, it is not necessary to run a special version of the kernel to support KVM. As a result, KVM support is already available for use with the standard kernel via installing a KVM kernel module, thereby negating the need to install and boot from a special kernel.

To avoid conflicts, however, if a Xen-enabled kernel is currently running on the system, reboot the system and select a non-Xen kernel from the boot menu before proceeding with the remainder of this chapter.

The tools required to set up and maintain a KVM-based virtualized system are only installed by default if selected explicitly during the AlmaLinux 9 operating system installation process. To install the KVM tools from the command prompt, execute the following command in a terminal window:

# dnf install qemu-kvm qemu-img libvirt virt-install libvirt-clientCode language: plaintext (plaintext)

If you have access to a graphical desktop environment, the virt-manager package is also recommended:

# dnf install virt-managerCode language: plaintext (plaintext)

Verifying the KVM Installation

It is worthwhile checking that the KVM installation worked correctly before moving forward. When KVM is installed and running, two modules will have been loaded into the kernel. The presence or otherwise of these modules can be verified in a terminal window by running the lsmod command:

# lsmod | grep kvmCode language: plaintext (plaintext)

Assuming that the installation was successful, the above command should generate output similar to the following:

kvm_intel             409600  0
kvm                  1134592  1 kvm_intel
irqbypass              16384  1 kvmCode language: plaintext (plaintext)

Installing KVM Virtualization on AlmaLinux 9 Note that if the system contains an AMD processor, the kvm module will likely read kvm_amd rather than kvm_intel.

The installation process should also have configured the libvirtd daemon to run in the background. Once again, using a terminal window, run the following command to ensure libvirtd is running:

# systemctl status libvirtd
● libvirtd.service - Virtualization daemon
     Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; preset:>
     Active: active (running) since Tue 2023-09-12 09:45:13 CDT; 3s agoCode language: plaintext (plaintext)

If the process is not running, enable and start it as follows:

# systemctl enable --now libvirtdCode language: plaintext (plaintext)

If the desktop environment is available, run the virt-manager tool by selecting Activities and entering “virt” into the search box. When the Virtual Machine Manager icon appears, click it to launch it. When loaded, the manager should appear as illustrated in the following figure:

Figure 21-1

If the QEMU/KVM entry is not listed, select the File -> Add Connection menu option and, in the resulting dialog, select the QEMU/KVM Hypervisor before clicking on the Connect button:

Figure 21-2

If the manager is not currently connected to the virtualization processes, right-click on the entry listed and select Connect from the popup menu.


KVM is a Type-1 hypervisor virtualization solution that implements full virtualization with support for unmodified guest operating systems using Intel VT and AMD-V hardware virtualization support. It is the default virtualization solution bundled with AlmaLinux 9 and can be installed quickly and easily on any AlmaLinux 9 system with appropriate processor support. With KVM support installed and enabled, the following chapters will outline some options for installing and managing virtual machines on an AlmaLinux 9 host.

Sharing Files between AlmaLinux 9 and Windows with Samba

Although Linux has made some inroads into the desktop market, its origins and future are very much server-based. It is unsurprising, therefore, that AlmaLinux 9 can act as a file server. It is also common for AlmaLinux and Windows systems to be used side by side in networked environments. Therefore, it is a common requirement that files on an AlmaLinux 9 system be accessible to Linux, UNIX, and Windows-based systems over network connections. Similarly, shared folders and printers residing on Windows systems may also need to be accessible from AlmaLinux 9-based systems.

Windows systems share resources such as file systems and printers using the Server Message Block (SMB) protocol. For an AlmaLinux 9 system to serve such resources over a network to a Windows system and vice versa, it must support SMB. This is achieved using a technology called Samba. In addition to providing integration between Linux and Windows systems, Samba may also provide folder sharing between Linux systems (as an alternative to NFS covered in the previous chapter).

In this chapter, we will look at the steps necessary to share file system resources and printers on an AlmaLinux 9 system with remote Windows and Linux systems and to access Windows resources from AlmaLinux 9.

Accessing Windows Resources from the GNOME Desktop

Before getting into more details of Samba sharing, it is worth noting that if all you want to do is access Windows shared folders from within the GNOME desktop, then support is already provided within the GNOME Files application. The Files application is located in the dash as highlighted in Figure 19-1:

Figure 19-1

Once launched, select the Other Locations option in the left-hand navigation panel, followed by the Windows Network icon in the main panel to browse available Windows resources:

Figure 19-2

Samba and Samba Client

Samba allows both AlmaLinux 9 resources to be shared with Windows systems and Windows resources to be shared with AlmaLinux 9 systems. AlmaLinux accesses Windows resources using the Samba client. On the other hand, AlmaLinux resources are shared with Windows systems by installing and configuring the Samba service.

Installing Samba on AlmaLinux 9

The default settings used during the AlmaLinux 9 installation do not typically install the necessary Samba packages. Unless you specifically requested that Samba be installed, it is unlikely that you have Samba installed on your system. To check whether Samba is installed, open a terminal window and run the following command:

# rpm -q samba samba-common samba-clientCode language: plaintext (plaintext)

Any missing packages can be installed using the dnf command-line tool:

# dnf install samba samba-common samba-clientCode language: plaintext (plaintext)

Configuring the AlmaLinux 9 Firewall to Enable Samba

Next, the firewall protecting the AlmaLinux 9 system must be configured to allow Samba traffic. This can be achieved using the firewall-cmd command as follows:

# firewall-cmd --permanent --add-port={139/tcp,445/tcp}
# firewall-cmd --reloadCode language: plaintext (plaintext)

Before starting the Samba service, some configuration steps are necessary to define how the AlmaLinux system will appear to Windows systems and the resources to be shared with remote clients. Most configuration tasks occur within the /etc/samba/smb.conf file.

Configuring the smb.conf File

Samba is a highly flexible and configurable system that provides many options for controlling how resources are shared on Windows networks. Unfortunately, this flexibility can lead to the sense that Samba is overly complex. In reality, however, the typical installation does not need many configuration options, and the learning curve to set up a basic configuration is relatively short.

For this chapter, we will look at joining an AlmaLinux 9 system to a Windows workgroup and setting up a directory as a shared resource that a specific user can access. This is a configuration known as a standalone Samba server. More advanced configurations, such as integrating Samba within an Active Directory environment, are also available, though these are outside the scope of this book.

The first step in configuring Samba is to edit the /etc/samba/smb.conf file.

Configuring the [global] Section

The smb.conf file is divided into sections. The first section is the [global] section, where settings that apply to the entire Samba configuration can be specified. While these settings are global, each option may be overridden within other configuration file sections.

The first task is defining the Windows workgroup name on which the AlmaLinux 9 resources will be shared. This is controlled via the workgroup = directive of the [global] section, which by default is configured as follows:

workgroup =Code language: plaintext (plaintext)

Begin by changing this to the actual name of the workgroup if necessary.

In addition to the workgroup setting, the other settings indicate that this is a standalone server on which user passwords will protect the shared resources. Before moving on to configuring the resources to be shared, other parameters also need to be added to the [global] section as follows:

        netbios name = LinuxServerCode language: plaintext (plaintext)

The “netbios name” property specifies the name by which the server will be visible to other systems on the network.

Configuring a Shared Resource

The next step is configuring the shared resources (in other words, the resources that will be accessible from other systems on the Windows network). To achieve this, the section is given a name by which it will be referred when shared. For example, if we plan to share the /sampleshare directory of our AlmaLinux 9 system, we might entitle the section [sampleshare]. In this section, a variety of configuration options are possible. For this example, however, we will define the directory that is to be shared, indicate that the directory is both browsable and writable, and declare the resource public so that guest users can gain access:

        comment = Example Samba share
        path = /sampleshare
        browseable = Yes
        public = yes
        writable = yesCode language: plaintext (plaintext)

To restrict access to specific users, the “valid users” property may be used, for example:

valid users = demo, bobyoung, marcewingCode language: plaintext (plaintext)

Removing Unnecessary Shares

The smb.conf file is pre-configured with sections for sharing printers and the home folders of the users on the system. If these resources do not need to be shared, the corresponding sections can be commented out so that Samba ignores them. In the following example, the [homes] section has been commented out:

#       comment = Home Directories
#       valid users = %S, %D%w%S
#       browseable = No
#       read only = No
#       inherit acls = Yes
.Code language: plaintext (plaintext)

Configuring SELinux for Samba

SELinux is a system integrated by default into the Linux kernel on all AlmaLinux 9systems, providing an extra layer of security and protection to the operating system and user files.

Traditionally, Linux security has been based on allowing users to decide who has access to their files and other resources they own. Consider, for example, a file located in the home directory of, and owned by, a particular user. That user can control the access permissions of that file in terms of whether other users on the system can read and write to or, in the case of a script or binary, execute the file. This type of security is called discretionary access control since resource access is left to the user’s discretion.

With SELinux, however, access is controlled by the system administrator and cannot be overridden by the user. This is called mandatory access control and is defined by the administrator using the SELinux policy. To continue the previous example, the owner of a file can only perform tasks on that file if the SELinux policy, defined either by default by the system or by the administrator, permits it.

The current status of SELinux on an AlmaLinux 9 system may be identified using the sestatus tool as follows:

# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:            enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actual (secure)
Max kernel policy version:      33Code language: plaintext (plaintext)

SELinux can be run in either enforcing or permissive mode. When enabled, enforcing mode denies all actions that are not permitted by SELinux policy. On the other hand, permissive mode allows actions that would generally have been denied to proceed but records the violation in a log file.

SELinux security is based on the concept of context labels. All resources on a system (including processes and files) are assigned SELinux context labels consisting of user, role, type, and optional security level. The SELinux context of files or folders, for example, may be viewed as follows:

$ ls -Z /home/demo
 unconfined_u:object_r:user_home_t:s0 Desktop
 unconfined_u:object_r:user_home_t:s0 DocumentsCode language: plaintext (plaintext)

Similarly, the ps command may be used to identify the context of a running process, in this case, the ls command:

$ ps -eZ | grep ls
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 14311 tty1 00:00:18 ls
Code language: plaintext (plaintext)

When a process (such as the above ls command) attempts to access a file or folder, the SELinux system will check the policy to identify whether or not access is permitted. Now consider the context of the Samba service:

$ ps -eZ | grep smb
system_u:system_r:smbd_t:s0       66576 ?        00:00:00 smbd
system_u:system_r:smbd_t:s0       66578 ?        00:00:00 smbd-notifyd
system_u:system_r:smbd_t:s0       66579 ?        00:00:00 cleanupdCode language: plaintext (plaintext)

SELinux implements security in several ways, the most common of which is called type enforcement. In basic terms, when a process attempts to perform a task on an object (for example, writing to a file), SELinux checks the context types of both the process and the object and verifies that the security policy allows the action to be taken. Suppose a process of type A, for example, attempts to write to a file of type B. In that case, it will only be permitted if SELinux policy states explicitly that a process of type A may perform a write operation to a file of type B. In SELinux enforcement, all actions are denied by default unless a rule specifically allows the action to be performed.

The issue with SELinux and Samba is that SELinux policy is not configured to allow processes of type smb_t to perform actions on files of any type other than samba_share_t. For example, the /home/demo directory listed above will be inaccessible to the Samba service because it has a type of user_home_t. To make files or folders on the system accessible to the Samba service, the enforcement type of those specific resources must be changed to samba_share_t.

For this example, we will create the /sampleshare directory referenced previously in the smb.conf file and change the enforcement type to make it accessible to the Samba service. Begin by creating the directory as follows:

# mkdir /sampleshareCode language: plaintext (plaintext)

Next, check the current SELinux context on the directory:

$ ls -aZ /sampleshare/
unconfined_u:object_r:root_t:s0 .Code language: plaintext (plaintext)

In this instance, the context label of the folder has been assigned a type of root_t. To make the folder sharable by Samba, the enforcement type needs to be set to samba_share_t using the semanage tool as follows:

# semanage fcontext -a -t samba_share_t "/sampleshare(/.*)?"Code language: plaintext (plaintext)

Note the use of a wildcard in the semanage command to ensure that the type is applied to any sub-directories and files contained within the /sampleshare directory. Once added, the change needs to be applied using the restorecon command, making use of the -R flag to apply the change recursively through any sub-directories:

# restorecon -R -v /sampleshare
Relabeled /sampleshare from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:samba_share_t:s0Code language: plaintext (plaintext)

Once these changes have been made, the folder is configured to comply with SELinux policy for the smb process and is ready to be shared by Samba.

Creating a Samba User

Any user that requires access to a Samba shared resource must be configured as a Samba User and assigned a password. This task is achieved using the smbpasswd command-line tool. Consider, for example, that a user named demo is required to be able to access the /sampleshare directory of our AlmaLinux 9 system from a Windows system. To fulfill this requirement, we must add demo as a Samba user as follows:

# smbpasswd -a demo
New SMB password:
Retype new SMB password:
Added user demo.Code language: plaintext (plaintext)

Now that we have completed the configuration of an elementary Samba server, it is time to test our configuration file and then start the Samba services.

Testing the smb.conf File

The settings in the smb.conf file may be checked for errors using the testparm command-line tool as follows:

# testparm
Load smb config files from /etc/samba/smb.conf
Loaded services file OK.
Weak crypto is allowed

Press enter to see a dump of your service definitions
# Global parameters
	log file = /var/log/samba/%m.log
	netbios name = LINUXSERVER
	printcap name = cups
	security = USER
	wins support = Yes
	idmap config * : backend = tdb
	cups options = raw
	comment = Example Samba share
	guest ok = Yes
	path = /sampleshare
	read only = No
	browseable = No
	comment = Home Directories
	inherit acls = Yes
	read only = No
	valid users = %S %D%w%S
	browseable = No
	comment = All Printers
	create mask = 0600
	path = /var/tmp
	printable = Yes
.Code language: plaintext (plaintext)

Starting the Samba and NetBIOS Name Services

For an AlmaLinux 9 server to operate within a Windows network, the Samba (SMB) and NetBIOS nameservice (NMB) services must be started. Optionally, also enable the services so that they start each time the system boots:

# systemctl enable smb nmb
# systemctl start smb nmbCode language: plaintext (plaintext)

Before attempting to connect from a Windows system, use the smbclient utility to verify that the share is configured:

# smbclient -U demo -L localhost 
Enter WORKGROUP\demo’s password: 
	Sharename       Type      Comment
	---------       ----      -------
	sampleshare     Disk      Example Samba share
	print$          Disk      Printer Drivers
	IPC$            IPC       IPC Service (Samba 4.9.1)
	demo            Disk      Home DirectoriesCode language: plaintext (plaintext)

Accessing Samba Shares

Now that the Samba resources are configured and the services are running, it is time to access the shared resource from a Windows system. On a suitable Windows system on the same workgroup as the AlmaLinux 9 system, open Windows Explorer and right-click on the Network entry in the side panel to display the menu shown in Figure 19-3:

Figure 19-3

Select the Map network drive… menu option to display the dialog illustrated in Figure 19-4:

Figure 19-4

Select a drive letter and enter the path to a samba share. For example, assuming that the server name is LinuxServer and the samba user name is demo, the path to the user’s home folder would be as follows:

\\LINUXSERVER\demoCode language: plaintext (plaintext)

Enable the Connect using different credentials checkbox and click finish. When the network credentials dialog appears, enter the Samba user name and the password that was assigned earlier using the smbpasswd command:

Figure 19-5

After the connection is established, a new Windows Explorer dialog will appear containing the contents of the shared Ubuntu folder:

Figure 19-6

Accessing Windows Shares from AlmaLinux 9

As previously mentioned, Samba is a two-way street, allowing not only Windows systems to access files and printers hosted on an AlmaLinux 9 system but also allowing the AlmaLinux 9 system to access shared resources on Windows systems. This is achieved using the samba-client package, installed at this chapter’s start. If it is not currently installed, install it from a terminal window as follows:

# dnf install samba-clientCode language: plaintext (plaintext)

Shared resources on a Windows system can be accessed from the AlmaLinux desktop using the Files application or the command-line prompt using the smbclient and mount tools. The steps in this section assume that the Windows system has enabled appropriate network-sharing settings.

To access any shared resources on a Windows system using the GNOME desktop, launch the Files application and select the Other Locations option. This will display the screen shown in Figure 19-7 below, including an icon for the Windows Network (if one is detected):

Figure 19-7

Selecting the Windows Network option will display the Windows systems detected on the network and allow access to any shared resources.

Figure 19-8

Alternatively, the Connect to Server option may be used to connect to a specific system. Note that the name or IP address of the remote system must be prefixed by smb:// and may be followed by the path to a specific shared resource, for example:

smb://WinServer/DocumentsCode language: plaintext (plaintext)

Without a desktop environment, a remote Windows share may be mounted from the command line using the mount command and specifying the cifs filesystem type. The following command, for example, mounts a share named Documents located on a Windows system named WinServer at a local mount point named /winfiles:

# mount -t cifs //WinServer/Documents /winfiles -o user=demoCode language: plaintext (plaintext)


In this chapter, we have looked at how to configure an AlmaLinux 9 system to act as both a Samba client and server, allowing the sharing of resources with Windows systems. Topics covered included the installation of Samba client and server packages and configuring Samba as a standalone server. In addition, the basic concepts of SELinux were introduced together with the steps to provide Samba access to a shared resource.

Using NFS on AlmaLinux 9 to Share Files with Remote Systems

AlmaLinux 9 provides two mechanisms for sharing files and folders with other systems on a network. One approach is to use a technology called Samba. Samba is based on Microsoft Windows Folder Sharing and allows Linux systems to make folders accessible to Windows systems and access Windows-based folder shares from Linux. This approach can also be used to share folders between other Linux and UNIX-based systems if they have Samba support installed and configured. This is the most popular approach to sharing folders in heterogeneous network environments. Folder sharing using Samba is covered in “Sharing Files between AlmaLinux 9 and Windows with Samba”.

Another option, explicitly targeted at sharing folders between Linux and UNIX-based systems, uses Network File System (NFS). NFS allows the file system on one Linux computer to be accessed over a network connection by another Linux or UNIX system. NFS was originally developed by Sun Microsystems (now part of Oracle Corporation) in the 1980s and remains the standard mechanism for sharing remote Linux/UNIX file systems.

NFS is very different from the Windows SMB resource-sharing technology used by Samba. This chapter will look at the network-based sharing of folders between AlmaLinux 9 and other UNIX/Linux-based systems using NFS.

Ensuring NFS Services are running on AlmaLinux 9

The first task is to verify that the NFS services are installed and running on your AlmaLinux 9 system. This can be achieved from the command line or the Cockpit interface.

Begin by installing the NFS service by running the following command from a terminal window:

# dnf install rpcbind nfs-utilsCode language: plaintext (plaintext)

Next, configure these services so that they automatically start at boot time:

# systemctl enable rpcbind nfs-serverCode language: plaintext (plaintext)

Once the services have been enabled, start them as follows:

# systemctl start rpcbind nfs-serverCode language: plaintext (plaintext)

Configuring the Firewall to Allow NFS Traffic

Next, the firewall needs to be configured to allow NFS traffic. To achieve this, run the following firewall-cmd commands where <zone> is replaced by the appropriate zone for your firewall and system configuration:

# firewall-cmd --zone=<zone> --permanent --add-service=mountd
# firewall-cmd --zone=<zone> --permanent --add-service=nfs
# firewall-cmd --zone=<zone> --permanent --add-service=rpc-bind
# firewall-cmd --reload 
Code language: plaintext (plaintext)

Specifying the Folders to be Shared

Now that NFS is running and the firewall has been configured, we need to specify which parts of the AlmaLinux 9 file system may be accessed by remote Linux or UNIX systems. These settings can be declared in the /etc/exports file, which must be modified to export the directories for remote access via NFS. The syntax for an export line in this file is as follows:

<export> <host1>(<options>) <host2>(<options>)...Code language: plaintext (plaintext)

In the above line, <export> is replaced by the directory to be exported, <host1> is the name or IP address of the system to which access is being granted, and <options> represents the restrictions that are to be imposed on that access (read-only, read-write, etc.). Multiple host and options entries may be placed on the same line if required. For example, the following line grants read-only permission to the /datafiles directory to a host with the IP address

/datafiles language: plaintext (plaintext)

The use of wildcards is permitted to apply an export to multiple hosts. For example, the following line permits read-write access to /home/demo to all external hosts:

/home/demo *(rw)Code language: plaintext (plaintext)

For this chapter, we will configure the /etc/exports file as follows:

/tmp *(rw,sync)
/vol1,sync)Code language: plaintext (plaintext)

Once configured, the table of exported file systems maintained by the NFS server needs to be updated with the latest /etc/exports settings using the exportfs command as follows:

# exportfs -aCode language: plaintext (plaintext)

It is also possible to view the current share settings from the command line using the exportfs tool:

# exportfsCode language: plaintext (plaintext)

The above command will generate the following output:

/tmp <world>Code language: plaintext (plaintext)

Accessing Shared Folders

The shared folders may be accessed from a client system by mounting them manually from the command line. However, before attempting to mount a remote NFS folder, the package must first be installed on the client system:

# dnf install nfs-utilsCode language: plaintext (plaintext)

To mount a remote folder from the command line, open a terminal window and create a directory where you would like the remote shared folder to be mounted:

$ mkdir /home/demo/tmpCode language: plaintext (plaintext)

Using NFS on AlmaLinux 9 to Share Files with Remote Systems Next, enter the command to mount the remote folder using either the IP address or hostname of the remote NFS server, for example:

$ sudo mount -t nfs /home/demo/tmpCode language: plaintext (plaintext)

The remote /tmp folder will then be mounted on the local system. Once mounted, the /home/ demo/tmp folder will contain the remote folder and all its contents.

Options may also be specified when mounting a remote NFS filesystem. The following command, for example, mounts the same folder but configures it to be read-only:

$ sudo mount -t nfs -o ro /home/demo/tmpCode language: plaintext (plaintext)

Mounting an NFS Filesystem on System Startup

It is also possible to configure an AlmaLinux 9 system to automatically mount a remote file system each time it starts up by editing the /etc/fstab file. When loaded into an editor, it will likely resemble the following:

/dev/mapper/almalinux-root /           xfs     defaults        0 0
UUID=bc3e41a5-24ff-47c7    /boot       xfs     defaults        0 0
UUID=78B1-8B87             /boot/efi    vfat    umask=0077,shortname=winnt 0 2
/dev/mapper/almalinux-home /home       xfs     defaults        0 0
/dev/mapper/almalinux-swap noneCode language: plaintext (plaintext)

To mount, for example, a folder with the path /tmp, which resides on a system with the IP address in the local folder with the path /home/demo/tmp (note that this folder must already exist), add the following line to the /etc/fstab file: /home/demo/tmp nfs rw 0 0Code language: plaintext (plaintext)

Next time the system reboots, the /tmp folder on the remote system will be mounted on the local /home/demo/tmp mount point. All the files in the remote folder can then be accessed as if they reside on the local hard disk drive.

Unmounting an NFS Mount Point

Once a remote file system is mounted using NFS, it can be unmounted using the umount command with the local mount point as the command-line argument. The following command, for example, will unmount our example filesystem mount point:

$ sudo umount /home/demo/tmpCode language: plaintext (plaintext)

Accessing NFS Filesystems in Cockpit

In addition to mounting a remote NFS file system on a client using the command line, it is also possible to perform mount operations from within the Cockpit web interface. Assuming that Cockpit has been installed and configured on the client system, log into the Cockpit interface from within a web browser and select the Storage option from the left-hand navigation panel. If the Storage option is not listed, the cockpit-storaged package will need to be installed:

# dnf install cockpit-storaged
# systemctl restart cockpit.socketCode language: plaintext (plaintext)

Once the Cockpit service has restarted, log back into the Cockpit interface, at which point the Storage option should now be visible.

Once selected, the main storage page will include a section listing any currently mounted NFS file systems, as illustrated in Figure 18-1:

Figure 18-1

To mount a remote filesystem, click on the ‘+’ button highlighted above and enter information about the remote NFS server and file system share together with the local mount point and any necessary options into the resulting dialog before clicking on the Add button:

Figure 18-2

To modify, unmount, or remove an NFS filesystem share, select the corresponding mount in the NFS Mounts list (Figure 18-1 above) to display the page shown in Figure 18-3 below:

Figure 18-3

Using NFS on AlmaLinux 9 to Share Files with Remote Systems Within this screen, perform tasks such as changing the server or mount points or unmounting the file system. For example, the Remove option unmounts the file system and deletes the entry from the /etc/fstab file so that it does not re-mount the next time the system reboots.


The Network File System (NFS) is a client/server-based system, originally developed by Sun Microsystems, which provides a way for Linux and Unix systems to share filesystems over a network. NFS allows a client system to access and (subject to permissions) modify files located on a remote server as though those files are stored on a local filesystem. This chapter has provided an overview of NFS and outlined the options for configuring client and server systems using the command line or the Cockpit web interface.

Displaying AlmaLinux 9 Applications Remotely (X11 Forwarding)

In the previous chapter, we looked at how to display the entire AlmaLinux 9 desktop on a remote computer. While this works well if you need to display the entire desktop remotely, it could be considered overkill if you only want to display a single application. Therefore, this chapter will look at displaying individual applications on a remote system.

Requirements for Remotely Displaying AlmaLinux 9 Applications

There are some prerequisites to running an application on one AlmaLinux 9 system and displaying it on another. First, the system on which the application is to be displayed must be running an X server. If the system is a Linux or UNIX-based system with a desktop environment running, then this is no problem. However, if the system is running Windows or macOS, you must install an X server on it before you can display applications from a remote system. Several commercial and free Windows-based X servers are available for this purpose, and a web search should provide you with a list of options.

Second, the system on which the application is being run (as opposed to the system on which the application is to be displayed) must be configured to allow SSH access. Details on configuring SSH on an AlmaLinux 9 system can be found in the chapter Configuring SSH Key-based Authentication on AlmaLinux 9. This system must also run the X Window System from instead of Wayland. To enable the system from within the desktop, log out of the Gnome desktop, select your user account from the login screen, and then click the settings button in the bottom right-hand corner of the screen:

Figure 17-1

Select the Standard (X11 display server) option from the menu before logging in as usual. To revert to Wayland, repeat these steps, selecting the Standard (Wayland display server) option from the login screen settings menu.

Another option is to edit the /etc/gdm/custom.conf file, uncomment the WaylandEnable line as follows and restart the system:

# Uncomment the line below to force the login screen to use Xorg
WaylandEnable=falseCode language: plaintext (plaintext)

Once you have logged back into the desktop, open a Terminal window and run the following command to confirm that the system has been enabled:

$ echo $XDG_SESSION_TYPECode language: plaintext (plaintext)

The above command will output either x11 or wayland, depending on the current configuration.

Finally, SSH must be configured to allow X11 forwarding. This is achieved by adding the following directive to the SSH configuration on the system from which forwarding is to occur. By default on AlmaLinux 9, the /etc/ssh/sshd_config file contains a directive to include all of the configuration files contained in the /etc/ssh/sshd_config.d directory:

Include /etc/ssh/sshd_config.d/*.confCode language: plaintext (plaintext)

Create a new file in the /etc/ssh/sshd_config.d folder named 05_x11forwarding and edit it to enable the X11Forwarding property is enabled as follows:

X11Forwarding yesCode language: plaintext (plaintext)

After making the change, save the file and restart the SSH service:

# systemctl restart sshdCode language: Kotlin (kotlin)

Once the above requirements are met, it should be possible to display an X-based desktop application remotely. Keep in mind that not all GNOME apps are compatible with X11 forwarding. If an app is incompatible, the following error will appear when you try to run it using X11 forwarding: X11 connection rejected because of wrong authentication.

Displaying an AlmaLinux 9 Application Remotely

The first step in remotely displaying an application is to move to the system where the application is to be displayed. At this system, establish an SSH connection to the remote system so that you have a command prompt. This can be achieved using the ssh command. When using the ssh command, we need to use the -X flag to tell it that we plan to tunnel X11 traffic through the connection:

$ ssh -X user@hostnameCode language: plaintext (plaintext)

In the above example, user is the user name to use to log into the remote system, and hostname is the hostname or IP address of the remote system. Enter your password at the login prompt and, once logged in, run the following command to see the DISPLAY setting:

Displaying AlmaLinux 9 Applications Remotely (X11 Forwarding)

$ echo $DISPLAYCode language: plaintext (plaintext)

The command should output something similar to the following: localhost:10.0

To display an application, run it from the command prompt. For example:

$ geditCode language: plaintext (plaintext)

When executed, the above command should run gedit on the remote system but display the user interface on the local system.

Trusted X11 Forwarding

You can also enable trusted X11 forwarding by adding the following line to the 05_x11forwarding and restarting the ssh server:

ForwardX11Trusted yesCode language: plaintext (plaintext)

Trusted X11 forwarding is slightly faster than untrusted forwarding but is less secure since it does not engage the X11 security controls. The -Y flag is needed when using trusted X11 forwarding:

$ ssh -Y user@hostnameCode language: plaintext (plaintext)

Compressed X11 Forwarding

When using slower connections, the X11 data can be compressed using the ssh -C flag to improve performance:

$ ssh -X -C user@hostnameCode language: plaintext (plaintext)

Displaying Remote AlmaLinux 9 Apps on Windows

To display AlmaLinux 9-based apps on Windows, an SSH client and an X server must be installed on the Windows system. Installing and using the PuTTY client on Windows was covered earlier in the book in the “Configuring SSH Key-based Authentication on Rocky Linux 9AlmaLinux 9”maLinux 9” chapter. Refer to this chapter if you have not already installed PuTTY on your Windows system.

In terms of the X server, several options are available, though a popular choice appears to be VcXsrv which is available for free from the following URL:

Once the VcXsrv X server has been installed, an application named XLaunch will appear on the desktop and in the start menu. Start XLaunch and select a display option (the most flexible being the Multiple windows option which allows each client app to appear in its own window):

Figure 17-2

Click the Next button to proceed through the remaining screens, accepting the default configuration settings. On the final screen, click the Finish button to start the X server. If the Windows Defender dialog appears, click the button to allow access to your chosen networks.

Once running, XLaunch will appear in the taskbar and can be exited by right-clicking on the icon and selecting the Exit… menu option:

Figure 17-3

With the X server installed and running, launch PuTTY and either enter the connection information for the remote host or load a previously saved session profile. Before establishing the connection, however, X11 forwarding needs to be enabled. Therefore, within the PuTTY main window, scroll down the options in the left-hand panel, unfold the SSH section, and select the X11 option, as shown in Figure 17-4:

Displaying AlmaLinux 9 Applications Remotely (X11 Forwarding)

Figure 17-4

Turn on the Enable X11 forwarding checkbox highlighted in Figure 17-5, return to the sessions screen, and open the connection (saving the session beforehand if you plan to use it again):

Figure 17-5

Log into the AlmaLinux 9 system within the PuTTY session window and run a desktop app. After a short delay, the app will appear on the Windows desktop in its own window. Any dialogs the app opens will also appear in separate windows, just as they would on the AlmaLinux 9 GNOME desktop. Figure 17-6, for example, shows the AlmaLinux 9 nm-connection-editor tool displayed on a Windows 11 system:

Figure 17-6


For situations where remote access to individual AlmaLinux 9 desktop applications is required as opposed to the entire GNOME desktop, X11 forwarding provides a lightweight solution to remotely displaying graphical applications. The system on which the applications are to appear must be running an X Window System-based desktop environment (such as GNOME) or have an X server installed and running. Once X11 forwarding has been enabled on the remote server and a secure SSH connection established from the local system using the X11 forwarding option, most applications can be displayed remotely on the local X server.

AlmaLinux 9 Remote Desktop Access with VNC

AlmaLinux 9 can be configured to provide remote access to the graphical desktop environment over a network or internet connection. Although not enabled by default, displaying and accessing an AlmaLinux 9 desktop from a system anywhere else on a network or the internet is relatively straightforward. This can be achieved regardless of whether that system runs Linux, Windows, or macOS. There are even apps available for Android and iOS that will allow you to access your AlmaLinux 9 desktop from just about anywhere that a data signal is available.

Remote desktop access can be helpful in many scenarios. For example, it enables you or another person to view and interact with your AlmaLinux 9 desktop environment from another computer system on the same network or over the internet. This is useful if you need to work on your computer when you are away from your desk, such as while traveling. It is also helpful when a coworker or IT support technician needs access to your desktop to resolve a problem.

When the AlmaLinux 9 system runs on a cloud-based server, it also allows access to the desktop environment as an alternative to performing administrative tasks using the command-line prompt or Cockpit web console.

The AlmaLinux 9 remote desktop functionality is based on a technology known as Virtual Network Computing (VNC). This chapter will cover the key aspects of configuring and using remote desktops within AlmaLinux 9.

Secure and Insecure Remote Desktop Access

In this chapter, we will cover both secure and insecure remote desktop access methods. Assuming you are accessing one system from another within a secure internal network, using the insecure access method is generally safe. If, on the other hand, you plan to access your desktop remotely over any public network, you must use the secure method of access to avoid your system and data being compromised.

Installing the GNOME Desktop Environment

It is, of course, only possible to access the desktop environment if the desktop itself has been installed. If, for example, the system was initially configured as a server, it is unlikely that the desktop packages were installed. The easiest way to install the packages necessary to run the GNOME desktop is to perform a group install. The key to installing groups of packages to enable a specific feature is knowing the group’s name. At the time of writing, there are two groups for installing the desktop environment on AlmaLinux 9: “Server with GUI” and “Workstation”. As the group names tend to change from one AlmaLinux release to another, it is helpful to know that the list of groups that are either installed or available to be installed can be obtained using the dnf utility as follows:

# dnf grouplist
Available Environment Groups:
   Minimal Install
   Virtualization Host
   Custom Operating System
Installed Environment Groups:
   Server with GUI
Installed Groups:
   Container Management
   Headless Management
Available Groups:
   RPM Development Tools
   .NET Development
   Console Internet Tools
   Scientific Support
   Legacy UNIX Compatibility
   Graphical Administration Tools
   Network Servers
   System Tools
   Development Tools
   Security Tools
   Smart Card Support
Code language: plaintext (plaintext)

The Workstation environment group is listed as available (and therefore not already installed) in the above example. To find out more information about the contents of a group before installation, use the following command:

# dnf groupinfo workstation
Environment Group: Workstation
 Description: Workstation is a user-friendly desktop system for laptops and PCs.
 Mandatory Groups:
   Common NetworkManager submodules
   Guest Desktop Agents
   Hardware Support
   Internet Browser
   Printing Client
   Workstation product core
 Optional Groups:
   Backup Client
   GNOME Applications
   Headless Management
   Internet Applications
   Office Suite and Productivity
   Remote Desktop Clients
   Smart Card Support
Code language: plaintext (plaintext)

Having confirmed that this is the correct group, it can be installed as follows:

# dnf groupinstall workstationCode language: plaintext (plaintext)

Once installed, and assuming that the system has a display added, the desktop can be launched using the following startx command:

$ startxCode language: plaintext (plaintext)

To launch the graphical desktop each time the system starts, change the default target as follows:

# systemctl set-default graphical.targetCode language: plaintext (plaintext)

If, on the other hand, the system is a server with no directly connected display, the only way to run and access the desktop will be to configure VNC support on the system.

Installing VNC on AlmaLinux 9

Access to a remote desktop requires a VNC server installed on the remote system, a VNC viewer on the system from which access is being established, and, optionally, a secure SSH connection. While several VNC server and viewer implementations are available, Red Hat has standardized on TigerVNC, which provides both server and viewer components for Linux-based operating systems. VNC viewer clients for non-Linux platforms include RealVNC and TightVNC. To install the TigerVNC server package on AlmaLinux 9, run the following command:

# dnf install tigervnc-serverCode language: plaintext (plaintext)

If required, the TigerVNC viewer may also be installed as follows:

# dnf install tigervncCode language: plaintext (plaintext)

Once the server has been installed, the system must be configured to run one or more VNC services and open the appropriate ports on the firewall.

Assigning Ports to Users

VNC uses a range of ports starting at 5900 to communicate with remote clients. When connecting to a VNC server, these ports are referenced as display numbers (where 5901 is display :1, 5902 is display :2, and so on).

When setting up VNC on AlmaLinux 9, it is helpful to assign a specific port to each remote user to provide consistency in gaining access. Port assignments are declared in the /etc/tigervnc/vncserver. users file and use the following format:

display_number=userCode language: plaintext (plaintext)

It is recommended that port assignments begin at 5902. For example, the following entry in the vncserver.users file assigns display :2 (port 5902) to user demo:

:2=demoCode language: plaintext (plaintext)

Configuring the VNC Server

With the VNC server packages installed, the next step is configuring the server. System-wide settings may be declared within the /etc/tigervnc/vncserver-config-defaults file, while settings for individual users can be placed in the $HOME/.vnc/config file. At a minimum, one of these files should contain the following entry:

session=gnomeCode language: plaintext (plaintext)

Setting up a VNC Password

The next step is to specify a password for the remote desktop environment user. While logged in as the remote user, execute the vncpasswd command as follows:

[demo@demoserver ~]$ vncpasswd
Would you like to enter a view-only password (y/n)? n
A view-only password is not usedCode language: plaintext (plaintext)

Next, the firewall needs to be configured to provide external access to the VNC server for remote VNC viewer instances, for example:

# firewall-cmd --permanent --add-service=vnc-server
# firewall-cmd --reloadCode language: plaintext (plaintext)

Starting VNC Server

With the service configuration file created, the service needs to be started as follows (where <number> is replaced by the VNC display number:

systemctl start vncserver@<number>Code language: plaintext (plaintext)

The following command, for example, starts the VNC server for display :2:

# systemctl start vncserver@:2Code language: plaintext (plaintext)

Check that the service has started successfully as follows:

# systemctl status vncserver@:2
● vncserver@:2.service - Remote desktop service (VNC)
     Loaded: loaded (/usr/lib/systemd/system/[email protected]; enabled; prese>
     Active: active (running) since Thu 2023-08-24 15:50:07 CDT; 21h ago
    Process: 1027 ExecStartPre=/usr/libexec/vncsession-restore :2 (code=exited,>
    Process: 1107 ExecStart=/usr/libexec/vncsession-start :2 (code=exited, stat>
   Main PID: 1114 (vncsession)
      Tasks: 0 (limit: 22131)
     Memory: 1.9M
        CPU: 38ms
     CGroup: /system.slice/system-vncserver.slice/vncserver@:2.service
             1114 /usr/sbin/vncsession demo :2Code language: plaintext (plaintext)

If the service fails to start, run the journalctl command to check for error messages:

# journalctl -xeCode language: plaintext (plaintext)

Also, try again after rebooting the system before tying again. If the problem persists, check the VNC log file located in the user’s $HOME/.vnc directory for diagnostic messages.

Connecting to a VNC Server

VNC viewer implementations are available for a wide range of operating systems. Therefore, a quick internet search will likely provide numerous links containing details on obtaining and installing this tool on your chosen platform.

First, verify that the remote user has logged out of all local desktop sessions (the VNC server will not start if the user has an active desktop session).

From the desktop of a Linux system on which a VNC viewer such as TigerVNC is installed, a remote desktop connection can be established as follows from a Terminal window:

$ vncviewer <hostname>:<display number>Code language: plaintext (plaintext)

In the above example, <hostname> is either the hostname or IP address of the remote system and <display number> is the display number of the VNC server desktop, for example:

$ vncviewer language: plaintext (plaintext)

Alternatively, run the command without any options to be prompted for the details of the remote server:

Figure 16-1

Enter the hostname or IP address followed by the display number (for example, into the VNC server field and click on the Connect button. The viewer will prompt for the user’s VNC password to complete the connection, at which point a new window containing the remote desktop will appear:

Figure 16-2

This section assumed that the remote desktop was accessed from a Linux or UNIX system; the same steps apply to most other operating systems.

Connecting to a remote VNC server using the steps in this section results in an insecure, unencrypted connection between the client and server. This means the data transmitted during the remote session is vulnerable to interception. Therefore, a few extra steps are necessary to establish a secure and encrypted connection.

Establishing a Secure Remote Desktop Session

The remote desktop configurations explored in this chapter are considered insecure because no encryption is used. This is acceptable when the remote connection does not extend outside an internal network protected by a firewall. However, a more secure option is needed when a remote session is required over an internet connection. This is achieved by tunneling the remote desktop through a secure shell (SSH) connection. This section will cover how to do this on Linux, UNIX, and macOS client systems.

The SSH server is typically installed and activated by default on AlmaLinux 9 systems. If this is not the case on your system, refer to the chapter Configuring SSH Key-based Authentication on AlmaLinux 9.

Assuming the SSH server is installed and active, it is time to move to the other system. At the other system, log in to the remote system using the following command, which will establish the secure tunnel between the two systems:

$ ssh -l <username> -L 5902:localhost:5902 <remotehost>Code language: plaintext (plaintext)

In the above example, <username> references the user account on the remote system for which VNC access has been configured, and <remotehost> is either the hostname or IP address of the remote system, for example:

$ ssh -l neilsmyth -L 5902:localhost:5902 language: plaintext (plaintext)

When prompted, log in using the account password. With the secure connection established, it is time to launch vncviewer to use the secure tunnel. Leaving the SSH session running in the other terminal window, launch another terminal and enter the following command:

$ vncviewer localhost:5902Code language: plaintext (plaintext)

The vncviewer session will prompt for a password if one is required, and then launch the VNC viewer providing secure access to your desktop environment.

Although the connection is now secure and encrypted, the VNC viewer will most likely still report that the connection is insecure. Figure 16-3, for example, shows the warning dialog displayed by the RealVNC viewer running on a macOS system:

Figure 16-3

Unfortunately, although the connection is now secure, the VNC viewer software has no way of knowing this and consequently continues to issue warnings. However, rest assured that as long as the SSH tunnel is being used, the connection is indeed secure.

In the above example, we left the SSH tunnel session running in a terminal window. If you would prefer to run the session in the background, this can be achieved by using the –f and –N flags when initiating the connection:

$ ssh -l <username> -f -N -L 5902:localhost:5902 <remotehost>Code language: plaintext (plaintext)

The above command will prompt for a password for the remote server and then establish the connection in the background, leaving the terminal window available for other tasks.

If you are connecting to the remote desktop from outside the firewall, keep in mind that the IP address for the SSH connection will be the external IP address provided by your ISP or cloud hosting provider, not the LAN IP address of the remote system (since this IP address is not visible to those outside the firewall). Therefore, you will also need to configure your firewall to forward port 22 (for the SSH connection) to the IP address of the system running the desktop. It is not necessary to forward port 5900. Steps to perform port forwarding differ between firewalls, so refer to the documentation for your firewall, router, or wireless base station for details specific to your configuration.

Establishing a Secure Tunnel on Windows using PuTTY

A similar approach is taken to establishing a secure desktop session from a Windows system to an AlmaLinux 9 server. Assuming you already have a VNC client such as TightVNC installed, the remaining requirement is a Windows SSH client (in this case, PuTTY).

Once PuTTY is downloaded and installed, the first step is establishing a secure connection between the Windows system and the remote AlmaLinux 9 system with appropriate tunneling configured. When launched, PuTTY displays the following screen:

Figure 16-4

Enter the IP address or hostname of the remote host (or the external IP address of the gateway if you are connecting from outside the firewall). The next step is to set up the tunnel. Click on the + next to SSH in the Category tree on the left-hand side of the dialog and select Tunnels. The screen should subsequently appear as follows:

Figure 16-5

Enter 5901 as the Source port and localhost:5901 as the Destination, and click the Add button. Finally, return to the main screen by clicking on the Session category. Enter a name for the session in the Saved Sessions text field and press Save. Click on Open to establish the connection. A terminal window will appear with the login prompt from the remote system. Enter the appropriate user login and password credentials.

The SSH connection is now established. Launch the TightVNC viewer, enter localhost:5901 in the VNC Server text field, and click Connect. The viewer will establish the connection, prompt for the password, and then display the desktop. You are now accessing the remote desktop of a Linux system from Windows over a secure SSH tunnel connection.

Shutting Down a Desktop Session

To shut down a VNC server-hosted desktop session, use the systemctl stop command. For example, to stop desktop :2:

# systemctl stop vncserver@:2Code language: plaintext (plaintext)

The VNC server must be stopped before the user attempts to log into a local desktop session. If the user’s VNC server is still running, the local desktop session will appear as a blank screen.


Remote access to the GNOME desktop environment of an AlmaLinux 9 system can be enabled by using Virtual Network Computing (VNC). Comprising the VNC server running on the remote server and a corresponding client on the local host, VNC allows remote access to multiple desktop instances running on the server.

When the VNC connection is being used over a public connection, SSH tunneling is recommended to ensure that the communication between the client and server is encrypted and secure.

Configuring SSH Key-based Authentication on AlmaLinux 9

When an AlmaLinux 9 system is first installed, it is configured by default to allow remote command-line access via Secure Shell (SSH) connections. SSH provides password-protected and encrypted access to the system for the root account and any other users added during the installation phase. However, this level of security is inadequate and should be upgraded to SSH key-based authentication as soon as possible.

This chapter will outline the steps to increase the security of an AlmaLinux 9 system by implementing key-based SSH authentication.

An Overview of Secure Shell (SSH)

SSH allows secure remote access to systems to gain shell access and transfer files and data. As will be covered in “AlmaLinux 9 Remote Desktop Access with VNC”, SSH can also provide a secure tunnel through which remote access to the GNOME desktop can be achieved over a network connection.

A basic SSH configuration consists of a client (used on the computer establishing the connection) and a server (running on the system to which the connection is to be established). A user might, for example, use an SSH client running on a Linux, Windows, or macOS system to connect to the SSH server running on an AlmaLinux 9 system to gain access to a shell command-line prompt or to perform file transfers. All communications between the client and server, including the password entered to gain access, are encrypted to prevent outside parties from intercepting the data.

The inherent weakness in a basic SSH implementation is that it depends entirely on the strength of the passwords assigned to the accounts on the system. If a malicious party is able to identify the password for an account (either through guesswork, deception, or a brute force attack), the system becomes vulnerable. This weakness can be addressed by implementing SSH key-based authentication.

SSH Key-based Authentication

SSH key-based authentication uses asymmetric public key encryption to add an extra layer of security to remote system access. The concept of public key encryption was devised in 1975 by Whitfield Diffie and Martin Hellman and is based on using a pair of private and public keys. In a public key encryption system, the public key is used to encrypt data that can only be decrypted by the owner of the private key.

In the case of SSH key-based authentication, the host holds the private key on which the SSH client is located, while the corresponding public key resides on the system on which the SSH server is running. Therefore, it is vital to protect the private key since ownership of the key will allow anyone to log into the remote system. As an added layer of protection, the private key may also be encrypted and protected by a password which must be entered each time a connection is established to the server.

Setting Up Key-based Authentication

There are four steps to setting up key-based SSH authentication, which can be summarized as follows:

  1. Generate the public and private keys.
  2. Install the public key on the server.
  3. Test authentication.
  4. Disable password-based authentication on the server.

The remainder of this chapter will outline these steps in greater detail for Linux, macOS, and Windows-based client operating systems.

Installing and Starting the SSH Service

If the SSH server is not already installed and running on the system, it can be added using the following commands:

# dnf install openssh-server
# systemctl start sshd.service
# systemctl enable sshd.serviceCode language: plaintext (plaintext)

SSH Key-based Authentication from Linux and macOS Clients

The first step in setting up SSH key-based authentication is to generate the key pairs on the client system. If the client system is running Linux or macOS, this is achieved using the ssh-keygen utility:

# ssh-keygenCode language: plaintext (plaintext)

This command will result in output similar to the following:

Generating public/private rsa key pair.
Enter file in which to save the key (/home/<username>/.ssh/id_rsa):
Code language: plaintext (plaintext)

Press the Enter key to accept the default location for the key files. This will place two files in the .ssh sub-directory of the current user’s home directory. The private key will be stored in a file named id_rsa while the public key will reside in the file named

Next, ssh-keygen will prompt for a passphrase with which to protect the private key. If a passphrase is provided, the private key will be encrypted on the local disk, and the passphrase will be required to access the remote system. Therefore, for better security, the use of a passphrase is recommended.

Enter passphrase (empty for no passphrase):Code language: plaintext (plaintext)

Finally, the ssh-keygen tool will generate the following output indicating that the keys have been generated:

Your identification has been saved in /home/neil/.ssh/id_rsa.
Your public key has been saved in /home/neil/.ssh/
The key fingerprint is:
SHA256:FOLGWEEGFIjWnCT5wtTOv5VK4hdimzWghZizUEMYbfo <username>@<hostname>
The key’s randomart image is:
+---[RSA 2048]----+
|.BB+=+*..        |
|o+B= * . .       |
|===.. + .        |
|*+ * . .         |
|.++ o   S        |
|..E+ * o         |
|  o B *          |
|   + +           |
|    .            |
Code language: plaintext (plaintext)

The next step is to install the public key onto the remote server system. This can be achieved using the ssh-copy-id utility as follows:

$ ssh-copy-id username@remote_hostname Code language: plaintext (plaintext)

For example:

$ ssh-copy-id [email protected]
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/neil/.ssh/"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]’s password: 
Number of key(s) added: 1
Now try logging into the machine, with:   "ssh '[email protected]'"
and check to make sure that only the key(s) you wanted were added.
Code language: plaintext (plaintext)

Once the key is installed, test that the authentication works by attempting a remote login using the ssh client:

$ ssh -l <username> <hostname>Code language: plaintext (plaintext)

If the private key is encrypted and protected with a passphrase, enter the phrase when prompted to complete the authentication and establish remote access to the AlmaLinux 9 system:

Enter passphrase for key '/home/neil/.ssh/id_rsa': 
Last login: Fri Mar 31 14:29:28 2023 from
[neil@demosystem02 ~]$Code language: plaintext (plaintext)

Repeat these steps for any other accounts on the server for which remote access is required. If access is also required from other client systems, copy the id_rsa private key file to the .ssh subdirectory of your home folder on the other systems.

As currently configured, access to the remote system can still be achieved using less secure password authentication. Once you have verified that key-based authentication works, password authentication will need to be disabled on the system. To understand how to change this setting, begin by opening the /etc/ssh/sshd_config file and locating the following line:

Include /etc/ssh/sshd_config.d/*.confCode language: PHP (php)

This tells us that sshd configuration settings are controlled by files in the /etc/ssh/sshd_config.d directory. These filenames must be prefixed with a number and have a .conf filename extension, for example:

50-redhat.confCode language: plaintext (plaintext)

The number prefix designates the priority assigned to the file relative to the other files in the folder, with 01 being the highest priority. This ensures that if a configuration file contains a setting conflicting with another file, the one with the highest priority will always take precedence. Within the /etc/ssh/sshd_config.d folder, create a new file named 02-nopasswordlogin.conf with content that reads as follows:

PasswordAuthentication noCode language: plaintext (plaintext)

Save the file and restart the sshd service to implement the change:

# systemctl restart sshd.serviceCode language: plaintext (plaintext)

From this point on, it will only be possible to remotely access the system using SSH key-based authentication, and when doing so, you won’t be required to enter a password.

Managing Multiple Keys

It is common for multiple private keys to reside on a client system, each providing access to a different server. As a result, several options exist for selecting a specific key when establishing a connection. It is possible, for example, to specify the private key file to be used when launching the ssh client as follows:

$ ssh -l neilsmyth -i ~/.ssh/id_work language: plaintext (plaintext)

Alternatively, the SSH client user configuration file may associate key files with servers. The configuration file is named config, must reside in the .ssh directory of the user’s home directory, and can be used to configure a wide range of options, including the private key file, the default port to use when connecting, the default user name, and an abbreviated nickname via which to reference the server. The following example config file defines different key files for two servers and allows them to be referenced by the nicknames home and work. In the case of the work system, the file also specifies the user name to be used when authenticating:

Host work
  IdentityFile ~/.ssh/id_work
  User neilsmyth
Host home
  IdentityFile ~/.ssh/id_home
Code language: plaintext (plaintext)

Before setting up the configuration file, the user would have used the following command to connect to the work system:

$ ssh -l neilsmyth -i ~/.ssh/id_work language: plaintext (plaintext)

Now, however, the command can be shortened as follows:

$ ssh workCode language: plaintext (plaintext)

A full listing of configuration file options can be found by running the following command:

$ man ssh_configCode language: plaintext (plaintext)

SSH Key-based Authentication from Windows Clients

Recent releases of Windows include a subset of the OpenSSH implementation used by most Linux and macOS systems as part of Windows PowerShell. This allows SSH key-based authentication to be set up from a Windows client using similar steps to those outlined above for Linux and macOS.

On Windows, search for Windows PowerShell and select it from the results. Once running, the PowerShell window will appear as shown in Figure 15-1:

Figure 15-1

If you already have a private key from another client system, copy the id_rsa file to a folder named .ssh on the Windows system. Once the file is in place, test the authentication within the PowerShell window as follows:

PS C:\Users\neil> ssh -l neil
Enter passphrase for key 'C:\Users\neil\.ssh\id_rsa':
Code language: plaintext (plaintext)

Enter the passphrase when prompted and complete the authentication process.

If the private key does not yet exist, generate a new private and public key pair within the PowerShell window using the ssh-keygen utility using the same steps outlined for Linux and macOS. Once the keys have been generated, they will again be located in the .ssh directory of the current user’s home folder, and the public key file will need to be installed on the remote AlmaLinux 9 system. Unfortunately, Windows PowerShell does not include the ssh-copy-id utility, so this task must be performed manually.

Within the PowerShell window, change directory into the .ssh sub-directory and display the content of the public key file:

PS C:\Users\neil> cd .ssh
PS C:\Users\neil\.ssh> type
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFgx1vzu59lll6/uQw7FbmKVsQ3fzLz9MW1fgo4sdsxXp81wCHNAlqcjx1Pgr9BJPXWUMInQOi7BQ5I+vc2xQ2AS0kMq3ZH9ybWuQe/U2GjueXZd0FKrEXrT55wM36Rm6Ii3roUCoGCzGR8mn95JvRB3VtCyDdzTWSi8JBpK5gV5oOxNTNPsewlLzouBlCT1qW3CKwEiIwu8S9MTL7m3nrcaNeLewTTHevvHw4QDwzFQ+B0PDg96fzsYoTXVhzyHSWyo6H0gqrft7aK+gILBtEIhWTkSVEMAzy1piKtCr1IYTmVK6engv0aoGtMUq6FnOeGp5FjvKkF4aQkh1QR28r neil@DESKTOP-S8P8D3NCode language: plaintext (plaintext)

Highlight the file’s content and copy it using the Ctrl-C keyboard shortcut.

Remaining within the PowerShell window, log into the remote system using password authentication:

PS C:\Users\neil\.ssh> ssh -l <username> <hostname>Code language: plaintext (plaintext)

Once signed in, check if the .ssh sub-directory exists. If it does not, create it as follows:

$ mkdir .sshCode language: plaintext (plaintext)

Change directory into .ssh and check whether a file named authorized_keys already exists. If it does not, create it and paste the content of the public key file from the Windows system into it.

If the authorized_keys file already exists, it likely contains other keys. If this is the case, edit the file and paste the new public key at the end of the file. The following file, for example, contains two keys:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzRWH27Xs8ZA5rIbZXKgxFY5XXauMv+6F5PljBLJ6j+9nkmykVe3GjZTp3oD+KMRbT2kTEPbDpFD67DNL0eiX2ZuEEiYsxZfGCRCPBGYmQttFRHEAFnlS1Jx/G4W5UNKvhAXWyMwDEKiWvqTVy6syB2Ritoak+D/Sc8nJflQ6dtw0jBs+S7Aim8TPfgpi4p5XJGruXNRScamk68NgnPfTL3vT726EuABCk6C934KARd+/AXa8/5rNOh4ETPstjBRfFJ0tpmsWWhhNEnwJRqS2LD0ug7E3yFI2qsNKGEzvAYUC8Up45MRP7liR3aMlCBil1tsy9R+IB7oMEycZAe/qj [email protected]
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFgx1vzu59lll6/uQw7FbmKVsQ3fzLz9MW1fgo4sdsxXp81wCHNAlqcjx1Pgr9BJPXWUMInQOi7BQ5I+vc2xQ2AS0kMq3ZH9ybWuQe/U2GjueXZd0FKrEXrT55wM36Rm6Ii3roUCoGCzGR8mn95JvRB3VtCyDdzTWSi8JBpK5gV5oOxNTNPsewlLzouBlCT1qW3CKwEiIwu8S9MTL7m3nrcaNeLewTTHevvHw4QDwzFQ+B0PDg96fzsYoTXVhzyHSWyo6H0gqrft7aK+gILBtEIhWTkSVEMAzy1piKtCr1IYTmVK6engv0aoGtMUq6FnOeGp5FjvKkF4aQkh1QR28r neil@DESKTOP-S8P8D3N
Code language: plaintext (plaintext)

Once the public key is installed on the server, test the authentication by logging in to the server from within the PowerShell window, for example:

PS C:\Users\neil\.ssh> ssh -l neil
Enter passphrase for key 'C:\Users\neil\.ssh\id_rsa':
Code language: plaintext (plaintext)

When key-based authentication has been set up for all the accounts and verified, disable password authentication on the AlmaLinux 9 system as outlined at the end of the previous section.

SSH Key-based Authentication using PuTTY

For Windows systems that do not have OpenSSH available or as a more flexible alternative to using PowerShell, the PuTTY tool is a widely used alternative. The first step in using PuTTY is downloading and installing it on any Windows system that needs an SSH client. PuTTY is a free utility and can be downloaded using the following link:

Download the Windows installer executable that matches your Windows system (32-bit and 64-bit versions are available), then execute the installer to complete the installation.

If a private key already exists on another system, create the .ssh folder in the current user’s home folder and copy the private id_rsa key into it.

Next, the private key file must be converted to a PuTTY private key format file using the PuTTYgen tool. Locate this utility by typing “PuTTY Key Generator” into the search bar of the Windows Start menu and launch it:

Figure 15-2

Once launched, click on the Load button located in the Actions section and navigate to the private key file previously copied to the .ssh folder (note that it may be necessary to change the file type filter to All Files (*.*) for the key file to be visible). Once located, select the file and load it into PuttyGen. When prompted, enter the passphrase used initially to encrypt the file. Once the private key has been imported, save it as a PuTTY key file by clicking the Save Private Key button. For consistency, save the key file to the .ssh folder but give it a different name to differentiate it from the original key file.

Launch PuTTY from the Start menu and enter the IP address or hostname of the remote server into the main screen before selecting the Connection -> SSH -> Auth -> Credentials category in the left-hand panel, as highlighted in Figure 15-3:

Figure 15-3

Click the Browse button next to the Private key for authentication field and navigate to and select the previously saved PuTTY private key file. Then, optionally, scroll to the top of the left-hand panel, select the Session entry, and enter a name for the session in the Saved Sessions field before clicking on the Save button. This will save the session configuration for future use without reentering the settings each time.

Finally, click on the Open button to establish the connection to the remote server, entering the user name and passphrase when prompted to do so to complete the authentication.

Generating a Private Key with PuTTYgen

The previous section explored using existing private and public keys when working with PuTTY. If keys do not exist, they can be created using the PuTTYgen tool, which is included in the main PuTTY installation.

To create new keys, launch PuttyGen and click on the Generate button highlighted in Figure 15-4:

Figure 15-4

Move the mouse pointer to generate random data as instructed, then enter an optional passphrase to encrypt the private key. Once the keys have been generated, save the files to suitable locations using the Save public key and Save private key buttons. As outlined in the previous section, the private key can be used with PuTTY. To install the public key on the remote server, use the steps covered in the earlier section on SSH within PowerShell on Windows.


Any remote access to an AlmaLinux 9 system must be implemented in a way that provides a high level of security. By default, SSH allows remote system access using password-based authentication. However, this leaves the system vulnerable to anyone who can guess a password or find out the password through other means. For this reason, key-based authentication is recommended to protect system access. Key-based authentication uses public key encryption involving public and private keys. When implemented, users can only connect to a server if they are using a client with a private key that matches a public key on the server. As an added layer of security, the private key may also be encrypted and password protected. Once key-based encryption has been implemented, the server system is configured to disable support for the less secure password-based authentication.

This chapter has provided an overview of SSH key-based authentication and outlined the steps involved in generating keys and configuring clients on macOS, Linux, and Windows, as well as installing and managing public keys on an AlmaLinux 9 server.