0% found this document useful (0 votes)
18 views501 pages

Red Hat Enterprise Linux-8-System Design Guide-En-US

The Red Hat Enterprise Linux 8 System Design Guide provides comprehensive instructions for designing and implementing RHEL 8 systems, including system image creation and security configurations. It covers various topics such as using the RHEL image builder for creating customized system images, performing automated installations with Kickstart, and implementing security measures during and after installation. The document is licensed under CC-BY-SA and includes legal notices regarding trademarks and copyrights.

Uploaded by

EiRsVi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views501 pages

Red Hat Enterprise Linux-8-System Design Guide-En-US

The Red Hat Enterprise Linux 8 System Design Guide provides comprehensive instructions for designing and implementing RHEL 8 systems, including system image creation and security configurations. It covers various topics such as using the RHEL image builder for creating customized system images, performing automated installations with Kickstart, and implementing security measures during and after installation. The document is licensed under CC-BY-SA and includes legal notices regarding trademarks and copyrights.

Uploaded by

EiRsVi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 501

Red Hat Enterprise Linux 8

System Design Guide

Designing a RHEL 8 system

Last Updated: 2025-01-09


Red Hat Enterprise Linux 8 System Design Guide
Designing a RHEL 8 system
Legal Notice
Copyright © 2025 Red Hat, Inc.

The text of and illustrations in this document are licensed by Red Hat under a Creative Commons
Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is
available at
http://creativecommons.org/licenses/by-sa/3.0/
. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must
provide the URL for the original version.

Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert,
Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.

Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift,
Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States
and other countries.

Linux ® is the registered trademark of Linus Torvalds in the United States and other countries.

Java ® is a registered trademark of Oracle and/or its affiliates.

XFS ® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States
and/or other countries.

MySQL ® is a registered trademark of MySQL AB in the United States, the European Union and
other countries.

Node.js ® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the
official Joyent Node.js open source or commercial project.

The OpenStack ® Word Mark and OpenStack logo are either registered trademarks/service marks
or trademarks/service marks of the OpenStack Foundation, in the United States and other
countries and are used with the OpenStack Foundation's permission. We are not affiliated with,
endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.

All other trademarks are the property of their respective owners.

Abstract
This content covers how to start using Red Hat Enterprise Linux 8. To learn about Red Hat
Enterprise Linux technology capabilities and limits, see https://access.redhat.com/articles/rhel-
limits.
Table of Contents

Table of Contents
. . . . . . . . . . . . . FEEDBACK
PROVIDING . . . . . . . . . . . . ON
. . . .RED
. . . . .HAT
. . . . .DOCUMENTATION
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
..............

. . . . . . .I.. DESIGN
PART . . . . . . . . .OF
. . . .INSTALLATION
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
..............

.CHAPTER
. . . . . . . . . . 1.. .COMPOSING
. . . . . . . . . . . . . .A. .CUSTOMIZED
. . . . . . . . . . . . . . .RHEL
. . . . . .SYSTEM
. . . . . . . . . IMAGE
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
..............
1.1. RHEL IMAGE BUILDER DESCRIPTION 17
1.1.1. RHEL image builder terminology 17
1.1.2. RHEL image builder output formats 17
1.1.3. Supported architectures for image builds 18
1.1.4. Additional resources 19
1.2. INSTALLING RHEL IMAGE BUILDER 19
1.2.1. RHEL image builder system requirements 19
1.2.2. Installing RHEL image builder 19
1.2.3. Reverting to lorax-composer RHEL image builder backend 21
1.3. CREATING SYSTEM IMAGES BY USING RHEL IMAGE BUILDER CLI 22
1.3.1. Introducing the RHEL image builder command-line interface 22
1.3.2. Using RHEL image builder as a non-root user 22
1.3.3. Creating a blueprint by using the command-line interface 22
1.3.4. Editing a blueprint with command-line interface 24
1.3.5. Creating a system image with RHEL image builder in the command-line interface 26
1.3.6. Basic RHEL image builder command-line commands 27
1.3.7. RHEL image builder blueprint format 28
1.3.8. Supported image customizations 29
1.3.8.1. Selecting a distribution 30
1.3.8.2. Selecting a package group 30
1.3.8.3. Embedding a container 31
1.3.8.4. Setting the image hostname 31
1.3.8.5. Specifying additional users 31
1.3.8.6. Specifying additional groups 32
1.3.8.7. Setting SSH key for existing users 33
1.3.8.8. Appending a kernel argument 33
1.3.8.9. Building RHEL images by using the real-time kernel 33
1.3.8.10. Setting time zone and NTP 35
1.3.8.11. Customizing the locale settings 36
1.3.8.12. Customizing firewall 36
1.3.8.13. Enabling or disabling services 37
1.3.8.14. Specifying a partition mode 38
1.3.8.15. Specifying a custom file system configuration 38
1.3.8.15.1. Specifying customized files in the blueprint 41
1.3.8.15.2. Specifying customized directories in the blueprint 41
1.3.9. Packages installed by RHEL image builder 44
1.3.10. Enabled services on custom images 49
1.4. CREATING SYSTEM IMAGES BY USING RHEL IMAGE BUILDER WEB CONSOLE INTERFACE 50
1.4.1. Accessing the RHEL image builder dashboard in the RHEL web console 50
1.4.2. Creating a blueprint in the web console interface 50
1.4.3. Importing a blueprint in the RHEL image builder web console interface 54
1.4.4. Exporting a blueprint from the RHEL image builder web console interface 55
1.4.5. Creating a system image by using RHEL image builder in the web console interface 55
1.5. PREPARING AND UPLOADING CLOUD IMAGES BY USING RHEL IMAGE BUILDER 56
1.5.1. Preparing and uploading AMI images to AWS 56
1.5.1.1. Preparing to manually upload AWS AMI images 56

1
Red Hat Enterprise Linux 8 System Design Guide

1.5.1.2. Manually uploading an AMI image to AWS by using the CLI 58


1.5.1.3. Creating and automatically uploading images to the AWS Cloud AMI 59
1.5.2. Preparing and uploading VHD images to Microsoft Azure 61
1.5.2.1. Preparing to manually upload Microsoft Azure VHD images 61
1.5.2.2. Manually uploading VHD images to Microsoft Azure cloud 63
1.5.2.3. Creating and automatically uploading VHD images to Microsoft Azure cloud 64
1.5.2.4. Uploading VMDK images and creating a RHEL virtual machine in vSphere 66
1.5.2.5. Creating and automatically uploading VMDK images to vSphere using image builder GUI 67
1.5.3. Preparing and uploading custom GCE images to GCP 69
1.5.3.1. Uploading images to GCP with RHEL image builder 70
1.5.3.1.1. Configuring and uploading a gce image to GCP by using the CLI 70
1.5.3.1.2. How RHEL image builder sorts the authentication order of different GCP credentials 71
1.5.3.1.2.1. Specifying GCP credentials with the composer-cli command 72
1.5.3.1.2.2. Specifying credentials in the osbuild-composer worker configuration 72
1.5.4. Preparing and uploading custom images directly to OCI 72
1.5.4.1. Creating and automatically uploading custom images to OCI 72
1.5.5. Preparing and uploading customized QCOW2 images directly to OpenStack 74
1.5.5.1. Uploading QCOW2 images to OpenStack 74
1.5.6. Preparing and uploading customized RHEL images to the Alibaba Cloud 76
1.5.6.1. Preparing to upload customized RHEL images to Alibaba Cloud 76
1.5.6.2. Uploading customized RHEL images to Alibaba 77
1.5.6.3. Importing images to Alibaba Cloud 78
1.5.6.4. Creating an instance of a customized RHEL image using Alibaba Cloud 79

. . . . . . . . . . . 2.
CHAPTER . . PERFORMING
. . . . . . . . . . . . . . . AN
. . . .AUTOMATED
. . . . . . . . . . . . . . INSTALLATION
. . . . . . . . . . . . . . . . .USING
. . . . . . .KICKSTART
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
..............

. . . . . . . . . . . 3.
CHAPTER . . ADVANCED
. . . . . . . . . . . . . CONFIGURATION
. . . . . . . . . . . . . . . . . . .OPTIONS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .82
..............

. . . . . . . . . . . 4.
CHAPTER . . .KICKSTART
. . . . . . . . . . . .REFERENCES
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .83
..............

. . . . . . .II.. .DESIGN
PART . . . . . . . . .OF
. . . SECURITY
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84
..............

. . . . . . . . . . . 5.
CHAPTER . . SECURING
. . . . . . . . . . . . RHEL
. . . . . . DURING
. . . . . . . . . AND
. . . . . RIGHT
. . . . . . . .AFTER
. . . . . . . INSTALLATION
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .85
..............
5.1. DISK PARTITIONING 85
5.2. RESTRICTING NETWORK CONNECTIVITY DURING THE INSTALLATION PROCESS 85
5.3. INSTALLING THE MINIMUM AMOUNT OF PACKAGES REQUIRED 86
5.4. POST-INSTALLATION PROCEDURES 86
5.5. DISABLING SMT TO PREVENT CPU SECURITY ISSUES BY USING THE WEB CONSOLE 86

.CHAPTER
. . . . . . . . . . 6.
. . .USING
. . . . . . .SYSTEM-WIDE
. . . . . . . . . . . . . . . .CRYPTOGRAPHIC
. . . . . . . . . . . . . . . . . . .POLICIES
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .88
..............
6.1. SYSTEM-WIDE CRYPTOGRAPHIC POLICIES 88
6.2. CHANGING THE SYSTEM-WIDE CRYPTOGRAPHIC POLICY 90
6.3. SWITCHING THE SYSTEM-WIDE CRYPTOGRAPHIC POLICY TO MODE COMPATIBLE WITH EARLIER
RELEASES 91
6.4. SETTING UP SYSTEM-WIDE CRYPTOGRAPHIC POLICIES IN THE WEB CONSOLE 91
6.5. EXCLUDING AN APPLICATION FROM FOLLOWING SYSTEM-WIDE CRYPTO POLICIES 93
6.5.1. Examples of opting out of system-wide crypto policies 94
6.6. CUSTOMIZING SYSTEM-WIDE CRYPTOGRAPHIC POLICIES WITH SUBPOLICIES 95
6.7. DISABLING SHA-1 BY CUSTOMIZING A SYSTEM-WIDE CRYPTOGRAPHIC POLICY 97
6.8. CREATING AND SETTING A CUSTOM SYSTEM-WIDE CRYPTOGRAPHIC POLICY 97
6.9. ENHANCING SECURITY WITH THE FUTURE CRYPTOGRAPHIC POLICY USING THE CRYPTO_POLICIES
RHEL SYSTEM ROLE 98
6.10. ADDITIONAL RESOURCES 101

. . . . . . . . . . . 7.
CHAPTER . . CONFIGURING
. . . . . . . . . . . . . . . . APPLICATIONS
. . . . . . . . . . . . . . . . .TO
. . . USE
. . . . . CRYPTOGRAPHIC
. . . . . . . . . . . . . . . . . . . HARDWARE
. . . . . . . . . . . . . THROUGH
. . . . . . . . . . . .PKCS
. . . . . .#11
..................

2
Table of Contents

102
7.1. CRYPTOGRAPHIC HARDWARE SUPPORT THROUGH PKCS #11 102
7.2. AUTHENTICATING BY SSH KEYS STORED ON A SMART CARD 102
7.3. CONFIGURING APPLICATIONS FOR AUTHENTICATION WITH CERTIFICATES ON SMART CARDS 104
7.4. USING HSMS PROTECTING PRIVATE KEYS IN APACHE 104
7.5. USING HSMS PROTECTING PRIVATE KEYS IN NGINX 105
7.6. ADDITIONAL RESOURCES 105

. . . . . . . . . . . 8.
CHAPTER . . .USING
. . . . . . .SHARED
. . . . . . . . . SYSTEM
. . . . . . . . . CERTIFICATES
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .106
...............
8.1. THE SYSTEM-WIDE TRUSTSTORE 106
8.2. ADDING NEW CERTIFICATES 106
8.3. MANAGING TRUSTED SYSTEM CERTIFICATES 107

. . . . . . . . . . . 9.
CHAPTER . . .SCANNING
. . . . . . . . . . . .THE
. . . . SYSTEM
. . . . . . . . . .FOR
. . . . .SECURITY
. . . . . . . . . . .COMPLIANCE
. . . . . . . . . . . . . . .AND
. . . . .VULNERABILITIES
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .109
...............
9.1. CONFIGURATION COMPLIANCE TOOLS IN RHEL 109
9.2. RED HAT SECURITY ADVISORIES OVAL FEED 109
9.3. VULNERABILITY SCANNING 111
9.3.1. Red Hat Security Advisories OVAL feed 111
9.3.2. Scanning the system for vulnerabilities 112
9.3.3. Scanning remote systems for vulnerabilities 112
9.4. CONFIGURATION COMPLIANCE SCANNING 113
9.4.1. Configuration compliance in RHEL 113
9.4.2. Possible results of an OpenSCAP scan 114
9.4.3. Viewing profiles for configuration compliance 115
9.4.4. Assessing configuration compliance with a specific baseline 116
9.5. REMEDIATING THE SYSTEM TO ALIGN WITH A SPECIFIC BASELINE 117
9.6. REMEDIATING THE SYSTEM TO ALIGN WITH A SPECIFIC BASELINE USING AN SSG ANSIBLE
PLAYBOOK 118
9.7. CREATING A REMEDIATION ANSIBLE PLAYBOOK TO ALIGN THE SYSTEM WITH A SPECIFIC BASELINE
119
9.8. CREATING A REMEDIATION BASH SCRIPT FOR A LATER APPLICATION 120
9.9. SCANNING THE SYSTEM WITH A CUSTOMIZED PROFILE USING SCAP WORKBENCH 121
9.9.1. Using SCAP Workbench to scan and remediate the system 121
9.9.2. Customizing a security profile with SCAP Workbench 123
9.9.3. Additional resources 125
9.10. SCANNING CONTAINER AND CONTAINER IMAGES FOR VULNERABILITIES 125
9.11. ASSESSING SECURITY COMPLIANCE OF A CONTAINER OR A CONTAINER IMAGE WITH A SPECIFIC
BASELINE 126
9.12. CHECKING INTEGRITY WITH AIDE 127
9.12.1. Installing AIDE 127
9.12.2. Performing integrity checks with AIDE 128
9.12.3. Updating an AIDE database 129
9.12.4. File-integrity tools: AIDE and IMA 129
9.12.5. Additional resources 130
9.13. ENCRYPTING BLOCK DEVICES USING LUKS 130
9.13.1. LUKS disk encryption 130
9.13.2. LUKS versions in RHEL 131
9.13.3. Options for data protection during LUKS2 re-encryption 132
9.13.4. Encrypting existing data on a block device using LUKS2 133
9.13.5. Encrypting existing data on a block device using LUKS2 with a detached header 135
9.13.6. Encrypting a blank block device using LUKS2 137
9.13.7. Configuring the LUKS passphrase in the web console 139
9.13.8. Changing the LUKS passphrase in the web console 139
9.13.9. Creating a LUKS2 encrypted volume by using the storage RHEL system role 141

3
Red Hat Enterprise Linux 8 System Design Guide

9.14. CONFIGURING AUTOMATED UNLOCKING OF ENCRYPTED VOLUMES BY USING POLICY-BASED


DECRYPTION 143
9.14.1. Network-bound disk encryption 143
9.14.2. Deploying a Tang server with SELinux in enforcing mode 145
9.14.3. Rotating Tang server keys and updating bindings on clients 147
9.14.4. Configuring automated unlocking by using a Tang key in the web console 148
9.14.5. Basic NBDE and TPM2 encryption-client operations 151
9.14.6. Configuring NBDE clients for automated unlocking of LUKS-encrypted volumes 153
9.14.7. Configuring NBDE clients with static IP configuration 155
9.14.8. Configuring manual enrollment of LUKS-encrypted volumes by using a TPM 2.0 policy 156
9.14.9. Removing a Clevis pin from a LUKS-encrypted volume manually 157
9.14.10. Configuring automated enrollment of LUKS-encrypted volumes by using Kickstart 159
9.14.11. Configuring automated unlocking of a LUKS-encrypted removable storage device 160
9.14.12. Deploying high-availability NBDE systems 161
High-available NBDE using Shamir’s Secret Sharing 161
Example 1: Redundancy with two Tang servers 161
Example 2: Shared secret on a Tang server and a TPM device 162
9.14.13. Deployment of virtual machines in a NBDE network 162
9.14.14. Building automatically-enrollable VM images for cloud environments by using NBDE 162
9.14.15. Deploying Tang as a container 163
9.14.16. Configuring NBDE by using RHEL system roles 164
9.14.16.1. Using the nbde_server RHEL system role for setting up multiple Tang servers 164
9.14.16.2. Setting up Clevis clients with DHCP by using the nbde_client RHEL system role 166
9.14.16.3. Setting up static-IP Clevis clients by using the nbde_client RHEL system role 168

. . . . . . . . . . . 10.
CHAPTER . . . USING
. . . . . . . .SELINUX
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .171
..............
10.1. GETTING STARTED WITH SELINUX 171
10.1.1. Introduction to SELinux 171
10.1.2. Benefits of running SELinux 172
10.1.3. SELinux examples 173
10.1.4. SELinux architecture and packages 174
10.1.5. SELinux states and modes 175
10.2. CHANGING SELINUX STATES AND MODES 175
10.2.1. Permanent changes in SELinux states and modes 175
10.2.2. Changing SELinux to permissive mode 176
10.2.3. Changing SELinux to enforcing mode 177
10.2.4. Enabling SELinux on systems that previously had it disabled 178
10.2.5. Disabling SELinux 180
10.2.6. Changing SELinux modes at boot time 181
10.3. TROUBLESHOOTING PROBLEMS RELATED TO SELINUX 182
10.3.1. Identifying SELinux denials 182
10.3.2. Analyzing SELinux denial messages 183
10.3.3. Fixing analyzed SELinux denials 184
10.3.4. Creating a local SELinux policy module 187
10.3.5. SELinux denials in the Audit log 189
10.3.6. Additional resources 190

. . . . . . .III.
PART . . DESIGN
. . . . . . . . . OF
. . . .NETWORK
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
...............

. . . . . . . . . . . 11.
CHAPTER . . .CONFIGURING
. . . . . . . . . . . . . . . .IP
. . NETWORKING
. . . . . . . . . . . . . . . WITH
. . . . . . IFCFG
. . . . . . . FILES
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .193
...............
11.1. CONFIGURING AN INTERFACE WITH STATIC NETWORK SETTINGS USING IFCFG FILES 193
11.2. CONFIGURING AN INTERFACE WITH DYNAMIC NETWORK SETTINGS USING IFCFG FILES 194
11.3. MANAGING SYSTEM-WIDE AND PRIVATE CONNECTION PROFILES WITH IFCFG FILES 194

4
Table of Contents

. . . . . . . . . . . 12.
CHAPTER . . . GETTING
. . . . . . . . . . STARTED
. . . . . . . . . . .WITH
. . . . . .IPVLAN
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .196
...............
12.1. IPVLAN MODES 196
12.2. COMPARISON OF IPVLAN AND MACVLAN 196
12.3. CREATING AND CONFIGURING THE IPVLAN DEVICE USING IPROUTE2 197

. . . . . . . . . . . 13.
CHAPTER . . . REUSING
. . . . . . . . . . THE
. . . . . SAME
. . . . . . .IP
. . ADDRESS
. . . . . . . . . . .ON
. . . .DIFFERENT
. . . . . . . . . . . . INTERFACES
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .199
...............
13.1. PERMANENTLY REUSING THE SAME IP ADDRESS ON DIFFERENT INTERFACES 199
13.2. TEMPORARILY REUSING THE SAME IP ADDRESS ON DIFFERENT INTERFACES 200
13.3. ADDITIONAL RESOURCES 202

. . . . . . . . . . . 14.
CHAPTER . . . SECURING
. . . . . . . . . . . .NETWORKS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .203
...............
14.1. USING SECURE COMMUNICATIONS BETWEEN TWO SYSTEMS WITH OPENSSH 203
14.1.1. Generating SSH key pairs 203
14.1.2. Setting key-based authentication as the only method on an OpenSSH server 204
14.1.3. Caching your SSH credentials by using ssh-agent 205
14.1.4. Authenticating by SSH keys stored on a smart card 206
14.1.5. Additional resources 207
14.2. PLANNING AND IMPLEMENTING TLS 207
14.2.1. SSL and TLS protocols 207
14.2.2. Security considerations for TLS in RHEL 8 208
14.2.2.1. Protocols 209
14.2.2.2. Cipher suites 209
14.2.2.3. Public key length 210
14.2.3. Hardening TLS configuration in applications 210
14.2.3.1. Configuring the Apache HTTP server to use TLS 210
14.2.3.2. Configuring the Nginx HTTP and proxy server to use TLS 211
14.2.3.3. Configuring the Dovecot mail server to use TLS 211
14.3. SETTING UP AN IPSEC VPN 212
14.3.1. Libreswan as an IPsec VPN implementation 212
14.3.2. Authentication methods in Libreswan 213
14.3.3. Installing Libreswan 215
14.3.4. Creating a host-to-host VPN 215
14.3.5. Configuring a site-to-site VPN 216
14.3.6. Configuring a remote access VPN 217
14.3.7. Configuring a mesh VPN 218
14.3.8. Deploying a FIPS-compliant IPsec VPN 222
14.3.9. Protecting the IPsec NSS database by a password 224
14.3.10. Configuring an IPsec VPN to use TCP 225
14.3.11. Configuring automatic detection and usage of ESP hardware offload to accelerate an IPsec connection
226
14.3.12. Configuring ESP hardware offload on a bond to accelerate an IPsec connection 227
14.3.13. Configuring VPN connections with IPsec by using RHEL system roles 228
14.3.13.1. Creating a host-to-host VPN with IPsec by using the vpn RHEL system role 229
14.3.13.2. Creating an opportunistic mesh VPN connection with IPsec by using the vpn RHEL system role 231
14.3.14. Configuring IPsec connections that opt out of the system-wide crypto policies 233
14.3.15. Troubleshooting IPsec VPN configurations 233
14.3.16. Configuring a VPN connection with control-center 237
14.3.17. Configuring a VPN connection using nm-connection-editor 242
14.3.18. Additional resources 245
14.4. USING MACSEC TO ENCRYPT LAYER-2 TRAFFIC IN THE SAME PHYSICAL NETWORK 245
14.4.1. How MACsec increases security 245
14.4.2. Configuring a MACsec connection by using nmcli 246
14.5. USING AND CONFIGURING FIREWALLD 247

5
Red Hat Enterprise Linux 8 System Design Guide

14.5.1. When to use firewalld, nftables, or iptables 247


14.5.2. Firewall zones 248
14.5.3. Firewall policies 250
14.5.4. Firewall rules 250
14.5.5. Zone configuration files 251
14.5.6. Predefined firewalld services 251
14.5.7. Working with firewalld zones 252
14.5.7.1. Customizing firewall settings for a specific zone to enhance security 252
14.5.7.2. Changing the default zone 253
14.5.7.3. Assigning a network interface to a zone 254
14.5.7.4. Assigning a zone to a connection using nmcli 254
14.5.7.5. Manually assigning a zone to a network connection in a connection profile file 255
14.5.7.6. Manually assigning a zone to a network connection in an ifcfg file 256
14.5.7.7. Creating a new zone 256
14.5.7.8. Enabling zones by using the web console 256
14.5.7.9. Disabling zones by using the web console 258
14.5.7.10. Using zone targets to set default behavior for incoming traffic 259
14.5.8. Controlling network traffic using firewalld 260
14.5.8.1. Controlling traffic with predefined services using the CLI 260
14.5.8.2. Controlling traffic with predefined services using the GUI 261
14.5.8.3. Enabling services on the firewall by using the web console 263
14.5.8.4. Configuring custom ports by using the web console 264
14.5.8.5. Configuring firewalld to allow hosting a secure web server 266
14.5.8.6. Closing unused or unnecessary ports to enhance network security 267
14.5.8.7. Controlling traffic through the CLI 268
14.5.8.8. Controlling traffic with protocols using GUI 269
14.5.9. Using zones to manage incoming traffic depending on a source 269
14.5.9.1. Adding a source 269
14.5.9.2. Removing a source 270
14.5.9.3. Removing a source port 270
14.5.9.4. Using zones and sources to allow a service for only a specific domain 271
14.5.10. Filtering forwarded traffic between zones 272
14.5.10.1. The relationship between policy objects and zones 272
14.5.10.2. Using priorities to sort policies 272
14.5.10.3. Using policy objects to filter traffic between locally hosted containers and a network physically
connected to the host 272
14.5.10.4. Setting the default target of policy objects 274
14.5.10.5. Using DNAT to forward HTTPS traffic to a different host 274
14.5.11. Configuring NAT using firewalld 276
14.5.11.1. Network address translation types 276
14.5.11.2. Configuring IP address masquerading 277
14.5.11.3. Using DNAT to forward incoming HTTP traffic 277
14.5.11.4. Redirecting traffic from a non-standard port to make the web service accessible on a standard port
278
14.5.12. Managing ICMP requests 280
14.5.12.1. Configuring ICMP filtering 280
14.5.13. Setting and controlling IP sets using firewalld 281
14.5.13.1. Configuring dynamic updates for allowlisting with IP sets 282
14.5.14. Prioritizing rich rules 283
14.5.14.1. How the priority parameter organizes rules into different chains 283
14.5.14.2. Setting the priority of a rich rule 284
14.5.15. Configuring firewall lockdown 284
14.5.15.1. Configuring lockdown using CLI 284

6
Table of Contents

14.5.15.2. Overview of lockdown allowlist configuration files 285


14.5.16. Enabling traffic forwarding between different interfaces or sources within a firewalld zone 285
14.5.16.1. The difference between intra-zone forwarding and zones with the default target set to ACCEPT
285
14.5.16.2. Using intra-zone forwarding to forward traffic between an Ethernet and Wi-Fi network 286
14.5.17. Configuring firewalld by using RHEL system roles 287
14.5.17.1. Resetting the firewalld settings by using the firewall RHEL system role 287
14.5.17.2. Forwarding incoming traffic in firewalld from one local port to a different local port by using the
firewall RHEL system role 289
14.5.17.3. Configuring a firewalld DMZ zone by using the firewall RHEL system role 290
14.6. GETTING STARTED WITH NFTABLES 291
14.6.1. Creating and managing nftables tables, chains, and rules 292
14.6.1.1. Basics of nftables tables 292
14.6.1.2. Basics of nftables chains 293
Chain types 293
Chain priorities 293
Chain policies 294
14.6.1.3. Basics of nftables rules 294
14.6.1.4. Managing tables, chains, and rules using nft commands 295
14.6.2. Migrating from iptables to nftables 297
14.6.2.1. When to use firewalld, nftables, or iptables 297
14.6.2.2. Concepts in the nftables framework 297
14.6.2.3. Concepts in the deprecated iptables framework 299
14.6.2.4. Converting iptables and ip6tables rule sets to nftables 300
14.6.2.5. Converting single iptables and ip6tables rules to nftables 301
14.6.2.6. Comparison of common iptables and nftables commands 302
14.6.3. Writing and executing nftables scripts 302
14.6.3.1. Supported nftables script formats 303
14.6.3.2. Running nftables scripts 303
14.6.3.3. Using comments in nftables scripts 304
14.6.3.4. Using variables in nftables script 304
14.6.3.5. Including files in nftables scripts 305
14.6.3.6. Automatically loading nftables rules when the system boots 306
14.6.4. Configuring NAT using nftables 306
14.6.4.1. NAT types 307
14.6.4.2. Configuring masquerading using nftables 307
14.6.4.3. Configuring source NAT using nftables 308
14.6.4.4. Configuring destination NAT using nftables 308
14.6.4.5. Configuring a redirect using nftables 309
14.6.4.6. Configuring flowtable by using nftables 310
14.6.5. Using sets in nftables commands 311
14.6.5.1. Using anonymous sets in nftables 311
14.6.5.2. Using named sets in nftables 312
14.6.5.3. Additional resources 313
14.6.6. Using verdict maps in nftables commands 313
14.6.6.1. Using anonymous maps in nftables 313
14.6.6.2. Using named maps in nftables 314
14.6.6.3. Additional resources 316
14.6.7. Example: Protecting a LAN and DMZ using an nftables script 316
14.6.7.1. Network conditions 316
14.6.7.2. Security requirements to the firewall script 317
14.6.7.3. Configuring logging of dropped packets to a file 317
14.6.7.4. Writing and activating the nftables script 318

7
Red Hat Enterprise Linux 8 System Design Guide

14.6.8. Configuring port forwarding using nftables 321


14.6.8.1. Forwarding incoming packets to a different local port 321
14.6.8.2. Forwarding incoming packets on a specific local port to a different host 322
14.6.9. Using nftables to limit the amount of connections 323
14.6.9.1. Limiting the number of connections by using nftables 323
14.6.9.2. Blocking IP addresses that attempt more than ten new incoming TCP connections within one minute
324
14.6.10. Debugging nftables rules 325
14.6.10.1. Creating a rule with a counter 325
14.6.10.2. Adding a counter to an existing rule 325
14.6.10.3. Monitoring packets that match an existing rule 326
14.6.11. Backing up and restoring the nftables rule set 327
14.6.11.1. Backing up the nftables rule set to a file 327
14.6.11.2. Restoring the nftables rule set from a file 327
14.6.12. Additional resources 328

. . . . . . .IV.
PART . . .DESIGN
. . . . . . . . OF
. . . .HARD
. . . . . . .DISK
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .329
...............

. . . . . . . . . . . 15.
CHAPTER . . . OVERVIEW
. . . . . . . . . . . . OF
. . . .AVAILABLE
. . . . . . . . . . . . FILE
. . . . . SYSTEMS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
................
15.1. TYPES OF FILE SYSTEMS 330
15.2. LOCAL FILE SYSTEMS 331
15.3. THE XFS FILE SYSTEM 331
15.4. THE EXT4 FILE SYSTEM 332
15.5. COMPARISON OF XFS AND EXT4 333
15.6. CHOOSING A LOCAL FILE SYSTEM 334
15.7. NETWORK FILE SYSTEMS 335
15.8. SHARED STORAGE FILE SYSTEMS 335
15.9. CHOOSING BETWEEN NETWORK AND SHARED STORAGE FILE SYSTEMS 336
15.10. VOLUME-MANAGING FILE SYSTEMS 336

. . . . . . . . . . . 16.
CHAPTER . . . MOUNTING
. . . . . . . . . . . . .AN
. . . SMB
. . . . . .SHARE
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .338
...............
16.1. SUPPORTED SMB PROTOCOL VERSIONS 338
16.2. UNIX EXTENSIONS SUPPORT 338
16.3. MANUALLY MOUNTING AN SMB SHARE 339
16.4. MOUNTING AN SMB SHARE AUTOMATICALLY WHEN THE SYSTEM BOOTS 340
16.5. CREATING A CREDENTIALS FILE TO AUTHENTICATE TO AN SMB SHARE 341
16.6. PERFORMING A MULTI-USER SMB MOUNT 341
16.6.1. Mounting a share with the multiuser option 342
16.6.2. Verifying if an SMB share is mounted with the multiuser option 342
16.6.3. Accessing a share as a user 342
16.7. FREQUENTLY USED SMB MOUNT OPTIONS 343

. . . . . . . . . . . 17.
CHAPTER . . . OVERVIEW
. . . . . . . . . . . . OF
. . . .PERSISTENT
. . . . . . . . . . . . . NAMING
. . . . . . . . . .ATTRIBUTES
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .345
...............
17.1. DISADVANTAGES OF NON-PERSISTENT NAMING ATTRIBUTES 345
17.2. FILE SYSTEM AND DEVICE IDENTIFIERS 345
File system identifiers 346
Device identifiers 346
Recommendations 346
17.3. DEVICE NAMES MANAGED BY THE UDEV MECHANISM IN /DEV/DISK/ 346
17.3.1. File system identifiers 346
The UUID attribute in /dev/disk/by-uuid/ 346
The Label attribute in /dev/disk/by-label/ 347
17.3.2. Device identifiers 347
The WWID attribute in /dev/disk/by-id/ 347

8
Table of Contents

The Partition UUID attribute in /dev/disk/by-partuuid 348


The Path attribute in /dev/disk/by-path/ 348
17.4. THE WORLD WIDE IDENTIFIER WITH DM MULTIPATH 348
17.5. LIMITATIONS OF THE UDEV DEVICE NAMING CONVENTION 349
17.6. LISTING PERSISTENT NAMING ATTRIBUTES 349
17.7. MODIFYING PERSISTENT NAMING ATTRIBUTES 350

.CHAPTER
. . . . . . . . . . 18.
. . . GETTING
. . . . . . . . . . STARTED
. . . . . . . . . . .WITH
. . . . . .PARTITIONS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .352
...............
18.1. CREATING A PARTITION TABLE ON A DISK WITH PARTED 352
18.2. VIEWING THE PARTITION TABLE WITH PARTED 353
18.3. CREATING A PARTITION WITH PARTED 354
18.4. SETTING A PARTITION TYPE WITH FDISK 355
18.5. RESIZING A PARTITION WITH PARTED 356
18.6. REMOVING A PARTITION WITH PARTED 358

. . . . . . . . . . . 19.
CHAPTER . . . GETTING
. . . . . . . . . . STARTED
. . . . . . . . . . .WITH
. . . . . .XFS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
................
19.1. THE XFS FILE SYSTEM 360
19.2. COMPARISON OF TOOLS USED WITH EXT4 AND XFS 361

.CHAPTER
. . . . . . . . . . 20.
. . . .MOUNTING
. . . . . . . . . . . . FILE
. . . . . .SYSTEMS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .362
...............
20.1. THE LINUX MOUNT MECHANISM 362
20.2. LISTING CURRENTLY MOUNTED FILE SYSTEMS 362
20.3. MOUNTING A FILE SYSTEM WITH MOUNT 363
20.4. MOVING A MOUNT POINT 364
20.5. UNMOUNTING A FILE SYSTEM WITH UMOUNT 364
20.6. MOUNTING AND UNMOUNTING FILE SYSTEMS IN THE WEB CONSOLE 365
20.7. COMMON MOUNT OPTIONS 365

.CHAPTER
. . . . . . . . . . 21.
. . . SHARING
..........A
. . MOUNT
. . . . . . . . .ON
. . . .MULTIPLE
. . . . . . . . . . . MOUNT
. . . . . . . . .POINTS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .367
...............
21.1. TYPES OF SHARED MOUNTS 367
21.2. CREATING A PRIVATE MOUNT POINT DUPLICATE 367
21.3. CREATING A SHARED MOUNT POINT DUPLICATE 368
21.4. CREATING A SLAVE MOUNT POINT DUPLICATE 370
21.5. PREVENTING A MOUNT POINT FROM BEING DUPLICATED 371

.CHAPTER
. . . . . . . . . . 22.
. . . .PERSISTENTLY
. . . . . . . . . . . . . . . . MOUNTING
. . . . . . . . . . . . .FILE
. . . . .SYSTEMS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .372
...............
22.1. THE /ETC/FSTAB FILE 372
22.2. ADDING A FILE SYSTEM TO /ETC/FSTAB 372

.CHAPTER
. . . . . . . . . . 23.
. . . .MOUNTING
. . . . . . . . . . . . FILE
. . . . . SYSTEMS
. . . . . . . . . . .ON
. . . .DEMAND
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .374
...............
23.1. THE AUTOFS SERVICE 374
23.2. THE AUTOFS CONFIGURATION FILES 374
23.3. CONFIGURING AUTOFS MOUNT POINTS 376
23.4. AUTOMOUNTING NFS SERVER USER HOME DIRECTORIES WITH AUTOFS SERVICE 377
23.5. OVERRIDING OR AUGMENTING AUTOFS SITE CONFIGURATION FILES 377
23.6. USING LDAP TO STORE AUTOMOUNTER MAPS 379
23.7. USING SYSTEMD.AUTOMOUNT TO MOUNT A FILE SYSTEM ON DEMAND WITH /ETC/FSTAB 380
23.8. USING SYSTEMD.AUTOMOUNT TO MOUNT A FILE SYSTEM ON-DEMAND WITH A MOUNT UNIT 381

.CHAPTER
. . . . . . . . . . 24.
. . . .USING
. . . . . . . SSSD
. . . . . . COMPONENT
. . . . . . . . . . . . . . .FROM
. . . . . . .IDM
. . . . TO
. . . .CACHE
. . . . . . . .THE
. . . . .AUTOFS
. . . . . . . . . MAPS
. . . . . . . . . . . . . . . . . . . . . . . . . . .382
...............
24.1. CONFIGURING AUTOFS MANUALLY TO USE IDM SERVER AS AN LDAP SERVER 382
24.2. CONFIGURING SSSD TO CACHE AUTOFS MAPS 383

.CHAPTER
. . . . . . . . . . 25.
. . . .SETTING
. . . . . . . . . .READ-ONLY
. . . . . . . . . . . . .PERMISSIONS
. . . . . . . . . . . . . . . FOR
. . . . . THE
. . . . .ROOT
. . . . . . .FILE
. . . . .SYSTEM
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .385
...............
25.1. FILES AND DIRECTORIES THAT ALWAYS RETAIN WRITE PERMISSIONS 385

9
Red Hat Enterprise Linux 8 System Design Guide

25.2. CONFIGURING THE ROOT FILE SYSTEM TO MOUNT WITH READ-ONLY PERMISSIONS ON BOOT 386

. . . . . . . . . . . 26.
CHAPTER . . . .MANAGING
. . . . . . . . . . . . STORAGE
. . . . . . . . . . . DEVICES
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .387
...............
26.1. SETTING UP STRATIS FILE SYSTEMS 387
26.1.1. What is Stratis 387
26.1.2. Components of a Stratis volume 387
26.1.3. Block devices usable with Stratis 388
Supported devices 388
Unsupported devices 389
26.1.4. Installing Stratis 389
26.1.5. Creating an unencrypted Stratis pool 389
26.1.6. Creating an unencrypted Stratis pool by using the web console 390
26.1.7. Creating an encrypted Stratis pool 391
26.1.8. Creating an encrypted Stratis pool by using the web console 393
26.1.9. Renaming a Stratis pool by using the web console 395
26.1.10. Setting overprovisioning mode in Stratis filesystem 396
26.1.11. Binding a Stratis pool to NBDE 397
26.1.12. Binding a Stratis pool to TPM 398
26.1.13. Unlocking an encrypted Stratis pool with kernel keyring 398
26.1.14. Unbinding a Stratis pool from supplementary encryption 399
26.1.15. Starting and stopping Stratis pool 399
26.1.16. Creating a Stratis file system 400
26.1.17. Creating a file system on a Stratis pool by using the web console 401
26.1.18. Mounting a Stratis file system 403
26.1.19. Setting up non-root Stratis filesystems in /etc/fstab using a systemd service 403
26.2. EXTENDING A STRATIS VOLUME WITH ADDITIONAL BLOCK DEVICES 404
26.2.1. Components of a Stratis volume 404
26.2.2. Adding block devices to a Stratis pool 405
26.2.3. Adding a block device to a Stratis pool by using the web console 405
26.2.4. Additional resources 406
26.3. MONITORING STRATIS FILE SYSTEMS 406
26.3.1. Stratis sizes reported by different utilities 407
26.3.2. Displaying information about Stratis volumes 407
26.3.3. Viewing a Stratis pool by using the web console 408
26.3.4. Additional resources 409
26.4. USING SNAPSHOTS ON STRATIS FILE SYSTEMS 409
26.4.1. Characteristics of Stratis snapshots 409
26.4.2. Creating a Stratis snapshot 410
26.4.3. Accessing the content of a Stratis snapshot 410
26.4.4. Reverting a Stratis file system to a previous snapshot 411
26.4.5. Removing a Stratis snapshot 411
26.4.6. Additional resources 412
26.5. REMOVING STRATIS FILE SYSTEMS 412
26.5.1. Components of a Stratis volume 412
26.5.2. Removing a Stratis file system 413
26.5.3. Deleting a file system from a Stratis pool by using the web console 413
26.5.4. Removing a Stratis pool 415
26.5.5. Deleting a Stratis pool by using the web console 416
26.5.6. Additional resources 416
26.6. GETTING STARTED WITH SWAP 416
26.6.1. Overview of swap space 416
26.6.2. Recommended system swap space 417
26.6.3. Creating an LVM2 logical volume for swap 418

10
Table of Contents

26.6.4. Creating a swap file 419


26.6.5. Extending swap on an LVM2 logical volume 420
26.6.6. Reducing swap on an LVM2 logical volume 421
26.6.7. Removing an LVM2 logical volume for swap 421
26.6.8. Removing a swap file 422
26.7. MANAGING LOCAL STORAGE BY USING RHEL SYSTEM ROLES 422
26.7.1. Creating an XFS file system on a block device by using the storage RHEL system role 423
26.7.2. Persistently mounting a file system by using the storage RHEL system role 424
26.7.3. Creating or resizing a logical volume by using the storage RHEL system role 425
26.7.4. Enabling online block discard by using the storage RHEL system role 426
26.7.5. Creating and mounting an Ext4 file system by using the storage RHEL system role 427
26.7.6. Creating and mounting an Ext3 file system by using the storage RHEL system role 428
26.7.7. Creating a swap volume by using the storage RHEL system role 429
26.7.8. Configuring a RAID volume by using the storage RHEL system role 430
26.7.9. Configuring an LVM pool with RAID by using the storage RHEL system role 432
26.7.10. Configuring a stripe size for RAID LVM volumes by using the storage RHEL system role 433
26.7.11. Configuring an LVM-VDO volume by using the storage RHEL system role 434
26.7.12. Creating a LUKS2 encrypted volume by using the storage RHEL system role 436
26.7.13. Creating shared LVM devices using the storage RHEL system role 438

.CHAPTER
. . . . . . . . . . 27.
. . . .DEDUPLICATING
. . . . . . . . . . . . . . . . . .AND
. . . . .COMPRESSING
. . . . . . . . . . . . . . . . .STORAGE
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
................
27.1. DEPLOYING VDO 440
27.1.1. Introduction to VDO 440
27.1.2. VDO deployment scenarios 440
KVM 440
File systems 441
Placement of VDO on iSCSI 441
LVM 442
Encryption 442
27.1.3. Components of a VDO volume 443
27.1.4. The physical and logical size of a VDO volume 444
27.1.5. Slab size in VDO 445
27.1.6. VDO requirements 445
27.1.6.1. VDO memory requirements 445
27.1.6.2. VDO storage space requirements 446
27.1.6.3. Placement of VDO in the storage stack 447
27.1.6.4. Examples of VDO requirements by physical size 448
27.1.7. Installing VDO 449
27.1.8. Creating a VDO volume 449
27.1.9. Mounting a VDO volume 451
27.1.10. Enabling periodic block discard 452
27.1.11. Monitoring VDO 452
27.2. MAINTAINING VDO 453
27.2.1. Managing free space on VDO volumes 453
27.2.1.1. The physical and logical size of a VDO volume 453
27.2.1.2. Thin provisioning in VDO 454
27.2.1.3. Monitoring VDO 455
27.2.1.4. Reclaiming space for VDO on file systems 455
27.2.1.5. Reclaiming space for VDO without a file system 456
27.2.1.6. Reclaiming space for VDO on Fibre Channel or Ethernet network 456
27.2.2. Starting or stopping VDO volumes 456
27.2.2.1. Started and activated VDO volumes 457
27.2.2.2. Starting a VDO volume 457

11
Red Hat Enterprise Linux 8 System Design Guide

27.2.2.3. Stopping a VDO volume 457


27.2.2.4. Additional resources 458
27.2.3. Automatically starting VDO volumes at system boot 458
27.2.3.1. Started and activated VDO volumes 458
27.2.3.2. Activating a VDO volume 459
27.2.3.3. Deactivating a VDO volume 459
27.2.4. Selecting a VDO write mode 459
27.2.4.1. VDO write modes 460
27.2.4.2. The internal processing of VDO write modes 460
27.2.4.3. Checking the write mode on a VDO volume 461
27.2.4.4. Checking for a volatile cache 461
27.2.4.5. Setting a VDO write mode 462
27.2.5. Recovering a VDO volume after an unclean shutdown 462
27.2.5.1. VDO write modes 463
27.2.5.2. VDO volume recovery 463
Automatic and manual recovery 464
27.2.5.3. VDO operating modes 464
27.2.5.4. Recovering a VDO volume online 465
27.2.5.5. Forcing an offline rebuild of a VDO volume metadata 465
27.2.5.6. Removing an unsuccessfully created VDO volume 466
27.2.6. Optimizing the UDS index 467
27.2.6.1. Components of a VDO volume 467
27.2.6.2. The UDS index 468
27.2.6.3. Recommended UDS index configuration 468
27.2.7. Enabling or disabling deduplication in VDO 469
27.2.7.1. Deduplication in VDO 469
27.2.7.2. Enabling deduplication on a VDO volume 469
27.2.7.3. Disabling deduplication on a VDO volume 470
27.2.8. Enabling or disabling compression in VDO 470
27.2.8.1. Compression in VDO 470
27.2.8.2. Enabling compression on a VDO volume 471
27.2.8.3. Disabling compression on a VDO volume 471
27.2.9. Increasing the size of a VDO volume 471
27.2.9.1. The physical and logical size of a VDO volume 471
27.2.9.2. Thin provisioning in VDO 472
27.2.9.3. Increasing the logical size of a VDO volume 473
27.2.9.4. Increasing the physical size of a VDO volume 474
27.2.10. Removing VDO volumes 474
27.2.10.1. Removing a working VDO volume 474
27.2.10.2. Removing an unsuccessfully created VDO volume 474
27.2.11. Additional resources 475
27.3. DISCARDING UNUSED BLOCKS 475
Requirements 475
27.3.1. Types of block discard operations 475
Recommendations 476
27.3.2. Performing batch block discard 476
27.3.3. Enabling online block discard 477
27.3.4. Enabling periodic block discard 477

. . . . . . .V.
PART . . DESIGN
. . . . . . . . .OF
. . . LOG
. . . . . .FILE
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
................

.CHAPTER
. . . . . . . . . . 28.
. . . .AUDITING
. . . . . . . . . . .THE
. . . . .SYSTEM
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
................
28.1. LINUX AUDIT 479

12
Table of Contents

28.2. AUDIT SYSTEM ARCHITECTURE 480


28.3. CONFIGURING AUDITD FOR A SECURE ENVIRONMENT 481
28.4. STARTING AND CONTROLLING AUDITD 482
28.5. UNDERSTANDING AUDIT LOG FILES 483
28.6. USING AUDITCTL FOR DEFINING AND EXECUTING AUDIT RULES 487
28.7. DEFINING PERSISTENT AUDIT RULES 488
28.8. PRE-CONFIGURED AUDIT RULES FILES FOR COMPLIANCE WITH STANDARDS 488
28.9. USING AUGENRULES TO DEFINE PERSISTENT RULES 489
28.10. DISABLING AUGENRULES 490
28.11. SETTING UP AUDIT TO MONITOR SOFTWARE UPDATES 491
28.12. MONITORING USER LOGIN TIMES WITH AUDIT 492
28.13. ADDITIONAL RESOURCES 493

. . . . . . .VI.
PART . . .DESIGN
. . . . . . . . OF
. . . .KERNEL
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
................

.CHAPTER
. . . . . . . . . . 29.
. . . .THE
. . . . .LINUX
. . . . . . .KERNEL
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
................
29.1. WHAT THE KERNEL IS 496
29.2. RPM PACKAGES 496
29.3. THE LINUX KERNEL RPM PACKAGE OVERVIEW 497

13
Red Hat Enterprise Linux 8 System Design Guide

14
PROVIDING FEEDBACK ON RED HAT DOCUMENTATION

PROVIDING FEEDBACK ON RED HAT DOCUMENTATION


We appreciate your feedback on our documentation. Let us know how we can improve it.

Submitting feedback through Jira (account required)

1. Log in to the Jira website.

2. Click Create in the top navigation bar.

3. Enter a descriptive title in the Summary field.

4. Enter your suggestion for improvement in the Description field. Include links to the relevant
parts of the documentation.

5. Click Create at the bottom of the dialogue.

15
Red Hat Enterprise Linux 8 System Design Guide

PART I. DESIGN OF INSTALLATION

16
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM


IMAGE

1.1. RHEL IMAGE BUILDER DESCRIPTION


To deploy a system, create a system image. To create RHEL system images, use the RHEL image
builder tool. You can use RHEL image builder to create customized system images of RHEL, including
system images prepared for deployment on cloud platforms. RHEL image builder automatically handles
the setup details for each output type and is therefore easier to use and faster to work with than manual
methods of image creation. You can access the RHEL image builder functionalities by using the
command-line interface in the composer-cli tool, or the graphical user interface in the RHEL web
console.

NOTE

From RHEL 8.3 onward, the osbuild-composer back end replaces lorax-composer. The
new service provides REST APIs for image building.

1.1.1. RHEL image builder terminology


RHEL image builder uses the following concepts:

Blueprint
A blueprint is a description of a customized system image. It lists the packages and customizations
that will be part of the system. You can edit blueprints with customizations and save them as a
particular version. When you create a system image from a blueprint, the image is associated with the
blueprint in the RHEL image builder interface.
Create blueprints in the TOML format.

Compose
Composes are individual builds of a system image, based on a specific version of a particular
blueprint. Compose as a term refers to the system image, the logs from its creation, inputs,
metadata, and the process itself.
Customizations
Customizations are specifications for the image that are not packages. This includes users, groups,
and SSH keys.

1.1.2. RHEL image builder output formats


RHEL image builder can create images in multiple output formats shown in the following table.

Table 1.1. RHEL image builder output formats

Description CLI name File extension

QEMU Image qcow2 .qcow2

Disk Archive tar .tar

Amazon Web Services raw .raw

17
Red Hat Enterprise Linux 8 System Design Guide

Description CLI name File extension

Microsoft Azure vhd .vhd

Google Cloud Platform gce .tar.gz

VMware vSphere vmdk .vmdk

VMware vSphere ova .ova

Openstack openstack .qcow2

RHEL for Edge Commit edge-commit .tar

RHEL for Edge Container edge-container .tar

RHEL for Edge Installer edge-installer .iso

RHEL for Edge Raw Image edge-raw-image .raw.xz

RHEL for Edge Simplified Installer edge-simplified- .iso


installer

RHEL for Edge AMI edge-ami .ami

RHEL for Edge VMDK edge-vsphere .vmdk

RHEL Installer image-installer .iso

Oracle Cloud Infrastructure .oci .qcow2

To check the supported types, run the command:

# composer-cli compose types

1.1.3. Supported architectures for image builds


RHEL image builder supports building images for the following architectures:

AMD and Intel 64-bit (x86_64)

ARM64 (aarch64)

IBM Z (s390x)

IBM POWER systems

However, RHEL image builder does not support multi-architecture builds. It only builds images of the

18
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

However, RHEL image builder does not support multi-architecture builds. It only builds images of the
same system architecture that it is running on. For example, if RHEL image builder is running on an
x86_64 system, it can only build images for the x86_64 architecture.

1.1.4. Additional resources


RHEL image builder additional documentation index

1.2. INSTALLING RHEL IMAGE BUILDER


RHEL image builder is a tool for creating custom system images. Before using RHEL image builder, you
must install it.

1.2.1. RHEL image builder system requirements


The host that runs RHEL image builder must meet the following requirements:

Table 1.2. RHEL image builder system requirements

Parameter Minimal Required Value

System type A dedicated host or virtual machine. Note that RHEL image builder is not
supported in containers, including Red Hat Universal Base Images (UBI).

Processor 2 cores

Memory 4 GiB

Disk space 20 GiB of free space in the ` /var/cache/` filesystem

Access privileges root

Network Internet connectivity to the Red Hat Content Delivery Network (CDN).

NOTE

If you do not have internet connectivity, use RHEL image builder in isolated networks. For
that, you must override the default repositories to point to your local repositories to not
connect to Red Hat Content Delivery Network (CDN). Ensure that you have your content
mirrored internally or use Red Hat Satellite.

Additional resources

Configuring RHEL image builder repositories

Provisioning to Satellite using a Red Hat image builder image

1.2.2. Installing RHEL image builder


Install RHEL image builder to have access to all the osbuild-composer package functionalities.

19
Red Hat Enterprise Linux 8 System Design Guide

Prerequisites

You are logged in to the RHEL host on which you want to install RHEL image builder.

The host is subscribed to Red Hat Subscription Manager (RHSM) or Red Hat Satellite.

You have enabled the BaseOS and AppStream repositories to be able to install the RHEL
image builder packages.

Procedure

1. Install RHEL image builder and other necessary packages:

# yum install osbuild-composer composer-cli cockpit-composer

osbuild-composer - A service to build customized RHEL operating system images.

composer-cli- This package enables access to the CLI interface.

cockpit-composer - This package enables access to the Web UI interface. The web
console is installed as a dependency of the cockpit-composer package.

2. Enable and start RHEL image builder socket:

# systemctl enable --now osbuild-composer.socket

3. If you want to use RHEL image builder in the web console, enable and start it.

# systemctl enable --now cockpit.socket

The osbuild-composer and cockpit services start automatically on first access.

4. Load the shell configuration script so that the autocomplete feature for the composer-cli
command starts working immediately without logging out and in:

$ source /etc/bash_completion.d/composer-cli

5. Restart the running osbuild-composer service on your RHEL host.

# systemctl restart osbuild-composer

IMPORTANT

The osbuild-composer package is the new backend engine that will be the preferred
default and focus of all new functionality beginning with Red Hat Enterprise Linux 8.3 and
later. The previous backend lorax-composer package is considered deprecated, will only
receive select fixes for the remainder of the Red Hat Enterprise Linux 8 life cycle and will
be omitted from future major releases. It is recommended to uninstall lorax-composer in
favor of osbuild-composer.

Verification

Verify that the installation works by running composer-cli:

20
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

# composer-cli status show

Troubleshooting
You can use a system journal to track RHEL image builder activities. Additionally, you can find the log
messages in the file.

To find the journal output for traceback, run the following commands:

$ journalctl | grep osbuild

To show both remote or local workers:

$ journalctl -u osbuild-worker*

To show the running services:

$ journalctl -u osbuild-composer.service

1.2.3. Reverting to lorax-composer RHEL image builder backend

The osbuild-composer backend, though much more extensible, does not currently achieve feature
parity with the previous lorax-composer backend.

To revert to the previous backend, follow the steps:

Prerequisites

You have installed the osbuild-composer package

Procedure

1. Remove the osbuild-composer backend.

# yum remove osbuild-composer


# yum remove weldr-client

2. In the /etc/yum.conf file, add an exclude entry for osbuild-composer package.

# cat /etc/yum.conf
[main]
gpgcheck=1
installonly_limit=3
clean_requirements_on_remove=True
best=True
skip_if_unavailable=False
exclude=osbuild-composer weldr-client

3. Install the lorax-composer package.

# yum install lorax-composer composer-cli

21
Red Hat Enterprise Linux 8 System Design Guide

4. Enable and start the lorax-composer service to start after each reboot.

# systemctl enable --now lorax-composer.socket


# systemctl start lorax-composer

Additional resources

Create a Case at Red Hat Support

1.3. CREATING SYSTEM IMAGES BY USING RHEL IMAGE BUILDER CLI


RHEL image builder is a tool for creating custom system images. To control RHEL image builder and
create your custom system images, you can use the command-line interface (CLI) or the web console
interface.

1.3.1. Introducing the RHEL image builder command-line interface


You can use the RHEL image builder command-line interface (CLI) to create blueprints, by running the
composer-cli command with the suitable options and subcommands.

The workflow for the command-line interface can be summarized as follows:

1. Create a blueprint or export (save) an existing blueprint definition to a plain text file

2. Edit this file in a text editor

3. Import the blueprint text file back into image builder

4. Run a compose to build an image from the blueprint

5. Export the image file to download it

Apart from the basic subcommands to create a blueprint, the composer-cli command offers many
subcommands to examine the state of configured blueprints and composes.

1.3.2. Using RHEL image builder as a non-root user


To run the composer-cli commands as non-root, the user must be in the weldr group.

Prerequisites

You have created a user

Procedure

To add a user to the weldr or root groups, run the following commands:

$ sudo usermod -a -G weldr user


$ newgrp weldr

1.3.3. Creating a blueprint by using the command-line interface

You can create a new blueprint by using the RHEL image builder command-line interface (CLI). The
22
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

You can create a new blueprint by using the RHEL image builder command-line interface (CLI). The
blueprint describes the final image and its customizations, such as packages, and kernel customizations.

Prerequisite

You are logged in as the root user or a user who is a member of the weldr group

Procedure

1. Create a plain text file with the following contents:

name = "BLUEPRINT-NAME"
description = "LONG FORM DESCRIPTION TEXT"
version = "0.0.1"
modules = []
groups = []

Replace BLUEPRINT-NAME and LONG FORM DESCRIPTION TEXT with a name and
description for your blueprint.

Replace 0.0.1 with a version number according to the Semantic Versioning scheme.

2. For every package that you want to be included in the blueprint, add the following lines to the
file:

[[packages]]
name = "package-name"
version = "package-version"

Replace package-name with the name of the package, such as httpd, gdb-doc, or coreutils.

Optionally, replace package-version with the version to use. This field supports dnf version
specifications:

For a specific version, use the exact version number such as 8.7.0.

For the latest available version, use the asterisk *.

For the latest minor version, use formats such as 8.*.

3. Customize your blueprints to suit your needs. For example, disable Simultaneous Multi
Threading (SMT), add the following lines to the blueprint file:

[customizations.kernel]
append = "nosmt=force"

For additional customizations available, see Supported Image Customizations.

Note that [] and [[]] are different data structures expressed in TOML.

The [customizations.kernel] header represents a single table that is defined by a collection


of keys and their respective value pairs, for example: append = "nosmt=force".

The [[packages]] header represents an array of tables. The first instance defines the array
and its first table element, for example, name = "package-name" and version = "package-
version", and each subsequent instance creates and defines a new table element in that

23
Red Hat Enterprise Linux 8 System Design Guide

array, in the order that you defined them.

4. Save the file, for example, as BLUEPRINT-NAME.toml and close the text editor.

5. Push the blueprint:

# composer-cli blueprints push BLUEPRINT-NAME.toml

Replace BLUEPRINT-NAME with the value you used in previous steps.

NOTE

To create images using composer-cli as non-root, add your user to the weldr or
root groups.

# usermod -a -G weldr user


$ newgrp weldr

Verification

List the existing blueprints to verify that the blueprint has been pushed and exists:

# composer-cli blueprints list

Display the blueprint configuration you have just added:

# composer-cli blueprints show BLUEPRINT-NAME

Check whether the components and versions listed in the blueprint and their dependencies are
valid:

# composer-cli blueprints depsolve BLUEPRINT-NAME

If RHEL image builder is unable to solve the dependencies of a package from your custom
repositories, remove the osbuild-composer cache:

$ sudo rm -rf /var/cache/osbuild-composer/*


$ sudo systemctl restart osbuild-composer

Additional resources

osbuild-composer is unable to depsolve a package from my custom repository Red Hat


Knowledgebase

Composing a customized RHEL system image with proxy server (Red Hat Knowledgebase)

1.3.4. Editing a blueprint with command-line interface


You can edit an existing blueprint in the command-line (CLI) interface to, for example, add a new
package, or define a new group, and to create your customized images. For that, follow the steps:

Prerequisites

24
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

You have created a blueprint

Procedure

1. List the existing blueprints:

# composer-cli blueprints list

2. Save the blueprint to a local text file:

# composer-cli blueprints save BLUEPRINT-NAME

3. Edit the BLUEPRINT-NAME.toml file with a text editor and make your changes.

4. Before finishing the edits, verify that the file is a valid blueprint:

a. Remove the following line from the blueprint, if present:

packages = []

b. Increase the version number, for example, from 0.0.1 to 0.1.0. Remember that RHEL image
builder blueprint versions must use the Semantic Versioning scheme. Note also that if you
do not change the version, the patch version component increases automatically.

5. Save the file and close the text editor.

6. Push the blueprint back into RHEL image builder:

# composer-cli blueprints push BLUEPRINT-NAME.toml

NOTE

To import the blueprint back into RHEL image builder, supply the file name
including the .toml extension, while in other commands use only the blueprint
name.

Verification

1. To verify that the contents uploaded to RHEL image builder match your edits, list the contents
of blueprint:

# composer-cli blueprints show BLUEPRINT-NAME

2. Check whether the components and versions listed in the blueprint and their dependencies are
valid:

# composer-cli blueprints depsolve BLUEPRINT-NAME

Additional resources

Supported Image Customizations

25
Red Hat Enterprise Linux 8 System Design Guide

1.3.5. Creating a system image with RHEL image builder in the command-line
interface
You can build a customized RHEL image by using the RHEL image builder command-line interface. For
that, you must specify a blueprint and an image type. Optionally, you can also specify a distribution. If
you do not specify a distribution, it will use the same distribution and version as the host system. The
architecture is also the same as the one on the host.

Prerequisites

You have a blueprint prepared for the image. See Creating a RHEL image builder blueprint
using the command-line interface.

Procedure

1. Optional: List the image formats you can create:

# composer-cli compose types

2. Start the compose:

# composer-cli compose start BLUEPRINT-NAME IMAGE-TYPE

Replace BLUEPRINT-NAME with the name of the blueprint, and IMAGE-TYPE with the type of
the image. For the available values, see the output of the composer-cli compose types
command.

The compose process starts in the background and shows the composer Universally Unique
Identifier (UUID).

3. The image creation can take up to ten minutes to complete.


To check the status of the compose:

# composer-cli compose status

A finished compose shows the FINISHED status value. To identify your compose in the list, use
its UUID.

4. After the compose process is finished, download the resulting image file:

# composer-cli compose image UUID

Replace UUID with the UUID value shown in the previous steps.

Verification
After you create your image, you can check the image creation progress using the following commands:

Download the metadata of the image to get a .tar file of the metadata for the compose:

$ sudo composer-cli compose metadata UUID

Download the logs of the image:

26
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

$ sudo composer-cli compose logs UUID

The command creates a .tar file that contains the logs for the image creation. If the logs are
empty, you can check the journal.

Check the journal:

$ journalctl | grep osbuild

Check the manifest of the image:

$ sudo cat /var/lib/osbuild-composer/jobs/job_UUID.json

You can find the job_UUID.json in the journal.

Additional resources

Tracing RHEL image builder (Red Hat Knowledgebase)

1.3.6. Basic RHEL image builder command-line commands


The RHEL image builder command-line interface offers the following subcommands.

Blueprint manipulation

List all available blueprints

# composer-cli blueprints list

Show a blueprint contents in the TOML format

# composer-cli blueprints show <BLUEPRINT-NAME>

Save (export) blueprint contents in the TOML format into a fileBLUEPRINT-NAME.toml

# composer-cli blueprints save <BLUEPRINT-NAME>

Remove a blueprint

# composer-cli blueprints delete <BLUEPRINT-NAME>

Push (import) a blueprint file in the TOML format into RHEL image builder

# composer-cli blueprints push <BLUEPRINT-NAME>

Composing images from blueprints

List the available image types

# composer-cli compose types

27
Red Hat Enterprise Linux 8 System Design Guide

Start a compose

# composer-cli compose start <BLUEPRINT> <COMPOSE-TYPE>

List all composes

# composer-cli compose list

List all composes and their status

# composer-cli compose status

Cancel a running compose

# composer-cli compose cancel <COMPOSE-UUID>

Delete a finished compose

# composer-cli compose delete <COMPOSE-UUID>

Show detailed information about a compose

# composer-cli compose info <COMPOSE-UUID>

Download image file of a compose

# composer-cli compose image <COMPOSE-UUID>

See more subcommands and options

# composer-cli help

Additional resources

The composer-cli(1) man page on your system

1.3.7. RHEL image builder blueprint format


RHEL image builder blueprints are presented to the user as plain text in the TOML format.

The elements of a typical blueprint file include the following:

The blueprint metadata

name = "<BLUEPRINT-NAME>"
description = "<LONG FORM DESCRIPTION TEXT>"
version = "<VERSION>"

The BLUEPRINT-NAME and LONG FORM DESCRIPTION TEXT field are a name and description for
your blueprint.

28
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

The VERSION is a version number according to the Semantic Versioning scheme, and is present only
once for the entire blueprint file.

Groups to include in the image

[[groups]]
name = "group-name"

The group entry describes a group of packages to be installed into the image. Groups use the
following package categories:

Mandatory

Default

Optional
The group-name is the name of the group, for example, anaconda-tools, widget, wheel or
users. Blueprints install the mandatory and default packages. There is no mechanism for
selecting optional packages.

Packages to include in the image

[[packages]]
name = "<package-name>"
version = "<package-version>"

package-name is the name of the package, such as httpd, gdb-doc, or coreutils.

package-version is a version to use. This field supports dnf version specifications:

For a specific version, use the exact version number such as 8.7.0.

For latest available version, use the asterisk *.

For a latest minor version, use a format such as 8.*.


Repeat this block for every package to include.

NOTE

There are no differences between packages and modules in the RHEL image builder tool.
Both are treated as RPM package dependencies.

1.3.8. Supported image customizations


You can customize your image by adding customizations to your blueprint, such as:

Adding an additional RPM package

Enabling a service

Customizing a kernel command line parameter.

Between others. You can use several image customizations within blueprints. By using the
customizations, you can add packages and groups to the image that are not available in the default

29
Red Hat Enterprise Linux 8 System Design Guide

packages. To use these options, configure the customizations in the blueprint and import (push) it to
RHEL image builder.

Additional resources

Blueprint import fails after adding filesystem customization "size" (Red Hat Knowledgebase)

1.3.8.1. Selecting a distribution

You can use the distro field to select the distribution to use when composing your images, or solving
dependencies in the blueprint. If distro is left blank it will use the host distribution. If you do not specify a
distribution, the blueprint uses the host distribution. In case you upgrade the host operating system, the
blueprints with no distribution set build images using the new operating system version. You cannot build
an operating system image that differs from the RHEL image builder host.

Customize the blueprint with the RHEL distribution to always build the specified RHEL image:

name = "blueprint_name"
description = "blueprint_version"
version = "0.1"
distro = "different_minor_version"

For example:

name = "tmux"
description = "tmux image with openssh"
version = "1.2.16"
distro = "rhel-9.5"

Replace "different_minor_version" to build a different minor version, for example, if you want to build a
RHEL 8.10 image, use distro = "rhel-810". On RHEL 8.10 image, you can build minor versions such as
RHEL 8.9 and earlier releases.

1.3.8.2. Selecting a package group

Customize the blueprint with package groups. The groups list describes the groups of packages that
you want to install into the image. The package groups are defined in the repository metadata. Each
group has a descriptive name that is used primarily for display in user interfaces, and an ID that is
commonly used in Kickstart files. In this case, you must use the ID to list a group. Groups have three
different ways of categorizing their packages: mandatory, default, and optional. Only mandatory and
default packages are installed in the blueprints. It is not possible to select optional packages.

The name attribute is a required string and must match exactly the package group id in the repositories.

NOTE

Currently, there are no differences between packages and modules in osbuild-


composer. Both are treated as an RPM package dependency.

Customize your blueprint with a package:

[[groups]]
name = "group_name"

30
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

Replace group_name with the name of the group. For example, anaconda-tools:

[[groups]]
name = "anaconda-tools"

1.3.8.3. Embedding a container

You can customize your blueprint to embed the latest RHEL container. The containers list contains
objects with a source, and optionally, the tls-verify attribute.

The container list entries describe the container images to be embedded into the image.

source - Mandatory field. It is a reference to the container image at a registry. This example
uses the registry.access.redhat.com registry. You can specify a tag version. The default tag
version is latest.

name - The name of the container in the local registry.

tls-verify - Boolean field. The tls-verify boolean field controls the transport layer security. The
default value is true.

The embedded containers do not start automatically. To start it, create systemd unit files or quadlets
with the files customization.

To embed a container from registry.access.redhat.com/ubi9/ubi:latest and a container from


your host, add the following customization to your blueprint:

[[containers]]
source = "registry.access.redhat.com/ubi9/ubi:latest"
name = "local-name"
tls-verify = true

[[containers]]
source = "localhost/test:latest"
local-storage = true

You can access protected container resources by using a containers-auth.json file. See Container
registry credentials.

1.3.8.4. Setting the image hostname

The customizations.hostname is an optional string that you can use to configure the final image
hostname. This customization is optional, and if you do not set it, the blueprint uses the default
hostname.

Customize the blueprint to configure the hostname:

[customizations]
hostname = "baseimage"

1.3.8.5. Specifying additional users

Add a user to the image, and optionally, set their SSH key. All fields for this section are optional except
for the name.

31
Red Hat Enterprise Linux 8 System Design Guide

Procedure

Customize the blueprint to add a user to the image:

[[customizations.user]]
name = "USER-NAME"
description = "USER-DESCRIPTION"
password = "PASSWORD-HASH"
key = "PUBLIC-SSH-KEY"
home = "/home/USER-NAME/"
shell = "/usr/bin/bash"
groups = ["users", "wheel"]
uid = NUMBER
gid = NUMBER

[[customizations.user]]
name = "admin"
description = "Administrator account"
password = "$6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31L..."
key = "PUBLIC SSH KEY"
home = "/srv/widget/"
shell = "/usr/bin/bash"
groups = ["widget", "users", "wheel"]
uid = 1200
gid = 1200
expiredate = 12345

The GID is optional and must already exist in the image. Optionally, a package creates it, or the
blueprint creates the GID by using the [[customizations.group]] entry.

Replace PASSWORD-HASH with the actual password hash. To generate the password hash,
use a command such as:

$ python3 -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if


(pw==getpass.getpass("Confirm: ")) else exit())'

Replace the other placeholders with suitable values.

Enter the name value and omit any lines you do not need.

Repeat this block for every user to include.

1.3.8.6. Specifying additional groups

Specify a group for the resulting system image. Both the name and the gid attributes are mandatory.

Customize the blueprint with a group:

[[customizations.group]]
name = "GROUP-NAME"
gid = NUMBER

Repeat this block for every group to include. For example:

32
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

[[customizations.group]]
name = "widget"
gid = 1130

1.3.8.7. Setting SSH key for existing users

You can use customizations.sshkey to set an SSH key for the existing users in the final image. Both
user and key attributes are mandatory.

Customize the blueprint by setting an SSH key for existing users:

[[customizations.sshkey]]
user = "root"
key = "PUBLIC-SSH-KEY"

For example:

[[customizations.sshkey]]
user = "root"
key = "SSH key for root"

NOTE

You can only configure the customizations.sshkey customization for existing


users. To create a user and set an SSH key, see the Specifying additional users
customization.

1.3.8.8. Appending a kernel argument

You can append arguments to the boot loader kernel command line. By default, RHEL image builder
builds a default kernel into the image. However, you can customize the kernel by configuring it in the
blueprint.

Append a kernel boot parameter option to the defaults:

[customizations.kernel]
append = "KERNEL-OPTION"

For example:

[customizations.kernel]
name = "kernel-debug"
append = "nosmt=force"

1.3.8.9. Building RHEL images by using the real-time kernel

To build a RHEL image by using the real-time kernel (kernel-rt), you need to override a repository so
that you can then build an image in which kernel-rt is correctly selected as the default kernel. Use the
.json from the /usr/share/osbuild-composer/repositories/ directory. Then, you can deploy the image
that you built to a system and use the real time kernel features.

NOTE
33
Red Hat Enterprise Linux 8 System Design Guide

NOTE

The real-time kernel runs on AMD64 and Intel 64 server platforms that are certified to
run Red Hat Enterprise Linux.

Prerequisites

Your system is registered and RHEL is attached to a RHEL for Real Time subscription. See
Installing RHEL for Real Time using dnf .

Procedure

1. Create the following directory:

# mkdir /etc/osbuild-composer/repositories/

2. Copy the content from the /usr/share/osbuild-composer/repositories/rhel-8.version.json file


to the new directory:

# cp /usr/share/osbuild-composer/repositories/rhel-8.version.json /etc/osbuild-
composer/repositories

3. Edit the /etc/osbuild-composer/repositories/rhel-8.version.json file to include the RT kernel


repo:

# grep -C 6 kernel-rt /etc/osbuild-composer/repositories/rhel-8.version.json


"baseurl": "https://cdn.redhat.com/content/dist/rhel8/8.version/x86_64/appstream/os",
"gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nm………..=\n=UZd/\n-----END
PGP PUBLIC KEY BLOCK-----\n",
"rhsm": true,
"check_gpg": true
},
{
"name": "kernel-rt",
"baseurl": "https://cdn.redhat.com/content/dist/rhel8/8.version/x86_64/rt/os",
"gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBEr………fg==\n=UZd/\n-
----END PGP PUBLIC KEY BLOCK-----\n",
"rhsm": true,
"check_gpg": true
},

4. Restart the service:

# systemctl restart osbuild-composer

5. Confirm that the kernel-rt has been included into the .json file:

# composer-cli sources list


# composer-cli sources info kernel-rt

You will see the URL that you have previously configured.

6. Create a blueprint. In the blueprint, add the "[customizations.kernel]" customization. The


following is an example that contains the "[customizations.kernel]" in the blueprint:

34
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

name = "rt-kernel-image"
description = ""
version = "2.0.0"
modules = []
groups = []
distro = "rhel-8_version_"
[[customizations.user]]
name = "admin"
password = "admin"
groups = ["users", "wheel"]
[customizations.kernel]
name = "kernel-rt"
append = ""

7. Push the blueprint to the server:

# composer-cli blueprints push rt-kernel-image.toml

8. Build your image from the blueprint you created. The following example builds a (.qcow2)
image:

# composer-cli compose start rt-kernel-image qcow2

9. Deploy the image that you built to the system where you want to use the real time kernel
features.

Verification

After booting a VM from the image, verify that the image was built with the kernel-rt correctly
selected as the default kernel.

$ cat /proc/cmdline
BOOT_IMAGE=(hd0,got3)/vmlinuz-5.14.0-362.24.1..el8_version_.x86_64+rt...

1.3.8.10. Setting time zone and NTP

You can customize your blueprint to configure the time zone and the Network Time Protocol (NTP).
Both timezone and ntpservers attributes are optional strings. If you do not customize the time zone,
the system uses Universal Time, Coordinated (UTC). If you do not set NTP servers, the system uses the
default distribution.

Customize the blueprint with the timezone and the ntpservers you want:

[customizations.timezone]
timezone = "TIMEZONE"
ntpservers = "NTP_SERVER"

For example:

[customizations.timezone]
timezone = "US/Eastern"
ntpservers = ["0.north-america.pool.ntp.org", "1.north-america.pool.ntp.org"]

NOTE
35
Red Hat Enterprise Linux 8 System Design Guide

NOTE

Some image types, such as Google Cloud, already have NTP servers set up. You
cannot override it because the image requires the NTP servers to boot in the
selected environment. However, you can customize the time zone in the
blueprint.

1.3.8.11. Customizing the locale settings

You can customize the locale settings for your resulting system image. Both language and the
keyboard attributes are mandatory. You can add many other languages. The first language you add is
the primary language and the other languages are secondary.

Procedure

Set the locale settings:

[customizations.locale]
languages = ["LANGUAGE"]
keyboard = "KEYBOARD"

For example:

[customizations.locale]
languages = ["en_US.UTF-8"]
keyboard = "us"

To list the values supported by the languages, run the following command:

$ localectl list-locales

To list the values supported by the keyboard, run the following command:

$ localectl list-keymaps

1.3.8.12. Customizing firewall

Set the firewall for the resulting system image. By default, the firewall blocks incoming connections,
except for services that enable their ports explicitly, such as sshd.

If you do not want to use the [customizations.firewall] or the [customizations.firewall.services],


either remove the attributes, or set them to an empty list []. If you only want to use the default firewall
setup, you can omit the customization from the blueprint.

NOTE

The Google and OpenStack templates explicitly disable the firewall for their environment.
You cannot override this behavior by setting the blueprint.

Procedure

Customize the blueprint with the following settings to open other ports and services:

36
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

[customizations.firewall]
ports = ["PORTS"]

Where ports is an optional list of strings that contain ports or a range of ports and protocols to
open. You can configure the ports by using the following format: port:protocol format. You can
configure the port ranges by using the portA-portB:protocol format. For example:

[customizations.firewall]
ports = ["22:tcp", "80:tcp", "imap:tcp", "53:tcp", "53:udp", "30000-32767:tcp", "30000-
32767:udp"]

You can use numeric ports, or their names from the /etc/services to enable or disable port lists.

Specify which firewall services to enable or disable in the customizations.firewall.service


section:

[customizations.firewall.services]
enabled = ["SERVICES"]
disabled = ["SERVICES"]

You can check the available firewall services:

$ firewall-cmd --get-services

For example:

[customizations.firewall.services]
enabled = ["ftp", "ntp", "dhcp"]
disabled = ["telnet"]

NOTE

The services listed in firewall.services are different from the service-names


available in the /etc/services file.

1.3.8.13. Enabling or disabling services

You can control which services to enable during the boot time. Some image types already have services
enabled or disabled to ensure that the image works correctly and you cannot override this setup. The
[customizations.services] settings in the blueprint do not replace these services, but add the services
to the list of services already present in the image templates.

Customize which services to enable during the boot time:

[customizations.services]
enabled = ["SERVICES"]
disabled = ["SERVICES"]

For example:

[customizations.services]
enabled = ["sshd", "cockpit.socket", "httpd"]
disabled = ["postfix", "telnetd"]

37
Red Hat Enterprise Linux 8 System Design Guide

1.3.8.14. Specifying a partition mode

Use the partitioning_mode variable to select how to partition the disk image that you are building. You
can customize your image with the following supported modes:

auto-lvm: It uses the raw partition mode, unless there are one or more filesystem
customizations. In that case, it uses the LVM partition mode.

lvm: It always uses the LVM partition mode, even when there are no extra mountpoints.

raw: It uses raw partitions even when there are one or more mountpoints.

You can customize your blueprint with the partitioning_mode variable by using the following
customization:

[customizations]
partitioning_mode = "lvm"

1.3.8.15. Specifying a custom file system configuration

You can specify a custom file system configuration in your blueprints and therefore create images with a
specific disk layout, instead of the default layout configuration. By using the non-default layout
configuration in your blueprints, you can benefit from:

Security benchmark compliance

Protection against out-of-disk errors

Improved performance

Consistency with existing setups

NOTE

The OSTree systems do not support the file system customizations, because OSTree
images have their own mount rule, such as read-only. The following image types are not
supported:

image-installer

edge-installer

edge-simplified-installer

Additionally, the following image types do not support file system customizations, because these image
types do not create partitioned operating system images:

edge-commit

edge-container

tar

container

However, the following image types have support for file system customization:

38
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

simplified-installer

edge-raw-image

edge-ami

edge-vsphere

With some additional exceptions for OSTree systems, you can choose arbitrary directory names at the
/root level of the file system, for example: ` /local`,` /mypartition`, /$PARTITION. In logical volumes,
these changes are made on top of the LVM partitioning system. The following directories are supported:
/var,` /var/log`, and /var/lib/containers on a separate logical volume. The following are exceptions at
root level:

"/home": {Deny: true},

"/mnt": {Deny: true},

"/opt": {Deny: true},

"/ostree": {Deny: true},

"/root": {Deny: true},

"/srv": {Deny: true},

"/var/home": {Deny: true},

"/var/mnt": {Deny: true},

"/var/opt": {Deny: true},

"/var/roothome": {Deny: true},

"/var/srv": {Deny: true},

"/var/usrlocal": {Deny: true},

For release distributions before RHEL 8.10 and 9.5, the blueprint supports the following mountpoints
and their sub-directories:

/ - the root mount point

/var

/home

/opt

/srv

/usr

/app

/data

/tmp

39
Red Hat Enterprise Linux 8 System Design Guide

From the RHEL 9.5 and 8.10 release distributions onward, you can specify arbitrary custom mountpoints,
except for specific paths that are reserved for the operating system.

You cannot specify arbitrary custom mountpoints on the following mountpoints and their sub-
directories:

/bin

/boot/efi

/dev

/etc

/lib

/lib64

/lost+found

/proc

/run

/sbin

/sys

/sysroot

/var/lock

/var/run

You can customize the file system in the blueprint for the /usr custom mountpoint, but its subdirectory
is not allowed.

NOTE

Customizing mount points is only supported from RHEL 8.5 distributions onward, by using
the CLI. In earlier distributions, you can only specify the root partition as a mount point
and specify the size argument as an alias for the image size. Beginning with RHEL 8.6, for
the osbuild-composer-46.1-1.el8 RPM and later version, the physical partitions are no
longer available and file system customizations create logical volumes.

If you have more than one partition in the customized image, you can create images with a customized
file system partition on LVM and resize those partitions at runtime. To do this, you can specify a
customized file system configuration in your blueprint and therefore create images with the required
disk layout. The default file system layout remains unchanged - if you use plain images without file
system customization, and cloud-init resizes the root partition.

The blueprint automatically converts the file system customization to an LVM partition.

You can use the custom file blueprint customization to create new files or to replace existing files. The
parent directory of the file you specify must exist, otherwise, the image build fails. Ensure that the
parent directory exists by specifying it in the [[customizations.directories]] customization.

40
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE


WARNING

If you combine the files customizations with other blueprint customizations, it might
affect the functioning of the other customizations, or it might override the current
files customizations.

1.3.8.15.1. Specifying customized files in the blueprint

With the [[customizations.files]] blueprint customization you can:

Create new text files.

Modifying existing files. WARNING: this can override the existing content.

Set user and group ownership for the file you are creating.

Set the mode permission in the octal format.

You cannot create or replace the following files:

/etc/fstab

/etc/shadow

/etc/passwd

/etc/group

You can create customized files and directories in your image, by using the [[customizations.files]] and
the [[customizations.directories]] blueprint customizations. You can use these customizations only in
the /etc directory.

NOTE

These blueprint customizations are supported by all image types, except the image types
that deploy OSTree commits, such as edge-raw-image, edge-installer, and edge-
simplified-installer.


WARNING

If you use the customizations.directories with a directory path which already exists
in the image with mode, user or group already set, the image build fails to prevent
changing the ownership or permissions of the existing directory.

1.3.8.15.2. Specifying customized directories in the blueprint

With the [[customizations.directories]] blueprint customization you can:

41
Red Hat Enterprise Linux 8 System Design Guide

Create new directories.

Set user and group ownership for the directory you are creating.

Set the directory mode permission in the octal format.

Ensure that parent directories are created as needed.

With the [[customizations.files]] blueprint customization you can:

Create new text files.

Modifying existing files. WARNING: this can override the existing content.

Set user and group ownership for the file you are creating.

Set the mode permission in the octal format.

NOTE

You cannot create or replace the following files:

/etc/fstab

/etc/shadow

/etc/passwd

/etc/group

The following customizations are available:

Customize the file system configuration in your blueprint:

[[customizations.filesystem]]
mountpoint = "MOUNTPOINT"
minsize = MINIMUM-PARTITION-SIZE

The MINIMUM-PARTITION-SIZE value has no default size format. The blueprint customization
supports the following values and units: kB to TB and KiB to TiB. For example, you can define
the mount point size in bytes:

[[customizations.filesystem]]
mountpoint = "/var"
minsize = 1073741824

Define the mount point size by using units. For example:

[[customizations.filesystem]]
mountpoint = "/opt"
minsize = "20 GiB"

[[customizations.filesystem]]
mountpoint = "/boot"
minsize = "1 GiB"

42
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

Define the minimum partition by setting minsize. For example:

[[customizations.filesystem]]
mountpoint = "/var"
minsize = 2147483648

Create customized directories under the /etc directory for your image by using
[[customizations.directories]]:

[[customizations.directories]]
path = "/etc/directory_name"
mode = "octal_access_permission"
user = "user_string_or_integer"
group = "group_string_or_integer"
ensure_parents = boolean

The blueprint entries are described as following:

path - Mandatory - enter the path to the directory that you want to create. It must be an
absolute path under the /etc directory.

mode - Optional - set the access permission on the directory, in the octal format. If you do
not specify a permission, it defaults to 0755. The leading zero is optional.

user - Optional - set a user as the owner of the directory. If you do not specify a user, it
defaults to root. You can specify the user as a string or as an integer.

group - Optional - set a group as the owner of the directory. If you do not specify a group, it
defaults to root. You can specify the group as a string or as an integer.

ensure_parents - Optional - Specify whether you want to create parent directories as


needed. If you do not specify a value, it defaults to false.

Create customized file under the /etc directory for your image by using
[[customizations.directories]]:

[[customizations.files]]
path = "/etc/directory_name"
mode = "octal_access_permission"
user = "user_string_or_integer"
group = "group_string_or_integer"
data = "Hello world!"

The blueprint entries are described as following:

path - Mandatory - enter the path to the file that you want to create. It must be an absolute
path under the /etc directory.

mode Optional - set the access permission on the file, in the octal format. If you do not
specify a permission, it defaults to 0644. The leading zero is optional.

user - Optional - set a user as the owner of the file. If you do not specify a user, it defaults
to root. You can specify the user as a string or as an integer.

group - Optional - set a group as the owner of the file. If you do not specify a group, it

43
Red Hat Enterprise Linux 8 System Design Guide

group - Optional - set a group as the owner of the file. If you do not specify a group, it
defaults to root. You can specify the group as a string or as an integer.

data - Optional - Specify the content of a plain text file. If you do not specify a content, it
creates an empty file.

1.3.9. Packages installed by RHEL image builder


When you create a system image by using RHEL image builder, the system installs a set of base package
groups.

NOTE

When you add additional components to your blueprint, ensure that the packages in the
components you added do not conflict with any other package components. Otherwise,
the system fails to solve dependencies and creating your customized image fails. You can
check if there is no conflict between the packages by running the command:

# composer-cli blueprints depsolve BLUEPRINT-NAME

By default, RHEL image builder uses the Core group as the base list of packages.

Table 1.3. Default packages to support image type creation

Image type Default Packages

ami checkpolicy, chrony, cloud-init, cloud-utils-


growpart, @Core, dhcp-client, gdisk,
insights-client, kernel, langpacks-en, net-
tools, NetworkManager, redhat-release,
redhat-release-eula, rng-tools, rsync, selinux-
policy-targeted, tar, yum-utils

openstack @core, langpacks-en

qcow2 @core, chrony, dnf, kernel, yum, nfs-utils,


dnf-utils, cloud-init, python3-jsonschema,
qemu-guest-agent, cloud-utils-growpart,
dracut-norescue, tar, tcpdump, rsync, dnf-
plugin-spacewalk, rhn-client-tools, rhnlib,
rhnsd, rhn-setup, NetworkManager, dhcp-
client, cockpit-ws, cockpit-system,
subscription-manager-cockpit, redhat-
release, redhat-release-eula, rng-tools,
insights-client

tar policycoreutils, selinux-policy-targeted

vhd @core, langpacks-en

44
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

Image type Default Packages

vmdk @core, chrony, cloud-init, firewalld,


langpacks-en, open-vm-tools, selinux-policy-
targeted

edge-commit redhat-release, glibc , glibc-minimal-langpack,


nss-altfiles, dracut-config-generic, dracut-
network, basesystem, bash , platform-python,
shadow-utils, chrony , setup, shadow-utils,
sudo, systemd , coreutils, util-linux, curl, vim-
minimal , rpm, rpm-ostree, polkit, lvm2,
cryptsetup, pinentry, e2fsprogs , dosfstools ,
keyutils, gnupg2 , attr , xz , gzip, firewalld ,
iptables , NetworkManager , NetworkManager-
wifi, NetworkManager-wwan, wpa_supplicant,
traceroute, hostname, iproute, iputils,
openssh-clients , procps-ng, rootfiles,
openssh-server, passwd, policycoreutils ,
policycoreutils-python-utils, selinux-policy-
targeted, setools-console , less, tar, rsync,
usbguard, bash-completion, tmux, ima-evm-
utils , audit, podman, containernetworking-
plugins, container-selinux, skopeo, criu,
slirp4netns , fuse-overlayfs, clevis , clevis-
dracut , clevis-luks, greenboot, greenboot-
default-health-checks, fdo-client, fdo-owner-
cli, sos,

edge-container dnf, dosfstools, e2fsprogs, glibc, lorax-


templates-generic, lorax-templates-rhel,
lvm2, policycoreutils, python36, python3-
iniparse, qemu-img, selinux-policy-targeted,
systemd, tar, xfsprogs, xz

45
Red Hat Enterprise Linux 8 System Design Guide

Image type Default Packages

edge-installer aajohan-comfortaa-fonts, abattis-cantarell-


fonts, alsa-firmware, alsa-tools-firmware,
anaconda, anaconda-install-env-deps,
anaconda-widgets, audit, bind-utils, bitmap-
fangsongti-fonts, bzip2, cryptsetup, dbus-
x11, dejavu-sans-fonts, dejavu-sans-mono-
fonts, device-mapper-persistent-data, dnf,
dump, ethtool, fcoe-utils, ftp, gdb-gdbserver,
gdisk, gfs2-utils, glibc-all-langpacks, google-
noto-sans-cjk-ttc-fonts, gsettings-desktop-
schemas, hdparm, hexedit, initscripts,
ipmitool, iwl3945-firmware, iwl4965-firmware,
iwl6000g2a-firmware, iwl6000g2b-firmware,
jomolhari-fonts, kacst-farsi-fonts, kacst-
qurn-fonts, kbd, kbd-misc, kdump-anaconda-
addon, khmeros-base-fonts, libblockdev-
lvm-dbus, libertas-sd8686-firmware, libertas-
sd8787-firmware, libertas-usb8388-firmware,
libertas-usb8388-olpc-firmware, libibverbs,
libreport-plugin-bugzilla, libreport-plugin-
reportuploader, libreport-rhel-anaconda-
bugzilla, librsvg2, linux-firmware, lklug-fonts,
lldpad, lohit-assamese-fonts, lohit-bengali-
fonts, lohit-devanagari-fonts, lohit-gujarati-
fonts, lohit-gurmukhi-fonts, lohit-kannada-
fonts, lohit-odia-fonts, lohit-tamil-fonts, lohit-
telugu-fonts, lsof, madan-fonts, metacity,
mtr, mt-st, net-tools, nmap-ncat, nm-
connection-editor, nss-tools, openssh-
server, oscap-anaconda-addon, pciutils, perl-
interpreter, pigz, python3-pyatspi, rdma-core,
redhat-release-eula, rpm-ostree, rsync,
rsyslog, sg3_utils, sil-abyssinica-fonts, sil-
padauk-fonts, sil-scheherazade-fonts,
smartmontools, smc-meera-fonts, spice-
vdagent, strace, system-storage-manager,
thai-scalable-waree-fonts, tigervnc-server-
minimal, tigervnc-server-module, udisks2,
udisks2-iscsi, usbutils, vim-minimal,
volume_key, wget, xfsdump, xorg-x11-
drivers,xorg-x11-fonts-misc,xorg-x11-server-
utils,xorg-x11-server-Xorg, xorg-x11-xauth

46
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

Image type Default Packages

edge-simplified-installer attr, basesystem, binutils, bsdtar, clevis-


dracut, clevis-luks, cloud-utils-growpart,
coreos-installer, coreos-installer-dracut,
coreutils, device-mapper-multipath,
dnsmasq, dosfstools, dracut-live, e2fsprogs,
fcoe-utils, fdo-init, gzip, ima-evm-utils,
iproute, iptables, iputils, iscsi-initiator-utils,
keyutils, lldpad, lvm2, passwd,
policycoreutils, policycoreutils-python-utils,
procps-ng, rootfiles, setools-console, sudo,
traceroute, util-linux

47
Red Hat Enterprise Linux 8 System Design Guide

Image type Default Packages

image-installer aajohan-comfortaa-fonts, abattis-cantarell-


fonts, alsa-firmware, alsa-tools-firmware ,
anaconda, anaconda-dracut , anaconda-
install-env-deps , anaconda-widgets, audit,
bind-utils, bitmap-fangsongti-fonts, bzip2,
cryptsetup, curl, dbus-x11, dejavu-sans-fonts,
dejavu-sans-mono-fonts , device-mapper-
persistent-data, dmidecode, dnf, dracut-
config-generic , dracut-network, efibootmgr,
ethtool , fcoe-utils, ftp, gdb-gdbserver, gdisk ,
glibc-all-langpacks, gnome-kiosk, google-
noto-sans-cjk-ttc-fonts, grub2-tools, grub2-
tools-extra, grub2-tools-minimal , grubby,
gsettings-desktop-schemas, hdparm, hexedit,
hostname, initscripts, ipmitool, iwl1000-
firmware, iwl100-firmware, iwl105-firmware,
iwl135-firmware, iwl2000-firmware , iwl2030-
firmware, iwl3160-firmware , iwl5000-firmware ,
iwl5150-firmware , iwl6000g2a-firmware,
iwl6000g2b-firmware, iwl6050-firmware ,
iwl7260-firmware , jomolhari-fonts, kacst-farsi-
fonts, kacst-qurn-fonts , kbd , kbd-misc,
kdump-anaconda-addon , kernel, khmeros-
base-fonts , less, libblockdev-lvm-dbus,
libibverbs, libreport-plugin-bugzilla, libreport-
plugin-reportuploader, librsvg2, linux-
firmware, lklug-fonts, lldpad, lohit-assamese-
fonts, lohit-bengali-fonts, lohit-devanagari-
fonts, lohit-gujarati-fonts, lohit-gurmukhi-
fonts, lohit-kannada-fonts, lohit-odia-fonts,
lohit-tamil-fonts, lohit-telugu-fonts, lsof ,
madan-fonts, mtr , mt-st, net-tools, nfs-utils,
nmap-ncat , nm-connection-editor, nss-tools,
openssh-clients , openssh-server, oscap-
anaconda-addon, ostree, pciutils, perl-
interpreter, pigz, plymouth, prefixdevname ,
python3-pyatspi, rdma-core, redhat-release-
eula, rng-tools , rpcbind, rpm-ostree, rsync,
rsyslog, selinux-policy-targeted, sg3_utils , sil-
abyssinica-fonts , sil-padauk-fonts, sil-
scheherazade-fonts, smartmontools, smc-
meera-fonts, spice-vdagent, strace, systemd ,
tar, thai-scalable-waree-fonts, tigervnc-server-
minimal , tigervnc-server-module,
udisks2,udisks2-iscsi,usbutils,vim-minimal,
volume_key, wget, xfsdump, xfsprogs, xorg-
x11-drivers , xorg-x11-fonts-misc, xorg-x11-
server-utils, xorg-x11-server-Xorg, xorg-x11-
xauth, xz ,

48
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

Image type Default Packages

edge-raw-image dnf, dosfstools, e2fsprogs, glibc, lorax-


templates-generic, lorax-templates-rhel,
lvm2, policycoreutils, python36, python3-
iniparse, qemu-img, selinux-policy-targeted,
systemd, tar, xfsprogs, xz

gce @core, langpacks-en, acpid, dhcp-client, dnf-


automatic, net-tools, python3, rng-tools, tar,
vim

Additional resources

RHEL image builder description

1.3.10. Enabled services on custom images


When you use image builder to configure a custom image, the default services that the image uses are
determined by the following:

The RHEL release on which you use the osbuild-composer utility

The image type

For example, the ami image type enables the sshd, chronyd, and cloud-init services by default. If these
services are not enabled, the custom image does not boot.

Table 1.4. Enabled services to support image type creation

Image type Default enabled Services

ami sshd, cloud-init, cloud-init-local, cloud-config, cloud-


final

openstack sshd, cloud-init, cloud-init-local, cloud-config, cloud-


final

qcow2 cloud-init

rhel-edge-commit No extra service enables by default

tar No extra service enables by default

vhd sshd, chronyd, waagent, cloud-init, cloud-init-local,


cloud-config, cloud-final

vmdk sshd, chronyd, vmtoolsd, cloud-init

Note: You can customize which services to enable during the system boot. However, the customization

49
Red Hat Enterprise Linux 8 System Design Guide

Note: You can customize which services to enable during the system boot. However, the customization
does not override services enabled by default for the mentioned image types.

Additional resources

Supported Image Customizations

1.4. CREATING SYSTEM IMAGES BY USING RHEL IMAGE BUILDER WEB


CONSOLE INTERFACE
RHEL image builder is a tool for creating custom system images. To control RHEL image builder and
create your custom system images, you can use the web console interface. Note that the command-line
interface is the currently preferred alternative, because it offers more features.

1.4.1. Accessing the RHEL image builder dashboard in the RHEL web console
With the cockpit-composer plugin for the RHEL web console, you can manage image builder blueprints
and composes using a graphical interface.

Prerequisites

You must have root access to the system.

You installed RHEL image builder.

You installed the cockpit-composer package.

Procedure

1. On the host, open https://<_localhost_>:9090/ in a web browser.

2. Log in to the web console as the root user.

3. To display the RHEL image builder controls, click the Image Builder button, in the upper-left
corner of the window.
The RHEL image builder dashboard opens, listing existing blueprints, if any.

Additional resources

Managing systems using the RHEL 8 web console

1.4.2. Creating a blueprint in the web console interface


Creating a blueprint is a necessary step before you build your customized RHEL system image. All the
customizations available are optional. You can create a customized blueprint by using the following
options:

Using the CLI. See Supported image customizations .

Using the web console. Follow the steps:

NOTE
50
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

NOTE

These blueprint customizations are available for Red Hat Enterprise Linux 9.2 or later
versions and Red Hat Enterprise Linux 8.8 or later versions.

Prerequisites

You have opened the RHEL image builder app from the web console in a browser. See
Accessing RHEL image builder GUI in the RHEL web console .

Procedure

1. Click Create Blueprint in the upper-right corner.


A dialog wizard with fields for the blueprint name and description opens.

2. On the Details page:

a. Enter the name of the blueprint and, optionally, its description.

b. Click Next.

3. Optional: In the Packages page:

a. On the Available packages search, enter the package name

b. Click the > button to move it to the Chosen packages field.

c. Repeat the previous steps to search and include as many packages as you want.

d. Click Next.

NOTE

These customizations are all optional unless otherwise specified.

4. On the Kernel page, enter a kernel name and the command-line arguments.

5. On the File system page, you can select Use automatic partitioning or Manually configure
partitions for your image file system. For manually configuring the partitions, complete the
following steps:

a. Click the Manually configure partitions button.


The Configure partitions section opens, showing the configuration based on Red Hat
standards and security guides.

b. From the dropdown menu, provide details to configure the partitions:

i. For the Mount point field, select one of the following mount point type options:

/ - the root mount point

/app

/boot

/data

51
Red Hat Enterprise Linux 8 System Design Guide

/home

/opt

/srv

/usr

/usr/local

/var
You can also add an additional path to the Mount point, such as /tmp. For example:
/var as a prefix and /tmp as an additional path results in /var/tmp.

NOTE

Depending on the Mount point type you choose, the file system type
changes to xfs.

ii. For the Minimum size partition field of the file system, enter the needed minimum
partition size. In the Minimum size dropdown menu, you can use common size units such
as GiB, MiB, or KiB. The default unit is GiB.

NOTE

Minimum size means that RHEL image builder can still increase the
partition sizes, in case they are too small to create a working image.

c. To add more partitions, click the Add partition button. If you see the following error
message: Duplicate partitions: Only one partition at each mount point can be created.,
you can:

i. Click the Remove button to remove the duplicated partition.

ii. Choose a new mount point for the partition you want to create.

d. After you finish the partitioning configuration, click Next.

6. On the Services page, you can enable or disable services:

a. Enter the service names you want to enable or disable, separating them by a comma, by
space, or by pressing the Enter key. Click Next.

b. Enter the Enabled services.

c. Enter the Disabled services.

7. On the Firewall page, set up your firewall setting:

a. Enter the Ports, and the firewall services you want to enable or disable.

b. Click the Add zone button to manage your firewall rules for each zone independently. Click
Next.

8. On the Users page, add a users by following the steps:

52
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

a. Click Add user.

b. Enter a Username, a Password, and a SSH key. You can also mark the user as a privileged
user, by clicking the Server administrator checkbox. Click Next.

9. On the Groups page, add groups by completing the following steps:

a. Click the Add groups button:

i. Enter a Group name and a Group ID. You can add more groups. Click Next.

10. On the SSH keys page, add a key:

a. Click the Add key button.

i. Enter the SSH key.

ii. Enter a User. Click Next.

11. On the Timezone page, set your time zone settings:

a. On the Timezone field, enter the time zone you want to add to your system image. For
example, add the following time zone format: "US/Eastern".
If you do not set a time zone, the system uses Universal Time, Coordinated (UTC) as
default.

b. Enter the NTP servers. Click Next.

12. On the Locale page, complete the following steps:

a. On the Keyboard search field, enter the package name you want to add to your system
image. For example: ["en_US.UTF-8"].

b. On the Languages search field, enter the package name you want to add to your system
image. For example: "us". Click Next.

13. On the Others page, complete the following steps:

a. On the Hostname field, enter the hostname you want to add to your system image. If you do
not add a hostname, the operating system determines the hostname.

b. Mandatory only for the Simplifier Installer image: On the Installation Devices field, enter a
valid node for your system image. For example: dev/sda1. Click Next.

14. Mandatory only when building images for FDO: On the FIDO device onboarding page,
complete the following steps:

a. On the Manufacturing server URL field, enter the following information:

i. On the DIUN public key insecure field, enter the insecure public key.

ii. On the DIUN public key hash field, enter the public key hash.

iii. On the DIUN public key root certs field, enter the public key root certs. Click Next.

15. On the OpenSCAP page, complete the following steps:

a. On the Datastream field, enter the datastream remediation instructions you want to add to
your system image.

53
Red Hat Enterprise Linux 8 System Design Guide

b. On the Profile ID field, enter the profile_id security profile you want to add to your system
image. Click Next.

16. Mandatory only when building images that use Ignition: On the Ignition page, complete the
following steps:

a. On the Firstboot URL field, enter the package name you want to add to your system image.

b. On the Embedded Data field, drag or upload your file. Click Next.

17. . On the Review page, review the details about the blueprint. Click Create.

The RHEL image builder view opens, listing existing blueprints.

1.4.3. Importing a blueprint in the RHEL image builder web console interface
You can import and use an already existing blueprint. The system automatically resolves all the
dependencies.

Prerequisites

You have opened the RHEL image builder app from the web console in a browser.

You have a blueprint that you want to import to use in the RHEL image builder web console
interface.

Procedure

1. On the RHEL image builder dashboard, click Import blueprint. The Import blueprint wizard
opens.

2. From the Upload field, either drag or upload an existing blueprint. This blueprint can be in either
TOML or JSON format.

3. Click Import. The dashboard lists the blueprint you imported.

Verification
When you click the blueprint you imported, you have access to a dashboard with all the customizations
for the blueprint that you imported.

To verify the packages that have been selected for the imported blueprint, navigate to the
Packages tab.

To list all the package dependencies, click All. The list is searchable and can be ordered.

Next steps

Optional: To modify any customization:

From the Customizations dashboard, click the customization you want to make a change.
Optionally, you can click Edit blueprint to navigate to all the available customization
options.

Additional resources

Creating a system image by using RHEL image builder in the web console interface

54
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

1.4.4. Exporting a blueprint from the RHEL image builder web console interface
You can export a blueprint to use the customizations in another system. You can export the blueprint in
the TOML or in the JSON format. Both formats work on the CLI and also in the API interface.

Prerequisites

You have opened the RHEL image builder app from the web console in a browser.

You have a blueprint that you want to export.

Procedure

1. On the image builder dashboard, select the blueprint you want to export.

2. Click Export blueprint. The Export blueprint wizard opens.

3. Click the Export button to download the blueprint as a file or click the Copy button to copy the
blueprint to the clipboard.

a. Optional: Click the Copy button to copy the blueprint.

Verification

Open the exported blueprint in a text editor to inspect and review it.

1.4.5. Creating a system image by using RHEL image builder in the web console
interface
You can create a customized RHEL system image from a blueprint by completing the following steps.

Prerequisites

You opened the RHEL image builder app from the web console in a browser.

You created a blueprint.

Procedure

1. In the RHEL image builder dashboard, click the blueprint tab.

2. On the blueprint table, find the blueprint you want to build an image.

3. On the right side of the chosen blueprint, click Create Image. The Create image dialog wizard
opens.

4. On the Image output page, complete the following steps:

a. From the Select a blueprint list, select the image type you want.

b. From the Image output type list, select the image output type you want.
Depending on the image type you select, you need to add further details.

5. Click Next.

6. On the Review page, review the details about the image creation and click Create image.

55
Red Hat Enterprise Linux 8 System Design Guide

The image build starts and takes up to 20 minutes to complete.

Verification
After the image finishes building, you can:

Download the image.

On the RHEL image builder dashboard, click the Node options ( ) menu and select
Download image.

Download the logs of the image to inspect the elements and verify if any issue is found.

On the RHEL image builder dashboard, click the Node options ( ) menu and select
Download logs.

1.5. PREPARING AND UPLOADING CLOUD IMAGES BY USING RHEL


IMAGE BUILDER
RHEL image builder can create custom system images ready for use on various cloud platforms. To use
your customized RHEL system image in a cloud, create the system image with RHEL image builder by
using the chosen output type, configure your system for uploading the image, and upload the image to
your cloud account. You can push customized image clouds through the Image Builder application in
the RHEL web console, available for a subset of the service providers that we support, such as AWS and
Microsoft Azure clouds. See Creating and automatically uploading images directly to AWS Cloud AMI
and Creating and automatically uploading VHD images directly to Microsoft Azure cloud .

1.5.1. Preparing and uploading AMI images to AWS


You can create custom images and can update them, either manually or automatically, to the AWS cloud
with RHEL image builder.

1.5.1.1. Preparing to manually upload AWS AMI images

Before uploading an AWS AMI image, you must configure a system for uploading the images.

Prerequisites

You must have an Access Key ID configured in the AWS IAM account manager.

You must have a writable S3 bucket prepared.

Procedure

1. Install Python 3 and the pip tool:

# yum install python3 python3-pip

2. Install the AWS command-line tools with pip:

# pip3 install awscli

3. Set your profile. The terminal prompts you to provide your credentials, region and output
format:

56
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

$ aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
Default output format [None]:

4. Define a name for your bucket and create a bucket:

$ BUCKET=bucketname
$ aws s3 mb s3://$BUCKET

Replace bucketname with the actual bucket name. It must be a globally unique name. As a
result, your bucket is created.

5. To grant permission to access the S3 bucket, create a vmimport S3 Role in the AWS Identity
and Access Management (IAM), if you have not already done so in the past:

a. Create a trust-policy.json file with the trust policy configuration, in the JSON format. For
example:

{
"Version": "2022-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "vmie.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:Externalid": "vmimport"
}
}
}]
}

b. Create a role-policy.json file with the role policy configuration, in the JSON format. For
example:

{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetBucketLocation", "s3:GetObject", "s3:ListBucket"],
"Resource": ["arn:aws:s3:::%s", "arn:aws:s3:::%s/"] }, { "Effect": "Allow", "Action":
["ec2:ModifySnapshotAttribute", "ec2:CopySnapshot", "ec2:RegisterImage",
"ec2:Describe"],
"Resource": "*"
}]
}
$BUCKET $BUCKET

c. Create a role for your Amazon Web Services account, by using the trust-policy.json file:

57
Red Hat Enterprise Linux 8 System Design Guide

$ aws iam create-role --role-name vmimport --assume-role-policy-document file://trust-


policy.json

d. Embed an inline policy document, by using the role-policy.json file:

$ aws iam put-role-policy --role-name vmimport --policy-name vmimport --policy-


document file://role-policy.json

Additional resources

Using high-level (s3) commands with the AWS CLI

1.5.1.2. Manually uploading an AMI image to AWS by using the CLI

You can use RHEL image builder to build ami images and manually upload them directly to Amazon
AWS Cloud service provider, by using the CLI.

Prerequisites

You have an Access Key ID configured in the AWS IAM account manager.

You have a writable S3 bucket prepared.

You have a defined blueprint.

Procedure

1. Using the text editor, create a configuration file with the following content:

provider = "aws"
[settings]
accessKeyID = "AWS_ACCESS_KEY_ID"
secretAccessKey = "AWS_SECRET_ACCESS_KEY"
bucket = "AWS_BUCKET"
region = "AWS_REGION"
key = "IMAGE_KEY"

Replace values in the fields with your credentials for accessKeyID, secretAccessKey, bucket,
and region. The IMAGE_KEY value is the name of your VM Image to be uploaded to EC2.

2. Save the file as CONFIGURATION-FILE.toml and close the text editor.

3. Start the compose to upload it to AWS:

# composer-cli compose start blueprint-name image-type image-key configuration-file.toml

Replace:

blueprint-name with the name of the blueprint you created

image-type with the ami image type.

image-key with the name of your VM Image to be uploaded to EC2.

58
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

configuration-file.toml with the name of the configuration file of the cloud provider.

NOTE

You must have the correct AWS Identity and Access Management (IAM)
settings for the bucket you are going to send your customized image to. You
have to set up a policy to your bucket before you are able to upload images
to it.

4. Check the status of the image build:

# composer-cli compose status

After the image upload process is complete, you can see the "FINISHED" status.

Verification
To confirm that the image upload was successful:

1. Access EC2 on the menu and select the correct region in the AWS console. The image must
have the available status, to indicate that it was successfully uploaded.

2. On the dashboard, select your image and click Launch.

Additional Resources

Required service role to import a VM

1.5.1.3. Creating and automatically uploading images to the AWS Cloud AMI

You can create a (.raw) image by using RHEL image builder, and choose to check the Upload to AWS
checkbox to automatically push the output image that you create directly to the Amazon AWS Cloud
AMI service provider.

Prerequisites

You must have root or wheel group user access to the system.

You have opened the RHEL image builder interface of the RHEL web console in a browser.

You have created a blueprint. See Creating a blueprint in the web console interface .

You must have an Access Key ID configured in the AWS IAM account manager.

You must have a writable S3 bucket prepared.

Procedure

1. In the RHEL image builder dashboard, click the blueprint name that you previously created.

2. Select the tab Images.

3. Click Create Image to create your customized image.


The Create Image window opens.

59
Red Hat Enterprise Linux 8 System Design Guide

a. From the Type drop-down menu list, select Amazon Machine Image Disk (.raw).

b. Check the Upload to AWS checkbox to upload your image to the AWS Cloud and click
Next.

c. To authenticate your access to AWS, type your AWS access key ID and AWS secret
access key in the corresponding fields. Click Next.

NOTE

You can view your AWS secret access key only when you create a new Access
Key ID. If you do not know your Secret Key, generate a new Access Key ID.

d. Type the name of the image in the Image name field, type the Amazon bucket name in the
Amazon S3 bucket name field and type the AWS region field for the bucket you are going
to add your customized image to. Click Next.

e. Review the information and click Finish.


Optionally, click Back to modify any incorrect detail.

NOTE

You must have the correct IAM settings for the bucket you are going to send
your customized image. This procedure uses the IAM Import and Export, so
you have to set up a policy to your bucket before you are able to upload
images to it. For more information, see Required Permissions for IAM Users .

4. A pop-up on the upper right informs you of the saving progress. It also informs that the image
creation has been initiated, the progress of this image creation and the subsequent upload to
the AWS Cloud.
After the process is complete, you can see the Image build complete status.

5. In a browser, access Service→EC2.

a. On the AWS console dashboard menu, choose the correct region. The image must have the
Available status, to indicate that it is uploaded.

b. On the AWS dashboard, select your image and click Launch.

6. A new window opens. Choose an instance type according to the resources you need to start your
image. Click Review and Launch.

7. Review your instance start details. You can edit each section if you need to make any changes.
Click Launch

8. Before you start the instance, select a public key to access it.
You can either use the key pair you already have or you can create a new key pair.

Follow the next steps to create a new key pair in EC2 and attach it to the new instance.

a. From the drop-down menu list, select Create a new key pair.

b. Enter the name to the new key pair. It generates a new key pair.

c. Click Download Key Pair to save the new key pair on your local system.

60
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

9. Then, you can click Launch Instance to start your instance.


You can check the status of the instance, which displays as Initializing.

10. After the instance status is running, the Connect button becomes available.

11. Click Connect. A window appears with instructions on how to connect by using SSH.

a. Select A standalone SSH client as the preferred connection method to and open a
terminal.

b. In the location you store your private key, ensure that your key is publicly viewable for SSH
to work. To do so, run the command:

$ chmod 400 <_your-instance-name.pem_>

c. Connect to your instance by using its Public DNS:

$ ssh -i <_your-instance-name.pem_> ec2-user@<_your-instance-IP-address_>

d. Type yes to confirm that you want to continue connecting.


As a result, you are connected to your instance over SSH.

Verification

Check if you are able to perform any action while connected to your instance by using SSH.

Additional resources

Open a case on Red Hat Customer Portal

Connecting to your Linux instance by using SSH

1.5.2. Preparing and uploading VHD images to Microsoft Azure


You can create custom images and can update them, either manually or automatically, to the Microsoft
Azure cloud with RHEL image builder.

1.5.2.1. Preparing to manually upload Microsoft Azure VHD images

To create a VHD image that you can manually upload to Microsoft Azure cloud, you can use RHEL
image builder.

Prerequisites

You must have a Microsoft Azure resource group and storage account.

You have Python installed. The AZ CLI tool depends on python.

Procedure

1. Import the Microsoft repository key:

# rpm --import https://packages.microsoft.com/keys/microsoft.asc

2. Create a local azure-cli.repo repository with the following information. Save the azure-cli.repo
61
Red Hat Enterprise Linux 8 System Design Guide

2. Create a local azure-cli.repo repository with the following information. Save the azure-cli.repo
repository under /etc/yum.repos.d/:

[azure-cli]
name=Azure CLI
baseurl=https://packages.microsoft.com/yumrepos/vscode
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc

3. Install the Microsoft Azure CLI:

# yumdownloader azure-cli
# rpm -ivh --nodeps azure-cli-2.0.64-1.el7.x86_64.rpm

NOTE

The downloaded version of the Microsoft Azure CLI package can vary depending
on the current available version.

4. Run the Microsoft Azure CLI:

$ az login

The terminal shows the following message Note, we have launched a browser for you to
login. For old experience with device code, use "az login --use-device-code. Then, the
terminal opens a browser with a link to https://microsoft.com/devicelogin from where you can
login.

NOTE

If you are running a remote (SSH) session, the login page link will not open in the
browser. In this case, you can copy the link to a browser and login to authenticate
your remote session. To sign in, use a web browser to open the page
https://microsoft.com/devicelogin and enter the device code to authenticate.

5. List the keys for the storage account in Microsoft Azure:

$ az storage account keys list --resource-group <resource_group_name> --account-name


<storage_account_name>

Replace resource-group-name with name of your Microsoft Azure resource group and storage-
account-name with name of your Microsoft Azure storage account.

NOTE

You can list the available resources using the following command:

$ az resource list

Make note of value key1 in the output of the previous command.

62
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

6. Create a storage container:

$ az storage container create --account-name <storage_account_name>\


--account-key <key1_value> --name <storage_account_name>

Replace storage-account-name with name of the storage account.

Additional resources

Microsoft Azure CLI.

1.5.2.2. Manually uploading VHD images to Microsoft Azure cloud

After you have created your customized VHD image, you can manually upload it to the Microsoft Azure
cloud.

Prerequisites

Your system must be set up for uploading Microsoft Azure VHD images. See Preparing to
upload Microsoft Azure VHD images.

You must have a Microsoft Azure VHD image created by RHEL image builder.

In the GUI, use the Azure Disk Image (.vhd) image type.

In the CLI, use the vhd output type.

Procedure

1. Push the image to Microsoft Azure and create an instance from it:

$ az storage blob upload --account-name <_account_name_> --container-name


<_container_name_> --file <_image_-disk.vhd> --name <_image_-disk.vhd> --type page
...

2. After the upload to the Microsoft Azure Blob storage completes, create a Microsoft Azure
image from it:

$ az image create --resource-group <_resource_group_name_> --name <_image_>-disk.vhd


--os-type linux --location <_location_> --source
https://$<_account_name_>.blob.core.windows.net/<_container_name_>/<_image_>-
disk.vhd
- Running ...

NOTE

Because the images that you create with RHEL image builder generate hybrid
images that support to both the V1 = BIOS and V2 = UEFI instances types, you
can specify the --hyper-v-generation argument. The default instance type is V1.

Verification

1. Create an instance either with the Microsoft Azure portal, or a command similar to the following:

63
Red Hat Enterprise Linux 8 System Design Guide

$ az vm create --resource-group <_resource_group_name_> --location <_location_> --name


<_vm_name_> --image <_image_>-disk.vhd --admin-username azure-user --generate-ssh-
keys
- Running ...

2. Use your private key via SSH to access the resulting instance. Log in as azure-user. This
username was set on the previous step.

Additional Resources

Composing an image for the .vhd format fails (Red Hat Knowledgebase)

1.5.2.3. Creating and automatically uploading VHD images to Microsoft Azure cloud

You can create .vhd images by using RHEL image builder that will be automatically uploaded to a Blob
Storage of the Microsoft Azure Cloud service provider.

Prerequisites

You have root access to the system.

You have access to the RHEL image builder interface of the RHEL web console.

You created a blueprint. See Creating a RHEL image builder blueprint in the web console
interface.

You have a Microsoft Storage Account created.

You have a writable Blob Storage prepared.

Procedure

1. In the RHEL image builder dashboard, select the blueprint you want to use.

2. Click the Images tab.

3. Click Create Image to create your customized .vhd image.


The Create image wizard opens.

a. Select Microsoft Azure (.vhd) from the Type drop-down menu list.

b. Check the Upload to Azure checkbox to upload your image to the Microsoft Azure Cloud.

c. Enter the Image Size and click Next.

4. On the Upload to Azure page, enter the following information:

a. On the Authentication page, enter:

i. Your Storage account name. You can find it on the Storage account page, in the
Microsoft Azure portal.

ii. Your Storage access key: You can find it on the Access Key Storage page.

iii. Click Next.

64
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

b. On the Authentication page, enter:

i. The image name.

ii. The Storage container. It is the blob container to which you will upload the image. Find
it under the Blob service section, in the Microsoft Azure portal.

iii. Click Next.

5. On the Review page, click Create. The RHEL image builder and upload processes start.
Access the image you pushed into Microsoft Azure Cloud.

6. Access the Microsoft Azure portal.

7. In the search bar, type "storage account" and click Storage accounts from the list.

8. On the search bar, type "Images" and select the first entry under Services. You are redirected
to the Image dashboard.

9. On the navigation panel, click Containers.

10. Find the container you created. Inside the container is the .vhd file you created and pushed by
using RHEL image builder.

Verification

1. Verify that you can create a VM image and launch it.

a. In the search bar, type images account and click Images from the list.

b. Click +Create.

c. From the dropdown list, choose the resource group you used earlier.

d. Enter a name for the image.

e. For the OS type, select Linux.

f. For the VM generation, select Gen 2.

g. Under Storage Blob, click Browse and click through the storage accounts and container
until you reach your VHD file.

h. Click Select at the end of the page.

i. Choose an Account Type, for example, Standard SSD.

j. Click Review + Create and then Create. Wait a few moments for the image creation.

2. To launch the VM, follow the steps:

a. Click Go to resource.

b. Click + Create VM from the menu bar on the header.

c. Enter a name for your virtual machine.

d. Complete the Size and Administrator account sections.

65
Red Hat Enterprise Linux 8 System Design Guide

e. Click Review + Create and then Create. You can see the deployment progress.
After the deployment finishes, click the virtual machine name to retrieve the public IP
address of the instance to connect by using SSH.

f. Open a terminal to create an SSH connection to connect to the VM.

Additional resources

Microsoft Azure Storage Documentation

Create a Microsoft Azure Storage account

Open a case on Red Hat Customer Portal

Help + support

Contacting Red Hat

1.5.2.4. Uploading VMDK images and creating a RHEL virtual machine in vSphere

With RHEL image builder, you can create customized VMware vSphere system images, either in the
Open virtualization format (.ova) or in the Virtual disk ( .vmdk) format. You can upload these images to
the VMware vSphere client. You can upload the .vmdk or .ova image to VMware vSphere using the
govc import.vmdk CLI tool. The vmdk you create contains the cloud-init package installed and you
can use it to provision users by using user data, for example.

NOTE

Uploading vmdk images by using the VMware vSphere GUI is not supported.

Prerequisites

You created a blueprint with username and password customizations.

You created a VMware vSphere image either in the .ova or .vmdk format by using RHEL image
builder and downloaded it to your host system.

You installed and configured the govc CLI tool, to be able use the import.vmdk command.

Procedure

1. Configure the following values in the user environment with the GOVC environment variables:

GOVC_URL
GOVC_DATACENTER
GOVC_FOLDER
GOVC_DATASTORE
GOVC_RESOURCE_POOL
GOVC_NETWORK

2. Navigate to the directory where you downloaded your VMware vSphere image.

3. Launch the VMware vSphere image on vSphere by following the steps:

a. Import the VMware vSphere image in to vSphere:

66
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

$ govc import.vmdk ./composer-api.vmdk foldername

For the .ova format:

$ govc import.ova ./composer-api.ova foldername

b. Create the VM in vSphere without powering it on:

govc vm.create \
-net.adapter=vmxnet3 \
-m=4096 -c=2 -g=rhel8_64Guest \
-firmware=efi -disk=”foldername/composer-api.vmdk” \
-disk.controller=scsi -on=false \
vmname

For the .ova format, replace the line -firmware=efi -disk=”foldername/composer-


api.vmdk” \ with `-firmware=efi -disk=” foldername/composer-api.ova” \

c. Power-on the VM:

govc vm.power -on vmname

d. Retrieve the VM IP address:

govc vm.ip vmname

e. Use SSH to log in to the VM, using the username and password you specified in your
blueprint:

$ ssh admin@<_ip_address_of_the_vm_>

NOTE

If you copied the .vmdk image from your local host to the destination using
the govc datastore.upload command, using the resulting image is not
supported. There is no option to use the import.vmdk command in the
vSphere GUI and as a result, the vSphere GUI does not support the direct
upload. As a consequence, the .vmdk image is not usable from the vSphere
GUI.

1.5.2.5. Creating and automatically uploading VMDK images to vSphere using image builder
GUI

You can build VMware images by using the RHEL image builder GUI tool and automatically push the
images directly to your vSphere instance. This avoids the need to download the image file and push it
manually. The vmdk you create contains the cloud-init package installed and you can use it to provision
users by using user data, for example. To build .vmdk images by using RHEL image builder and push
them directly to vSphere instances service provider, follow the steps:

Prerequisites

You are a member of the root or the weldr group.

67
Red Hat Enterprise Linux 8 System Design Guide

You have opened link:https://localhost:9090/RHEL image builder in a browser.

You have created a blueprint. See Creating a RHEL image builder blueprint in the web console
interface.

You have a vSphere Account.

Procedure

1. For the blueprint you created, click the Images tab .

2. Click Create Image to create your customized image.


The Image type window opens.

3. In the Image type window:

a. From the dropdown menu, select the Type: VMware vSphere (.vmdk).

b. Check the Upload to VMware checkbox to upload your image to the vSphere.

c. Optional: Set the size of the image you want to instantiate. The minimal default size is 2 GB.

d. Click Next.

4. In the Upload to VMware window, under Authentication, enter the following details:

a. Username: username of the vSphere account.

b. Password: password of the vSphere account.

5. In the Upload to VMware window, under Destination, enter the following details about the
image upload destination:

a. Image name: a name for the image.

b. Host: The URL of your VMware vSphere.

c. Cluster: The name of the cluster.

d. Data center: The name of the data center.

e. Data store:The name of the Data store.

f. Click Next.

6. In the Review window, review the details of the image creation and click Finish.
You can click Back to modify any incorrect detail.

RHEL image builder adds the compose of a RHEL vSphere image to the queue, and creates and
uploads the image to the Cluster on the vSphere instance you specified.

NOTE

The image build and upload processes take a few minutes to complete.

After the process is complete, you can see the Image build complete status.

68
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

Verification
After the image status upload is completed successfully, you can create a Virtual Machine (VM) from the
image you uploaded and login into it. To do so:

1. Access VMware vSphere Client.

2. Search for the image in the Cluster on the vSphere instance you specified.

3. Select the image you uploaded.

4. Right-click the selected image.

5. Click New Virtual Machine.


A New Virtual Machine window opens.

In the New Virtual Machine window, provide the following details:

a. Select New Virtual Machine.

b. Select a name and a folder for your VM.

c. Select a computer resource: choose a destination computer resource for this operation.

d. Select storage: For example, select NFS-Node1

e. Select compatibility: The image should be BIOS only.

f. Select a guest operating system: For example, select Linux and Red Hat Fedora (64-bit) .

g. Customize hardware: When creating a VM, on the Device Configuration button on the
upper right, delete the default New Hard Disk and use the drop-down to select an Existing
Hard Disk disk image:

h. Ready to complete: Review the details and click Finish to create the image.

6. Navigate to the VMs tab.

a. From the list, select the VM you created.

b. Click the Start button from the panel. A new window appears, showing the VM image
loading.

c. Log in with the credentials you created for the blueprint.

d. You can verify if the packages you added to the blueprint are installed. For example:

$ rpm -qa | grep firefox

Additional resources

Introduction to vSphere Installation and Setup

1.5.3. Preparing and uploading custom GCE images to GCP


You can create custom images and then automatically update them to the Oracle Cloud Infrastructure
(OCI) instance with RHEL image builder.

69
Red Hat Enterprise Linux 8 System Design Guide

1.5.3.1. Uploading images to GCP with RHEL image builder

With RHEL image builder, you can build a gce image, provide credentials for your user or GCP service
account, and then upload the gce image directly to the GCP environment.

1.5.3.1.1. Configuring and uploading a gce image to GCP by using the CLI

Set up a configuration file with credentials to upload your gce image to GCP by using the RHEL image
builder CLI.


WARNING

You cannot manually import gce image to GCP, because the image will not boot.
You must use either gcloud or RHEL image builder to upload it.

Prerequisites

You have a valid Google account and credentials to upload your image to GCP. The credentials
can be from a user account or a service account. The account associated with the credentials
must have at least the following IAM roles assigned:

roles/storage.admin - to create and delete storage objects

roles/compute.storageAdmin - to import a VM image to Compute Engine.

You have an existing GCP bucket.

Procedure

1. Use a text editor to create a gcp-config.toml configuration file with the following content:

provider = "gcp"
[settings]
bucket = "GCP_BUCKET"
region = "GCP_STORAGE_REGION"
object = "OBJECT_KEY"
credentials = "GCP_CREDENTIALS"

GCP_BUCKET points to an existing bucket. It is used to store the intermediate storage


object of the image which is being uploaded.

GCP_STORAGE_REGION is both a regular Google storage region and a dual or multi


region.

OBJECT_KEY is the name of an intermediate storage object. It must not exist before the
upload, and it is deleted when the upload process is done. If the object name does not end
with .tar.gz, the extension is automatically added to the object name.

GCP_CREDENTIALS is a Base64-encoded scheme of the credentials JSON file


downloaded from GCP. The credentials determine which project the GCP uploads the
image to.

NOTE
70
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

NOTE

Specifying GCP_CREDENTIALS in the gcp-config.toml file is optional if


you use a different mechanism to authenticate with GCP. For other
authentication methods, see Authenticating with GCP.

2. Retrieve the GCP_CREDENTIALS from the JSON file downloaded from GCP.

$ sudo base64 -w 0 cee-gcp-nasa-476a1fa485b7.json

3. Create a compose with an additional image name and cloud provider profile:

$ sudo composer-cli compose start BLUEPRINT-NAME gce IMAGE_KEY gcp-config.toml

The image build, upload, and cloud registration processes can take up to ten minutes to
complete.

Verification

Verify that the image status is FINISHED:

$ sudo composer-cli compose status

Additional resources

Identity and Access Management

Create storage buckets

1.5.3.1.2. How RHEL image builder sorts the authentication order of different GCP credentials

You can use several different types of credentials with RHEL image builder to authenticate with GCP. If
RHEL image builder configuration is set to authenticate with GCP using multiple sets of credentials, it
uses the credentials in the following order of preference:

1. Credentials specified with the composer-cli command in the configuration file.

2. Credentials configured in the osbuild-composer worker configuration.

3. Application Default Credentials from the Google GCP SDK library, which tries to
automatically find a way to authenticate by using the following options:

a. If the GOOGLE_APPLICATION_CREDENTIALS environment variable is set, Application


Default Credentials tries to load and use credentials from the file pointed to by the variable.

b. Application Default Credentials tries to authenticate by using the service account attached
to the resource that is running the code. For example, Google Compute Engine VM.

NOTE

You must use the GCP credentials to determine which GCP project to
upload the image to. Therefore, unless you want to upload all of your images
to the same GCP project, you always must specify the credentials in the
gcp-config.toml configuration file with the composer-cli command.

71
Red Hat Enterprise Linux 8 System Design Guide

1.5.3.1.2.1. Specifying GCP credentials with the composer-cli command

You can specify GCP authentication credentials in the upload target configuration gcp-config.toml file.
Use a Base64-encoded scheme of the Google account credentials JSON file to save time.

Procedure

1. Get the encoded content of the Google account credentials file with the path stored in
GOOGLE_APPLICATION_CREDENTIALS environment variable, by running the following
command:

$ base64 -w 0 "${GOOGLE_APPLICATION_CREDENTIALS}"

2. In the upload target configuration gcp-config.toml file, set the credentials:

provider = "gcp"

[settings]
provider = "gcp"

[settings]
credentials = "GCP_CREDENTIALS"

1.5.3.1.2.2. Specifying credentials in the osbuild-composer worker configuration

You can configure GCP authentication credentials to be used for GCP globally for all image builds. This
way, if you want to import images to the same GCP project, you can use the same credentials for all
image uploads to GCP.

Procedure

In the /etc/osbuild-worker/osbuild-worker.toml worker configuration, set the following


credential value:

[gcp]
credentials = "PATH_TO_GCP_ACCOUNT_CREDENTIALS"

1.5.4. Preparing and uploading custom images directly to OCI


You can create custom images and then automatically update them to the Oracle Cloud Infrastructure
(OCI) instance with RHEL image builder.

1.5.4.1. Creating and automatically uploading custom images to OCI

With RHEL image builder, build customized images and automatically push them directly to your Oracle
Cloud Infrastructure (OCI) instance. Then, you can start an image instance from the OCI dashboard.

Prerequisites

You have root or weldr group user access to the system.

You have an Oracle Cloud account.

You must be granted security access in an OCI policy by your administrator.

72
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

You have created an OCI Bucket in the OCI_REGION of your choice.

Procedure

1. Open the RHEL image builder interface of the web console in a browser.

2. Click Create blueprint. The Create blueprint wizard opens.

3. On the Details page, enter a name for the blueprint, and optionally, a description. Click Next.

4. On the Packages page, select the components and packages that you want to include in the
image. Click Next.

5. On the Customizations page, configure the customizations that you want for your blueprint.
Click Next.

6. On the Review page, click Create.

7. To create an image, click Create Image. The Create image wizard opens.

8. On the Image output page, complete the following steps:

a. From the "Select a blueprint" drop-down menu, select the blueprint you want.

b. From the "Image output type" drop-down menu, select Oracle Cloud Infrastructure
(.qcow2).

c. Check the "Upload OCI checkbox to upload your image to the OCI.

d. Enter the "image size". Click Next.

9. On the Upload to OCI - Authentication page, enter the following mandatory details:

a. User OCID: you can find it in the Console on the page showing the user’s details.

b. Private key

10. On the Upload to OCI - Destination page, enter the following mandatory details and click
Next.

a. Image name: a name for the image to be uploaded.

b. OCI bucket

c. Bucket namespace

d. Bucket region

e. Bucket compartment

f. Bucket tenancy

11. Review the details in the wizard and click Finish.

RHEL image builder adds the compose of a RHEL .qcow2 image to the queue.

Verification

73
Red Hat Enterprise Linux 8 System Design Guide

1. Access the OCI dashboard → Custom Images.

2. Select the Compartment you specified for the image and locate the image in the Import
image table.

3. Click the image name and verify the image information.

Additional resources

Managing custom images in the OCI.

Managing buckets in the OCI.

Generating SSH keys.

1.5.5. Preparing and uploading customized QCOW2 images directly to OpenStack


You can create custom .qcow2 images with RHEL image builder, and manually upload them to the
OpenStack cloud deployments.

1.5.5.1. Uploading QCOW2 images to OpenStack

With the RHEL image builder tool, you can create customized .qcow2 images that are suitable for
uploading to OpenStack cloud deployments, and starting instances there. RHEL image builder creates
images in the QCOW2 format, but with further changes specific to OpenStack.


WARNING

Do not mistake the generic QCOW2 image type output format you create by using
RHEL image builder with the OpenStack image type, which is also in the QCOW2
format, but contains further changes specific to OpenStack.

Prerequisites

You have created a blueprint.

Procedure

1. Start the compose of a QCOW2 image.

# composer-cli compose start blueprint_name openstack

2. Check the status of the building.

# composer-cli compose status

After the image build finishes, you can download the image.

3. Download the QCOW2 image:

74
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

# composer-cli compose image UUID

4. Access the OpenStack dashboard and click +Create Image.

5. On the left menu, select the Admin tab.

6. From the System Panel, click Image.


The Create An Image wizard opens.

7. In the Create An Image wizard:

a. Enter a name for the image

b. Click Browse to upload the QCOW2 image.

c. From the Format dropdown list, select the QCOW2 - QEMU Emulator.

d. Click Create Image.

8. On the left menu, select the Project tab.

75
Red Hat Enterprise Linux 8 System Design Guide

a. From the Compute menu, select Instances.

b. Click the Launch Instance button.


The Launch Instance wizard opens.

c. On the Details page, enter a name for the instance. Click Next.

d. On the Source page, select the name of the image you uploaded. Click Next.

e. On the Flavor page, select the machine resources that best fit your needs. Click Launch.

9. You can run the image instance using any mechanism (CLI or OpenStack web UI) from the
image. Use your private key via SSH to access the resulting instance. Log in as cloud-user.

1.5.6. Preparing and uploading customized RHEL images to the Alibaba Cloud
You can upload a customized .ami images that you created by using RHEL image builder to the Alibaba
Cloud.

1.5.6.1. Preparing to upload customized RHEL images to Alibaba Cloud

To deploy a customized RHEL image to the Alibaba Cloud, first you need to verify the customized
image. The image needs a specific configuration to boot successfully, because Alibaba Cloud requests
the custom images to meet certain requirements before you use it.

NOTE
76
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

NOTE

RHEL image builder generates images that conform to Alibaba’s requirements. However,
Red Hat recommends also using the Alibaba image_check tool to verify the format
compliance of your image.

Prerequisites

You must have created an Alibaba image by using RHEL image builder.

Procedure

1. Connect to the system containing the image that you want to check by using the Alibaba
image_check tool.

2. Download the image_check tool:

$ curl -O https://docs-aliyun.cn-hangzhou.oss.aliyun-
inc.com/assets/attach/73848/cn_zh/1557459863884/image_check

3. Change the file permission of the image compliance tool:

# chmod +x image_check

4. Run the command to start the image compliance tool checkup:

# ./image_check

The tool verifies the system configuration and generates a report that is displayed on your
screen. The image_check tool saves this report in the same folder where the image compliance
tool is running.

Troubleshooting
If any of the Detection Items fail, follow the instructions in the terminal to correct it.

Additional resources

Image Compliance Tool.

1.5.6.2. Uploading customized RHEL images to Alibaba

You can upload a customized AMI image you created by using RHEL image builder to the Object
Storage Service (OSS).

Prerequisites

Your system is set up for uploading Alibaba images. See Preparing for uploading images to
Alibaba.

You have created an ami image by using RHEL image builder.

You have a bucket. See Creating a bucket .

You have an active Alibaba Account .

77
Red Hat Enterprise Linux 8 System Design Guide

You activated OSS.

Procedure

1. Log in to the OSS console.

2. In the Bucket menu on the left, select the bucket to which you want to upload an image.

3. In the upper right menu, click the Files tab.

4. Click Upload. A dialog window opens on the right side. Configure the following:

Upload To: Choose to upload the file to the Current directory or to a Specified directory.

File ACL: Choose the type of permission of the uploaded file.

5. Click Upload.

6. Select the image you want to upload to the OSS Console..

7. Click Open.

Additional resources

Upload an object.

Creating an instance from custom images.

Importing images.

1.5.6.3. Importing images to Alibaba Cloud

To import a customized Alibaba RHEL image that you created by using RHEL image builder to the
Elastic Compute Service (ECS), follow the steps:

Prerequisites

Your system is set up for uploading Alibaba images. See Preparing for uploading images to
Alibaba.

You have created an ami image by using RHEL image builder.

You have a bucket. See Creating a bucket .

You have an active Alibaba Account .

You activated OSS.

You have uploaded the image to Object Storage Service (OSS). See Uploading images to
Alibaba.

Procedure

1. Log in to the ECS console.

i. On the left-side menu, click Images.

78
CHAPTER 1. COMPOSING A CUSTOMIZED RHEL SYSTEM IMAGE

ii. On the upper right side, click Import Image. A dialog window opens.

iii. Confirm that you have set up the correct region where the image is located. Enter the
following information:

a. OSS Object Address: See how to obtain OSS Object Address .

b. Image Name

c. Operating System

d. System Disk Size

e. System Architecture

f. Platform: Red Hat

iv. Optional: Provide the following details:

g. Image Format: qcow2 or ami, depending on the uploaded image format.

h. Image Description

i. Add Images of Data Disks


The address can be determined in the OSS management console. After selecting the
required bucket in the left menu:

2. Select Files section.

3. Click the Details link on the right for the appropriate image.
A window appears on the right side of the screen, showing image details. The OSS object
address is in the URL box.

4. Click OK.

NOTE

The importing process time can vary depending on the image size.

The customized image is imported to the ECS Console.

Additional resources

Notes for importing images.

Creating an instance from custom images.

Upload an object.

1.5.6.4. Creating an instance of a customized RHEL image using Alibaba Cloud

You can create instances of a customized RHEL image by using the Alibaba ECS Console.

Prerequisites

You have activated OSS and uploaded your custom image.

79
Red Hat Enterprise Linux 8 System Design Guide

You have successfully imported your image to ECS Console. See Importing images to Alibaba .

Procedure

1. Log in to the ECS console.

2. On the left-side menu, select Instances.

3. In the upper-right corner, click Create Instance. You are redirected to a new window.

4. Complete all the required information. See Creating an instance by using the wizard for more
details.

5. Click Create Instance and confirm the order.

NOTE

You can see the option Create Order instead of Create Instance, depending on
your subscription.

As a result, you have an active instance ready for deployment from the Alibaba ECS Console.

Additional resources

Creating an instance by using a custom image.

Create an instance by using the wizard.

80
CHAPTER 2. PERFORMING AN AUTOMATED INSTALLATION USING KICKSTART

CHAPTER 2. PERFORMING AN AUTOMATED INSTALLATION


USING KICKSTART

81
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 3. ADVANCED CONFIGURATION OPTIONS

82
CHAPTER 4. KICKSTART REFERENCES

CHAPTER 4. KICKSTART REFERENCES

83
Red Hat Enterprise Linux 8 System Design Guide

PART II. DESIGN OF SECURITY

84
CHAPTER 5. SECURING RHEL DURING AND RIGHT AFTER INSTALLATION

CHAPTER 5. SECURING RHEL DURING AND RIGHT AFTER


INSTALLATION
Security begins even before you start the installation of Red Hat Enterprise Linux. Configuring your
system securely from the beginning makes it easier to implement additional security settings later.

5.1. DISK PARTITIONING


The recommended practices for disk partitioning differ for installations on bare-metal machines and for
virtualized or cloud environments that support adjusting virtual disk hardware and file systems
containing already-installed operating systems.

To ensure separation and protection of data on bare-metal installations, create separate partitions for
the /boot, /, /home, /tmp, and /var/tmp/ directories:

/boot
This partition is the first partition that is read by the system during boot up. The boot loader and
kernel images that are used to boot your system into Red Hat Enterprise Linux 8 are stored in this
partition. This partition should not be encrypted. If this partition is included in / and that partition is
encrypted or otherwise becomes unavailable then your system is not able to boot.
/home
When user data (/home) is stored in / instead of in a separate partition, the partition can fill up
causing the operating system to become unstable. Also, when upgrading your system to the next
version of Red Hat Enterprise Linux 8 it is a lot easier when you can keep your data in the /home
partition as it is not be overwritten during installation. If the root partition (/) becomes corrupt your
data could be lost forever. By using a separate partition there is slightly more protection against data
loss. You can also target this partition for frequent backups.
/tmp and /var/tmp/
Both the /tmp and /var/tmp/ directories are used to store data that does not need to be stored for a
long period of time. However, if a lot of data floods one of these directories it can consume all of your
storage space. If this happens and these directories are stored within / then your system could
become unstable and crash. For this reason, moving these directories into their own partitions is a
good idea.

For virtual machines or cloud instances, the separate /boot, /home, /tmp, and /var/tmp partitions are
optional because you can increase the virtual disk size and the / partition if it begins to fill up. Set up
monitoring to regularly check the / partition usage so that it does not fill up before you increase the
virtual disk size accordingly.

NOTE

During the installation process, you have an option to encrypt partitions. You must supply
a passphrase. This passphrase serves as a key to unlock the bulk encryption key, which is
used to secure the partition’s data.

5.2. RESTRICTING NETWORK CONNECTIVITY DURING THE


INSTALLATION PROCESS
When installing Red Hat Enterprise Linux 8, the installation medium represents a snapshot of the system
at a particular time. Because of this, it may not be up-to-date with the latest security fixes and may be
vulnerable to certain issues that were fixed only after the system provided by the installation medium
was released.

85
Red Hat Enterprise Linux 8 System Design Guide

When installing a potentially vulnerable operating system, always limit exposure only to the closest
necessary network zone. The safest choice is the “no network” zone, which means to leave your machine
disconnected during the installation process. In some cases, a LAN or intranet connection is sufficient
while the Internet connection is the riskiest. To follow the best security practices, choose the closest
zone with your repository while installing Red Hat Enterprise Linux 8 from a network.

5.3. INSTALLING THE MINIMUM AMOUNT OF PACKAGES REQUIRED


It is best practice to install only the packages you will use because each piece of software on your
computer could possibly contain a vulnerability. If you are installing from the DVD media, take the
opportunity to select exactly what packages you want to install during the installation. If you find you
need another package, you can always add it to the system later.

5.4. POST-INSTALLATION PROCEDURES


The following steps are the security-related procedures that should be performed immediately after
installation of Red Hat Enterprise Linux 8.

Update your system. Enter the following command as root:

# yum update

Even though the firewall service, firewalld, is automatically enabled with the installation of
Red Hat Enterprise Linux, it might be explicitly disabled, for example, in the Kickstart
configuration. In such a case, re-enable the firewall.
To start firewalld enter the following commands as root:

# systemctl start firewalld


# systemctl enable firewalld

To enhance security, disable services you do not need. For example, if no printers are installed
on your computer, disable the cups service by using the following command:

# systemctl disable cups

To review active services, enter the following command:

$ systemctl list-units | grep service

5.5. DISABLING SMT TO PREVENT CPU SECURITY ISSUES BY USING


THE WEB CONSOLE
Disable Simultaneous Multi Threading (SMT) in case of attacks that misuse CPU SMT. Disabling SMT
can mitigate security vulnerabilities, such as L1TF or MDS.

IMPORTANT

Disabling SMT might lower the system performance.

Prerequisites

You have installed the RHEL 8 web console.

86
CHAPTER 5. SECURING RHEL DURING AND RIGHT AFTER INSTALLATION

For instructions, see Installing and enabling the web console .

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. In the Overview tab find the System information field and click View hardware details.

3. On the CPU Security line, click Mitigations.


If this link is not present, it means that your system does not support SMT, and therefore is not
vulnerable.

4. In the CPU Security Toggles table, turn on the Disable simultaneous multithreading (nosmt)
option.

5. Click the Save and reboot button.

After the system restart, the CPU no longer uses SMT.

Additional resources

L1TF - L1 Terminal Fault Attack - CVE-2018-3620 & CVE-2018-3646

MDS - Microarchitectural Data Sampling - CVE-2018-12130, CVE-2018-12126, CVE-2018-12127,


and CVE-2019-11091

87
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 6. USING SYSTEM-WIDE CRYPTOGRAPHIC


POLICIES
The system-wide cryptographic policies is a system component that configures the core cryptographic
subsystems, covering the TLS, IPsec, SSH, DNSSec, and Kerberos protocols. It provides a small set of
policies, which the administrator can select.

6.1. SYSTEM-WIDE CRYPTOGRAPHIC POLICIES


When a system-wide policy is set up, applications in RHEL follow it and refuse to use algorithms and
protocols that do not meet the policy, unless you explicitly request the application to do so. That is, the
policy applies to the default behavior of applications when running with the system-provided
configuration but you can override it if required.

RHEL 8 contains the following predefined policies:

DEFAULT
The default system-wide cryptographic policy level offers secure settings for current threat models.
It allows the TLS 1.2 and 1.3 protocols, as well as the IKEv2 and SSH2 protocols. The RSA keys and
Diffie-Hellman parameters are accepted if they are at least 2048 bits long.
LEGACY
Ensures maximum compatibility with Red Hat Enterprise Linux 5 and earlier; it is less secure due to an
increased attack surface. In addition to the DEFAULT level algorithms and protocols, it includes
support for the TLS 1.0 and 1.1 protocols. The algorithms DSA, 3DES, and RC4 are allowed, while RSA
keys and Diffie-Hellman parameters are accepted if they are at least 1023 bits long.
FUTURE
A stricter forward-looking security level intended for testing a possible future policy. This policy does
not allow the use of SHA-1 in signature algorithms. It allows the TLS 1.2 and 1.3 protocols, as well as
the IKEv2 and SSH2 protocols. The RSA keys and Diffie-Hellman parameters are accepted if they are
at least 3072 bits long. If your system communicates on the public internet, you might face
interoperability problems.

IMPORTANT

Because a cryptographic key used by a certificate on the Customer Portal API does
not meet the requirements by the FUTURE system-wide cryptographic policy, the
redhat-support-tool utility does not work with this policy level at the moment.

To work around this problem, use the DEFAULT cryptographic policy while connecting
to the Customer Portal API.

FIPS
Conforms with the FIPS 140 requirements. The fips-mode-setup tool, which switches the RHEL
system into FIPS mode, uses this policy internally. Switching to the FIPS policy does not guarantee
compliance with the FIPS 140 standard. You also must re-generate all cryptographic keys after you
set the system to FIPS mode. This is not possible in many scenarios.
RHEL also provides the FIPS:OSPP system-wide subpolicy, which contains further restrictions for
cryptographic algorithms required by the Common Criteria (CC) certification. The system becomes
less interoperable after you set this subpolicy. For example, you cannot use RSA and DH keys
shorter than 3072 bits, additional SSH algorithms, and several TLS groups. Setting FIPS:OSPP also
prevents connecting to Red Hat Content Delivery Network (CDN) structure. Furthermore, you

88
CHAPTER 6. USING SYSTEM-WIDE CRYPTOGRAPHIC POLICIES

cannot integrate Active Directory (AD) into the IdM deployments that use FIPS:OSPP,
communication between RHEL hosts using FIPS:OSPP and AD domains might not work, or some AD
accounts might not be able to authenticate.

NOTE

Your system is not CC-compliant after you set the FIPS:OSPP cryptographic
subpolicy. The only correct way to make your RHEL system compliant with the CC
standard is by following the guidance provided in the cc-config package. See the
Common Criteria section in the Compliance Activities and Government Standards
Knowledgebase article for a list of certified RHEL versions, validation reports, and
links to CC guides.

Red Hat continuously adjusts all policy levels so that all libraries provide secure defaults, except when
using the LEGACY policy. Even though the LEGACY profile does not provide secure defaults, it does
not include any algorithms that are easily exploitable. As such, the set of enabled algorithms or
acceptable key sizes in any provided policy may change during the lifetime of Red Hat Enterprise Linux.

Such changes reflect new security standards and new security research. If you must ensure
interoperability with a specific system for the whole lifetime of Red Hat Enterprise Linux, you should
opt-out from the system-wide cryptographic policies for components that interact with that system or
re-enable specific algorithms using custom cryptographic policies.

The specific algorithms and ciphers described as allowed in the policy levels are available only if an
application supports them:

Table 6.1. Cipher suites and protocols enabled in the cryptographic policies

LEGACY DEFAULT FIPS FUTURE

IKEv1 no no no no

3DES yes no no no

RC4 yes no no no

DH min. 1024-bit min. 2048-bit min. 2048-bit[a] min. 3072-bit

RSA min. 1024-bit min. 2048-bit min. 2048-bit min. 3072-bit

DSA yes no no no

TLS v1.0 yes no no no

TLS v1.1 yes no no no

SHA-1 in digital yes yes no no


signatures

89
Red Hat Enterprise Linux 8 System Design Guide

LEGACY DEFAULT FIPS FUTURE

CBC mode yes yes yes no[b]


ciphers

Symmetric yes yes yes no


ciphers with keys
< 256 bits

SHA-1 and SHA- yes yes yes no


224 signatures in
certificates

[a] You can use only Diffie-Hellman groups defined in RFC 7919 and RFC 3526.

[b] CBC ciphers are disabled for TLS. In a non-TLS scenario, AES-128-CBC is disabled but AES-256-CBC is
enabled. To disable also AES-256-CBC, apply a custom subpolicy.

Additional resources

crypto-policies(7) and update-crypto-policies(8) man pages on your system

6.2. CHANGING THE SYSTEM-WIDE CRYPTOGRAPHIC POLICY


You can change the system-wide cryptographic policy on your system by using the update-crypto-
policies tool and restarting your system.

Prerequisites

You have root privileges on the system.

Procedure

1. Optional: Display the current cryptographic policy:

$ update-crypto-policies --show
DEFAULT

2. Set the new cryptographic policy:

# update-crypto-policies --set <POLICY>


<POLICY>

Replace <POLICY> with the policy or subpolicy you want to set, for example FUTURE,
LEGACY or FIPS:OSPP.

3. Restart the system:

# reboot

90
CHAPTER 6. USING SYSTEM-WIDE CRYPTOGRAPHIC POLICIES

Verification

Display the current cryptographic policy:

$ update-crypto-policies --show
<POLICY>

Additional resources

For more information on system-wide cryptographic policies, see System-wide cryptographic


policies

6.3. SWITCHING THE SYSTEM-WIDE CRYPTOGRAPHIC POLICY TO


MODE COMPATIBLE WITH EARLIER RELEASES
The default system-wide cryptographic policy in Red Hat Enterprise Linux 8 does not allow
communication using older, insecure protocols. For environments that require to be compatible with
Red Hat Enterprise Linux 6 and in some cases also with earlier releases, the less secure LEGACY policy
level is available.


WARNING

Switching to the LEGACY policy level results in a less secure system and
applications.

Procedure

1. To switch the system-wide cryptographic policy to the LEGACY level, enter the following
command as root:

# update-crypto-policies --set LEGACY


Setting system policy to LEGACY

Additional resources

For the list of available cryptographic policy levels, see the update-crypto-policies(8) man
page on your system.

For defining custom cryptographic policies, see the Custom Policies section in the update-
crypto-policies(8) man page and the Crypto Policy Definition Format section in the crypto-
policies(7) man page on your system.

6.4. SETTING UP SYSTEM-WIDE CRYPTOGRAPHIC POLICIES IN THE


WEB CONSOLE
You can set one of system-wide cryptographic policies and subpolicies directly in the RHEL web
console interface. Besides the four predefined system-wide cryptographic policies, you can also apply
the following combinations of policies and subpolicies through the graphical interface now:

91
Red Hat Enterprise Linux 8 System Design Guide

DEFAULT:SHA1
The DEFAULT policy with the SHA-1 algorithm enabled.
LEGACY:AD-SUPPORT
The LEGACY policy with less secure settings that improve interoperability for Active Directory
services.
FIPS:OSPP
The FIPS policy with further restrictions required by the Common Criteria for Information
Technology Security Evaluation standard.


WARNING

Because the FIPS:OSPP system-wide subpolicy contains further restrictions for


cryptographic algorithms required by the Common Criteria (CC) certification, the
system is less interoperable after you set it. For example, you cannot use RSA and
DH keys shorter than 3072 bits, additional SSH algorithms, and several TLS groups.
Setting FIPS:OSPP also prevents connecting to Red Hat Content Delivery Network
(CDN) structure. Furthermore, you cannot integrate Active Directory (AD) into the
IdM deployments that use FIPS:OSPP, communication between RHEL hosts using
FIPS:OSPP and AD domains might not work, or some AD accounts might not be
able to authenticate.

Note that your system is not CC-compliant after you set the FIPS:OSPP
cryptographic subpolicy. The only correct way to make your RHEL system compliant
with the CC standard is by following the guidance provided in the cc-config
package. See the Common Criteria section in the Compliance Activities and
Government Standards Knowledgebase article for a list of certified RHEL versions,
validation reports, and links to CC guides hosted at the National Information
Assurance Partnership (NIAP) website.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

You have root privileges or permissions to enter administrative commands with sudo.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. In the Configuration card of the Overview page, click your current policy value next to Crypto
policy.

92
CHAPTER 6. USING SYSTEM-WIDE CRYPTOGRAPHIC POLICIES

3. In the Change crypto policy dialog window, click on the policy you want to start using on your
system.

4. Click the Apply and reboot button.

Verification

After the restart, log back in to web console, and check that the Crypto policy value
corresponds to the one you selected.
Alternatively, you can enter the update-crypto-policies --show command to display the current
system-wide cryptographic policy in your terminal.

6.5. EXCLUDING AN APPLICATION FROM FOLLOWING SYSTEM-WIDE


CRYPTO POLICIES

93
Red Hat Enterprise Linux 8 System Design Guide

You can customize cryptographic settings used by your application preferably by configuring supported
cipher suites and protocols directly in the application.

You can also remove a symlink related to your application from the /etc/crypto-policies/back-ends
directory and replace it with your customized cryptographic settings. This configuration prevents the
use of system-wide cryptographic policies for applications that use the excluded back end.
Furthermore, this modification is not supported by Red Hat.

6.5.1. Examples of opting out of system-wide crypto policies

wget
To customize cryptographic settings used by the wget network downloader, use --secure-protocol and
--ciphers options. For example:

$ wget --secure-protocol=TLSv1_1 --ciphers="SECURE128" https://example.com

See the HTTPS (SSL/TLS) Options section of the wget(1) man page for more information.

curl
To specify ciphers used by the curl tool, use the --ciphers option and provide a colon-separated list of
ciphers as a value. For example:

$ curl https://example.com --ciphers '@SECLEVEL=0:DES-CBC3-SHA:RSA-DES-CBC3-SHA'

See the curl(1) man page for more information.

Firefox
Even though you cannot opt out of system-wide cryptographic policies in the Firefox web browser, you
can further restrict supported ciphers and TLS versions in Firefox’s Configuration Editor. Type
about:config in the address bar and change the value of the security.tls.version.min option as
required. Setting security.tls.version.min to 1 allows TLS 1.0 as the minimum required,
security.tls.version.min 2 enables TLS 1.1, and so on.

OpenSSH
To opt out of the system-wide cryptographic policies for your OpenSSH server, uncomment the line
with the CRYPTO_POLICY= variable in the /etc/sysconfig/sshd file. After this change, values that you
specify in the Ciphers, MACs, KexAlgoritms, and GSSAPIKexAlgorithms sections in the
/etc/ssh/sshd_config file are not overridden.

See the sshd_config(5) man page for more information.

To opt out of system-wide cryptographic policies for your OpenSSH client, perform one of the following
tasks:

For a given user, override the global ssh_config with a user-specific configuration in the
~/.ssh/config file.

For the entire system, specify the cryptographic policy in a drop-in configuration file located in
the /etc/ssh/ssh_config.d/ directory, with a two-digit number prefix smaller than 5, so that it
lexicographically precedes the 05-redhat.conf file, and with a .conf suffix, for example, 04-
crypto-policy-override.conf.

See the ssh_config(5) man page for more information.

94
CHAPTER 6. USING SYSTEM-WIDE CRYPTOGRAPHIC POLICIES

Libreswan
See the Configuring IPsec connections that opt out of the system-wide crypto policies in the Securing
networks document for detailed information.

Additional resources

update-crypto-policies(8) man page on your system

6.6. CUSTOMIZING SYSTEM-WIDE CRYPTOGRAPHIC POLICIES WITH


SUBPOLICIES
Use this procedure to adjust the set of enabled cryptographic algorithms or protocols.

You can either apply custom subpolicies on top of an existing system-wide cryptographic policy or
define such a policy from scratch.

The concept of scoped policies allows enabling different sets of algorithms for different back ends. You
can limit each configuration directive to specific protocols, libraries, or services.

Furthermore, directives can use asterisks for specifying multiple values using wildcards.

The /etc/crypto-policies/state/CURRENT.pol file lists all settings in the currently applied system-wide
cryptographic policy after wildcard expansion. To make your cryptographic policy more strict, consider
using values listed in the /usr/share/crypto-policies/policies/FUTURE.pol file.

You can find example subpolicies in the /usr/share/crypto-policies/policies/modules/ directory. The


subpolicy files in this directory contain also descriptions in lines that are commented out.

NOTE

Customization of system-wide cryptographic policies is available from RHEL 8.2. You can
use the concept of scoped policies and the option of using wildcards in RHEL 8.5 and
newer.

Procedure

1. Checkout to the /etc/crypto-policies/policies/modules/ directory:

# cd /etc/crypto-policies/policies/modules/

2. Create subpolicies for your adjustments, for example:

# touch MYCRYPTO-1.pmod
# touch SCOPES-AND-WILDCARDS.pmod

IMPORTANT

Use upper-case letters in file names of policy modules.

3. Open the policy modules in a text editor of your choice and insert options that modify the
system-wide cryptographic policy, for example:

95
Red Hat Enterprise Linux 8 System Design Guide

# vi MYCRYPTO-1.pmod

min_rsa_size = 3072
hash = SHA2-384 SHA2-512 SHA3-384 SHA3-512

# vi SCOPES-AND-WILDCARDS.pmod

# Disable the AES-128 cipher, all modes


cipher = -AES-128-*

# Disable CHACHA20-POLY1305 for the TLS protocol (OpenSSL, GnuTLS, NSS, and
OpenJDK)
cipher@TLS = -CHACHA20-POLY1305

# Allow using the FFDHE-1024 group with the SSH protocol (libssh and OpenSSH)
group@SSH = FFDHE-1024+

# Disable all CBC mode ciphers for the SSH protocol (libssh and OpenSSH)
cipher@SSH = -*-CBC

# Allow the AES-256-CBC cipher in applications using libssh


cipher@libssh = AES-256-CBC+

4. Save the changes in the module files.

5. Apply your policy adjustments to the DEFAULT system-wide cryptographic policy level:

# update-crypto-policies --set DEFAULT:MYCRYPTO-1:SCOPES-AND-WILDCARDS

6. To make your cryptographic settings effective for already running services and applications,
restart the system:

# reboot

Verification

Check that the /etc/crypto-policies/state/CURRENT.pol file contains your changes, for


example:

$ cat /etc/crypto-policies/state/CURRENT.pol | grep rsa_size


min_rsa_size = 3072

Additional resources

Custom Policies section in the update-crypto-policies(8) man page on your system

Crypto Policy Definition Format section in the crypto-policies(7) man page on your system

How to customize crypto policies in RHEL 8.2 Red Hat blog article

6.7. DISABLING SHA-1 BY CUSTOMIZING A SYSTEM-WIDE


96
CHAPTER 6. USING SYSTEM-WIDE CRYPTOGRAPHIC POLICIES

6.7. DISABLING SHA-1 BY CUSTOMIZING A SYSTEM-WIDE


CRYPTOGRAPHIC POLICY
Because the SHA-1 hash function has an inherently weak design, and advancing cryptanalysis has made it
vulnerable to attacks, RHEL 8 does not use SHA-1 by default. Nevertheless, some third-party
applications, for example, public signatures, still use SHA-1. To disable the use of SHA-1 in signature
algorithms on your system, you can use the NO-SHA1 policy module.

IMPORTANT

The NO-SHA1 policy module disables the SHA-1 hash function only in signatures and not
elsewhere. In particular, the NO-SHA1 module still allows the use of SHA-1 with hash-
based message authentication codes (HMAC). This is because HMAC security properties
do not rely on the collision resistance of the corresponding hash function, and therefore
the recent attacks on SHA-1 have a significantly lower impact on the use of SHA-1 for
HMAC.

If your scenario requires disabling a specific key exchange (KEX) algorithm combination, for example,
diffie-hellman-group-exchange-sha1, but you still want to use both the relevant KEX and the algorithm
in other combinations, see Steps to disable the diffie-hellman-group1-sha1 algorithm in SSH for
instructions on opting out of system-wide crypto-policies for SSH and configuring SSH directly.

NOTE

The module for disabling SHA-1 is available from RHEL 8.3. Customization of system-
wide cryptographic policies is available from RHEL 8.2.

Procedure

1. Apply your policy adjustments to the DEFAULT system-wide cryptographic policy level:

# update-crypto-policies --set DEFAULT:NO-SHA1

2. To make your cryptographic settings effective for already running services and applications,
restart the system:

# reboot

Additional resources

Custom Policies section in the update-crypto-policies(8) man page on your system

Crypto Policy Definition Format section in the crypto-policies(7) man page on your system

How to customize crypto policies in RHEL Red Hat blog article.

6.8. CREATING AND SETTING A CUSTOM SYSTEM-WIDE


CRYPTOGRAPHIC POLICY
For specific scenarios, you can customize the system-wide cryptographic policy by creating and using a
complete policy file.

NOTE
97
Red Hat Enterprise Linux 8 System Design Guide

NOTE

Customization of system-wide cryptographic policies is available from RHEL 8.2.

Procedure

1. Create a policy file for your customizations:

# cd /etc/crypto-policies/policies/
# touch MYPOLICY.pol

Alternatively, start by copying one of the four predefined policy levels:

# cp /usr/share/crypto-policies/policies/DEFAULT.pol /etc/crypto-
policies/policies/MYPOLICY.pol

2. Edit the file with your custom cryptographic policy in a text editor of your choice to fit your
requirements, for example:

# vi /etc/crypto-policies/policies/MYPOLICY.pol

3. Switch the system-wide cryptographic policy to your custom level:

# update-crypto-policies --set MYPOLICY

4. To make your cryptographic settings effective for already running services and applications,
restart the system:

# reboot

Additional resources

Custom Policies section in the update-crypto-policies(8) man page and the Crypto Policy
Definition Format section in the crypto-policies(7) man page on your system

How to customize crypto policies in RHEL Red Hat blog article

6.9. ENHANCING SECURITY WITH THE FUTURE CRYPTOGRAPHIC


POLICY USING THE CRYPTO_POLICIES RHEL SYSTEM ROLE
You can use the crypto_policies RHEL system role to configure the FUTURE policy on your managed
nodes. This policy helps to achieve for example:

Future-proofing against emerging threats: anticipates advancements in computational power.

Enhanced security: stronger encryption standards require longer key lengths and more secure
algorithms.

Compliance with high-security standards: for example in healthcare, telco, and finance the data
sensitivity is high, and availability of strong cryptography is critical.

Typically, FUTURE is suitable for environments handling highly sensitive data, preparing for future
regulations, or adopting long-term security strategies.

98
CHAPTER 6. USING SYSTEM-WIDE CRYPTOGRAPHIC POLICIES


WARNING

Legacy systems or software does not have to support the more modern and stricter
algorithms and protocols enforced by the FUTURE policy. For example, older
systems might not support TLS 1.3 or larger key sizes. This could lead to
compatibility problems.

Also, using strong algorithms usually increases the computational workload, which
could negatively affect your system performance.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Configure cryptographic policies
hosts: managed-node-01.example.com
tasks:
- name: Configure the FUTURE cryptographic security policy on the managed node
ansible.builtin.include_role:
name: rhel-system-roles.crypto_policies
vars:
- crypto_policies_policy: FUTURE
- crypto_policies_reboot_ok: true

The settings specified in the example playbook include the following:

crypto_policies_policy: FUTURE
Configures the required cryptographic policy (FUTURE) on the managed node. It can be
either the base policy or a base policy with some sub-policies. The specified base policy and
sub-policies have to be available on the managed node. The default value is null. It means
that the configuration is not changed and the crypto_policies RHEL system role will only
collect the Ansible facts.
crypto_policies_reboot_ok: true
Causes the system to reboot after the cryptographic policy change to make sure all of the
services and applications will read the new configuration files. The default value is false.

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.crypto_policies/README.md file on the control node.

2. Validate the playbook syntax:

99
Red Hat Enterprise Linux 8 System Design Guide

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml


WARNING

Because the FIPS:OSPP system-wide subpolicy contains further restrictions for


cryptographic algorithms required by the Common Criteria (CC) certification, the
system is less interoperable after you set it. For example, you cannot use RSA and
DH keys shorter than 3072 bits, additional SSH algorithms, and several TLS groups.
Setting FIPS:OSPP also prevents connecting to Red Hat Content Delivery Network
(CDN) structure. Furthermore, you cannot integrate Active Directory (AD) into the
IdM deployments that use FIPS:OSPP, communication between RHEL hosts using
FIPS:OSPP and AD domains might not work, or some AD accounts might not be
able to authenticate.

Note that your system is not CC-compliant after you set the FIPS:OSPP
cryptographic subpolicy. The only correct way to make your RHEL system compliant
with the CC standard is by following the guidance provided in the cc-config
package. See the Common Criteria section in the Compliance Activities and
Government Standards Knowledgebase article for a list of certified RHEL versions,
validation reports, and links to CC guides hosted at the National Information
Assurance Partnership (NIAP) website.

Verification

1. On the control node, create another playbook named, for example, verify_playbook.yml:

---
- name: Verification
hosts: managed-node-01.example.com
tasks:
- name: Verify active cryptographic policy
ansible.builtin.include_role:
name: rhel-system-roles.crypto_policies
- name: Display the currently active cryptographic policy
ansible.builtin.debug:
var: crypto_policies_active

The settings specified in the example playbook include the following:

crypto_policies_active
An exported Ansible fact that contains the currently active policy name in the format as
accepted by the crypto_policies_policy variable.

100
CHAPTER 6. USING SYSTEM-WIDE CRYPTOGRAPHIC POLICIES

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/verify_playbook.yml

3. Run the playbook:

$ ansible-playbook ~/verify_playbook.yml
TASK [debug] **************************
ok: [host] => {
"crypto_policies_active": "FUTURE"
}

The crypto_policies_active variable shows the active policy on the managed node.

Additional resources

/usr/share/ansible/roles/rhel-system-roles.crypto_policies/README.md file

/usr/share/doc/rhel-system-roles/crypto_policies/ directory

update-crypto-policies(8) and crypto-policies(7) manual pages

6.10. ADDITIONAL RESOURCES


System-wide crypto policies in RHEL 8 and Strong crypto defaults in RHEL 8 and deprecation
of weak crypto algorithms Knowledgebase articles

101
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 7. CONFIGURING APPLICATIONS TO USE


CRYPTOGRAPHIC HARDWARE THROUGH PKCS #11
Separating parts of your secret information about dedicated cryptographic devices, such as smart cards
and cryptographic tokens for end-user authentication and hardware security modules (HSM) for server
applications, provides an additional layer of security. In RHEL, support for cryptographic hardware
through the PKCS #11 API is consistent across different applications, and the isolation of secrets on
cryptographic hardware is not a complicated task.

7.1. CRYPTOGRAPHIC HARDWARE SUPPORT THROUGH PKCS #11


Public-Key Cryptography Standard (PKCS) #11 defines an application programming interface (API) to
cryptographic devices that hold cryptographic information and perform cryptographic functions.

PKCS #11 introduces the cryptographic token, an object that presents each hardware or software device
to applications in a unified manner. Therefore, applications view devices such as smart cards, which are
typically used by persons, and hardware security modules, which are typically used by computers, as
PKCS #11 cryptographic tokens.

A PKCS #11 token can store various object types including a certificate; a data object; and a public,
private, or secret key. These objects are uniquely identifiable through the PKCS #11 Uniform Resource
Identifier (URI) scheme.

A PKCS #11 URI is a standard way to identify a specific object in a PKCS #11 module according to the
object attributes. This enables you to configure all libraries and applications with the same configuration
string in the form of a URI.

RHEL provides the OpenSC PKCS #11 driver for smart cards by default. However, hardware tokens and
HSMs can have their own PKCS #11 modules that do not have their counterpart in the system. You can
register such PKCS #11 modules with the p11-kit tool, which acts as a wrapper over the registered smart-
card drivers in the system.

To make your own PKCS #11 module work on the system, add a new text file to the
/etc/pkcs11/modules/ directory

You can add your own PKCS #11 module into the system by creating a new text file in the
/etc/pkcs11/modules/ directory. For example, the OpenSC configuration file in p11-kit looks as follows:

$ cat /usr/share/p11-kit/modules/opensc.module
module: opensc-pkcs11.so

Additional resources

Consistent PKCS #11 support in Red Hat Enterprise Linux 8

The PKCS #11 URI Scheme

Controlling access to smart cards

7.2. AUTHENTICATING BY SSH KEYS STORED ON A SMART CARD


You can create and store ECDSA and RSA keys on a smart card and authenticate by the smart card on
an OpenSSH client. Smart-card authentication replaces the default password authentication.

102
CHAPTER 7. CONFIGURING APPLICATIONS TO USE CRYPTOGRAPHIC HARDWARE THROUGH PKCS #11

Prerequisites

On the client side, the opensc package is installed and the pcscd service is running.

Procedure

1. List all keys provided by the OpenSC PKCS #11 module including their PKCS #11 URIs and save
the output to the keys.pub file:

$ ssh-keygen -D pkcs11: > keys.pub

2. Transfer the public key to the remote server. Use the ssh-copy-id command with the keys.pub
file created in the previous step:

$ ssh-copy-id -f -i keys.pub <[email protected]>

3. Connect to <ssh-server-example.com> by using the ECDSA key. You can use just a subset of the
URI, which uniquely references your key, for example:

$ ssh -i "pkcs11:id=%01?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so" <ssh-server-


example.com>
Enter PIN for 'SSH key':
[ssh-server-example.com] $

Because OpenSSH uses the p11-kit-proxy wrapper and the OpenSC PKCS #11 module is
registered to the p11-kit tool, you can simplify the previous command:

$ ssh -i "pkcs11:id=%01" <ssh-server-example.com>


Enter PIN for 'SSH key':
[ssh-server-example.com] $

If you skip the id= part of a PKCS #11 URI, OpenSSH loads all keys that are available in the proxy
module. This can reduce the amount of typing required:

$ ssh -i pkcs11: <ssh-server-example.com>


Enter PIN for 'SSH key':
[ssh-server-example.com] $

4. Optional: You can use the same URI string in the ~/.ssh/config file to make the configuration
permanent:

$ cat ~/.ssh/config
IdentityFile "pkcs11:id=%01?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so"
$ ssh <ssh-server-example.com>
Enter PIN for 'SSH key':
[ssh-server-example.com] $

The ssh client utility now automatically uses this URI and the key from the smart card.

Additional resources

p11-kit(8), opensc.conf(5), pcscd(8), ssh(1), and ssh-keygen(1) man pages on your system

103
Red Hat Enterprise Linux 8 System Design Guide

7.3. CONFIGURING APPLICATIONS FOR AUTHENTICATION WITH


CERTIFICATES ON SMART CARDS
Authentication by using smart cards in applications may increase security and simplify automation. You
can integrate the Public Key Cryptography Standard (PKCS) #11 URIs into your application by using the
following methods:

The Firefox web browser automatically loads the p11-kit-proxy PKCS #11 module. This means
that every supported smart card in the system is automatically detected. For using TLS client
authentication, no additional setup is required and keys and certificates from a smart card are
automatically used when a server requests them.

If your application uses the GnuTLS or NSS library, it already supports PKCS #11 URIs. Also,
applications that rely on the OpenSSL library can access cryptographic hardware modules,
including smart cards, through the pkcs11 engine provided by the openssl-pkcs11 package.

Applications that require working with private keys on smart cards and that do not use NSS,
GnuTLS, nor OpenSSL can use the p11-kit API directly to work with cryptographic hardware
modules, including smart cards, rather than using the PKCS #11 API of specific PKCS #11
modules.

With the the wget network downloader, you can specify PKCS #11 URIs instead of paths to
locally stored private keys and certificates. This might simplify creation of scripts for tasks that
require safely stored private keys and certificates. For example:

$ wget --private-key 'pkcs11:token=softhsm;id=%01;type=private?pin-value=111111' --


certificate 'pkcs11:token=softhsm;id=%01;type=cert' https://example.com/

You can also specify PKCS #11 URI when using the curl tool:

$ curl --key 'pkcs11:token=softhsm;id=%01;type=private?pin-value=111111' --cert


'pkcs11:token=softhsm;id=%01;type=cert' https://example.com/

Additional resources

curl(1), wget(1), and p11-kit(8) man pages on your system

7.4. USING HSMS PROTECTING PRIVATE KEYS IN APACHE


The Apache HTTP server can work with private keys stored on hardware security modules (HSMs),
which helps to prevent the keys' disclosure and man-in-the-middle attacks. Note that this usually
requires high-performance HSMs for busy servers.

For secure communication in the form of the HTTPS protocol, the Apache HTTP server (httpd) uses
the OpenSSL library. OpenSSL does not support PKCS #11 natively. To use HSMs, you have to install the
openssl-pkcs11 package, which provides access to PKCS #11 modules through the engine interface.
You can use a PKCS #11 URI instead of a regular file name to specify a server key and a certificate in the
/etc/httpd/conf.d/ssl.conf configuration file, for example:

SSLCertificateFile "pkcs11:id=%01;token=softhsm;type=cert"
SSLCertificateKeyFile "pkcs11:id=%01;token=softhsm;type=private?pin-value=111111"

Install the httpd-manual package to obtain complete documentation for the Apache HTTP Server,

104
CHAPTER 7. CONFIGURING APPLICATIONS TO USE CRYPTOGRAPHIC HARDWARE THROUGH PKCS #11

Install the httpd-manual package to obtain complete documentation for the Apache HTTP Server,
including TLS configuration. The directives available in the /etc/httpd/conf.d/ssl.conf configuration file
are described in detail in the /usr/share/httpd/manual/mod/mod_ssl.html file.

7.5. USING HSMS PROTECTING PRIVATE KEYS IN NGINX


The Nginx HTTP server can work with private keys stored on hardware security modules (HSMs), which
helps to prevent the keys' disclosure and man-in-the-middle attacks. Note that this usually requires
high-performance HSMs for busy servers.

Because Nginx also uses the OpenSSL for cryptographic operations, support for PKCS #11 must go
through the openssl-pkcs11 engine. Nginx currently supports only loading private keys from an HSM,
and a certificate must be provided separately as a regular file. Modify the ssl_certificate and
ssl_certificate_key options in the server section of the /etc/nginx/nginx.conf configuration file:

ssl_certificate /path/to/cert.pem
ssl_certificate_key "engine:pkcs11:pkcs11:token=softhsm;id=%01;type=private?pin-value=111111";

Note that the engine:pkcs11: prefix is needed for the PKCS #11 URI in the Nginx configuration file.
This is because the other pkcs11 prefix refers to the engine name.

7.6. ADDITIONAL RESOURCES


pkcs11.conf(5) man page on your system

105
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 8. USING SHARED SYSTEM CERTIFICATES


The shared system certificates storage enables NSS, GnuTLS, OpenSSL, and Java to share a default
source for retrieving system certificate anchors and block-list information. By default, the truststore
contains the Mozilla CA list, including positive and negative trust. The system allows updating the core
Mozilla CA list or choosing another certificate list.

8.1. THE SYSTEM-WIDE TRUSTSTORE


In RHEL, the consolidated system-wide truststore is located in the /etc/pki/ca-trust/ and
/usr/share/pki/ca-trust-source/ directories. The trust settings in /usr/share/pki/ca-trust-source/ are
processed with lower priority than settings in /etc/pki/ca-trust/.

Certificate files are treated depending on the subdirectory they are installed to. For example, trust
anchors belong to the /usr/share/pki/ca-trust-source/anchors/ or /etc/pki/ca-trust/source/anchors/
directory.

NOTE

In a hierarchical cryptographic system, a trust anchor is an authoritative entity that other


parties consider trustworthy. In the X.509 architecture, a root certificate is a trust anchor
from which a chain of trust is derived. To enable chain validation, the trusting party must
have access to the trust anchor first.

Additional resources

update-ca-trust(8) and trust(1) man pages on your system

8.2. ADDING NEW CERTIFICATES


To acknowledge applications on your system with a new source of trust, add the corresponding
certificate to the system-wide store, and use the update-ca-trust command.

Prerequisites

The ca-certificates package is present on the system.

Procedure

1. To add a certificate in the simple PEM or DER file formats to the list of CAs trusted on the
system, copy the certificate file to the /usr/share/pki/ca-trust-source/anchors/ or /etc/pki/ca-
trust/source/anchors/ directory, for example:

# cp ~/certificate-trust-examples/Cert-trust-test-ca.pem /usr/share/pki/ca-trust-
source/anchors/

2. To update the system-wide trust store configuration, use the update-ca-trust command:

# update-ca-trust extract

NOTE
106
CHAPTER 8. USING SHARED SYSTEM CERTIFICATES

NOTE

Even though the Firefox browser can use an added certificate without a prior execution
of update-ca-trust, enter the update-ca-trust command after every CA change. Also
note that browsers, such as Firefox, Chromium, and GNOME Web cache files, and you
might have to clear your browser’s cache or restart your browser to load the current
system certificate configuration.

Additional resources

update-ca-trust(8) and trust(1) man pages on your system

8.3. MANAGING TRUSTED SYSTEM CERTIFICATES


The trust command provides a convenient way for managing certificates in the shared system-wide
truststore.

To list, extract, add, remove, or change trust anchors, use the trust command. To see the built-
in help for this command, enter it without any arguments or with the --help directive:

$ trust
usage: trust command <args>...

Common trust commands are:


list List trust or certificates
extract Extract certificates and trust
extract-compat Extract trust compatibility bundles
anchor Add, remove, change trust anchors
dump Dump trust objects in internal format

See 'trust <command> --help' for more information

To list all system trust anchors and certificates, use the trust list command:

$ trust list
pkcs11:id=%d2%87%b4%e3%df%37%27%93%55%f6%56%ea%81%e5%36%cc%8c%1e%3
f%bd;type=cert
type: certificate
label: ACCVRAIZ1
trust: anchor
category: authority

pkcs11:id=%a6%b3%e1%2b%2b%49%b6%d7%73%a1%aa%94%f5%01%e7%73%65%4c%
ac%50;type=cert
type: certificate
label: ACEDICOM Root
trust: anchor
category: authority
...

To store a trust anchor into the system-wide truststore, use the trust anchor sub-command
and specify a path to a certificate. Replace <path.to/certificate.crt> by a path to your certificate
and its file name:

# trust anchor <path.to/certificate.crt>

107
Red Hat Enterprise Linux 8 System Design Guide

To remove a certificate, use either a path to a certificate or an ID of a certificate:

# trust anchor --remove <path.to/certificate.crt>


# trust anchor --remove "pkcs11:id=<%AA%BB%CC%DD%EE>;type=cert"

Additional resources

All sub-commands of the trust commands offer a detailed built-in help, for example:

$ trust list --help


usage: trust list --filter=<what>

--filter=<what> filter of what to export


ca-anchors certificate anchors
...
--purpose=<usage> limit to certificates usable for the purpose
server-auth for authenticating servers
...

Additional resources

update-ca-trust(8) and trust(1) man pages on your system

108
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY


COMPLIANCE AND VULNERABILITIES

9.1. CONFIGURATION COMPLIANCE TOOLS IN RHEL


You can perform a fully automated compliance audit in Red Hat Enterprise Linux by using the following
configuration compliance tools. These tools are based on the Security Content Automation Protocol
(SCAP) standard and are designed for automated tailoring of compliance policies.

SCAP Workbench
The scap-workbench graphical utility is designed to perform configuration and vulnerability scans
on a single local or remote system. You can also use it to generate security reports based on these
scans and evaluations.
OpenSCAP
The OpenSCAP library, with the accompanying oscap command-line utility, is designed to perform
configuration and vulnerability scans on a local system, to validate configuration compliance content,
and to generate reports and guides based on these scans and evaluations.

IMPORTANT

You can experience memory-consumption problems while using OpenSCAP, which


can cause stopping the program prematurely and prevent generating any result files.
See the OpenSCAP memory-consumption problems Knowledgebase article for
details.

SCAP Security Guide (SSG)


The scap-security-guide package provides collections of security policies for Linux systems. The
guidance consists of a catalog of practical hardening advice, linked to government requirements
where applicable. The project bridges the gap between generalized policy requirements and specific
implementation guidelines.
Script Check Engine (SCE)
With SCE, which is an extension to the SCAP protocol, administrators can write their security content
by using a scripting language, such as Bash, Python, and Ruby. The SCE extension is provided in the
openscap-engine-sce package. The SCE itself is not part of the SCAP standard.

To perform automated compliance audits on multiple systems remotely, you can use the OpenSCAP
solution for Red Hat Satellite.

Additional resources

oscap(8), scap-workbench(8), and scap-security-guide(8) man pages on your system

Red Hat Security Demos: Creating Customized Security Policy Content to Automate Security
Compliance

Red Hat Security Demos: Defend Yourself with RHEL Security Technologies

Managing security compliance in Red Hat Satellite

9.2. RED HAT SECURITY ADVISORIES OVAL FEED

109
Red Hat Enterprise Linux 8 System Design Guide

Red Hat Enterprise Linux security auditing capabilities are based on the Security Content Automation
Protocol (SCAP) standard. SCAP is a multi-purpose framework of specifications that supports
automated configuration, vulnerability and patch checking, technical control compliance activities, and
security measurement.

SCAP specifications create an ecosystem where the format of security content is well-known and
standardized although the implementation of the scanner or policy editor is not mandated. This enables
organizations to build their security policy (SCAP content) once, no matter how many security vendors
they employ.

The Open Vulnerability Assessment Language (OVAL) is the essential and oldest component of SCAP.
Unlike other tools and custom scripts, OVAL describes a required state of resources in a declarative
manner. OVAL code is never executed directly but using an OVAL interpreter tool called scanner. The
declarative nature of OVAL ensures that the state of the assessed system is not accidentally modified.

Like all other SCAP components, OVAL is based on XML. The SCAP standard defines several document
formats. Each of them includes a different kind of information and serves a different purpose.

Red Hat Product Security helps customers evaluate and manage risk by tracking and investigating all
security issues affecting Red Hat customers. It provides timely and concise patches and security
advisories on the Red Hat Customer Portal. Red Hat creates and supports OVAL patch definitions,
providing machine-readable versions of our security advisories.

Because of differences between platforms, versions, and other factors, Red Hat Product Security
qualitative severity ratings of vulnerabilities do not directly align with the Common Vulnerability Scoring
System (CVSS) baseline ratings provided by third parties. Therefore, we recommend that you use the
RHSA OVAL definitions instead of those provided by third parties.

The RHSA OVAL definitions are available individually and as a complete package, and are updated within
an hour of a new security advisory being made available on the Red Hat Customer Portal.

Each OVAL patch definition maps one-to-one to a Red Hat Security Advisory (RHSA). Because an
RHSA can contain fixes for multiple vulnerabilities, each vulnerability is listed separately by its Common
Vulnerabilities and Exposures (CVE) name and has a link to its entry in our public bug database.

The RHSA OVAL definitions are designed to check for vulnerable versions of RPM packages installed on
a system. It is possible to extend these definitions to include further checks, for example, to find out if
the packages are being used in a vulnerable configuration. These definitions are designed to cover
software and updates shipped by Red Hat. Additional definitions are required to detect the patch status
of third-party software.

NOTE

The Red Hat Insights for Red Hat Enterprise Linux compliance service helps IT security
and compliance administrators to assess, monitor, and report on the security policy
compliance of Red Hat Enterprise Linux systems. You can also create and manage your
SCAP security policies entirely within the compliance service UI.

Additional resources

Red Hat and OVAL compatibility

Red Hat and CVE compatibility

Notifications and Advisories in the Product Security Overview

110
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

Security Data Metrics

9.3. VULNERABILITY SCANNING

9.3.1. Red Hat Security Advisories OVAL feed


Red Hat Enterprise Linux security auditing capabilities are based on the Security Content Automation
Protocol (SCAP) standard. SCAP is a multi-purpose framework of specifications that supports
automated configuration, vulnerability and patch checking, technical control compliance activities, and
security measurement.

SCAP specifications create an ecosystem where the format of security content is well-known and
standardized although the implementation of the scanner or policy editor is not mandated. This enables
organizations to build their security policy (SCAP content) once, no matter how many security vendors
they employ.

The Open Vulnerability Assessment Language (OVAL) is the essential and oldest component of SCAP.
Unlike other tools and custom scripts, OVAL describes a required state of resources in a declarative
manner. OVAL code is never executed directly but using an OVAL interpreter tool called scanner. The
declarative nature of OVAL ensures that the state of the assessed system is not accidentally modified.

Like all other SCAP components, OVAL is based on XML. The SCAP standard defines several document
formats. Each of them includes a different kind of information and serves a different purpose.

Red Hat Product Security helps customers evaluate and manage risk by tracking and investigating all
security issues affecting Red Hat customers. It provides timely and concise patches and security
advisories on the Red Hat Customer Portal. Red Hat creates and supports OVAL patch definitions,
providing machine-readable versions of our security advisories.

Because of differences between platforms, versions, and other factors, Red Hat Product Security
qualitative severity ratings of vulnerabilities do not directly align with the Common Vulnerability Scoring
System (CVSS) baseline ratings provided by third parties. Therefore, we recommend that you use the
RHSA OVAL definitions instead of those provided by third parties.

The RHSA OVAL definitions are available individually and as a complete package, and are updated within
an hour of a new security advisory being made available on the Red Hat Customer Portal.

Each OVAL patch definition maps one-to-one to a Red Hat Security Advisory (RHSA). Because an
RHSA can contain fixes for multiple vulnerabilities, each vulnerability is listed separately by its Common
Vulnerabilities and Exposures (CVE) name and has a link to its entry in our public bug database.

The RHSA OVAL definitions are designed to check for vulnerable versions of RPM packages installed on
a system. It is possible to extend these definitions to include further checks, for example, to find out if
the packages are being used in a vulnerable configuration. These definitions are designed to cover
software and updates shipped by Red Hat. Additional definitions are required to detect the patch status
of third-party software.

NOTE

The Red Hat Insights for Red Hat Enterprise Linux compliance service helps IT security
and compliance administrators to assess, monitor, and report on the security policy
compliance of Red Hat Enterprise Linux systems. You can also create and manage your
SCAP security policies entirely within the compliance service UI.

Additional resources

111
Red Hat Enterprise Linux 8 System Design Guide

Red Hat and OVAL compatibility

Red Hat and CVE compatibility

Notifications and Advisories in the Product Security Overview

Security Data Metrics

9.3.2. Scanning the system for vulnerabilities


The oscap command-line utility enables you to scan local systems, validate configuration compliance
content, and generate reports and guides based on these scans and evaluations. This utility serves as a
front end to the OpenSCAP library and groups its functionalities to modules (sub-commands) based on
the type of SCAP content it processes.

Prerequisites

The openscap-scanner and bzip2 packages are installed.

Procedure

1. Download the latest RHSA OVAL definitions for your system:

# wget -O - https://www.redhat.com/security/data/oval/v2/RHEL8/rhel-8.oval.xml.bz2 | bzip2 -


-decompress > rhel-8.oval.xml

2. Scan the system for vulnerabilities and save results to the vulnerability.html file:

# oscap oval eval --report vulnerability.html rhel-8.oval.xml

Verification

Check the results in a browser of your choice, for example:

$ firefox vulnerability.html &

Additional resources

oscap(8) man page on your system

Red Hat OVAL definitions

OpenSCAP memory consumption problems

9.3.3. Scanning remote systems for vulnerabilities


You can check remote systems for vulnerabilities with the OpenSCAP scanner by using the oscap-ssh
tool over the SSH protocol.

Prerequisites

The openscap-utils and bzip2 packages are installed on the system you use for scanning.

112
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

The openscap-scanner package is installed on the remote systems.

The SSH server is running on the remote systems.

Procedure

1. Download the latest RHSA OVAL definitions for your system:

# wget -O - https://www.redhat.com/security/data/oval/v2/RHEL8/rhel-8.oval.xml.bz2 | bzip2 -


-decompress > rhel-8.oval.xml

2. Scan a remote system for vulnerabilities and save the results to a file:

# oscap-ssh <username>@<hostname> <port> oval eval --report <scan-report.html> rhel-


8.oval.xml

Replace:

<username>@<hostname> with the user name and host name of the remote system.

<port> with the port number through which you can access the remote system, for example,
22.

<scan-report.html> with the file name where oscap saves the scan results.

Additional resources

oscap-ssh(8)

Red Hat OVAL definitions

OpenSCAP memory consumption problems

9.4. CONFIGURATION COMPLIANCE SCANNING

9.4.1. Configuration compliance in RHEL


You can use configuration compliance scanning to conform to a baseline defined by a specific
organization. For example, if you work with the US government, you might have to align your systems
with the Operating System Protection Profile (OSPP), and if you are a payment processor, you might
have to align your systems with the Payment Card Industry Data Security Standard (PCI-DSS). You can
also perform configuration compliance scanning to harden your system security.

Red Hat recommends you follow the Security Content Automation Protocol (SCAP) content provided
in the SCAP Security Guide package because it is in line with Red Hat best practices for affected
components.

The SCAP Security Guide package provides content which conforms to the SCAP 1.2 and SCAP 1.3
standards. The openscap scanner utility is compatible with both SCAP 1.2 and SCAP 1.3 content
provided in the SCAP Security Guide package.

IMPORTANT
113
Red Hat Enterprise Linux 8 System Design Guide

IMPORTANT

Performing a configuration compliance scanning does not guarantee the system is


compliant.

The SCAP Security Guide suite provides profiles for several platforms in a form of data stream
documents. A data stream is a file that contains definitions, benchmarks, profiles, and individual rules.
Each rule specifies the applicability and requirements for compliance. RHEL provides several profiles for
compliance with security policies. In addition to the industry standard, Red Hat data streams also contain
information for remediation of failed rules.

Structure of compliance scanning resources

Data stream
├── xccdf
| ├── benchmark
| ├── profile
| | ├──rule reference
| | └──variable
| ├── rule
| ├── human readable data
| ├── oval reference
├── oval ├── ocil reference
├── ocil ├── cpe reference
└── cpe └── remediation

A profile is a set of rules based on a security policy, such as OSPP, PCI-DSS, and Health Insurance
Portability and Accountability Act (HIPAA). This enables you to audit the system in an automated way
for compliance with security standards.

You can modify (tailor) a profile to customize certain rules, for example, password length. For more
information about profile tailoring, see Customizing a security profile with SCAP Workbench .

9.4.2. Possible results of an OpenSCAP scan


Depending on the data stream and profile applied to an OpenSCAP scan, as well as various properties of
your system, each rule may produce a specific result. These are the possible results with brief
explanations of their meanings:

Pass
The scan did not find any conflicts with this rule.
Fail
The scan found a conflict with this rule.
Not checked
OpenSCAP does not perform an automatic evaluation of this rule. Check whether your system
conforms to this rule manually.
Not applicable
This rule does not apply to the current configuration.
Not selected
This rule is not part of the profile. OpenSCAP does not evaluate this rule and does not display these
rules in the results.

114
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

Error
The scan encountered an error. For additional information, you can enter the oscap command with
the --verbose DEVEL option. File a support case on the Red Hat customer portal or open a ticket in
the RHEL project in Red Hat Jira .
Unknown
The scan encountered an unexpected situation. For additional information, you can enter the oscap
command with the `--verbose DEVEL option. File a support case on the Red Hat customer portal or
open a ticket in the RHEL project in Red Hat Jira .

9.4.3. Viewing profiles for configuration compliance


Before you decide to use profiles for scanning or remediation, you can list them and check their detailed
descriptions using the oscap info subcommand.

Prerequisites

The openscap-scanner and scap-security-guide packages are installed.

Procedure

1. List all available files with security compliance profiles provided by the SCAP Security Guide
project:

$ ls /usr/share/xml/scap/ssg/content/
ssg-firefox-cpe-dictionary.xml ssg-rhel6-ocil.xml
ssg-firefox-cpe-oval.xml ssg-rhel6-oval.xml

ssg-rhel6-ds-1.2.xml ssg-rhel8-oval.xml
ssg-rhel8-ds.xml ssg-rhel8-xccdf.xml

2. Display detailed information about a selected data stream using the oscap info subcommand.
XML files containing data streams are indicated by the -ds string in their names. In the Profiles
section, you can find a list of available profiles and their IDs:

$ oscap info /usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml


Profiles:

Title: Health Insurance Portability and Accountability Act (HIPAA)
Id: xccdf_org.ssgproject.content_profile_hipaa
Title: PCI-DSS v3.2.1 Control Baseline for Red Hat Enterprise Linux 8
Id: xccdf_org.ssgproject.content_profile_pci-dss
Title: OSPP - Protection Profile for General Purpose Operating Systems
Id: xccdf_org.ssgproject.content_profile_ospp

3. Select a profile from the data stream file and display additional details about the selected
profile. To do so, use oscap info with the --profile option followed by the last section of the ID
displayed in the output of the previous command. For example, the ID of the HIPPA profile is
xccdf_org.ssgproject.content_profile_hipaa, and the value for the --profile option is hipaa:

$ oscap info --profile hipaa /usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml


115
Red Hat Enterprise Linux 8 System Design Guide

Profile
Title: Health Insurance Portability and Accountability Act (HIPAA)

Description: The HIPAA Security Rule establishes U.S. national standards to protect
individuals’ electronic personal health information that is created, received, used, or
maintained by a covered entity.

Additional resources

scap-security-guide(8) man page on your system

OpenSCAP memory consumption problems

9.4.4. Assessing configuration compliance with a specific baseline


You can determine whether your system or a remote system conforms to a specific baseline, and save
the results in a report by using the oscap command-line tool.

Prerequisites

The openscap-scanner and scap-security-guide packages are installed.

You know the ID of the profile within the baseline with which the system should comply. To find
the ID, see the Viewing profiles for configuration compliance section.

Procedure

1. Scan the local system for compliance with the selected profile and save the scan results to a file:

$ oscap xccdf eval --report <scan-report.html> --profile <profileID>


/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml

Replace:

<scan-report.html> with the file name where oscap saves the scan results.

<profileID> with the profile ID with which the system should comply, for example, hipaa.

2. Optional: Scan a remote system for compliance with the selected profile and save the scan
results to a file:

$ oscap-ssh <username>@<hostname> <port> xccdf eval --report <scan-report.html> --


profile <profileID> /usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml

Replace:

<username>@<hostname> with the user name and host name of the remote system.

<port> with the port number through which you can access the remote system.

<scan-report.html> with the file name where oscap saves the scan results.

<profileID> with the profile ID with which the system should comply, for example, hipaa.

116
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

Additional resources

scap-security-guide(8) man page on your system

SCAP Security Guide documentation in the /usr/share/doc/scap-security-guide/ directory

/usr/share/doc/scap-security-guide/guides/ssg-rhel8-guide-index.html - [Guide to the


Secure Configuration of Red Hat Enterprise Linux 8] installed with the scap-security-guide-
doc package

OpenSCAP memory consumption problems

9.5. REMEDIATING THE SYSTEM TO ALIGN WITH A SPECIFIC


BASELINE
You can remediate the RHEL system to align with a specific baseline. You can remediate the system to
align with any profile provided by the SCAP Security Guide. For the details on listing the available
profiles, see the Viewing profiles for configuration compliance section.


WARNING

If not used carefully, running the system evaluation with the Remediate option
enabled might render the system non-functional. Red Hat does not provide any
automated method to revert changes made by security-hardening remediations.
Remediations are supported on RHEL systems in the default configuration. If your
system has been altered after the installation, running remediation might not make
it compliant with the required security profile.

Prerequisites

The scap-security-guide package is installed.

Procedure

1. Remediate the system by using the oscap command with the --remediate option:

# oscap xccdf eval --profile <profileID> --remediate /usr/share/xml/scap/ssg/content/ssg-


rhel8-ds.xml

Replace <profileID> with the profile ID with which the system should comply, for example,
hipaa.

2. Restart your system.

Verification

1. Evaluate compliance of the system with the profile, and save the scan results to a file:

$ oscap xccdf eval --report <scan-report.html> --profile <profileID>


/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml

117
Red Hat Enterprise Linux 8 System Design Guide

Replace:

<scan-report.html> with the file name where oscap saves the scan results.

<profileID> with the profile ID with which the system should comply, for example, hipaa.

Additional resources

scap-security-guide(8) and oscap(8) man pages on your system

Complementing the DISA benchmark using the SSG content Knowledgebase article

9.6. REMEDIATING THE SYSTEM TO ALIGN WITH A SPECIFIC


BASELINE USING AN SSG ANSIBLE PLAYBOOK
You can remediate your system to align with a specific baseline by using an Ansible playbook file from
the SCAP Security Guide project. This example uses the Health Insurance Portability and Accountability
Act (HIPAA) profile, but you can remediate to align with any other profile provided by the SCAP Security
Guide. For the details on listing the available profiles, see the Viewing profiles for configuration
compliance section.


WARNING

If not used carefully, running the system evaluation with the Remediate option
enabled might render the system non-functional. Red Hat does not provide any
automated method to revert changes made by security-hardening remediations.
Remediations are supported on RHEL systems in the default configuration. If your
system has been altered after the installation, running remediation might not make
it compliant with the required security profile.

Prerequisites

The scap-security-guide package is installed.

The ansible-core package is installed. See the Ansible Installation Guide for more information.

RHEL 8.6 or later is installed. For more information about installing RHEL, see Interactively
installing RHEL from installation media.

NOTE

In RHEL 8.5 and earlier versions, Ansible packages were provided through Ansible
Engine instead of Ansible Core, and with a different level of support. Do not use
Ansible Engine because the packages might not be compatible with Ansible
automation content in RHEL 8.6 and later. For more information, see Scope of
support for the Ansible Core package included in the RHEL 9 and RHEL 8.6 and
later AppStream repositories.

Procedure

118
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

1. Remediate your system to align with HIPAA by using Ansible:

# ansible-playbook -i localhost, -c local /usr/share/scap-security-guide/ansible/rhel8-


playbook-hipaa.yml

2. Restart the system.

Verification

1. Evaluate the compliance of the system with the HIPAA profile, and save the scan results to a
file:

# oscap xccdf eval --profile hipaa --report <scan-report.html>


/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml

Replace <scan-report.html> with the file name where oscap saves the scan results.

Additional resources

scap-security-guide(8) and oscap(8) man pages on your system

Ansible Documentation

9.7. CREATING A REMEDIATION ANSIBLE PLAYBOOK TO ALIGN THE


SYSTEM WITH A SPECIFIC BASELINE
You can create an Ansible playbook containing only the remediations that are required to align your
system with a specific baseline. This playbook is smaller because it does not cover already satisfied
requirements. Creating the playbook does not modify your system in any way, you only prepare a file for
later application. This example uses the Health Insurance Portability and Accountability Act (HIPAA)
profile.

NOTE

In RHEL 8.6, Ansible Engine is replaced by the ansible-core package, which contains only
built-in modules. Note that many Ansible remediations use modules from the community
and Portable Operating System Interface (POSIX) collections, which are not included in
the built-in modules. In this case, you can use Bash remediations as a substitute for
Ansible remediations. The Red Hat Connector in RHEL 8.6 includes the Ansible modules
necessary for the remediation playbooks to function with Ansible Core.

Prerequisites

The scap-security-guide package is installed.

Procedure

1. Scan the system and save the results:

# oscap xccdf eval --profile hipaa --results <hipaa-results.xml>


/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml

2. Find the value of the result ID in the file with the results:

119
Red Hat Enterprise Linux 8 System Design Guide

# oscap info <hipaa-results.xml>

3. Generate an Ansible playbook based on the file generated in step 1:

# oscap xccdf generate fix --fix-type ansible --result-id <xccdf_org.open-


scap_testresult_xccdf_org.ssgproject.content_profile_hipaa> --output <hipaa-
remediations.yml> <hipaa-results.xml>

4. Review the generated file, which contains the Ansible remediations for rules that failed during
the scan performed in step 1. After reviewing this generated file, you can apply it by using the
ansible-playbook <hipaa-remediations.yml> command.

Verification

In a text editor of your choice, review that the generated <hipaa-remediations.yml> file
contains rules that failed in the scan performed in step 1.

Additional resources

scap-security-guide(8) and oscap(8) man pages on your system

Ansible Documentation

9.8. CREATING A REMEDIATION BASH SCRIPT FOR A LATER


APPLICATION
Use this procedure to create a Bash script containing remediations that align your system with a security
profile such as HIPAA. Using the following steps, you do not do any modifications to your system, you
only prepare a file for later application.

Prerequisites

The scap-security-guide package is installed on your RHEL system.

Procedure

1. Use the oscap command to scan the system and to save the results to an XML file. In the
following example, oscap evaluates the system against the hipaa profile:

# oscap xccdf eval --profile hipaa --results <hipaa-results.xml>


/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml

2. Find the value of the result ID in the file with the results:

# oscap info <hipaa-results.xml>

3. Generate a Bash script based on the results file generated in step 1:

# oscap xccdf generate fix --fix-type bash --result-id <xccdf_org.open-


scap_testresult_xccdf_org.ssgproject.content_profile_hipaa> --output <hipaa-
remediations.sh> <hipaa-results.xml>

4. The <hipaa-remediations.sh> file contains remediations for rules that failed during the scan
120
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

4. The <hipaa-remediations.sh> file contains remediations for rules that failed during the scan
performed in step 1. After reviewing this generated file, you can apply it with the ./<hipaa-
remediations.sh> command when you are in the same directory as this file.

Verification

In a text editor of your choice, review that the <hipaa-remediations.sh> file contains rules that
failed in the scan performed in step 1.

Additional resources

scap-security-guide(8), oscap(8), and bash(1) man pages on your system

9.9. SCANNING THE SYSTEM WITH A CUSTOMIZED PROFILE USING


SCAP WORKBENCH
SCAP Workbench, which is contained in the scap-workbench package, is a graphical utility that
enables users to perform configuration and vulnerability scans on a single local or a remote system,
perform remediation of the system, and generate reports based on scan evaluations. Note that SCAP
Workbench has limited functionality compared with the oscap command-line utility. SCAP
Workbench processes security content in the form of data stream files.

9.9.1. Using SCAP Workbench to scan and remediate the system


To evaluate your system against the selected security policy, use the following procedure.

Prerequisites

The scap-workbench package is installed on your system.

Procedure

1. To run SCAP Workbench from the GNOME Classic desktop environment, press the Super
key to enter the Activities Overview, type scap-workbench, and then press Enter.
Alternatively, use:

$ scap-workbench &

2. Select a security policy using either of the following options:

Load Content button on the starting window

Open content from SCAP Security Guide

Open Other Content in the File menu, and search the respective XCCDF, SCAP RPM, or
data stream file.

121
Red Hat Enterprise Linux 8 System Design Guide

3. You can allow automatic correction of the system configuration by selecting the Remediate
check box. With this option enabled, SCAP Workbench attempts to change the system
configuration in accordance with the security rules applied by the policy. This process should fix
the related checks that fail during the system scan.


WARNING

If not used carefully, running the system evaluation with the Remediate
option enabled might render the system non-functional. Red Hat does not
provide any automated method to revert changes made by security-
hardening remediations. Remediations are supported on RHEL systems in
the default configuration. If your system has been altered after the
installation, running remediation might not make it compliant with the
required security profile.

4. Scan your system with the selected profile by clicking the Scan button.

122
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

5. To store the scan results in form of an XCCDF, ARF, or HTML file, click the Save Results
combo box. Choose the HTML Report option to generate the scan report in human-readable
format. The XCCDF and ARF (data stream) formats are suitable for further automatic
processing. You can repeatedly choose all three options.

6. To export results-based remediations to a file, use the Generate remediation role pop-up
menu.

9.9.2. Customizing a security profile with SCAP Workbench


You can customize a security profile by changing parameters in certain rules (for example, minimum
password length), removing rules that you cover in a different way, and selecting additional rules, to
implement internal policies. You cannot define new rules by customizing a profile.

The following procedure demonstrates the use of SCAP Workbench for customizing (tailoring) a
profile. You can also save the tailored profile for use with the oscap command-line utility.

Prerequisites

The scap-workbench package is installed on your system.

Procedure

1. Run SCAP Workbench, and select the profile to customize by using either Open content from
SCAP Security Guide or Open Other Content in the File menu.

2. To adjust the selected security profile according to your needs, click the Customize button.

This opens the new Customization window that enables you to modify the currently selected

123
Red Hat Enterprise Linux 8 System Design Guide

This opens the new Customization window that enables you to modify the currently selected
profile without changing the original data stream file. Choose a new profile ID.

3. Find a rule to modify using either the tree structure with rules organized into logical groups or
the Search field.

4. Include or exclude rules using check boxes in the tree structure, or modify values in rules where
applicable.

5. Confirm the changes by clicking the OK button.

6. To store your changes permanently, use one of the following options:

Save a customization file separately by using Save Customization Only in the File menu.

Save all security content at once by Save All in the File menu.
If you select the Into a directory option, SCAP Workbench saves both the data stream file
and the customization file to the specified location. You can use this as a backup solution.

124
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

By selecting the As RPM option, you can instruct SCAP Workbench to create an RPM
package containing the data stream file and the customization file. This is useful for
distributing the security content to systems that cannot be scanned remotely, and for
delivering the content for further processing.

NOTE

Because SCAP Workbench does not support results-based remediations for tailored
profiles, use the exported remediations with the oscap command-line utility.

9.9.3. Additional resources


scap-workbench(8) man page on your system

/usr/share/doc/scap-workbench/user_manual.html file provided by the scap-workbench


package

Deploy customized SCAP policies with Satellite 6.x (Red Hat Knowledgebase)

9.10. SCANNING CONTAINER AND CONTAINER IMAGES FOR


VULNERABILITIES
Use this procedure to find security vulnerabilities in a container or a container image.

NOTE

The oscap-podman command is available from RHEL 8.2. For RHEL 8.1 and 8.0, use the
workaround described in the Using OpenSCAP for scanning containers in RHEL 8
Knowledgebase article.

Prerequisites

The openscap-utils and bzip2 packages are installed.

Procedure

1. Download the latest RHSA OVAL definitions for your system:

# wget -O - https://www.redhat.com/security/data/oval/v2/RHEL8/rhel-8.oval.xml.bz2 | bzip2 -


-decompress > rhel-8.oval.xml

2. Get the ID of a container or a container image, for example:

# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.access.redhat.com/ubi8/ubi latest 096cae65a207 7 weeks ago 239 MB

3. Scan the container or the container image for vulnerabilities and save results to the
vulnerability.html file:

# oscap-podman 096cae65a207 oval eval --report vulnerability.html rhel-8.oval.xml

Note that the oscap-podman command requires root privileges, and the ID of a container is the

125
Red Hat Enterprise Linux 8 System Design Guide

Note that the oscap-podman command requires root privileges, and the ID of a container is the
first argument.

Verification

Check the results in a browser of your choice, for example:

$ firefox vulnerability.html &

Additional resources

For more information, see the oscap-podman(8) and oscap(8) man pages.

9.11. ASSESSING SECURITY COMPLIANCE OF A CONTAINER OR A


CONTAINER IMAGE WITH A SPECIFIC BASELINE
You can assess the compliance of your container or a container image with a specific security baseline,
such as Operating System Protection Profile (OSPP), Payment Card Industry Data Security Standard
(PCI-DSS), and Health Insurance Portability and Accountability Act (HIPAA).

NOTE

The oscap-podman command is available from RHEL 8.2. For RHEL 8.1 and 8.0, use the
workaround described in the Using OpenSCAP for scanning containers in RHEL 8
Knowledgebase article.

Prerequisites

The openscap-utils and scap-security-guide packages are installed.

You have root access to the system.

Procedure

1. Find the ID of a container or a container image:

a. To find the ID of a container, enter the podman ps -a command.

b. To find the ID of a container image, enter the podman images command.

2. Evaluate the compliance of the container or container image with a profile and save the scan
results into a file:

# oscap-podman <ID> xccdf eval --report <scan-report.html> --profile <profileID>


/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml

Replace:

<ID> with the ID of your container or container image

<scan-report.html> with the file name where oscap saves the scan results

<profileID> with the profile ID with which the system should comply, for example, hipaa,
ospp, or pci-dss

126
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

Verification

Check the results in a browser of your choice, for example:

$ firefox <scan-report.html> &amp;

NOTE

The rules marked as notapplicable apply only to bare-metal and virtualized systems and
not to containers or container images.

Additional resources

oscap-podman(8) and scap-security-guide(8) man pages.

/usr/share/doc/scap-security-guide/ directory.

9.12. CHECKING INTEGRITY WITH AIDE


Advanced Intrusion Detection Environment (AIDE) is a utility that creates a database of files on the
system, and then uses that database to ensure file integrity and detect system intrusions.

9.12.1. Installing AIDE


To start file-integrity checking with AIDE, you must install the corresponding package and initiate the
AIDE database.

Prerequisites

The AppStream repository is enabled.

Procedure

1. Install the aide package:

# yum install aide

2. Generate an initial database:

# aide --init
Start timestamp: 2024-07-08 10:39:23 -0400 (AIDE 0.16)
AIDE initialized database at /var/lib/aide/aide.db.new.gz

Number of entries: 55856

---------------------------------------------------
The attributes of the (uncompressed) database(s):
---------------------------------------------------

/var/lib/aide/aide.db.new.gz

127
Red Hat Enterprise Linux 8 System Design Guide

SHA512 : mZaWoGzL2m6ZcyyZ/AXTIowliEXWSZqx
IFYImY4f7id4u+Bq8WeuSE2jasZur/A4
FPBFaBkoCFHdoE/FW/V94Q==

3. Optional: In the default configuration, the aide --init command checks just a set of directories
and files defined in the /etc/aide.conf file. To include additional directories or files in the AIDE
database, and to change their watched parameters, edit /etc/aide.conf accordingly.

4. To start using the database, remove the .new substring from the initial database file name:

# mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

5. Optional: To change the location of the AIDE database, edit the /etc/aide.conf file and modify
the DBDIR value. For additional security, store the database, configuration, and the
/usr/sbin/aide binary file in a secure location such as a read-only media.

9.12.2. Performing integrity checks with AIDE


You can use the crond service to schedule regular file-integrity checks with AIDE.

Prerequisites

AIDE is properly installed and its database is initialized. See Installing AIDE

Procedure

1. To initiate a manual check:

# aide --check
Start timestamp: 2024-07-08 10:43:46 -0400 (AIDE 0.16)
AIDE found differences between database and filesystem!!

Summary:
Total number of entries: 55856
Added entries: 0
Removed entries: 0
Changed entries: 1

---------------------------------------------------
Changed entries:
---------------------------------------------------

f ... ..S : /root/.viminfo

---------------------------------------------------
Detailed information about changes:
---------------------------------------------------

File: /root/.viminfo
SELinux : system_u:object_r:admin_home_t:s | unconfined_u:object_r:admin_home
0 | _t:s0

2. At a minimum, configure the system to run AIDE weekly. Optimally, run AIDE daily. For example,
128
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

2. At a minimum, configure the system to run AIDE weekly. Optimally, run AIDE daily. For example,
to schedule a daily execution of AIDE at 04:05 a.m. by using the cron command, add the
following line to the /etc/crontab file:

05 4 * * * root /usr/sbin/aide --check

Additional resources

cron(8) man page on your system

9.12.3. Updating an AIDE database


After verifying the changes of your system, such as package updates or configuration files adjustments,
update also your baseline AIDE database.

Prerequisites

AIDE is properly installed and its database is initialized. See Installing AIDE

Procedure

1. Update your baseline AIDE database:

# aide --update

The aide --update command creates the /var/lib/aide/aide.db.new.gz database file.

2. To start using the updated database for integrity checks, remove the .new substring from the
file name.

9.12.4. File-integrity tools: AIDE and IMA


Red Hat Enterprise Linux provides several tools for checking and preserving the integrity of files and
directories on your system. The following table helps you decide which tool better fits your scenario.

Table 9.1. Comparison between AIDE and IMA

Question Advanced Intrusion Detection Integrity Measurement Architecture (IMA)


Environment (AIDE)

What AIDE is a utility that creates a database of IMA detects if a file is altered by checking file
files and directories on the system. This measurement (hash values) compared to
database serves for checking file integrity previously stored extended attributes.
and detect intrusion detection.

How AIDE uses rules to compare the integrity IMA uses file hash values to detect the
state of the files and directories. intrusion.

Why Detection - AIDE detects if a file is modified Detection and Prevention - IMA detects and
by verifying the rules. prevents an attack by replacing the extended
attribute of a file.

129
Red Hat Enterprise Linux 8 System Design Guide

Question Advanced Intrusion Detection Integrity Measurement Architecture (IMA)


Environment (AIDE)

Usage AIDE detects a threat when the file or IMA detects a threat when someone tries to
directory is modified. alter the entire file.

Extension AIDE checks the integrity of files and IMA ensures security on the local and remote
directories on the local system. systems.

9.12.5. Additional resources


aide(1) man page on your system

Kernel integrity subsystem

9.13. ENCRYPTING BLOCK DEVICES USING LUKS


By using the disk encryption, you can protect the data on a block device by encrypting it. To access the
device’s decrypted contents, enter a passphrase or key as authentication. This is important for mobile
computers and removable media because it helps to protect the device’s contents even if it has been
physically removed from the system. The LUKS format is a default implementation of block device
encryption in Red Hat Enterprise Linux.

9.13.1. LUKS disk encryption


Linux Unified Key Setup-on-disk-format (LUKS) provides a set of tools that simplifies managing the
encrypted devices. With LUKS, you can encrypt block devices and enable multiple user keys to decrypt a
master key. For bulk encryption of the partition, use this master key.

Red Hat Enterprise Linux uses LUKS to perform block device encryption. By default, the option to
encrypt the block device is unchecked during the installation. If you select the option to encrypt your
disk, the system prompts you for a passphrase every time you boot the computer. This passphrase
unlocks the bulk encryption key that decrypts your partition. If you want to modify the default partition
table, you can select the partitions that you want to encrypt. This is set in the partition table settings.

Ciphers
The default cipher used for LUKS is aes-xts-plain64. The default key size for LUKS is 512 bits. The
default key size for LUKS with Anaconda XTS mode is 512 bits. The following are the available ciphers:

Advanced Encryption Standard (AES)

Twofish

Serpent

Operations performed by LUKS

LUKS encrypts entire block devices and is therefore well-suited for protecting contents of
mobile devices such as removable storage media or laptop disk drives.

The underlying contents of the encrypted block device are arbitrary, which makes it useful for
130
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

The underlying contents of the encrypted block device are arbitrary, which makes it useful for
encrypting swap devices. This can also be useful with certain databases that use specially
formatted block devices for data storage.

LUKS uses the existing device mapper kernel subsystem.

LUKS provides passphrase strengthening, which protects against dictionary attacks.

LUKS devices contain multiple key slots, which means you can add backup keys or passphrases.

IMPORTANT

LUKS is not recommended for the following scenarios:

Disk-encryption solutions such as LUKS protect the data only when your system
is off. After the system is on and LUKS has decrypted the disk, the files on that
disk are available to anyone who have access to them.

Scenarios that require multiple users to have distinct access keys to the same
device. The LUKS1 format provides eight key slots and LUKS2 provides up to 32
key slots.

Applications that require file-level encryption.

Additional resources

LUKS Project Home Page

LUKS On-Disk Format Specification

FIPS 197: Advanced Encryption Standard (AES)

9.13.2. LUKS versions in RHEL


In Red Hat Enterprise Linux, the default format for LUKS encryption is LUKS2. The old LUKS1 format
remains fully supported and it is provided as a format compatible with earlier Red Hat Enterprise Linux
releases. LUKS2 re-encryption is considered more robust and safe to use as compared to LUKS1 re-
encryption.

The LUKS2 format enables future updates of various parts without a need to modify binary structures.
Internally it uses JSON text format for metadata, provides redundancy of metadata, detects metadata
corruption, and automatically repairs from a metadata copy.

IMPORTANT
131
Red Hat Enterprise Linux 8 System Design Guide

IMPORTANT

Do not use LUKS2 in systems that support only LUKS1 because LUKS2 and LUKS1 use
different commands to encrypt the disk. Using the wrong command for a LUKS version
might cause data loss.

Table 9.2. Encryption commands depending on the LUKS version

LUKS version Encryption command

LUKS2 cryptsetup reencrypt

LUKS1 cryptsetup-reencrypt

Online re-encryption
The LUKS2 format supports re-encrypting encrypted devices while the devices are in use. For example,
you do not have to unmount the file system on the device to perform the following tasks:

Changing the volume key

Changing the encryption algorithm


When encrypting a non-encrypted device, you must still unmount the file system. You can
remount the file system after a short initialization of the encryption.

The LUKS1 format does not support online re-encryption.

Conversion
In certain situations, you can convert LUKS1 to LUKS2. The conversion is not possible specifically in the
following scenarios:

A LUKS1 device is marked as being used by a Policy-Based Decryption (PBD) Clevis solution.
The cryptsetup tool does not convert the device when some luksmeta metadata are detected.

A device is active. The device must be in an inactive state before any conversion is possible.

9.13.3. Options for data protection during LUKS2 re-encryption


LUKS2 provides several options that prioritize performance or data protection during the re-encryption
process. It provides the following modes for the resilience option, and you can select any of these
modes by using the cryptsetup reencrypt --resilience resilience-mode /dev/sdx command:

checksum
The default mode. It balances data protection and performance.
This mode stores individual checksums of the sectors in the re-encryption area, which the recovery
process can detect for the sectors that were re-encrypted by LUKS2. The mode requires that the
block device sector write is atomic.

journal
The safest mode but also the slowest. Since this mode journals the re-encryption area in the binary
area, the LUKS2 writes the data twice.
none

132
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

The none mode prioritizes performance and provides no data protection. It protects the data only
against safe process termination, such as the SIGTERM signal or the user pressing Ctrl+C key. Any
unexpected system failure or application failure might result in data corruption.

If a LUKS2 re-encryption process terminates unexpectedly by force, LUKS2 can perform the recovery in
one of the following ways:

Automatically
By performing any one of the following actions triggers the automatic recovery action during the
next LUKS2 device open action:

Executing the cryptsetup open command.

Attaching the device with the systemd-cryptsetup command.

Manually
By using the cryptsetup repair /dev/sdx command on the LUKS2 device.

Additional resources

cryptsetup-reencrypt(8) and cryptsetup-repair(8) man pages on your system

9.13.4. Encrypting existing data on a block device using LUKS2


You can encrypt the existing data on a not yet encrypted device by using the LUKS2 format. A new
LUKS header is stored in the head of the device.

Prerequisites

The block device has a file system.

You have backed up your data.


WARNING

You might lose your data during the encryption process due to a hardware,
kernel, or human failure. Ensure that you have a reliable backup before you
start encrypting the data.

Procedure

1. Unmount all file systems on the device that you plan to encrypt, for example:

# umount /dev/mapper/vg00-lv00

2. Make free space for storing a LUKS header. Use one of the following options that suits your
scenario:

In the case of encrypting a logical volume, you can extend the logical volume without
resizing the file system. For example:

133
Red Hat Enterprise Linux 8 System Design Guide

# lvextend -L+32M /dev/mapper/vg00-lv00

Extend the partition by using partition management tools, such as parted.

Shrink the file system on the device. You can use the resize2fs utility for the ext2, ext3, or
ext4 file systems. Note that you cannot shrink the XFS file system.

3. Initialize the encryption:

# cryptsetup reencrypt --encrypt --init-only --reduce-device-size 32M /dev/mapper/vg00-lv00


lv00_encrypted

/dev/mapper/lv00_encrypted is now active and ready for online encryption.

4. Mount the device:

# mount /dev/mapper/lv00_encrypted /mnt/lv00_encrypted

5. Add an entry for a persistent mapping to the /etc/crypttab file:

a. Find the luksUUID:

# cryptsetup luksUUID /dev/mapper/vg00-lv00

a52e2cc9-a5be-47b8-a95d-6bdf4f2d9325

b. Open /etc/crypttab in a text editor of your choice and add a device in this file:

$ vi /etc/crypttab

lv00_encrypted UUID=a52e2cc9-a5be-47b8-a95d-6bdf4f2d9325 none

Replace a52e2cc9-a5be-47b8-a95d-6bdf4f2d9325 with your device’s luksUUID.

c. Refresh initramfs with dracut:

$ dracut -f --regenerate-all

6. Add an entry for a persistent mounting to the /etc/fstab file:

a. Find the file system’s UUID of the active LUKS block device:

$ blkid -p /dev/mapper/lv00_encrypted

/dev/mapper/lv00-encrypted: UUID="37bc2492-d8fa-4969-9d9b-bb64d3685aa9"
BLOCK_SIZE="4096" TYPE="xfs" USAGE="filesystem"

b. Open /etc/fstab in a text editor of your choice and add a device in this file, for example:

$ vi /etc/fstab

UUID=37bc2492-d8fa-4969-9d9b-bb64d3685aa9 /home auto rw,user,auto 0

134
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

Replace 37bc2492-d8fa-4969-9d9b-bb64d3685aa9 with your file system’s UUID.

7. Resume the online encryption:

# cryptsetup reencrypt --resume-only /dev/mapper/vg00-lv00

Enter passphrase for /dev/mapper/vg00-lv00:


Auto-detected active dm device 'lv00_encrypted' for data device /dev/mapper/vg00-lv00.
Finished, time 00:31.130, 10272 MiB written, speed 330.0 MiB/s

Verification

1. Verify if the existing data was encrypted:

# cryptsetup luksDump /dev/mapper/vg00-lv00

LUKS header information


Version: 2
Epoch: 4
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: a52e2cc9-a5be-47b8-a95d-6bdf4f2d9325
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)

Data segments:
0: crypt
offset: 33554432 [bytes]
length: (whole device)
cipher: aes-xts-plain64
[...]

2. View the status of the encrypted blank block device:

# cryptsetup status lv00_encrypted

/dev/mapper/lv00_encrypted is active and is in use.


type: LUKS2
cipher: aes-xts-plain64
keysize: 512 bits
key location: keyring
device: /dev/mapper/vg00-lv00

Additional resources

cryptsetup(8), cryptsetup-reencrypt(8), lvextend(8), resize2fs(8), and parted(8) man pages


on your system

9.13.5. Encrypting existing data on a block device using LUKS2 with a detached
header

You can encrypt existing data on a block device without creating free space for storing a LUKS header.
135
Red Hat Enterprise Linux 8 System Design Guide

You can encrypt existing data on a block device without creating free space for storing a LUKS header.
The header is stored in a detached location, which also serves as an additional layer of security. The
procedure uses the LUKS2 encryption format.

Prerequisites

The block device has a file system.

You have backed up your data.


WARNING

You might lose your data during the encryption process due to a hardware,
kernel, or human failure. Ensure that you have a reliable backup before you
start encrypting the data.

Procedure

1. Unmount all file systems on the device, for example:

# umount /dev/nvme0n1p1

2. Initialize the encryption:

# cryptsetup reencrypt --encrypt --init-only --header /home/header /dev/nvme0n1p1


nvme_encrypted

WARNING!
========
Header file does not exist, do you want to create it?

Are you sure? (Type 'yes' in capital letters): YES


Enter passphrase for /home/header:
Verify passphrase:
/dev/mapper/nvme_encrypted is now active and ready for online encryption.

Replace /home/header with a path to the file with a detached LUKS header. The detached
LUKS header has to be accessible to unlock the encrypted device later.

3. Mount the device:

# mount /dev/mapper/nvme_encrypted /mnt/nvme_encrypted

4. Resume the online encryption:

# cryptsetup reencrypt --resume-only --header /home/header /dev/nvme0n1p1

Enter passphrase for /dev/nvme0n1p1:


Auto-detected active dm device 'nvme_encrypted' for data device /dev/nvme0n1p1.
Finished, time 00m51s, 10 GiB written, speed 198.2 MiB/s

136
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

Verification

1. Verify if the existing data on a block device using LUKS2 with a detached header is encrypted:

# cryptsetup luksDump /home/header

LUKS header information


Version: 2
Epoch: 88
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: c4f5d274-f4c0-41e3-ac36-22a917ab0386
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)

Data segments:
0: crypt
offset: 0 [bytes]
length: (whole device)
cipher: aes-xts-plain64
sector: 512 [bytes]
[...]

2. View the status of the encrypted blank block device:

# cryptsetup status nvme_encrypted

/dev/mapper/nvme_encrypted is active and is in use.


type: LUKS2
cipher: aes-xts-plain64
keysize: 512 bits
key location: keyring
device: /dev/nvme0n1p1

Additional resources

cryptsetup(8) and cryptsetup-reencrypt(8) man pages on your system

9.13.6. Encrypting a blank block device using LUKS2


You can encrypt a blank block device, which you can use for an encrypted storage by using the LUKS2
format.

Prerequisites

A blank block device. You can use commands such as lsblk to find if there is no real data on that
device, for example, a file system.

Procedure

1. Setup a partition as an encrypted LUKS partition:

# cryptsetup luksFormat /dev/nvme0n1p1

137
Red Hat Enterprise Linux 8 System Design Guide

WARNING!
========
This will overwrite data on /dev/nvme0n1p1 irrevocably.
Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/nvme0n1p1:
Verify passphrase:

2. Open an encrypted LUKS partition:

# cryptsetup open /dev/nvme0n1p1 nvme0n1p1_encrypted

Enter passphrase for /dev/nvme0n1p1:

This unlocks the partition and maps it to a new device by using the device mapper. To not
overwrite the encrypted data, this command alerts the kernel that the device is an encrypted
device and addressed through LUKS by using the /dev/mapper/device_mapped_name path.

3. Create a file system to write encrypted data to the partition, which must be accessed through
the device mapped name:

# mkfs -t ext4 /dev/mapper/nvme0n1p1_encrypted

4. Mount the device:

# mount /dev/mapper/nvme0n1p1_encrypted mount-point

Verification

1. Verify if the blank block device is encrypted:

# cryptsetup luksDump /dev/nvme0n1p1

LUKS header information


Version: 2
Epoch: 3
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: 34ce4870-ffdf-467c-9a9e-345a53ed8a25
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)

Data segments:
0: crypt
offset: 16777216 [bytes]
length: (whole device)
cipher: aes-xts-plain64
sector: 512 [bytes]
[...]

2. View the status of the encrypted blank block device:

# cryptsetup status nvme0n1p1_encrypted

138
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

/dev/mapper/nvme0n1p1_encrypted is active and is in use.


type: LUKS2
cipher: aes-xts-plain64
keysize: 512 bits
key location: keyring
device: /dev/nvme0n1p1
sector size: 512
offset: 32768 sectors
size: 20938752 sectors
mode: read/write

Additional resources

cryptsetup(8), cryptsetup-open (8), and cryptsetup-lusFormat(8) man pages on your system

9.13.7. Configuring the LUKS passphrase in the web console


If you want to add encryption to an existing logical volume on your system, you can only do so through
formatting the volume.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

The cockpit-storaged package is installed on your system.

Available existing logical volume without encryption.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Storage.

3. In the Storage table, click the menu button, ⋮, next to the storage device you want to encrypt.

4. From the drop-down menu, select Format.

5. In the Encryption field, select the encryption specification, LUKS1 or LUKS2.

6. Set and confirm your new passphrase.

7. Optional: Modify further encryption options.

8. Finalize formatting settings.

9. Click Format.

9.13.8. Changing the LUKS passphrase in the web console


Change a LUKS passphrase on an encrypted disk or partition in the web console.

139
Red Hat Enterprise Linux 8 System Design Guide

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

The cockpit-storaged package is installed on your system.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Storage

3. In the Storage table, select the disk with encrypted data.

4. On the disk page, scroll to the Keys section and click the edit button.

5. In the Change passphrase dialog window:

a. Enter your current passphrase.

b. Enter your new passphrase.

c. Confirm your new passphrase.

140
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

6. Click Save

9.13.9. Creating a LUKS2 encrypted volume by using the storage RHEL system role

You can use the storage role to create and configure a volume encrypted with LUKS by running an
Ansible playbook.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Store your sensitive variables in an encrypted file:

a. Create the vault:

$ ansible-vault create vault.yml


New Vault password: <vault_password>
Confirm New Vault password: <vault_password>

b. After the ansible-vault create command opens an editor, enter the sensitive data in the
<key>: <value> format:

luks_password: <password>

c. Save the changes, and close the editor. Ansible encrypts the data in the vault.

2. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Manage local storage
hosts: managed-node-01.example.com
vars_files:
- vault.yml
tasks:
- name: Create and configure a volume encrypted with LUKS
ansible.builtin.include_role:
name: rhel-system-roles.storage
vars:
storage_volumes:
- name: barefs
type: disk
disks:
- sdb
fs_type: xfs
fs_label: <label>
mount_point: /mnt/data
encryption: true
encryption_password: "{{ luks_password }}"

141
Red Hat Enterprise Linux 8 System Design Guide

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.storage/README.md file on the control node.

3. Validate the playbook syntax:

$ ansible-playbook --ask-vault-pass --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

4. Run the playbook:

$ ansible-playbook --ask-vault-pass ~/playbook.yml

Verification

1. Find the luksUUID value of the LUKS encrypted volume:

# ansible managed-node-01.example.com -m command -a 'cryptsetup luksUUID


/dev/sdb'

4e4e7970-1822-470e-b55a-e91efe5d0f5c

2. View the encryption status of the volume:

# ansible managed-node-01.example.com -m command -a 'cryptsetup status luks-


4e4e7970-1822-470e-b55a-e91efe5d0f5c'

/dev/mapper/luks-4e4e7970-1822-470e-b55a-e91efe5d0f5c is active and is in use.


type: LUKS2
cipher: aes-xts-plain64
keysize: 512 bits
key location: keyring
device: /dev/sdb
...

3. Verify the created LUKS encrypted volume:

# ansible managed-node-01.example.com -m command -a 'cryptsetup luksDump


/dev/sdb'

LUKS header information


Version: 2
Epoch: 3
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: 4e4e7970-1822-470e-b55a-e91efe5d0f5c
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)

Data segments:
0: crypt
offset: 16777216 [bytes]

142
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

length: (whole device)


cipher: aes-xts-plain64
sector: 512 [bytes]
...

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

Encrypting block devices by using LUKS

Ansible vault

9.14. CONFIGURING AUTOMATED UNLOCKING OF ENCRYPTED


VOLUMES BY USING POLICY-BASED DECRYPTION
Policy-Based Decryption (PBD) is a collection of technologies that enable unlocking encrypted root and
secondary volumes of hard drives on physical and virtual machines. PBD uses a variety of unlocking
methods, such as user passwords, a Trusted Platform Module (TPM) device, a PKCS #11 device
connected to a system, for example, a smart card, or a special network server.

PBD allows combining different unlocking methods into a policy, which makes it possible to unlock the
same volume in different ways. The current implementation of the PBD in RHEL consists of the Clevis
framework and plug-ins called pins. Each pin provides a separate unlocking capability. Currently, the
following pins are available:

tang
Allows unlocking volumes using a network server.
tpm2
allows unlocking volumes using a TPM2 policy.
sss
allows deploying high-availability systems using the Shamir’s Secret Sharing (SSS) cryptographic
scheme.

9.14.1. Network-bound disk encryption


The Network Bound Disc Encryption (NBDE) is a subcategory of Policy-Based Decryption (PBD) that
allows binding encrypted volumes to a special network server. The current implementation of the NBDE
includes a Clevis pin for the Tang server and the Tang server itself.

In RHEL, NBDE is implemented through the following components and technologies:

Figure 9.1. NBDE scheme when using a LUKS1-encrypted volume. The luksmeta package is not used
143
Red Hat Enterprise Linux 8 System Design Guide

Figure 9.1. NBDE scheme when using a LUKS1-encrypted volume. The luksmeta package is not used
for LUKS2 volumes.

Tang is a server for binding data to network presence. It makes a system containing your data available
when the system is bound to a certain secure network. Tang is stateless and does not require TLS or
authentication. Unlike escrow-based solutions, where the server stores all encryption keys and has
knowledge of every key ever used, Tang never interacts with any client keys, so it never gains any
identifying information from the client.

Clevis is a pluggable framework for automated decryption. In NBDE, Clevis provides automated
unlocking of LUKS volumes. The clevis package provides the client side of the feature.

A Clevis pin is a plug-in into the Clevis framework. One of such pins is a plug-in that implements
interactions with the NBDE server — Tang.

Clevis and Tang are generic client and server components that provide network-bound encryption. In
RHEL, they are used in conjunction with LUKS to encrypt and decrypt root and non-root storage
volumes to accomplish Network-Bound Disk Encryption.

Both client- and server-side components use the José library to perform encryption and decryption
operations.

When you begin provisioning NBDE, the Clevis pin for Tang server gets a list of the Tang server’s
advertised asymmetric keys. Alternatively, since the keys are asymmetric, a list of Tang’s public keys can
be distributed out of band so that clients can operate without access to the Tang server. This mode is
called offline provisioning.

The Clevis pin for Tang uses one of the public keys to generate a unique, cryptographically-strong
encryption key. Once the data is encrypted using this key, the key is discarded. The Clevis client should
store the state produced by this provisioning operation in a convenient location. This process of
encrypting data is the provisioning step.

The LUKS version 2 (LUKS2) is the default disk-encryption format in RHEL, hence, the provisioning
state for NBDE is stored as a token in a LUKS2 header. The leveraging of provisioning state for NBDE by
the luksmeta package is used only for volumes encrypted with LUKS1.

The Clevis pin for Tang supports both LUKS1 and LUKS2 without specification need. Clevis can encrypt
plain-text files but you have to use the cryptsetup tool for encrypting block devices. See the Encrypting
block devices using LUKS for more information.

144
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

When the client is ready to access its data, it loads the metadata produced in the provisioning step and it
responds to recover the encryption key. This process is the recovery step.

In NBDE, Clevis binds a LUKS volume using a pin so that it can be automatically unlocked. After
successful completion of the binding process, the disk can be unlocked using the provided Dracut
unlocker.

NOTE

If the kdump kernel crash dumping mechanism is set to save the content of the system
memory to a LUKS-encrypted device, you are prompted for entering a password during
the second kernel boot.

Additional resources

NBDE (Network-Bound Disk Encryption) Technology Knowledgebase article

tang(8), clevis(1), jose(1), and clevis-luks-unlockers(7) man pages on your system

How to set up Network-Bound Disk Encryption with multiple LUKS devices (Clevis + Tang
unlocking) Knowledgebase article

9.14.2. Deploying a Tang server with SELinux in enforcing mode


You can use a Tang server to automatically unlock LUKS-encrypted volumes on Clevis-enabled clients.
In the minimalistic scenario, you deploy a Tang server on port 80 by installing the tang package and
entering the systemctl enable tangd.socket --now command. The following example procedure
demonstrates the deployment of a Tang server running on a custom port as a confined service in
SELinux enforcing mode.

Prerequisites

The policycoreutils-python-utils package and its dependencies are installed.

The firewalld service is running.

Procedure

1. To install the tang package and its dependencies, enter the following command as root:

# yum install tang

2. Pick an unoccupied port, for example, 7500/tcp, and allow the tangd service to bind to that
port:

# semanage port -a -t tangd_port_t -p tcp 7500

Note that a port can be used only by one service at a time, and thus an attempt to use an
already occupied port implies the ValueError: Port already defined error message.

3. Open the port in the firewall:

# firewall-cmd --add-port=7500/tcp
# firewall-cmd --runtime-to-permanent

145
Red Hat Enterprise Linux 8 System Design Guide

4. Enable the tangd service:

# systemctl enable tangd.socket

5. Create an override file:

# systemctl edit tangd.socket

6. In the following editor screen, which opens an empty override.conf file located in the
/etc/systemd/system/tangd.socket.d/ directory, change the default port for the Tang server
from 80 to the previously picked number by adding the following lines:

[Socket]
ListenStream=
ListenStream=7500

IMPORTANT

Insert the previous code snippet between the lines starting with # Anything
between here and # Lines below this, otherwise the system discards your
changes.

7. Save the changes by pressing Ctrl+O and Enter. Exit the editor by pressing Ctrl+X.

8. Reload the changed configuration:

# systemctl daemon-reload

9. Check that your configuration is working:

# systemctl show tangd.socket -p Listen


Listen=[::]:7500 (Stream)

10. Start the tangd service:

# systemctl restart tangd.socket

Because tangd uses the systemd socket activation mechanism, the server starts as soon as the
first connection comes in. A new set of cryptographic keys is automatically generated at the first
start. To perform cryptographic operations such as manual key generation, use the jose utility.

Verification

On your NBDE client, verify that your Tang server works correctly by using the following
command. The command must return the identical message you pass for encryption and
decryption:

# echo test | clevis encrypt tang '{"url":"<tang.server.example.com:7500>"}' -y | clevis decrypt


test

Additional resources

tang(8), semanage(8), firewall-cmd(1), jose(1), systemd.unit(5), and systemd.socket(5) man


146
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

tang(8), semanage(8), firewall-cmd(1), jose(1), systemd.unit(5), and systemd.socket(5) man


pages on your system

9.14.3. Rotating Tang server keys and updating bindings on clients


For security reasons, rotate your Tang server keys and update existing bindings on clients periodically.
The precise interval at which you should rotate them depends on your application, key sizes, and
institutional policy.

Alternatively, you can rotate Tang keys by using the nbde_server RHEL system role. See Using the
nbde_server system role for setting up multiple Tang servers for more information.

Prerequisites

A Tang server is running.

The clevis and clevis-luks packages are installed on your clients.

Note that clevis luks list, clevis luks report, and clevis luks regen have been introduced in
RHEL 8.2.

Procedure

1. Rename all keys in the /var/db/tang key database directory to have a leading . to hide them
from advertisement. Note that the file names in the following example differs from unique file
names in the key database directory of your Tang server:

# cd /var/db/tang
# ls -l
-rw-r--r--. 1 root root 349 Feb 7 14:55 UV6dqXSwe1bRKG3KbJmdiR020hY.jwk
-rw-r--r--. 1 root root 354 Feb 7 14:55 y9hxLTQSiSB5jSEGWnjhY8fDTJU.jwk
# mv UV6dqXSwe1bRKG3KbJmdiR020hY.jwk .UV6dqXSwe1bRKG3KbJmdiR020hY.jwk
# mv y9hxLTQSiSB5jSEGWnjhY8fDTJU.jwk .y9hxLTQSiSB5jSEGWnjhY8fDTJU.jwk

2. Check that you renamed and therefore hid all keys from the Tang server advertisement:

# ls -l
total 0

3. Generate new keys using the /usr/libexec/tangd-keygen command in /var/db/tang on the Tang
server:

# /usr/libexec/tangd-keygen /var/db/tang
# ls /var/db/tang
3ZWS6-cDrCG61UPJS2BMmPU4I54.jwk zyLuX6hijUy_PSeUEFDi7hi38.jwk

4. Check that your Tang server advertises the signing key from the new key pair, for example:

# tang-show-keys 7500
3ZWS6-cDrCG61UPJS2BMmPU4I54

5. On your NBDE clients, use the clevis luks report command to check if the keys advertised by
the Tang server remains the same. You can identify slots with the relevant binding using the
clevis luks list command, for example:

147
Red Hat Enterprise Linux 8 System Design Guide

# clevis luks list -d /dev/sda2


1: tang '{"url":"http://tang.srv"}'
# clevis luks report -d /dev/sda2 -s 1
...
Report detected that some keys were rotated.
Do you want to regenerate luks metadata with "clevis luks regen -d /dev/sda2 -s 1"? [ynYN]

6. To regenerate LUKS metadata for the new keys either press y to the prompt of the previous
command, or use the clevis luks regen command:

# clevis luks regen -d /dev/sda2 -s 1

7. When you are sure that all old clients use the new keys, you can remove the old keys from the
Tang server, for example:

# cd /var/db/tang
# rm .*.jwk


WARNING

Removing the old keys while clients are still using them can result in data loss. If you
accidentally remove such keys, use the clevis luks regen command on the clients,
and provide your LUKS password manually.

Additional resources

tang-show-keys(1), clevis-luks-list(1), clevis-luks-report(1), and clevis-luks-regen(1) man


pages on your system

9.14.4. Configuring automated unlocking by using a Tang key in the web console
You can configure automated unlocking of a LUKS-encrypted storage device using a key provided by a
Tang server.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

The cockpit-storaged and clevis-luks packages are installed on your system.

The cockpit.socket service is running at port 9090.

A Tang server is available. See Deploying a Tang server with SELinux in enforcing mode for
details.

You have root privileges or permissions to enter administrative commands with sudo.

Procedure

148
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Switch to administrative access, provide your credentials, and click Storage. In the Storage
table, click the disk that contains an encrypted volume you plan to add to unlock automatically.

3. In the following page with details of the selected disk, click + in the Keys section to add a Tang
key:

4. Select Tang keyserver as Key source, provide the address of your Tang server, and a password
that unlocks the LUKS-encrypted device. Click Add to confirm:

149
Red Hat Enterprise Linux 8 System Design Guide

The following dialog window provides a command to verify that the key hash matches.

5. In a terminal on the Tang server, use the tang-show-keys command to display the key hash for
comparison. In this example, the Tang server is running on the port 7500:

# tang-show-keys 7500
x100_1k6GPiDOaMlL3WbpCjHOy9ul1bSfdhI3M08wO0

6. Click Trust key when the key hashes in the web console and in the output of previously listed
commands are the same:

7. In RHEL 8.8 and later, after you select an encrypted root file system and a Tang server, you can
skip adding the rd.neednet=1 parameter to the kernel command line, installing the clevis-
dracut package, and regenerating an initial RAM disk ( initrd). For non-root file systems, the
web console now enables the remote-cryptsetup.target and clevis-luks-akspass.path
systemd units, installs the clevis-systemd package, and adds the _netdev parameter to the
fstab and crypttab configuration files.

Verification

1. Check that the newly added Tang key is now listed in the Keys section with the Keyserver type:

150
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

2. Verify that the bindings are available for the early boot, for example:

# lsinitrd | grep clevis-luks


lrwxrwxrwx 1 root root 48 Jan 4 02:56
etc/systemd/system/cryptsetup.target.wants/clevis-luks-askpass.path ->
/usr/lib/systemd/system/clevis-luks-askpass.path

Additional resources

Configuring automated unlocking of encrypted volumes using policy-based decryption

9.14.5. Basic NBDE and TPM2 encryption-client operations


The Clevis framework can encrypt plain-text files and decrypt both ciphertexts in the JSON Web
Encryption (JWE) format and LUKS-encrypted block devices. Clevis clients can use either Tang network
servers or Trusted Platform Module 2.0 (TPM 2.0) chips for cryptographic operations.

The following commands demonstrate the basic functionality provided by Clevis on examples containing
plain-text files. You can also use them for troubleshooting your NBDE or Clevis+TPM deployments.

Encryption client bound to a Tang server

To check that a Clevis encryption client binds to a Tang server, use the clevis encrypt tang
sub-command:

$ clevis encrypt tang '{"url":"http://tang.srv:port"}' < input-plain.txt > secret.jwe


The advertisement contains the following signing keys:

_OsIk0T-E2l6qjfdDiwVmidoZjA

Do you wish to trust these keys? [ynYN] y

Change the http://tang.srv:port URL in the previous example to match the URL of the server

151
Red Hat Enterprise Linux 8 System Design Guide

Change the http://tang.srv:port URL in the previous example to match the URL of the server
where tang is installed. The secret.jwe output file contains your encrypted cipher text in the
JWE format. This cipher text is read from the input-plain.txt input file.

Alternatively, if your configuration requires a non-interactive communication with a Tang server


without SSH access, you can download an advertisement and save it to a file:

$ curl -sfg http://tang.srv:port/adv -o adv.jws

Use the advertisement in the adv.jws file for any following tasks, such as encryption of files or
messages:

$ echo 'hello' | clevis encrypt tang '{"url":"http://tang.srv:port","adv":"adv.jws"}'

To decrypt data, use the clevis decrypt command and provide the cipher text (JWE):

$ clevis decrypt < secret.jwe > output-plain.txt

Encryption client using TPM 2.0

To encrypt using a TPM 2.0 chip, use the clevis encrypt tpm2 sub-command with the only
argument in form of the JSON configuration object:

$ clevis encrypt tpm2 '{}' < input-plain.txt > secret.jwe

To choose a different hierarchy, hash, and key algorithms, specify configuration properties, for
example:

$ clevis encrypt tpm2 '{"hash":"sha256","key":"rsa"}' < input-plain.txt > secret.jwe

To decrypt the data, provide the ciphertext in the JSON Web Encryption (JWE) format:

$ clevis decrypt < secret.jwe > output-plain.txt

The pin also supports sealing data to a Platform Configuration Registers (PCR) state. That way, the
data can only be unsealed if the PCR hashes values match the policy used when sealing.

For example, to seal the data to the PCR with index 0 and 7 for the SHA-256 bank:

$ clevis encrypt tpm2 '{"pcr_bank":"sha256","pcr_ids":"0,7"}' < input-plain.txt > secret.jwe

152
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES


WARNING

Hashes in PCRs can be rewritten, and you no longer can unlock your encrypted
volume. For this reason, add a strong passphrase that enable you to unlock the
encrypted volume manually even when a value in a PCR changes.

If the system cannot automatically unlock your encrypted volume after an upgrade
of the shim-x64 package, follow the steps in the Clevis TPM2 no longer decrypts
LUKS devices after a restart KCS article.

Additional resources

clevis-encrypt-tang(1), clevis-luks-unlockers(7), clevis(1), and clevis-encrypt-tpm2(1) man


pages on your system

clevis, clevis decrypt, and clevis encrypt tang commands without any arguments show the
built-in CLI help, for example:

$ clevis encrypt tang


Usage: clevis encrypt tang CONFIG < PLAINTEXT > JWE
...

9.14.6. Configuring NBDE clients for automated unlocking of LUKS-encrypted


volumes
With the Clevis framework, you can configure clients for automated unlocking of LUKS-encrypted
volumes when a selected Tang server is available. This creates an NBDE (Network-Bound Disk
Encryption) deployment.

Prerequisites

A Tang server is running and available.

Procedure

1. To automatically unlock an existing LUKS-encrypted volume, install the clevis-luks subpackage:

# yum install clevis-luks

2. Identify the LUKS-encrypted volume for PBD. In the following example, the block device is
referred as /dev/sda2:

# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 12G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 11G 0 part
└─luks-40e20552-2ade-4954-9d56-565aa7994fb6 253:0 0 11G 0 crypt
├─rhel-root 253:0 0 9.8G 0 lvm /
└─rhel-swap 253:1 0 1.2G 0 lvm [SWAP]

153
Red Hat Enterprise Linux 8 System Design Guide

3. Bind the volume to a Tang server using the clevis luks bind command:

# clevis luks bind -d /dev/sda2 tang '{"url":"http://tang.srv"}'


The advertisement contains the following signing keys:

_OsIk0T-E2l6qjfdDiwVmidoZjA

Do you wish to trust these keys? [ynYN] y


You are about to initialize a LUKS device for metadata storage.
Attempting to initialize it may result in data loss if data was
already written into the LUKS header gap in a different format.
A backup is advised before initialization is performed.

Do you wish to initialize /dev/sda2? [yn] y


Enter existing LUKS password:

This command performs four steps:

a. Creates a new key with the same entropy as the LUKS master key.

b. Encrypts the new key with Clevis.

c. Stores the Clevis JWE object in the LUKS2 header token or uses LUKSMeta if the non-
default LUKS1 header is used.

d. Enables the new key for use with LUKS.

NOTE

The binding procedure assumes that there is at least one free LUKS password
slot. The clevis luks bind command takes one of the slots.

The volume can now be unlocked with your existing password as well as with the Clevis policy.

4. To enable the early boot system to process the disk binding, use the dracut tool on an already
installed system. In RHEL, Clevis produces a generic initrd (initial RAM disk) without host-
specific configuration options and does not automatically add parameters such as rd.neednet=1
to the kernel command line. If your configuration relies on a Tang pin that requires network
during early boot, use the --hostonly-cmdline argument and dracut adds rd.neednet=1 when it
detects a Tang binding:

a. Install the clevis-dracut package:

# yum install clevis-dracut

b. Regenerate the initial RAM disk:

# dracut -fv --regenerate-all --hostonly-cmdline

c. Alternatively, create a .conf file in the /etc/dracut.conf.d/ directory, and add the
hostonly_cmdline=yes option to the file. Then, you can use dracut without --hostonly-
cmdline, for example:

154
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

# echo "hostonly_cmdline=yes" > /etc/dracut.conf.d/clevis.conf


# dracut -fv --regenerate-all

d. You can also ensure that networking for a Tang pin is available during early boot by using
the grubby tool on the system where Clevis is installed:

# grubby --update-kernel=ALL --args="rd.neednet=1"

Verification

1. Verify that the Clevis JWE object is successfully placed in a LUKS header, use the clevis luks
list command:

# clevis luks list -d /dev/sda2


1: tang '{"url":"http://tang.srv:port"}'

2. Check that the bindings are available for the early boot, for example:

# lsinitrd | grep clevis-luks


lrwxrwxrwx 1 root root 48 Jan 4 02:56
etc/systemd/system/cryptsetup.target.wants/clevis-luks-askpass.path ->
/usr/lib/systemd/system/clevis-luks-askpass.path

Additional resources

clevis-luks-bind(1) and dracut.cmdline(7) man pages on your system

Looking forward to Linux network configuration in the initial ramdisk (initrd) (Red Hat Enable
Sysadmin)

9.14.7. Configuring NBDE clients with static IP configuration


To use NBDE for clients with static IP configuration (without DHCP), you must pass your network
configuration to the dracut tool manually.

Prerequisites

A Tang server is running and available.

The NBDE client is configured for automated unlocking of encrypted volumes by the Tang
server.
For details, see Configuring NBDE clients for automated unlocking of LUKS-encrypted volumes .

Procedure

1. You can provide your static network configuration as a value for the kernel-cmdline option in a
dracut command, for example:

# dracut -fv --regenerate-all --kernel-cmdline


"ip=192.0.2.10::192.0.2.1:255.255.255.0::ens3:none nameserver=192.0.2.100"

2. Alternatively, create a .conf file in the /etc/dracut.conf.d/ directory with the static network
155
Red Hat Enterprise Linux 8 System Design Guide

2. Alternatively, create a .conf file in the /etc/dracut.conf.d/ directory with the static network
information and then, regenerate the initial RAM disk image:

# cat /etc/dracut.conf.d/static_ip.conf
kernel_cmdline="ip=192.0.2.10::192.0.2.1:255.255.255.0::ens3:none
nameserver=192.0.2.100"
# dracut -fv --regenerate-all

9.14.8. Configuring manual enrollment of LUKS-encrypted volumes by using a TPM


2.0 policy
You can configure unlocking of LUKS-encrypted volumes by using a Trusted Platform Module 2.0 (TPM
2.0) policy.

Prerequisites

An accessible TPM 2.0-compatible device.

A system with the 64-bit Intel or 64-bit AMD architecture.

Procedure

1. To automatically unlock an existing LUKS-encrypted volume, install the clevis-luks subpackage:

# yum install clevis-luks

2. Identify the LUKS-encrypted volume for PBD. In the following example, the block device is
referred as /dev/sda2:

# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 12G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 11G 0 part
└─luks-40e20552-2ade-4954-9d56-565aa7994fb6 253:0 0 11G 0 crypt
├─rhel-root 253:0 0 9.8G 0 lvm /
└─rhel-swap 253:1 0 1.2G 0 lvm [SWAP]

3. Bind the volume to a TPM 2.0 device using the clevis luks bind command, for example:

# clevis luks bind -d /dev/sda2 tpm2 '{"hash":"sha256","key":"rsa"}'


...
Do you wish to initialize /dev/sda2? [yn] y
Enter existing LUKS password:

This command performs four steps:

a. Creates a new key with the same entropy as the LUKS master key.

b. Encrypts the new key with Clevis.

c. Stores the Clevis JWE object in the LUKS2 header token or uses LUKSMeta if the non-
default LUKS1 header is used.

156
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

d. Enables the new key for use with LUKS.

NOTE

The binding procedure assumes that there is at least one free LUKS
password slot. The clevis luks bind command takes one of the slots.

Alternatively, if you want to seal data to specific Platform Configuration Registers (PCR)
states, add the pcr_bank and pcr_ids values to the clevis luks bind command, for
example:

# clevis luks bind -d /dev/sda2 tpm2


'{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"0,1"}'

IMPORTANT

Because the data can only be unsealed if PCR hashes values match the
policy used when sealing and the hashes can be rewritten, add a strong
passphrase that enable you to unlock the encrypted volume manually when a
value in a PCR changes.

If the system cannot automatically unlock your encrypted volume after an


upgrade of the shim-x64 package, follow the steps in the Clevis TPM2 no
longer decrypts LUKS devices after a restart KCS article.

4. The volume can now be unlocked with your existing password as well as with the Clevis policy.

5. To enable the early boot system to process the disk binding, use the dracut tool on an already
installed system:

# yum install clevis-dracut


# dracut -fv --regenerate-all

Verification

1. To verify that the Clevis JWE object is successfully placed in a LUKS header, use the clevis
luks list command:

# clevis luks list -d /dev/sda2


1: tpm2 '{"hash":"sha256","key":"rsa"}'

Additional resources

clevis-luks-bind(1), clevis-encrypt-tpm2(1), and dracut.cmdline(7) man pages on your


system

9.14.9. Removing a Clevis pin from a LUKS-encrypted volume manually


Use the following procedure for manual removing the metadata created by the clevis luks bind
command and also for wiping a key slot that contains passphrase added by Clevis.

IMPORTANT
157
Red Hat Enterprise Linux 8 System Design Guide

IMPORTANT

The recommended way to remove a Clevis pin from a LUKS-encrypted volume is through
the clevis luks unbind command. The removal procedure using clevis luks unbind
consists of only one step and works for both LUKS1 and LUKS2 volumes. The following
example command removes the metadata created by the binding step and wipe the key
slot 1 on the /dev/sda2 device:

# clevis luks unbind -d /dev/sda2 -s 1

Prerequisites

A LUKS-encrypted volume with a Clevis binding.

Procedure

1. Check which LUKS version the volume, for example /dev/sda2, is encrypted by and identify a
slot and a token that is bound to Clevis:

# cryptsetup luksDump /dev/sda2


LUKS header information
Version: 2
...
Keyslots:
0: luks2
...
1: luks2
Key: 512 bits
Priority: normal
Cipher: aes-xts-plain64
...
Tokens:
0: clevis
Keyslot: 1
...

In the previous example, the Clevis token is identified by 0 and the associated key slot is 1.

2. In case of LUKS2 encryption, remove the token:

# cryptsetup token remove --token-id 0 /dev/sda2

3. If your device is encrypted by LUKS1, which is indicated by the Version: 1 string in the output of
the cryptsetup luksDump command, perform this additional step with the luksmeta wipe
command:

# luksmeta wipe -d /dev/sda2 -s 1

4. Wipe the key slot containing the Clevis passphrase:

# cryptsetup luksKillSlot /dev/sda2 1

Additional resources

158
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

clevis-luks-unbind(1), cryptsetup(8), and luksmeta(8) man pages on your system

9.14.10. Configuring automated enrollment of LUKS-encrypted volumes by using


Kickstart
Follow the steps in this procedure to configure an automated installation process that uses Clevis for
the enrollment of LUKS-encrypted volumes.

Procedure

1. Instruct Kickstart to partition the disk such that LUKS encryption has enabled for all mount
points, other than /boot, with a temporary password. The password is temporary for this step of
the enrollment process.

part /boot --fstype="xfs" --ondisk=vda --size=256


part / --fstype="xfs" --ondisk=vda --grow --encrypted --passphrase=temppass

Note that OSPP-compliant systems require a more complex configuration, for example:

part /boot --fstype="xfs" --ondisk=vda --size=256


part / --fstype="xfs" --ondisk=vda --size=2048 --encrypted --passphrase=temppass
part /var --fstype="xfs" --ondisk=vda --size=1024 --encrypted --passphrase=temppass
part /tmp --fstype="xfs" --ondisk=vda --size=1024 --encrypted --passphrase=temppass
part /home --fstype="xfs" --ondisk=vda --size=2048 --grow --encrypted --
passphrase=temppass
part /var/log --fstype="xfs" --ondisk=vda --size=1024 --encrypted --passphrase=temppass
part /var/log/audit --fstype="xfs" --ondisk=vda --size=1024 --encrypted --
passphrase=temppass

2. Install the related Clevis packages by listing them in the %packages section:

%packages
clevis-dracut
clevis-luks
clevis-systemd
%end

3. Optional: To ensure that you can unlock the encrypted volume manually when required, add a
strong passphrase before you remove the temporary passphrase. See the How to add a
passphrase, key, or keyfile to an existing LUKS device article for more information.

4. Call clevis luks bind to perform binding in the %post section. Afterward, remove the
temporary password:

%post
clevis luks bind -y -k - -d /dev/vda2 \
tang '{"url":"http://tang.srv"}' <<< "temppass"
cryptsetup luksRemoveKey /dev/vda2 <<< "temppass"
dracut -fv --regenerate-all
%end

If your configuration relies on a Tang pin that requires network during early boot or you use
NBDE clients with static IP configurations, you have to modify the dracut command as
described in Configuring manual enrollment of LUKS-encrypted volumes .

159
Red Hat Enterprise Linux 8 System Design Guide

Note that the -y option for the clevis luks bind command is available from RHEL 8.3. In RHEL
8.2 and older, replace -y by -f in the clevis luks bind command and download the
advertisement from the Tang server:

%post
curl -sfg http://tang.srv/adv -o adv.jws
clevis luks bind -f -k - -d /dev/vda2 \
tang '{"url":"http://tang.srv","adv":"adv.jws"}' <<< "temppass"
cryptsetup luksRemoveKey /dev/vda2 <<< "temppass"
dracut -fv --regenerate-all
%end


WARNING

The cryptsetup luksRemoveKey command prevents any further


administration of a LUKS2 device on which you apply it. You can recover a
removed master key using the dmsetup command only for LUKS1 devices.

You can use an analogous procedure when using a TPM 2.0 policy instead of a Tang server.

Additional resources

clevis(1), clevis-luks-bind(1), cryptsetup(8), and dmsetup(8) man pages on your system

Automatically installing RHEL

9.14.11. Configuring automated unlocking of a LUKS-encrypted removable storage


device
You can set up an automated unlocking process of a LUKS-encrypted USB storage device.

Procedure

1. To automatically unlock a LUKS-encrypted removable storage device, such as a USB drive,


install the clevis-udisks2 package:

# yum install clevis-udisks2

2. Reboot the system, and then perform the binding step using the clevis luks bind command as
described in Configuring manual enrollment of LUKS-encrypted volumes , for example:

# clevis luks bind -d /dev/sdb1 tang '{"url":"http://tang.srv"}'

3. The LUKS-encrypted removable device can be now unlocked automatically in your GNOME
desktop session. The device bound to a Clevis policy can be also unlocked by the clevis luks
unlock command:

# clevis luks unlock -d /dev/sdb1

160
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

You can use an analogous procedure when using a TPM 2.0 policy instead of a Tang server.

Additional resources

clevis-luks-unlockers(7) man page on your system

9.14.12. Deploying high-availability NBDE systems


Tang provides two methods for building a high-availability deployment:

Client redundancy (recommended)


Clients should be configured with the ability to bind to multiple Tang servers. In this setup, each Tang
server has its own keys and clients can decrypt by contacting a subset of these servers. Clevis already
supports this workflow through its sss plug-in. Red Hat recommends this method for a high-
availability deployment.
Key sharing
For redundancy purposes, more than one instance of Tang can be deployed. To set up a second or
any subsequent instance, install the tang packages and copy the key directory to the new host using
rsync over SSH. Note that Red Hat does not recommend this method because sharing keys
increases the risk of key compromise and requires additional automation infrastructure.

High-available NBDE using Shamir’s Secret Sharing


Shamir’s Secret Sharing (SSS) is a cryptographic scheme that divides a secret into several unique parts.
To reconstruct the secret, a number of parts is required. The number is called threshold and SSS is also
referred to as a thresholding scheme.

Clevis provides an implementation of SSS. It creates a key and divides it into a number of pieces. Each
piece is encrypted using another pin including even SSS recursively. Additionally, you define the
threshold t. If an NBDE deployment decrypts at least t pieces, then it recovers the encryption key and
the decryption process succeeds. When Clevis detects a smaller number of parts than specified in the
threshold, it prints an error message.

Example 1: Redundancy with two Tang servers


The following command decrypts a LUKS-encrypted device when at least one of two Tang servers is
available:

# clevis luks bind -d /dev/sda1 sss '{"t":1,"pins":{"tang":[{"url":"http://tang1.srv"},


{"url":"http://tang2.srv"}]}}'

The previous command used the following configuration scheme:

{
"t":1,
"pins":{
"tang":[
{
"url":"http://tang1.srv"
},
{
"url":"http://tang2.srv"
}
]
}
}

161
Red Hat Enterprise Linux 8 System Design Guide

In this configuration, the SSS threshold t is set to 1 and the clevis luks bind command successfully
reconstructs the secret if at least one from two listed tang servers is available.

Example 2: Shared secret on a Tang server and a TPM device


The following command successfully decrypts a LUKS-encrypted device when both the tang server and
the tpm2 device are available:

# clevis luks bind -d /dev/sda1 sss '{"t":2,"pins":{"tang":[{"url":"http://tang1.srv"}], "tpm2":


{"pcr_ids":"0,7"}}}'

The configuration scheme with the SSS threshold 't' set to '2' is now:

{
"t":2,
"pins":{
"tang":[
{
"url":"http://tang1.srv"
}
],
"tpm2":{
"pcr_ids":"0,7"
}
}
}

Additional resources

tang(8) (section High Availability), clevis(1) (section Shamir’s Secret Sharing), and clevis-
encrypt-sss(1) man pages on your system

9.14.13. Deployment of virtual machines in a NBDE network


The clevis luks bind command does not change the LUKS master key. This implies that if you create a
LUKS-encrypted image for use in a virtual machine or cloud environment, all the instances that run this
image share a master key. This is extremely insecure and should be avoided at all times.

This is not a limitation of Clevis but a design principle of LUKS. If your scenario requires having encrypted
root volumes in a cloud, perform the installation process (usually using Kickstart) for each instance of
Red Hat Enterprise Linux in the cloud as well. The images cannot be shared without also sharing a LUKS
master key.

To deploy automated unlocking in a virtualized environment, use systems such as lorax or virt-install
together with a Kickstart file (see Configuring automated enrollment of LUKS-encrypted volumes using
Kickstart) or another automated provisioning tool to ensure that each encrypted VM has a unique
master key.

Additional resources

clevis-luks-bind(1) man page on your system

9.14.14. Building automatically-enrollable VM images for cloud environments by


using NBDE

Deploying automatically-enrollable encrypted images in a cloud environment can provide a unique set
162
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

Deploying automatically-enrollable encrypted images in a cloud environment can provide a unique set
of challenges. Like other virtualization environments, it is recommended to reduce the number of
instances started from a single image to avoid sharing the LUKS master key.

Therefore, the best practice is to create customized images that are not shared in any public repository
and that provide a base for the deployment of a limited amount of instances. The exact number of
instances to create should be defined by deployment’s security policies and based on the risk tolerance
associated with the LUKS master key attack vector.

To build LUKS-enabled automated deployments, systems such as Lorax or virt-install together with a
Kickstart file should be used to ensure master key uniqueness during the image building process.

Cloud environments enable two Tang server deployment options which we consider here. First, the Tang
server can be deployed within the cloud environment itself. Second, the Tang server can be deployed
outside of the cloud on independent infrastructure with a VPN link between the two infrastructures.

Deploying Tang natively in the cloud does allow for easy deployment. However, given that it shares
infrastructure with the data persistence layer of ciphertext of other systems, it may be possible for both
the Tang server’s private key and the Clevis metadata to be stored on the same physical disk. Access to
this physical disk permits a full compromise of the ciphertext data.

IMPORTANT

Always maintain a physical separation between the location where the data is stored and
the system where Tang is running. This separation between the cloud and the Tang
server ensures that the Tang server’s private key cannot be accidentally combined with
the Clevis metadata. It also provides local control of the Tang server if the cloud
infrastructure is at risk.

9.14.15. Deploying Tang as a container


The tang container image provides Tang-server decryption capabilities for Clevis clients that run either
in OpenShift Container Platform (OCP) clusters or in separate virtual machines.

Prerequisites

The podman package and its dependencies are installed on the system.

You have logged in on the registry.redhat.io container catalog using the podman login
registry.redhat.io command. See Red Hat Container Registry Authentication for more
information.

The Clevis client is installed on systems containing LUKS-encrypted volumes that you want to
automatically unlock by using a Tang server.

Procedure

1. Pull the tang container image from the registry.redhat.io registry:

# podman pull registry.redhat.io/rhel8/tang

2. Run the container, specify its port, and specify the path to the Tang keys. The previous example
runs the tang container, specifies the port 7500, and indicates a path to the Tang keys of the
/var/db/tang directory:

163
Red Hat Enterprise Linux 8 System Design Guide

# podman run -d -p 7500:7500 -v tang-keys:/var/db/tang --name tang


registry.redhat.io/rhel8/tang

Note that Tang uses port 80 by default but this may collide with other services such as the
Apache HTTP server.

3. Optional: For increased security, rotate the Tang keys periodically. You can use the tangd-
rotate-keys script, for example:

# podman run --rm -v tang-keys:/var/db/tang registry.redhat.io/rhel8/tang tangd-rotate-keys -


v -d /var/db/tang
Rotated key 'rZAMKAseaXBe0rcKXL1hCCIq-DY.jwk' -> .'rZAMKAseaXBe0rcKXL1hCCIq-
DY.jwk'
Rotated key 'x1AIpc6WmnCU-CabD8_4q18vDuw.jwk' -> .'x1AIpc6WmnCU-
CabD8_4q18vDuw.jwk'
Created new key GrMMX_WfdqomIU_4RyjpcdlXb0E.jwk
Created new key _dTTfn17sZZqVAp80u3ygFDHtjk.jwk
Keys rotated successfully.

Verification

On a system that contains LUKS-encrypted volumes for automated unlocking by the presence
of the Tang server, check that the Clevis client can encrypt and decrypt a plain-text message
using Tang:

# echo test | clevis encrypt tang '{"url":"http://localhost:7500"}' | clevis decrypt


The advertisement contains the following signing keys:

x1AIpc6WmnCU-CabD8_4q18vDuw

Do you wish to trust these keys? [ynYN] y


test

The previous example command shows the test string at the end of its output when a Tang
server is available on the localhost URL and communicates through port 7500.

Additional resources

podman(1), clevis(1), and tang(8) man pages on your system

For more details on automated unlocking of LUKS-encrypted volumes using Clevis and Tang,
see the Configuring automated unlocking of encrypted volumes using policy-based decryption
chapter.

9.14.16. Configuring NBDE by using RHEL system roles


You can use the nbde_client and nbde_server RHEL system roles for automated deployments of
Policy-Based Decryption (PBD) solutions using Clevis and Tang. The rhel-system-roles package
contains these system roles, the related examples, and also the reference documentation.

9.14.16.1. Using the nbde_server RHEL system role for setting up multiple Tang servers

By using the nbde_server system role, you can deploy and manage a Tang server as part of an
automated disk encryption solution. This role supports the following features:

164
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

Rotating Tang keys

Deploying and backing up Tang keys

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Deploy a Tang server
hosts: tang.server.example.com
tasks:
- name: Install and configure periodic key rotation
ansible.builtin.include_role:
name: rhel-system-roles.nbde_server
vars:
nbde_server_rotate_keys: yes
nbde_server_manage_firewall: true
nbde_server_manage_selinux: true

This example playbook ensures deploying of your Tang server and a key rotation.

The settings specified in the example playbook include the following:

nbde_server_manage_firewall: true
Use the firewall system role to manage ports used by the nbde_server role.
nbde_server_manage_selinux: true
Use the selinux system role to manage ports used by the nbde_server role.
For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.nbde_server/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

On your NBDE client, verify that your Tang server works correctly by using the following

165
Red Hat Enterprise Linux 8 System Design Guide

On your NBDE client, verify that your Tang server works correctly by using the following
command. The command must return the identical message you pass for encryption and
decryption:

# ansible managed-node-01.example.com -m command -a 'echo test | clevis encrypt tang


'{"url":"<tang.server.example.com>"}' -y | clevis decrypt'
test

Additional resources

/usr/share/ansible/roles/rhel-system-roles.nbde_server/README.md file

/usr/share/doc/rhel-system-roles/nbde_server/ directory

9.14.16.2. Setting up Clevis clients with DHCP by using the nbde_client RHEL system role

The nbde_client system role enables you to deploy multiple Clevis clients in an automated way.

This role supports binding a LUKS-encrypted volume to one or more Network-Bound (NBDE) servers -
Tang servers. You can either preserve the existing volume encryption with a passphrase or remove it.
After removing the passphrase, you can unlock the volume only using NBDE. This is useful when a volume
is initially encrypted using a temporary key or password that you should remove after you provision the
system.

If you provide both a passphrase and a key file, the role uses what you have provided first. If it does not
find any of these valid, it attempts to retrieve a passphrase from an existing binding.

Policy-Based Decryption (PBD) defines a binding as a mapping of a device to a slot. This means that
you can have multiple bindings for the same device. The default slot is slot 1.

NOTE

The nbde_client system role supports only Tang bindings. Therefore, you cannot use it
for TPM2 bindings.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

A volume that is already encrypted by using LUKS.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Configure clients for unlocking of encrypted volumes by Tang servers
hosts: managed-node-01.example.com
tasks:
- name: Create NBDE client bindings
ansible.builtin.include_role:

166
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

name: rhel-system-roles.nbde_client
vars:
nbde_client_bindings:
- device: /dev/rhel/root
encryption_key_src: /etc/luks/keyfile
nbde_client_early_boot: true
state: present
servers:
- http://server1.example.com
- http://server2.example.com
- device: /dev/rhel/swap
encryption_key_src: /etc/luks/keyfile
servers:
- http://server1.example.com
- http://server2.example.com

This example playbook configures Clevis clients for automated unlocking of two LUKS-
encrypted volumes when at least one of two Tang servers is available.

The settings specified in the example playbook include the following:

state: present
The values of state indicate the configuration after you run the playbook. Use the present
value for either creating a new binding or updating an existing one. Contrary to a clevis luks
bind command, you can use state: present also for overwriting an existing binding in its
device slot. The absent value removes a specified binding.
nbde_client_early_boot: true
The nbde_client role ensures that networking for a Tang pin is available during early boot by
default. If you scenario requires to disable this feature, add the nbde_client_early_boot:
false variable to your playbook.
For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.nbde_client/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

1. On your NBDE client, check that the encrypted volume that should be automatically unlocked
by your Tang servers contain the corresponding information in its LUKS pins:

# ansible managed-node-01.example.com -m command -a 'clevis luks list -d /dev/rhel/root'


1: tang '{"url":"<http://server1.example.com/>"}'
2: tang '{"url":"<http://server2.example.com/>"}'

167
Red Hat Enterprise Linux 8 System Design Guide

2. If you do not use the nbde_client_early_boot: false variable, verify that the bindings are
available for the early boot, for example:

# ansible managed-node-01.example.com -m command -a 'lsinitrd | grep clevis-luks'


lrwxrwxrwx 1 root root 48 Jan 4 02:56
etc/systemd/system/cryptsetup.target.wants/clevis-luks-askpass.path ->
/usr/lib/systemd/system/clevis-luks-askpass.path

Additional resources

/usr/share/ansible/roles/rhel-system-roles.nbde_client/README.md file

/usr/share/doc/rhel-system-roles/nbde_client/ directory

9.14.16.3. Setting up static-IP Clevis clients by using the nbde_client RHEL system role

The nbde_client RHEL system role supports only scenarios with Dynamic Host Configuration Protocol
(DHCP). On an NBDE client with static IP configuration, you must pass your network configuration as a
kernel boot parameter.

Typically, administrators want to reuse a playbook and not maintain individual playbooks for each host to
which Ansible assigns static IP addresses during early boot. In this case, you can use variables in the
playbook and provide the settings in an external file. As a result, you need only one playbook and one file
with the settings.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

A volume that is already encrypted by using LUKS.

Procedure

1. Create a file with the network settings of your hosts, for example, static-ip-settings-
clients.yml, and add the values you want to dynamically assign to the hosts:

clients:
managed-node-01.example.com:
ip_v4: 192.0.2.1
gateway_v4: 192.0.2.254
netmask_v4: 255.255.255.0
interface: enp1s0
managed-node-02.example.com:
ip_v4: 192.0.2.2
gateway_v4: 192.0.2.254
netmask_v4: 255.255.255.0
interface: enp1s0

2. Create a playbook file, for example, ~/playbook.yml, with the following content:

168
CHAPTER 9. SCANNING THE SYSTEM FOR SECURITY COMPLIANCE AND VULNERABILITIES

- name: Configure clients for unlocking of encrypted volumes by Tang servers


hosts: managed-node-01.example.com,managed-node-02.example.com
vars_files:
- ~/static-ip-settings-clients.yml
tasks:
- name: Create NBDE client bindings
ansible.builtin.include_role:
name: rhel-system-roles.network
vars:
nbde_client_bindings:
- device: /dev/rhel/root
encryption_key_src: /etc/luks/keyfile
servers:
- http://server1.example.com
- http://server2.example.com
- device: /dev/rhel/swap
encryption_key_src: /etc/luks/keyfile
servers:
- http://server1.example.com
- http://server2.example.com

- name: Configure a Clevis client with static IP address during early boot
ansible.builtin.include_role:
name: rhel-system-roles.bootloader
vars:
bootloader_settings:
- kernel: ALL
options:
- name: ip
value: "{{ clients[inventory_hostname]['ip_v4'] }}::{{ clients[inventory_hostname]
['gateway_v4'] }}:{{ clients[inventory_hostname]['netmask_v4'] }}::{{
clients[inventory_hostname]['interface'] }}:none"

This playbook reads certain values dynamically for each host listed in the ~/static-ip-settings-
clients.yml file.

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.network/README.md file on the control node.

3. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

4. Run the playbook:

$ ansible-playbook ~/playbook.yml

Additional resources

/usr/share/ansible/roles/rhel-system-roles.nbde_client/README.md file

/usr/share/doc/rhel-system-roles/nbde_client/ directory

169
Red Hat Enterprise Linux 8 System Design Guide

Looking forward to Linux network configuration in the initial ramdisk (initrd) (Red Hat Enable
Sysadmin)

170
CHAPTER 10. USING SELINUX

CHAPTER 10. USING SELINUX

10.1. GETTING STARTED WITH SELINUX


Security Enhanced Linux (SELinux) provides an additional layer of system security. SELinux
fundamentally answers the question: May <subject> do <action> to <object>? , for example: May a web
server access files in users' home directories?

10.1.1. Introduction to SELinux


The standard access policy based on the user, group, and other permissions, known as Discretionary
Access Control (DAC), does not enable system administrators to create comprehensive and fine-
grained security policies, such as restricting specific applications to only viewing log files, while allowing
other applications to append new data to the log files.

Security Enhanced Linux (SELinux) implements Mandatory Access Control (MAC). Every process and
system resource has a special security label called an SELinux context. A SELinux context, sometimes
referred to as an SELinux label, is an identifier which abstracts away the system-level details and focuses
on the security properties of the entity. Not only does this provide a consistent way of referencing
objects in the SELinux policy, but it also removes any ambiguity that can be found in other identification
methods. For example, a file can have multiple valid path names on a system that makes use of bind
mounts.

The SELinux policy uses these contexts in a series of rules which define how processes can interact with
each other and the various system resources. By default, the policy does not allow any interaction unless
a rule explicitly grants access.

NOTE

Remember that SELinux policy rules are checked after DAC rules. SELinux policy rules
are not used if DAC rules deny access first, which means that no SELinux denial is logged
if the traditional DAC rules prevent the access.

SELinux contexts have several fields: user, role, type, and security level. The SELinux type information is
perhaps the most important when it comes to the SELinux policy, as the most common policy rule which
defines the allowed interactions between processes and system resources uses SELinux types and not
the full SELinux context. SELinux types end with _t. For example, the type name for the web server is
httpd_t. The type context for files and directories normally found in /var/www/html/ is
httpd_sys_content_t. The type contexts for files and directories normally found in /tmp and /var/tmp/
is tmp_t. The type context for web server ports is http_port_t.

There is a policy rule that permits Apache (the web server process running as httpd_t) to access files
and directories with a context normally found in /var/www/html/ and other web server directories
(httpd_sys_content_t). There is no allow rule in the policy for files normally found in /tmp and /var/tmp/,
so access is not permitted. With SELinux, even if Apache is compromised, and a malicious script gains
access, it is still not able to access the /tmp directory.

Figure 10.1. An example how can SELinux help to run Apache and MariaDB in a secure way.
171
Red Hat Enterprise Linux 8 System Design Guide

Figure 10.1. An example how can SELinux help to run Apache and MariaDB in a secure way.

As the previous scheme shows, SELinux allows the Apache process running as httpd_t to access the
/var/www/html/ directory and it denies the same process to access the /data/mysql/ directory because
there is no allow rule for the httpd_t and mysqld_db_t type contexts. On the other hand, the MariaDB
process running as mysqld_t is able to access the /data/mysql/ directory and SELinux also correctly
denies the process with the mysqld_t type to access the /var/www/html/ directory labeled as
httpd_sys_content_t.

Additional resources

selinux(8) man page and man pages listed by the apropos selinux command.

Man pages listed by the man -k _selinux command when the selinux-policy-doc package is
installed.

The SELinux Coloring Book helps you to better understand SELinux basic concepts.

SELinux Wiki FAQ

10.1.2. Benefits of running SELinux


SELinux provides the following benefits:

All processes and files are labeled. SELinux policy rules define how processes interact with files,
as well as how processes interact with each other. Access is only allowed if an SELinux policy
rule exists that specifically allows it.

SELinux provides fine-grained access control. Stepping beyond traditional UNIX permissions
that are controlled at user discretion and based on Linux user and group IDs, SELinux access
decisions are based on all available information, such as an SELinux user, role, type, and,
optionally, a security level.

SELinux policy is administratively-defined and enforced system-wide.

SELinux can mitigate privilege escalation attacks. Processes run in domains, and are therefore
separated from each other. SELinux policy rules define how processes access files and other
processes. If a process is compromised, the attacker only has access to the normal functions of
that process, and to files the process has been configured to have access to. For example, if the

172
CHAPTER 10. USING SELINUX

Apache HTTP Server is compromised, an attacker cannot use that process to read files in user
home directories, unless a specific SELinux policy rule was added or configured to allow such
access.

SELinux can enforce data confidentiality and integrity, and can protect processes from
untrusted inputs.

SELinux is designed to enhance existing security solutions, not replace antivirus software, secure
passwords, firewalls, or other security systems. Even when running SELinux, it is important to continue to
follow good security practices, such as keeping software up-to-date, using hard-to-guess passwords,
and firewalls.

10.1.3. SELinux examples


The following examples demonstrate how SELinux increases security:

The default action is deny. If an SELinux policy rule does not exist to allow access, such as for a
process opening a file, access is denied.

SELinux can confine Linux users. A number of confined SELinux users exist in the SELinux
policy. Linux users can be mapped to confined SELinux users to take advantage of the security
rules and mechanisms applied to them. For example, mapping a Linux user to the SELinux
user_u user, results in a Linux user that is not able to run unless configured otherwise set user
ID (setuid) applications, such as sudo and su.

Increased process and data separation. The concept of SELinux domains allows defining which
processes can access certain files and directories. For example, when running SELinux, unless
otherwise configured, an attacker cannot compromise a Samba server, and then use that Samba
server as an attack vector to read and write to files used by other processes, such as MariaDB
databases.

SELinux helps mitigate the damage made by configuration mistakes. Domain Name System
(DNS) servers often replicate information between each other in a zone transfer. Attackers can
use zone transfers to update DNS servers with false information. When running the Berkeley
Internet Name Domain (BIND) as a DNS server in RHEL, even if an administrator forgets to limit
which servers can perform a zone transfer, the default SELinux policy prevent updates for zone
files [1] that use zone transfers, by the BIND named daemon itself, and by other processes.

Without SELinux, an attacker can misuse a vulnerability to path traversal on an Apache web
server and access files and directories stored on the file system by using special elements such
as ../. If an attacker attempts an attack on a server running with SELinux in enforcing mode,
SELinux denies access to files that the httpd process must not access. SELinux cannot block
this type of attack completely but it effectively mitigates it.

SELinux in enforcing mode successfully prevents exploitation of kernel NULL pointer


dereference operators on non-SMAP platforms (CVE-2019-9213). Attackers use a vulnerability
in the mmap function, which does not check mapping of a null page, for placing arbitrary code
on this page.

The deny_ptrace SELinux boolean and SELinux in enforcing mode protect systems from the
PTRACE_TRACEME vulnerability (CVE-2019-13272). Such configuration prevents scenarios
when an attacker can get root privileges.

The nfs_export_all_rw and nfs_export_all_ro SELinux booleans provide an easy-to-use tool


to prevent misconfigurations of Network File System (NFS) such as accidental sharing /home
directories.

173
Red Hat Enterprise Linux 8 System Design Guide

Additional resources

SELinux as a security pillar of an operating system - Real-world benefits and examples (Red Hat
Knowledgebase)

SELinux hardening with Ansible (Red Hat Knowledgebase)

selinux-playbooks Github repository with Ansible playbooks for SELinux hardening

10.1.4. SELinux architecture and packages


SELinux is a Linux Security Module (LSM) that is built into the Linux kernel. The SELinux subsystem in
the kernel is driven by a security policy which is controlled by the administrator and loaded at boot. All
security-relevant, kernel-level access operations on the system are intercepted by SELinux and
examined in the context of the loaded security policy. If the loaded policy allows the operation, it
continues. Otherwise, the operation is blocked and the process receives an error.

SELinux decisions, such as allowing or disallowing access, are cached. This cache is known as the Access
Vector Cache (AVC). When using these cached decisions, SELinux policy rules need to be checked less,
which increases performance. Remember that SELinux policy rules have no effect if DAC rules deny
access first. Raw audit messages are logged to the /var/log/audit/audit.log and they start with the
type=AVC string.

In RHEL 8, system services are controlled by the systemd daemon; systemd starts and stops all
services, and users and processes communicate with systemd using the systemctl utility. The systemd
daemon can consult the SELinux policy and check the label of the calling process and the label of the
unit file that the caller tries to manage, and then ask SELinux whether or not the caller is allowed the
access. This approach strengthens access control to critical system capabilities, which include starting
and stopping system services.

The systemd daemon also works as an SELinux Access Manager. It retrieves the label of the process
running systemctl or the process that sent a D-Bus message to systemd. The daemon then looks up
the label of the unit file that the process wanted to configure. Finally, systemd can retrieve information
from the kernel if the SELinux policy allows the specific access between the process label and the unit
file label. This means a compromised application that needs to interact with systemd for a specific
service can now be confined by SELinux. Policy writers can also use these fine-grained controls to
confine administrators.

If a process is sending a D-Bus message to another process and if the SELinux policy does not allow the
D-Bus communication of these two processes, then the system prints a USER_AVC denial message,
and the D-Bus communication times out. Note that the D-Bus communication between two processes
works bidirectionally.

IMPORTANT

To avoid incorrect SELinux labeling and subsequent problems, ensure that you start
services using a systemctl start command.

RHEL 8 provides the following packages for working with SELinux:

policies: selinux-policy-targeted, selinux-policy-mls

tools: policycoreutils, policycoreutils-gui, libselinux-utils, policycoreutils-python-utils,


setools-console, checkpolicy

174
CHAPTER 10. USING SELINUX

10.1.5. SELinux states and modes


SELinux can run in one of three modes: enforcing, permissive, or disabled.

Enforcing mode is the default, and recommended, mode of operation; in enforcing mode
SELinux operates normally, enforcing the loaded security policy on the entire system.

In permissive mode, the system acts as if SELinux is enforcing the loaded security policy,
including labeling objects and emitting access denial entries in the logs, but it does not actually
deny any operations. While not recommended for production systems, permissive mode can be
helpful for SELinux policy development and debugging.

Disabled mode is strongly discouraged; not only does the system avoid enforcing the SELinux
policy, it also avoids labeling any persistent objects such as files, making it difficult to enable
SELinux in the future.

Use the setenforce utility to change between enforcing and permissive mode. Changes made with
setenforce do not persist across reboots. To change to enforcing mode, enter the setenforce 1
command as the Linux root user. To change to permissive mode, enter the setenforce 0 command. Use
the getenforce utility to view the current SELinux mode:

# getenforce
Enforcing

# setenforce 0
# getenforce
Permissive

# setenforce 1
# getenforce
Enforcing

In Red Hat Enterprise Linux, you can set individual domains to permissive mode while the system runs in
enforcing mode. For example, to make the httpd_t domain permissive:

# semanage permissive -a httpd_t

Note that permissive domains are a powerful tool that can compromise security of your system. Red Hat
recommends to use permissive domains with caution, for example, when debugging a specific scenario.

10.2. CHANGING SELINUX STATES AND MODES


When enabled, SELinux can run in one of two modes: enforcing or permissive. The following sections
show how to permanently change into these modes.

10.2.1. Permanent changes in SELinux states and modes


As discussed in SELinux states and modes, SELinux can be enabled or disabled. When enabled, SELinux
has two modes: enforcing and permissive.

Use the getenforce or sestatus commands to check in which mode SELinux is running. The getenforce
command returns Enforcing, Permissive, or Disabled.

The sestatus command returns the SELinux status and the SELinux policy being used:

175
Red Hat Enterprise Linux 8 System Design Guide

$ 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: 31


WARNING

When systems run SELinux in permissive mode, users and processes might label
various file-system objects incorrectly. File-system objects created while SELinux is
disabled are not labeled at all. This behavior causes problems when changing to
enforcing mode because SELinux relies on correct labels of file-system objects.

To prevent incorrectly labeled and unlabeled files from causing problems, SELinux
automatically relabels file systems when changing from the disabled state to
permissive or enforcing mode. Use the fixfiles -F onboot command as root to
create the /.autorelabel file containing the -F option to ensure that files are
relabeled upon next reboot.

Before rebooting the system for relabeling, make sure the system will boot in
permissive mode, for example by using the enforcing=0 kernel option. This
prevents the system from failing to boot in case the system contains unlabeled files
required by systemd before launching the selinux-autorelabel service. For more
information, see RHBZ#2021835.

10.2.2. Changing SELinux to permissive mode


When SELinux is running in permissive mode, SELinux policy is not enforced. The system remains
operational and SELinux does not deny any operations but only logs AVC messages, which can be then
used for troubleshooting, debugging, and SELinux policy improvements. Each AVC is logged only once
in this case.

Prerequisites

The selinux-policy-targeted, libselinux-utils, and policycoreutils packages are installed on


your system.

The selinux=0 or enforcing=0 kernel parameters are not used.

Procedure

1. Open the /etc/selinux/config file in a text editor of your choice, for example:

# vi /etc/selinux/config

176
CHAPTER 10. USING SELINUX

2. Configure the SELINUX=permissive option:

# This file controls the state of SELinux on the system.


# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=permissive
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted

3. Restart the system:

# reboot

Verification

1. After the system restarts, confirm that the getenforce command returns Permissive:

$ getenforce
Permissive

10.2.3. Changing SELinux to enforcing mode


When SELinux is running in enforcing mode, it enforces the SELinux policy and denies access based on
SELinux policy rules. In RHEL, enforcing mode is enabled by default when the system was initially
installed with SELinux.

Prerequisites

The selinux-policy-targeted, libselinux-utils, and policycoreutils packages are installed on


your system.

The selinux=0 or enforcing=0 kernel parameters are not used.

Procedure

1. Open the /etc/selinux/config file in a text editor of your choice, for example:

# vi /etc/selinux/config

2. Configure the SELINUX=enforcing option:

# This file controls the state of SELinux on the system.


# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:

177
Red Hat Enterprise Linux 8 System Design Guide

# targeted - Targeted processes are protected,


# mls - Multi Level Security protection.
SELINUXTYPE=targeted

3. Save the change, and restart the system:

# reboot

On the next boot, SELinux relabels all the files and directories within the system and adds
SELinux context for files and directories that were created when SELinux was disabled.

Verification

1. After the system restarts, confirm that the getenforce command returns Enforcing:

$ getenforce
Enforcing

Troubleshooting
After changing to enforcing mode, SELinux may deny some actions because of incorrect or missing
SELinux policy rules.

To view what actions SELinux denies, enter the following command as root:

# ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts today

Alternatively, with the setroubleshoot-server package installed, enter:

# grep "SELinux is preventing" /var/log/messages

If SELinux is active and the Audit daemon (auditd) is not running on your system, then search
for certain SELinux messages in the output of the dmesg command:

# dmesg | grep -i -e type=1300 -e type=1400

See Troubleshooting problems related to SELinux for more information.

10.2.4. Enabling SELinux on systems that previously had it disabled


To avoid problems, such as systems unable to boot or process failures, when enabling SELinux on
systems that previously had it disabled, resolve Access Vector Cache (AVC) messages in permissive
mode first.

When systems run SELinux in permissive mode, users and processes might label various file-system
objects incorrectly. File-system objects created while SELinux is disabled are not labeled at all. This
behavior causes problems when changing to enforcing mode because SELinux relies on correct labels of
file-system objects.

To prevent incorrectly labeled and unlabeled files from causing problems, SELinux automatically
relabels file systems when changing from the disabled state to permissive or enforcing mode.

178
CHAPTER 10. USING SELINUX


WARNING

Before rebooting the system for relabeling, make sure the system will boot in
permissive mode, for example by using the enforcing=0 kernel option. This
prevents the system from failing to boot in case the system contains unlabeled files
required by systemd before launching the selinux-autorelabel service. For more
information, see RHBZ#2021835.

Procedure

1. Enable SELinux in permissive mode. For more information, see Changing to permissive mode .

2. Restart your system:

# reboot

3. Check for SELinux denial messages. For more information, see Identifying SELinux denials.

4. Ensure that files are relabeled upon the next reboot:

# fixfiles -F onboot

This creates the /.autorelabel file containing the -F option.


WARNING

Always switch to permissive mode before entering the fixfiles -F onboot


command.

By default, autorelabel uses as many threads in parallel as the system has available CPU cores.
To use only a single thread during automatic relabeling, use the fixfiles -T 1 onboot command.

5. If there are no denials, switch to enforcing mode. For more information, see Changing SELinux
modes at boot time.

Verification

1. After the system restarts, confirm that the getenforce command returns Enforcing:

$ getenforce
Enforcing

Next steps
To run custom applications with SELinux in enforcing mode, choose one of the following scenarios:

179
Red Hat Enterprise Linux 8 System Design Guide

Run your application in the unconfined_service_t domain.

Write a new policy for your application. See the Writing a custom SELinux policy section for
more information.

Additional resources

SELinux states and modes section covers temporary changes in modes.

10.2.5. Disabling SELinux


When you disable SELinux, your system does not load your SELinux policy. As a result, the system does
not enforce the SELinux policy and does not log Access Vector Cache (AVC) messages. Therefore, all
benefits of running SELinux are lost.

Do not disable SELinux except in specific scenarios, such as performance-sensitive systems where the
weakened security does not impose significant risks.

IMPORTANT

If your scenario requires to perform debugging in a production environment, temporarily


use permissive mode instead of permanently disabling SELinux. See Changing to
permissive mode for more information about permissive mode.

Prerequisites

The grubby package is installed:

$ rpm -q grubby
grubby-<version>

Procedure

1. Configure your boot loader to add selinux=0 to the kernel command line:

$ sudo grubby --update-kernel ALL --args selinux=0

2. Restart your system:

$ reboot

Verification

After the reboot, confirm that the getenforce command returns Disabled:

$ getenforce
Disabled

Alternative method
In RHEL 8, you can still use the deprecated method for disabling SELinux by using the
SELINUX=disabled option in the /etc/selinux/config file. This results the kernel booting with SELinux
enabled and switching to disabled mode later in the boot process. Consequently, memory leaks and race

180
CHAPTER 10. USING SELINUX

conditions might occur that cause kernel panics. To use this method:

1. Open the /etc/selinux/config file in a text editor of your choice, for example:

# vi /etc/selinux/config

2. Configure the SELINUX=disabled option:

# This file controls the state of SELinux on the system.


# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted

3. Save the change, and restart your system:

# reboot

10.2.6. Changing SELinux modes at boot time


On boot, you can set the following kernel parameters to change the way SELinux runs:

enforcing=0
Setting this parameter causes the system to start in permissive mode, which is useful when
troubleshooting issues. Using permissive mode might be the only option to detect a problem if your
file system is too corrupted. Moreover, in permissive mode, the system continues to create the labels
correctly. The AVC messages that are created in this mode can be different than in enforcing mode.
In permissive mode, only the first denial from a series of the same denials is reported. However, in
enforcing mode, you might get a denial related to reading a directory, and an application stops. In
permissive mode, you get the same AVC message, but the application continues reading files in the
directory and you get an AVC for each denial in addition.

selinux=0
This parameter causes the kernel to not load any part of the SELinux infrastructure. The init scripts
notice that the system booted with the selinux=0 parameter and touch the /.autorelabel file. This
causes the system to automatically relabel the next time you boot with SELinux enabled.

IMPORTANT

Do not use the selinux=0 parameter in a production environment. To debug your


system, temporarily use permissive mode instead of disabling SELinux.

autorelabel=1
This parameter forces the system to relabel similarly to the following commands:

# touch /.autorelabel
# reboot

181
Red Hat Enterprise Linux 8 System Design Guide

If a file system contains a large amount of mislabeled objects, start the system in permissive mode to
make the autorelabel process successful.

Additional resources

For additional SELinux-related kernel boot parameters, such as checkreqprot, see the
/usr/share/doc/kernel-doc-<KERNEL_VER>/Documentation/admin-guide/kernel-
parameters.txt file installed with the kernel-doc package. Replace the <KERNEL_VER> string
with the version number of the installed kernel, for example:

# yum install kernel-doc


$ less /usr/share/doc/kernel-doc-4.18.0/Documentation/admin-guide/kernel-parameters.txt

10.3. TROUBLESHOOTING PROBLEMS RELATED TO SELINUX


If you plan to enable SELinux on systems where it has been previously disabled or if you run a service in a
non-standard configuration, you might need to troubleshoot situations potentially blocked by SELinux.
Note that in most cases, SELinux denials are signs of misconfiguration.

10.3.1. Identifying SELinux denials


Follow only the necessary steps from this procedure; in most cases, you need to perform just step 1.

Procedure

1. When your scenario is blocked by SELinux, the /var/log/audit/audit.log file is the first place to
check for more information about a denial. To query Audit logs, use the ausearch tool. Because
the SELinux decisions, such as allowing or disallowing access, are cached and this cache is known
as the Access Vector Cache (AVC), use the AVC and USER_AVC values for the message type
parameter, for example:

# ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent

If there are no matches, check if the Audit daemon is running. If it does not, repeat the denied
scenario after you start auditd and check the Audit log again.

2. In case auditd is running, but there are no matches in the output of ausearch, check messages
provided by the systemd Journal:

# journalctl -t setroubleshoot

3. If SELinux is active and the Audit daemon is not running on your system, then search for certain
SELinux messages in the output of the dmesg command:

# dmesg | grep -i -e type=1300 -e type=1400

4. Even after the previous three checks, it is still possible that you have not found anything. In this
case, AVC denials can be silenced because of dontaudit rules.
To temporarily disable dontaudit rules, allowing all denials to be logged:

# semodule -DB

After re-running your denied scenario and finding denial messages using the previous steps, the
182
CHAPTER 10. USING SELINUX

After re-running your denied scenario and finding denial messages using the previous steps, the
following command enables dontaudit rules in the policy again:

# semodule -B

5. If you apply all four previous steps, and the problem still remains unidentified, consider if
SELinux really blocks your scenario:

Switch to permissive mode:

# setenforce 0
$ getenforce
Permissive

Repeat your scenario.

If the problem still occurs, something different than SELinux is blocking your scenario.

10.3.2. Analyzing SELinux denial messages


After identifying that SELinux is blocking your scenario, you might need to analyze the root cause before
you choose a fix.

Prerequisites

The policycoreutils-python-utils and setroubleshoot-server packages are installed on your


system.

Procedure

1. List more details about a logged denial using the sealert command, for example:

$ sealert -l "*"
SELinux is preventing /usr/bin/passwd from write access on the file
/root/test.

***** Plugin leaks (86.2 confidence) suggests *****************************

If you want to ignore passwd trying to write access the test file,
because you believe it should not need this access.
Then you should report this as a bug.
You can generate a local policy module to dontaudit this access.
Do
# ausearch -x /usr/bin/passwd --raw | audit2allow -D -M my-passwd
# semodule -X 300 -i my-passwd.pp

***** Plugin catchall (14.7 confidence) suggests **************************

...

Raw Audit Messages


type=AVC msg=audit(1553609555.619:127): avc: denied { write } for
pid=4097 comm="passwd" path="/root/test" dev="dm-0" ino=17142697
scontext=unconfined_u:unconfined_r:passwd_t:s0-s0:c0.c1023
tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0

183
Red Hat Enterprise Linux 8 System Design Guide

...

Hash: passwd,passwd_t,admin_home_t,file,write

2. If the output obtained in the previous step does not contain clear suggestions:

Enable full-path auditing to see full paths to accessed objects and to make additional Linux
Audit event fields visible:

# auditctl -w /etc/shadow -p w -k shadow-write

Clear the setroubleshoot cache:

# rm -f /var/lib/setroubleshoot/setroubleshoot.xml

Reproduce the problem.

Repeat step 1.
After you finish the process, disable full-path auditing:

# auditctl -W /etc/shadow -p w -k shadow-write

3. If sealert returns only catchall suggestions or suggests adding a new rule using the audit2allow
tool, match your problem with examples listed and explained in SELinux denials in the Audit log .

Additional resources

sealert(8) man page on your system

10.3.3. Fixing analyzed SELinux denials


In most cases, suggestions provided by the sealert tool give you the right guidance about how to fix
problems related to the SELinux policy. See Analyzing SELinux denial messages for information how to
use sealert to analyze SELinux denials.

Be careful when the tool suggests using the audit2allow tool for configuration changes. You should not
use audit2allow to generate a local policy module as your first option when you see an SELinux denial.
Troubleshooting should start with a check if there is a labeling problem. The second most often case is
that you have changed a process configuration, and you forgot to tell SELinux about it.

Labeling problems
A common cause of labeling problems is when a non-standard directory is used for a service. For
example, instead of using /var/www/html/ for a website, an administrator might want to use
/srv/myweb/. On Red Hat Enterprise Linux, the /srv directory is labeled with the var_t type. Files and
directories created in /srv inherit this type. Also, newly-created objects in top-level directories, such as
/myserver, can be labeled with the default_t type. SELinux prevents the Apache HTTP Server ( httpd)
from accessing both of these types. To allow access, SELinux must know that the files in /srv/myweb/
are to be accessible by httpd:

# semanage fcontext -a -t httpd_sys_content_t "/srv/myweb(/.*)?"

This semanage command adds the context for the /srv/myweb/ directory and all files and directories

184
CHAPTER 10. USING SELINUX

This semanage command adds the context for the /srv/myweb/ directory and all files and directories
under it to the SELinux file-context configuration. The semanage utility does not change the context.
As root, use the restorecon utility to apply the changes:

# restorecon -R -v /srv/myweb

Incorrect context
The matchpathcon utility checks the context of a file path and compares it to the default label for that
path. The following example demonstrates the use of matchpathcon on a directory that contains
incorrectly labeled files:

$ matchpathcon -V /var/www/html/*
/var/www/html/index.html has context unconfined_u:object_r:user_home_t:s0, should be
system_u:object_r:httpd_sys_content_t:s0
/var/www/html/page1.html has context unconfined_u:object_r:user_home_t:s0, should be
system_u:object_r:httpd_sys_content_t:s0

In this example, the index.html and page1.html files are labeled with the user_home_t type. This type
is used for files in user home directories. Using the mv command to move files from your home directory
may result in files being labeled with the user_home_t type. This type should not exist outside of home
directories. Use the restorecon utility to restore such files to their correct type:

# restorecon -v /var/www/html/index.html
restorecon reset /var/www/html/index.html context unconfined_u:object_r:user_home_t:s0-
>system_u:object_r:httpd_sys_content_t:s0

To restore the context for all files under a directory, use the -R option:

# restorecon -R -v /var/www/html/
restorecon reset /var/www/html/page1.html context unconfined_u:object_r:samba_share_t:s0-
>system_u:object_r:httpd_sys_content_t:s0
restorecon reset /var/www/html/index.html context unconfined_u:object_r:samba_share_t:s0-
>system_u:object_r:httpd_sys_content_t:s0

Confined applications configured in non-standard ways


Services can be run in a variety of ways. To account for that, you need to specify how you run your
services. You can achieve this through SELinux booleans that allow parts of SELinux policy to be
changed at runtime. This enables changes, such as allowing services access to NFS volumes, without
reloading or recompiling SELinux policy. Also, running services on non-default port numbers requires
policy configuration to be updated using the semanage command.

For example, to allow the Apache HTTP Server to communicate with MariaDB, enable the
httpd_can_network_connect_db boolean:

# setsebool -P httpd_can_network_connect_db on

Note that the -P option makes the setting persistent across reboots of the system.

If access is denied for a particular service, use the getsebool and grep utilities to see if any booleans
are available to allow access. For example, use the getsebool -a | grep ftp command to search for FTP
related booleans:

$ getsebool -a | grep ftp

185
Red Hat Enterprise Linux 8 System Design Guide

ftpd_anon_write --> off


ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_nfs --> off

ftpd_connect_db --> off


httpd_enable_ftp_server --> off
tftp_anon_write --> off

To get a list of booleans and to find out if they are enabled or disabled, use the getsebool -a command.
To get a list of booleans including their meaning, and to find out if they are enabled or disabled, install
the selinux-policy-devel package and use the semanage boolean -l command as root.

Port numbers
Depending on policy configuration, services can only be allowed to run on certain port numbers.
Attempting to change the port a service runs on without changing policy may result in the service failing
to start. For example, run the semanage port -l | grep http command as root to list http related ports:

# semanage port -l | grep http


http_cache_port_t tcp 3128, 8080, 8118
http_cache_port_t udp 3130
http_port_t tcp 80, 443, 488, 8008, 8009, 8443
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989

The http_port_t port type defines the ports Apache HTTP Server can listen on, which in this case, are
TCP ports 80, 443, 488, 8008, 8009, and 8443. If an administrator configures httpd.conf so that httpd
listens on port 9876 (Listen 9876), but policy is not updated to reflect this, the following command fails:

# systemctl start httpd.service


Job for httpd.service failed. See 'systemctl status httpd.service' and 'journalctl -xn' for details.

# systemctl status httpd.service


httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled)
Active: failed (Result: exit-code) since Thu 2013-08-15 09:57:05 CEST; 59s ago
Process: 16874 ExecStop=/usr/sbin/httpd $OPTIONS -k graceful-stop (code=exited,
status=0/SUCCESS)
Process: 16870 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited,
status=1/FAILURE)

An SELinux denial message similar to the following is logged to /var/log/audit/audit.log:

type=AVC msg=audit(1225948455.061:294): avc: denied { name_bind } for pid=4997


comm="httpd" src=9876 scontext=unconfined_u:system_r:httpd_t:s0
tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket

To allow httpd to listen on a port that is not listed for the http_port_t port type, use the semanage port
command to assign a different label to the port:

# semanage port -a -t http_port_t -p tcp 9876

The -a option adds a new record; the -t option defines a type; and the -p option defines a protocol. The
last argument is the port number to add.

186
CHAPTER 10. USING SELINUX

Corner cases, evolving or broken applications, and compromised systems


Applications may contain bugs, causing SELinux to deny access. Also, SELinux rules are evolving –
SELinux may not have seen an application running in a certain way, possibly causing it to deny access,
even though the application is working as expected. For example, if a new version of PostgreSQL is
released, it may perform actions the current policy does not account for, causing access to be denied,
even though access should be allowed.

For these situations, after access is denied, use the audit2allow utility to create a custom policy module
to allow access. You can report missing rules in the SELinux policy in Red Hat Bugzilla. For Red Hat
Enterprise Linux 8, create bugs against the Red Hat Enterprise Linux 8 product, and select the
selinux-policy component. Include the output of the audit2allow -w -a and audit2allow -a commands
in such bug reports.

If an application asks for major security privileges, it could be a signal that the application is
compromised. Use intrusion detection tools to inspect such suspicious behavior.

The Solution Engine on the Red Hat Customer Portal can also provide guidance in the form of an article
containing a possible solution for the same or very similar problem you have. Select the relevant product
and version and use SELinux-related keywords, such as selinux or avc, together with the name of your
blocked service or application, for example: selinux samba.

10.3.4. Creating a local SELinux policy module


Adding specific SELinux policy modules to an active SELinux policy can fix certain problems with the
SELinux policy. You can use this procedure to fix a specific Known Issue described in Red Hat release
notes, or to implement a specific Red Hat Solution .


WARNING

Use only rules provided by Red Hat. Red Hat does not support creating SELinux
policy modules with custom rules, because this falls outside of the Production
Support Scope of Coverage. If you are not an expert, contact your Red Hat sales
representative and request consulting services.

Prerequisites

The setools-console and audit packages for verification.

Procedure

1. Open a new .cil file with a text editor, for example:

# vim <local_module>.cil

To keep your local modules better organized, use the local_ prefix in the names of local SELinux
policy modules.

2. Insert the custom rules from a Known Issue or a Red Hat Solution.

IMPORTANT
187
Red Hat Enterprise Linux 8 System Design Guide

IMPORTANT

Do not write your own rules. Use only the rules provided in a specific Known Issue
or Red Hat Solution.

For example, to implement the SELinux denies cups-lpd read access to cups.sock in RHEL
solution, insert the following rule:

(allow cupsd_lpd_t cupsd_var_run_t (sock_file (read)))

The example solution has been fixed permanently for RHEL in RHBA-2021:4420. Therefore,
the parts of this procedure specific to this solution have no effect on updated RHEL 8 and 9
systems, and are included only as examples of syntax.

You can use either of the two SELinux rule syntaxes, Common Intermediate Language
(CIL) and m4. For example, (allow cupsd_lpd_t cupsd_var_run_t (sock_file (read))) in
CIL is equivalent to the following in m4:

module local_cupslpd-read-cupssock 1.0;

require {
type cupsd_var_run_t;
type cupsd_lpd_t;
class sock_file read;
}

#============= cupsd_lpd_t ==============


allow cupsd_lpd_t cupsd_var_run_t:sock_file read;

3. Save and close the file.

4. Install the policy module:

# semodule -i <local_module>.cil

If you want to remove a local policy module which you created by using semodule -i, refer to the
module name without the .cil suffix. To remove a local policy module, use semodule -r
<local_module>.

5. Restart any services related to the rules:

# systemctl restart <service-name>

Verification

1. List the local modules installed in your SELinux policy:

# semodule -lfull | grep "local_"


400 local_module cil

Because local modules have priority 400, you can filter them from the list also by using that
value, for example, by using the semodule -lfull | grep -v ^100 command.

2. Search the SELinux policy for the relevant allow rules:

188
CHAPTER 10. USING SELINUX

# sesearch -A --source=<SOURCENAME> --target=<TARGETNAME> --


class=<CLASSNAME> --perm=<P1>,<P2>

Where <SOURCENAME> is the source SELinux type, <TARGETNAME> is the target SELinux
type, <CLASSNAME> is the security class or object class name, and <P1> and <P2> are the
specific permissions of the rule.

For example, for the SELinux denies cups-lpd read access to cups.sock in RHEL solution:

# sesearch -A --source=cupsd_lpd_t --target=cupsd_var_run_t --class=sock_file --


perm=read
allow cupsd_lpd_t cupsd_var_run_t:sock_file { append getattr open read write };

The last line should now include the read operation.

3. Verify that the relevant service runs confined by SELinux:

a. Identify the process related to the relevant service:

$ systemctl status <service-name>

b. Check the SELinux context of the process listed in the output of the previous command:

$ ps -efZ | grep <process-name>

4. Verify that the service does not cause any SELinux denials:

# ausearch -m AVC -i -ts recent


<no matches>

The -i option interprets the numeric values into human-readable text.

Additional resources

How to create custom SELinux policy module wisely Knowledgebase article

Troubleshooting problems related to SELinux

10.3.5. SELinux denials in the Audit log


The Linux Audit system stores log entries in the /var/log/audit/audit.log file by default.

To list only SELinux-related records, use the ausearch command with the message type parameter set
to AVC and AVC_USER at a minimum, for example:

# ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR

An SELinux denial entry in the Audit log file can look as follows:

type=AVC msg=audit(1395177286.929:1638): avc: denied { read } for pid=6591 comm="httpd"


name="webpages" dev="0:37" ino=2112 scontext=system_u:system_r:httpd_t:s0
tcontext=system_u:object_r:nfs_t:s0 tclass=dir

189
Red Hat Enterprise Linux 8 System Design Guide

The most important parts of this entry are:

avc: denied - the action performed by SELinux and recorded in Access Vector Cache (AVC)

{ read } - the denied action

pid=6591 - the process identifier of the subject that tried to perform the denied action

comm="httpd" - the name of the command that was used to invoke the analyzed process

httpd_t - the SELinux type of the process

nfs_t - the SELinux type of the object affected by the process action

tclass=dir - the target object class

The previous log entry can be translated to:

SELinux denied the httpd process with PID 6591 and the httpd_t type to read from a directory with the
nfs_t type.

The following SELinux denial message occurs when the Apache HTTP Server attempts to access a
directory labeled with a type for the Samba suite:

type=AVC msg=audit(1226874073.147:96): avc: denied { getattr } for pid=2465 comm="httpd"


path="/var/www/html/file1" dev=dm-0 ino=284133 scontext=unconfined_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file

{ getattr } - the getattr entry indicates the source process was trying to read the target file’s
status information. This occurs before reading files. SELinux denies this action because the
process accesses the file and it does not have an appropriate label. Commonly seen permissions
include getattr, read, and write.

path="/var/www/html/file1" - the path to the object (target) the process attempted to access.

scontext="unconfined_u:system_r:httpd_t:s0" - the SELinux context of the process


(source) that attempted the denied action. In this case, it is the SELinux context of the Apache
HTTP Server, which is running with the httpd_t type.

tcontext="unconfined_u:object_r:samba_share_t:s0" - the SELinux context of the object


(target) the process attempted to access. In this case, it is the SELinux context of file1.

This SELinux denial can be translated to:

SELinux denied the httpd process with PID 2465 to access the /var/www/html/file1 file with the
samba_share_t type, which is not accessible to processes running in the httpd_t domain unless
configured otherwise.

Additional resources

auditd(8) and ausearch(8) man pages on your system

10.3.6. Additional resources


Basic SELinux Troubleshooting in CLI (Red Hat Knowledgebase)

190
CHAPTER 10. USING SELINUX

What is SELinux trying to tell me? The 4 key causes of SELinux errors (Fedora People)

[1] Text files that include DNS information, such as hostname to IP address mappings.

191
Red Hat Enterprise Linux 8 System Design Guide

PART III. DESIGN OF NETWORK

192
CHAPTER 11. CONFIGURING IP NETWORKING WITH IFCFG FILES

CHAPTER 11. CONFIGURING IP NETWORKING WITH IFCFG


FILES
Interface configuration (ifcfg) files control the software interfaces for individual network devices. As the
system boots, it uses these files to determine what interfaces to bring up and how to configure them.
These files are named ifcfg-name_pass, where the suffix name refers to the name of the device that
the configuration file controls. By convention, the ifcfg file’s suffix is the same as the string given by the
DEVICE directive in the configuration file itself.

IMPORTANT

NetworkManager supports profiles stored in the keyfile format. However, by default,


NetworkManager uses the ifcfg format when you use the NetworkManager API to create
or update profiles.

In a future major RHEL release, the keyfile format will be default. Consider using the
keyfile format if you want to manually create and manage configuration files. For details,
see NetworkManager connection profiles in keyfile format .

11.1. CONFIGURING AN INTERFACE WITH STATIC NETWORK SETTINGS


USING IFCFG FILES
If you do not use the NetworkManager utilities and applications, you can manually configure a network
interface by creating ifcfg files.

Procedure

To configure an interface with static network settings using ifcfg files, for an interface with the
name enp1s0, create a file with the name ifcfg-enp1s0 in the /etc/sysconfig/network-scripts/
directory that contains:

For IPv4 configuration:

DEVICE=enp1s0
BOOTPROTO=none
ONBOOT=yes
PREFIX=24
IPADDR=192.0.2.1
GATEWAY=192.0.2.254

For IPv6 configuration:

DEVICE=enp1s0
BOOTPROTO=none
ONBOOT=yes
IPV6INIT=yes
IPV6ADDR=2001:db8:1::2/64

Additional resources

nm-settings-ifcfg-rh(5) man page on your system

11.2. CONFIGURING AN INTERFACE WITH DYNAMIC NETWORK


193
Red Hat Enterprise Linux 8 System Design Guide

11.2. CONFIGURING AN INTERFACE WITH DYNAMIC NETWORK


SETTINGS USING IFCFG FILES
If you do not use the NetworkManager utilities and applications, you can manually configure a network
interface by creating ifcfg files.

Procedure

1. To configure an interface named em1 with dynamic network settings using ifcfg files, create a
file with the name ifcfg-em1 in the /etc/sysconfig/network-scripts/ directory that contains:

DEVICE=em1
BOOTPROTO=dhcp
ONBOOT=yes

2. To configure an interface to send:

A different host name to the DHCP server, add the following line to the ifcfg file:

DHCP_HOSTNAME=hostname

A different fully qualified domain name (FQDN) to the DHCP server, add the following line
to the ifcfg file:

DHCP_FQDN=fully.qualified.domain.name

NOTE

You can use only one of these settings. If you specify both DHCP_HOSTNAME
and DHCP_FQDN, only DHCP_FQDN is used.

3. To configure an interface to use particular DNS servers, add the following lines to the ifcfg file:

PEERDNS=no
DNS1=ip-address
DNS2=ip-address

where ip-address is the address of a DNS server. This will cause the network service to update
/etc/resolv.conf with the specified DNS servers specified. Only one DNS server address is
necessary, the other is optional.

11.3. MANAGING SYSTEM-WIDE AND PRIVATE CONNECTION


PROFILES WITH IFCFG FILES
By default, all users on a host can use the connections defined in ifcfg files. You can limit this behavior to
specific users by adding the USERS parameter to the ifcfg file.

Prerequisite

The ifcfg file already exists.

Procedure

194
CHAPTER 11. CONFIGURING IP NETWORKING WITH IFCFG FILES

1. Edit the ifcfg file in the /etc/sysconfig/network-scripts/ directory that you want to limit to
certain users, and add:

USERS="username1 username2 ..."

2. Reactive the connection:

# nmcli connection up connection_name

195
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 12. GETTING STARTED WITH IPVLAN


IPVLAN is a driver for a virtual network device that can be used in container environment to access the
host network. IPVLAN exposes a single MAC address to the external network regardless the number of
IPVLAN device created inside the host network. This means that a user can have multiple IPVLAN
devices in multiple containers and the corresponding switch reads a single MAC address. IPVLAN driver
is useful when the local switch imposes constraints on the total number of MAC addresses that it can
manage.

12.1. IPVLAN MODES


The following modes are available for IPVLAN:

L2 mode
In IPVLAN L2 mode, virtual devices receive and respond to address resolution protocol (ARP)
requests. The netfilter framework runs only inside the container that owns the virtual device. No
netfilter chains are executed in the default namespace on the containerized traffic. Using L2
mode provides good performance, but less control on the network traffic.

L3 mode
In L3 mode, virtual devices process only L3 traffic and above. Virtual devices do not respond to
ARP request and users must configure the neighbour entries for the IPVLAN IP addresses on
the relevant peers manually. The egress traffic of a relevant container is landed on the netfilter
POSTROUTING and OUTPUT chains in the default namespace while the ingress traffic is
threaded in the same way as L2 mode. Using L3 mode provides good control but decreases the
network traffic performance.

L3S mode
In L3S mode, virtual devices process the same way as in L3 mode, except that both egress and
ingress traffics of a relevant container are landed on netfilter chain in the default namespace.
L3S mode behaves in a similar way to L3 mode but provides greater control of the network.

NOTE

The IPVLAN virtual device does not receive broadcast and multicast traffic in case of L3
and L3S modes.

12.2. COMPARISON OF IPVLAN AND MACVLAN


The following table shows the major differences between MACVLAN and IPVLAN:

MACVLAN IPVLAN

Uses MAC address for each MACVLAN device. Uses single MAC address which does not limit the
number of IPVLAN devices.
Note that, if a switch reaches the maximum number
of MAC addresses it can store in its MAC table,
connectivity can be lost.

Netfilter rules for a global namespace cannot affect It is possible to control traffic to or from a IPVLAN
traffic to or from a MACVLAN device in a child device in L3 mode and L3S mode.
namespace.

196
CHAPTER 12. GETTING STARTED WITH IPVLAN

Both IPVLAN and MACVLAN do not require any level of encapsulation.

12.3. CREATING AND CONFIGURING THE IPVLAN DEVICE USING


IPROUTE2
This procedure shows how to set up the IPVLAN device using iproute2.

Procedure

1. To create an IPVLAN device, enter the following command:

# ip link add link real_NIC_device name IPVLAN_device type ipvlan mode l2

Note that network interface controller (NIC) is a hardware component which connects a
computer to a network.

Example 12.1. Creating an IPVLAN device

# ip link add link enp0s31f6 name my_ipvlan type ipvlan mode l2


# ip link
47: my_ipvlan@enp0s31f6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state
DOWN mode DEFAULT group default qlen 1000 link/ether e8:6a:6e:8a:a2:44 brd
ff:ff:ff:ff:ff:ff

2. To assign an IPv4 or IPv6 address to the interface, enter the following command:

# ip addr add dev IPVLAN_device IP_address/subnet_mask_prefix

3. In case of configuring an IPVLAN device in L3 mode or L3S mode, make the following setups:

a. Configure the neighbor setup for the remote peer on the remote host:

# ip neigh add dev peer_device IPVLAN_device_IP_address lladdr MAC_address

where MAC_address is the MAC address of the real NIC on which an IPVLAN device is based
on.

b. Configure an IPVLAN device for L3 mode with the following command:

# ip route add dev <real_NIC_device> <peer_IP_address/32>

For L3S mode:

# ip route add dev real_NIC_device peer_IP_address/32

where IP-address represents the address of the remote peer.

4. To set an IPVLAN device active, enter the following command:

# ip link set dev IPVLAN_device up

197
Red Hat Enterprise Linux 8 System Design Guide

5. To check if the IPVLAN device is active, execute the following command on the remote host:

# ping IP_address

where the IP_address uses the IP address of the IPVLAN device.

198
CHAPTER 13. REUSING THE SAME IP ADDRESS ON DIFFERENT INTERFACES

CHAPTER 13. REUSING THE SAME IP ADDRESS ON


DIFFERENT INTERFACES
With Virtual routing and forwarding (VRF), administrators can use multiple routing tables simultaneously
on the same host. For that, VRF partitions a network at layer 3. This enables the administrator to isolate
traffic using separate and independent route tables per VRF domain. This technique is similar to virtual
LANs (VLAN), which partitions a network at layer 2, where the operating system uses different VLAN
tags to isolate traffic sharing the same physical medium.

One benefit of VRF over partitioning on layer 2 is that routing scales better considering the number of
peers involved.

Red Hat Enterprise Linux uses a virtual vrt device for each VRF domain and adds routes to a VRF
domain by adding existing network devices to a VRF device. Addresses and routes previously attached
to the original device will be moved inside the VRF domain.

Note that each VRF domain is isolated from each other.

13.1. PERMANENTLY REUSING THE SAME IP ADDRESS ON DIFFERENT


INTERFACES
You can use the virtual routing and forwarding (VRF) feature to permanently use the same IP address
on different interfaces in one server.

IMPORTANT

To enable remote peers to contact both VRF interfaces while reusing the same IP
address, the network interfaces must belong to different broadcasting domains. A
broadcast domain in a network is a set of nodes, which receive broadcast traffic sent by
any of them. In most configurations, all nodes connected to the same switch belong to
the same broadcasting domain.

Prerequisites

You are logged in as the root user.

The network interfaces are not configured.

Procedure

1. Create and configure the first VRF device:

a. Create a connection for the VRF device and assign it to a routing table. For example, to
create a VRF device named vrf0 that is assigned to the 1001 routing table:

# nmcli connection add type vrf ifname vrf0 con-name vrf0 table 1001 ipv4.method
disabled ipv6.method disabled

b. Enable the vrf0 device:

# nmcli connection up vrf0

c. Assign a network device to the VRF just created. For example, to add the enp1s0 Ethernet

199
Red Hat Enterprise Linux 8 System Design Guide

c. Assign a network device to the VRF just created. For example, to add the enp1s0 Ethernet
device to the vrf0 VRF device and assign an IP address and the subnet mask to enp1s0,
enter:

# nmcli connection add type ethernet con-name vrf.enp1s0 ifname enp1s0 master
vrf0 ipv4.method manual ipv4.address 192.0.2.1/24

d. Activate the vrf.enp1s0 connection:

# nmcli connection up vrf.enp1s0

2. Create and configure the next VRF device:

a. Create the VRF device and assign it to a routing table. For example, to create a VRF device
named vrf1 that is assigned to the 1002 routing table, enter:

# nmcli connection add type vrf ifname vrf1 con-name vrf1 table 1002 ipv4.method
disabled ipv6.method disabled

b. Activate the vrf1 device:

# nmcli connection up vrf1

c. Assign a network device to the VRF just created. For example, to add the enp7s0 Ethernet
device to the vrf1 VRF device and assign an IP address and the subnet mask to enp7s0,
enter:

# nmcli connection add type ethernet con-name vrf.enp7s0 ifname enp7s0 master
vrf1 ipv4.method manual ipv4.address 192.0.2.1/24

d. Activate the vrf.enp7s0 device:

# nmcli connection up vrf.enp7s0

13.2. TEMPORARILY REUSING THE SAME IP ADDRESS ON DIFFERENT


INTERFACES
You can use the virtual routing and forwarding (VRF) feature to temporarily use the same IP address on
different interfaces in one server. Use this procedure only for testing purposes, because the
configuration is temporary and lost after you reboot the system.

IMPORTANT

To enable remote peers to contact both VRF interfaces while reusing the same IP
address, the network interfaces must belong to different broadcasting domains. A
broadcast domain in a network is a set of nodes which receive broadcast traffic sent by
any of them. In most configurations, all nodes connected to the same switch belong to
the same broadcasting domain.

Prerequisites

You are logged in as the root user.

200
CHAPTER 13. REUSING THE SAME IP ADDRESS ON DIFFERENT INTERFACES

The network interfaces are not configured.

Procedure

1. Create and configure the first VRF device:

a. Create the VRF device and assign it to a routing table. For example, to create a VRF device
named blue that is assigned to the 1001 routing table:

# ip link add dev blue type vrf table 1001

b. Enable the blue device:

# ip link set dev blue up

c. Assign a network device to the VRF device. For example, to add the enp1s0 Ethernet
device to the blue VRF device:

# ip link set dev enp1s0 master blue

d. Enable the enp1s0 device:

# ip link set dev enp1s0 up

e. Assign an IP address and subnet mask to the enp1s0 device. For example, to set it to
192.0.2.1/24:

# ip addr add dev enp1s0 192.0.2.1/24

2. Create and configure the next VRF device:

a. Create the VRF device and assign it to a routing table. For example, to create a VRF device
named red that is assigned to the 1002 routing table:

# ip link add dev red type vrf table 1002

b. Enable the red device:

# ip link set dev red up

c. Assign a network device to the VRF device. For example, to add the enp7s0 Ethernet
device to the red VRF device:

# ip link set dev enp7s0 master red

d. Enable the enp7s0 device:

# ip link set dev enp7s0 up

e. Assign the same IP address and subnet mask to the enp7s0 device as you used for enp1s0
in the blue VRF domain:

201
Red Hat Enterprise Linux 8 System Design Guide

# ip addr add dev enp7s0 192.0.2.1/24

3. Optional: Create further VRF devices as described above.

13.3. ADDITIONAL RESOURCES


/usr/share/doc/kernel-doc-<kernel_version>/Documentation/networking/vrf.txt from the
kernel-doc package

202
CHAPTER 14. SECURING NETWORKS

CHAPTER 14. SECURING NETWORKS

14.1. USING SECURE COMMUNICATIONS BETWEEN TWO SYSTEMS


WITH OPENSSH
SSH (Secure Shell) is a protocol which provides secure communications between two systems using a
client-server architecture and allows users to log in to server host systems remotely. Unlike other
remote communication protocols, such as FTP or Telnet, SSH encrypts the login session, which prevents
intruders from collecting unencrypted passwords from the connection.

14.1.1. Generating SSH key pairs


You can log in to an OpenSSH server without entering a password by generating an SSH key pair on a
local system and copying the generated public key to the OpenSSH server. Each user who wants to
create a key must run this procedure.

To preserve previously generated key pairs after you reinstall the system, back up the ~/.ssh/ directory
before you create new keys. After reinstalling, copy it back to your home directory. You can do this for all
users on your system, including root.

Prerequisites

You are logged in as a user who wants to connect to the OpenSSH server by using keys.

The OpenSSH server is configured to allow key-based authentication.

Procedure

1. Generate an ECDSA key pair:

$ ssh-keygen -t ecdsa
Generating public/private ecdsa key pair.
Enter file in which to save the key (/home/<username>/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase): <password>
Enter same passphrase again: <password>
Your identification has been saved in /home/<username>/.ssh/id_ecdsa.
Your public key has been saved in /home/<username>/.ssh/id_ecdsa.pub.
The key fingerprint is:
SHA256:Q/x+qms4j7PCQ0qFd09iZEFHA+SqwBKRNaU72oZfaCI
<username>@<localhost.example.com>
The key's randomart image is:
+---[ECDSA 256]---+
|.oo..o=++ |
|.. o .oo . |
|. .. o. o |
|....o.+... |
|o.oo.o +S . |
|.=.+. .o |
|E.*+. . . . |
|.=..+ +.. o |
| . oo*+o. |
+----[SHA256]-----+

You can also generate an RSA key pair by using the ssh-keygen command without any

203
Red Hat Enterprise Linux 8 System Design Guide

parameter or an Ed25519 key pair by entering the ssh-keygen -t ed25519 command. Note that
the Ed25519 algorithm is not FIPS-140-compliant, and OpenSSH does not work with Ed25519
keys in FIPS mode.

2. Copy the public key to a remote machine:

$ ssh-copy-id <username>@<ssh-server-example.com>
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are
already installed
<username>@<ssh-server-example.com>'s password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh '<username>@<ssh-server-example.com>'" and
check to make sure that only the key(s) you wanted were added.

Replace <username>@<ssh-server-example.com> with your credentials.

If you do not use the ssh-agent program in your session, the previous command copies the
most recently modified ~/.ssh/id*.pub public key if it is not yet installed. To specify another
public-key file or to prioritize keys in files over keys cached in memory by ssh-agent, use the
ssh-copy-id command with the -i option.

Verification

Log in to the OpenSSH server by using the key file:

$ ssh -o PreferredAuthentications=publickey <username>@<ssh-server-example.com>

Additional resources

ssh-keygen(1) and ssh-copy-id(1) man pages on your system

14.1.2. Setting key-based authentication as the only method on an OpenSSH server


To improve system security, enforce key-based authentication by disabling password authentication on
your OpenSSH server.

Prerequisites

The openssh-server package is installed.

The sshd daemon is running on the server.

You can already connect to the OpenSSH server by using a key.


See the Generating SSH key pairs section for details.

Procedure

1. Open the /etc/ssh/sshd_config configuration in a text editor, for example:

# vi /etc/ssh/sshd_config

2. Change the PasswordAuthentication option to no:

204
CHAPTER 14. SECURING NETWORKS

PasswordAuthentication no

3. On a system other than a new default installation, check that the PubkeyAuthentication
parameter is either not set or set to yes.

4. Set the ChallengeResponseAuthentication directive to no.


Note that the corresponding entry is commented out in the configuration file and the default
value is yes.

5. To use key-based authentication with NFS-mounted home directories, enable the


use_nfs_home_dirs SELinux boolean:

# setsebool -P use_nfs_home_dirs 1

6. If you are connected remotely, not using console or out-of-band access, test the key-based
login process before disabling password authentication.

7. Reload the sshd daemon to apply the changes:

# systemctl reload sshd

Additional resources

sshd_config(5) and setsebool(8) man pages on your system

14.1.3. Caching your SSH credentials by using ssh-agent


To avoid entering a passphrase each time you initiate an SSH connection, you can use the ssh-agent
utility to cache the private SSH key for a login session. If the agent is running and your keys are
unlocked, you can log in to SSH servers by using these keys but without having to enter the key’s
password again. The private key and the passphrase remain secure.

Prerequisites

You have a remote host with the SSH daemon running and reachable through the network.

You know the IP address or hostname and credentials to log in to the remote host.

You have generated an SSH key pair with a passphrase and transferred the public key to the
remote machine.
See the Generating SSH key pairs section for details.

Procedure

1. Add the command for automatically starting ssh-agent in your session to the ~/.bashrc file:

a. Open ~/.bashrc in a text editor of your choice, for example:

$ vi ~/.bashrc

b. Add the following line to the file:

eval $(ssh-agent)

205
Red Hat Enterprise Linux 8 System Design Guide

c. Save the changes, and quit the editor.

2. Add the following line to the ~/.ssh/config file:

AddKeysToAgent yes

With this option and ssh-agent started in your session, the agent prompts for a password only
for the first time when you connect to a host.

Verification

Log in to a host which uses the corresponding public key of the cached private key in the agent,
for example:

$ ssh <example.user>@<[email protected]>

Note that you did not have to enter the passphrase.

14.1.4. Authenticating by SSH keys stored on a smart card


You can create and store ECDSA and RSA keys on a smart card and authenticate by the smart card on
an OpenSSH client. Smart-card authentication replaces the default password authentication.

Prerequisites

On the client side, the opensc package is installed and the pcscd service is running.

Procedure

1. List all keys provided by the OpenSC PKCS #11 module including their PKCS #11 URIs and save
the output to the keys.pub file:

$ ssh-keygen -D pkcs11: > keys.pub

2. Transfer the public key to the remote server. Use the ssh-copy-id command with the keys.pub
file created in the previous step:

$ ssh-copy-id -f -i keys.pub <[email protected]>

3. Connect to <ssh-server-example.com> by using the ECDSA key. You can use just a subset of the
URI, which uniquely references your key, for example:

$ ssh -i "pkcs11:id=%01?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so" <ssh-server-


example.com>
Enter PIN for 'SSH key':
[ssh-server-example.com] $

Because OpenSSH uses the p11-kit-proxy wrapper and the OpenSC PKCS #11 module is
registered to the p11-kit tool, you can simplify the previous command:

$ ssh -i "pkcs11:id=%01" <ssh-server-example.com>


Enter PIN for 'SSH key':
[ssh-server-example.com] $

206
CHAPTER 14. SECURING NETWORKS

If you skip the id= part of a PKCS #11 URI, OpenSSH loads all keys that are available in the proxy
module. This can reduce the amount of typing required:

$ ssh -i pkcs11: <ssh-server-example.com>


Enter PIN for 'SSH key':
[ssh-server-example.com] $

4. Optional: You can use the same URI string in the ~/.ssh/config file to make the configuration
permanent:

$ cat ~/.ssh/config
IdentityFile "pkcs11:id=%01?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so"
$ ssh <ssh-server-example.com>
Enter PIN for 'SSH key':
[ssh-server-example.com] $

The ssh client utility now automatically uses this URI and the key from the smart card.

Additional resources

p11-kit(8), opensc.conf(5), pcscd(8), ssh(1), and ssh-keygen(1) man pages on your system

14.1.5. Additional resources


sshd(8), ssh(1), scp(1), sftp(1), ssh-keygen(1), ssh-copy-id(1), ssh_config(5),
sshd_config(5), update-crypto-policies(8), and crypto-policies(7) man pages on your system

Configuring SELinux for applications and services with non-standard configurations

Controlling network traffic using firewalld

14.2. PLANNING AND IMPLEMENTING TLS


TLS (Transport Layer Security) is a cryptographic protocol used to secure network communications.
When hardening system security settings by configuring preferred key-exchange protocols,
authentication methods, and encryption algorithms, it is necessary to bear in mind that the broader the
range of supported clients, the lower the resulting security. Conversely, strict security settings lead to
limited compatibility with clients, which can result in some users being locked out of the system. Be sure
to target the strictest available configuration and only relax it when it is required for compatibility
reasons.

14.2.1. SSL and TLS protocols


The Secure Sockets Layer (SSL) protocol was originally developed by Netscape Corporation to provide
a mechanism for secure communication over the Internet. Subsequently, the protocol was adopted by
the Internet Engineering Task Force (IETF) and renamed to Transport Layer Security (TLS).

The TLS protocol sits between an application protocol layer and a reliable transport layer, such as
TCP/IP. It is independent of the application protocol and can thus be layered underneath many different
protocols, for example: HTTP, FTP, SMTP, and so on.

207
Red Hat Enterprise Linux 8 System Design Guide

Protocol version Usage recommendation

SSL v2 Do not use. Has serious security vulnerabilities. Removed from the core crypto libraries
since RHEL 7.

SSL v3 Do not use. Has serious security vulnerabilities. Removed from the core crypto libraries
since RHEL 8.

TLS 1.0 Not recommended to use. Has known issues that cannot be mitigated in a way that
guarantees interoperability, and does not support modern cipher suites. In RHEL 8,
enabled only in the LEGACY system-wide cryptographic policy profile.

TLS 1.1 Use for interoperability purposes where needed. Does not support modern cipher suites.
In RHEL 8, enabled only in the LEGACY policy.

TLS 1.2 Supports the modern AEAD cipher suites. This version is enabled in all system-wide
crypto policies, but optional parts of this protocol contain vulnerabilities and TLS 1.2 also
allows outdated algorithms.

TLS 1.3 Recommended version. TLS 1.3 removes known problematic options, provides
additional privacy by encrypting more of the negotiation handshake and can be faster
thanks usage of more efficient modern cryptographic algorithms. TLS 1.3 is also
enabled in all system-wide cryptographic policies.

Additional resources

IETF: The Transport Layer Security (TLS) Protocol Version 1.3

14.2.2. Security considerations for TLS in RHEL 8


In RHEL 8, cryptography-related considerations are significantly simplified thanks to the system-wide
crypto policies. The DEFAULT crypto policy allows only TLS 1.2 and 1.3. To allow your system to
negotiate connections using the earlier versions of TLS, you need to either opt out from following crypto
policies in an application or switch to the LEGACY policy with the update-crypto-policies command.
See Using system-wide cryptographic policies for more information.

The default settings provided by libraries included in RHEL 8 are secure enough for most deployments.
The TLS implementations use secure algorithms where possible while not preventing connections from
or to legacy clients or servers. Apply hardened settings in environments with strict security requirements
where legacy clients or servers that do not support secure algorithms or protocols are not expected or
allowed to connect.

The most straightforward way to harden your TLS configuration is switching the system-wide
cryptographic policy level to FUTURE using the update-crypto-policies --set FUTURE command.

208
CHAPTER 14. SECURING NETWORKS


WARNING

Algorithms disabled for the LEGACY cryptographic policy do not conform to Red
Hat’s vision of RHEL 8 security, and their security properties are not reliable.
Consider moving away from using these algorithms instead of re-enabling them. If
you do decide to re-enable them, for example for interoperability with old
hardware, treat them as insecure and apply extra protection measures, such as
isolating their network interactions to separate network segments. Do not use them
across public networks.

If you decide to not follow RHEL system-wide crypto policies or create custom cryptographic policies
tailored to your setup, use the following recommendations for preferred protocols, cipher suites, and
key lengths on your custom configuration:

14.2.2.1. Protocols

The latest version of TLS provides the best security mechanism. Unless you have a compelling reason to
include support for older versions of TLS, allow your systems to negotiate connections using at least
TLS version 1.2.

Note that even though RHEL 8 supports TLS version 1.3, not all features of this protocol are fully
supported by RHEL 8 components. For example, the 0-RTT (Zero Round Trip Time) feature, which
reduces connection latency, is not yet fully supported by the Apache web server.

14.2.2.2. Cipher suites

Modern, more secure cipher suites should be preferred to old, insecure ones. Always disable the use of
eNULL and aNULL cipher suites, which do not offer any encryption or authentication at all. If at all
possible, ciphers suites based on RC4 or HMAC-MD5, which have serious shortcomings, should also be
disabled. The same applies to the so-called export cipher suites, which have been intentionally made
weaker, and thus are easy to break.

While not immediately insecure, cipher suites that offer less than 128 bits of security should not be
considered for their short useful life. Algorithms that use 128 bits of security or more can be expected to
be unbreakable for at least several years, and are thus strongly recommended. Note that while 3DES
ciphers advertise the use of 168 bits, they actually offer 112 bits of security.

Always prefer cipher suites that support (perfect) forward secrecy (PFS), which ensures the
confidentiality of encrypted data even in case the server key is compromised. This rules out the fast
RSA key exchange, but allows for the use of ECDHE and DHE. Of the two, ECDHE is the faster and
therefore the preferred choice.

You should also prefer AEAD ciphers, such as AES-GCM, over CBC-mode ciphers as they are not
vulnerable to padding oracle attacks. Additionally, in many cases, AES-GCM is faster than AES in CBC
mode, especially when the hardware has cryptographic accelerators for AES.

Note also that when using the ECDHE key exchange with ECDSA certificates, the transaction is even
faster than a pure RSA key exchange. To provide support for legacy clients, you can install two pairs of
certificates and keys on a server: one with ECDSA keys (for new clients) and one with RSA keys (for
legacy ones).

209
Red Hat Enterprise Linux 8 System Design Guide

14.2.2.3. Public key length

When using RSA keys, always prefer key lengths of at least 3072 bits signed by at least SHA-256, which
is sufficiently large for true 128 bits of security.


WARNING

The security of your system is only as strong as the weakest link in the chain. For
example, a strong cipher alone does not guarantee good security. The keys and the
certificates are just as important, as well as the hash functions and keys used by the
Certification Authority (CA) to sign your keys.

Additional resources

System-wide crypto policies in RHEL 8

update-crypto-policies(8) man page on your system

14.2.3. Hardening TLS configuration in applications


In RHEL, system-wide crypto policies provide a convenient way to ensure that your applications that use
cryptographic libraries do not allow known insecure protocols, ciphers, or algorithms.

If you want to harden your TLS-related configuration with your customized cryptographic settings, you
can use the cryptographic configuration options described in this section, and override the system-wide
crypto policies just in the minimum required amount.

Regardless of the configuration you choose to use, always ensure that your server application enforces
server-side cipher order , so that the cipher suite to be used is determined by the order you configure.

14.2.3.1. Configuring the Apache HTTP server to use TLS

The Apache HTTP Server can use both OpenSSL and NSS libraries for its TLS needs. RHEL 8
provides the mod_ssl functionality through eponymous packages:

# yum install mod_ssl

The mod_ssl package installs the /etc/httpd/conf.d/ssl.conf configuration file, which can be used to
modify the TLS-related settings of the Apache HTTP Server.

Install the httpd-manual package to obtain complete documentation for the Apache HTTP Server,
including TLS configuration. The directives available in the /etc/httpd/conf.d/ssl.conf configuration file
are described in detail in the /usr/share/httpd/manual/mod/mod_ssl.html file. Examples of various
settings are described in the /usr/share/httpd/manual/ssl/ssl_howto.html file.

When modifying the settings in the /etc/httpd/conf.d/ssl.conf configuration file, be sure to consider the
following three directives at the minimum:

SSLProtocol
Use this directive to specify the version of TLS or SSL you want to allow.

210
CHAPTER 14. SECURING NETWORKS

SSLCipherSuite
Use this directive to specify your preferred cipher suite or disable the ones you want to disallow.
SSLHonorCipherOrder
Uncomment and set this directive to on to ensure that the connecting clients adhere to the order of
ciphers you specified.

For example, to use only the TLS 1.2 and 1.3 protocol:

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1

See the Configuring TLS encryption on an Apache HTTP Server chapter in the Deploying different
types of servers document for more information.

14.2.3.2. Configuring the Nginx HTTP and proxy server to use TLS

To enable TLS 1.3 support in Nginx, add the TLSv1.3 value to the ssl_protocols option in the server
section of the /etc/nginx/nginx.conf configuration file:

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
....
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers
....
}

See the Adding TLS encryption to an Nginx web server chapter in the Deploying different types of
servers document for more information.

14.2.3.3. Configuring the Dovecot mail server to use TLS

To configure your installation of the Dovecot mail server to use TLS, modify the
/etc/dovecot/conf.d/10-ssl.conf configuration file. You can find an explanation of some of the basic
configuration directives available in that file in the
/usr/share/doc/dovecot/wiki/SSL.DovecotConfiguration.txt file, which is installed along with the
standard installation of Dovecot.

When modifying the settings in the /etc/dovecot/conf.d/10-ssl.conf configuration file, be sure to


consider the following three directives at the minimum:

ssl_protocols
Use this directive to specify the version of TLS or SSL you want to allow or disable.
ssl_cipher_list
Use this directive to specify your preferred cipher suites or disable the ones you want to disallow.
ssl_prefer_server_ciphers
Uncomment and set this directive to yes to ensure that the connecting clients adhere to the order of
ciphers you specified.

For example, the following line in /etc/dovecot/conf.d/10-ssl.conf allows only TLS 1.1 and later:

ssl_protocols = !SSLv2 !SSLv3 !TLSv1

211
Red Hat Enterprise Linux 8 System Design Guide

Additional resources

Deploying different types of servers on RHEL 8

config(5) and ciphers(1) man pages.

Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport
Layer Security (DTLS).

Mozilla SSL Configuration Generator.

SSL Server Test.

14.3. SETTING UP AN IPSEC VPN


A virtual private network (VPN) is a way of connecting to a local network over the internet. IPsec
provided by Libreswan is the preferred method for creating a VPN. Libreswan is a user-space IPsec
implementation for VPN. A VPN enables the communication between your LAN, and another, remote
LAN by setting up a tunnel across an intermediate network such as the internet. For security reasons, a
VPN tunnel always uses authentication and encryption. For cryptographic operations, Libreswan uses
the NSS library.

14.3.1. Libreswan as an IPsec VPN implementation


In RHEL, you can configure a Virtual Private Network (VPN) by using the IPsec protocol, which is
supported by the Libreswan application. Libreswan is a continuation of the Openswan application, and
many examples from the Openswan documentation are interchangeable with Libreswan.

The IPsec protocol for a VPN is configured using the Internet Key Exchange (IKE) protocol. The terms
IPsec and IKE are used interchangeably. An IPsec VPN is also called an IKE VPN, IKEv2 VPN, XAUTH
VPN, Cisco VPN or IKE/IPsec VPN. A variant of an IPsec VPN that also uses the Layer 2 Tunneling
Protocol (L2TP) is usually called an L2TP/IPsec VPN, which requires the xl2tpd package provided by the
optional repository.

Libreswan is an open-source, user-space IKE implementation. IKE v1 and v2 are implemented as a user-
level daemon. The IKE protocol is also encrypted. The IPsec protocol is implemented by the Linux kernel,
and Libreswan configures the kernel to add and remove VPN tunnel configurations.

The IKE protocol uses UDP port 500 and 4500. The IPsec protocol consists of two protocols:

Encapsulated Security Payload (ESP), which has protocol number 50.

Authenticated Header (AH), which has protocol number 51.

The AH protocol is not recommended for use. Users of AH are recommended to migrate to ESP with null
encryption.

The IPsec protocol provides two modes of operation:

Tunnel Mode (the default)

Transport Mode.

You can configure the kernel with IPsec without IKE. This is called manual keying. You can also configure
manual keying using the ip xfrm commands, however, this is strongly discouraged for security reasons.
Libreswan communicates with the Linux kernel using the Netlink interface. The kernel performs packet

212
CHAPTER 14. SECURING NETWORKS

encryption and decryption.

Libreswan uses the Network Security Services (NSS) cryptographic library. NSS is certified for use with
the Federal Information Processing Standard (FIPS) Publication 140-2.

IMPORTANT

IKE/IPsec VPNs, implemented by Libreswan and the Linux kernel, is the only VPN
technology recommended for use in RHEL. Do not use any other VPN technology
without understanding the risks of doing so.

In RHEL, Libreswan follows system-wide cryptographic policies by default. This ensures that
Libreswan uses secure settings for current threat models including IKEv2 as a default protocol. See
Using system-wide crypto policies for more information.

Libreswan does not use the terms "source" and "destination" or "server" and "client" because IKE/IPsec
are peer to peer protocols. Instead, it uses the terms "left" and "right" to refer to end points (the hosts).
This also allows you to use the same configuration on both end points in most cases. However,
administrators usually choose to always use "left" for the local host and "right" for the remote host.

The leftid and rightid options serve as identification of the respective hosts in the authentication
process. See the ipsec.conf(5) man page for more information.

14.3.2. Authentication methods in Libreswan


Libreswan supports several authentication methods, each of which fits a different scenario.

Pre-Shared key (PSK)


Pre-Shared Key (PSK) is the simplest authentication method. For security reasons, do not use PSKs
shorter than 64 random characters. In FIPS mode, PSKs must comply with a minimum-strength
requirement depending on the integrity algorithm used. You can set PSK by using the authby=secret
connection.

Raw RSA keys


Raw RSA keys are commonly used for static host-to-host or subnet-to-subnet IPsec configurations.
Each host is manually configured with the public RSA keys of all other hosts, and Libreswan sets up an
IPsec tunnel between each pair of hosts. This method does not scale well for large numbers of hosts.

You can generate a raw RSA key on a host using the ipsec newhostkey command. You can list
generated keys by using the ipsec showhostkey command. The leftrsasigkey= line is required for
connection configurations that use CKA ID keys. Use the authby=rsasig connection option for raw RSA
keys.

X.509 certificates
X.509 certificates are commonly used for large-scale deployments with hosts that connect to a common
IPsec gateway. A central certificate authority (CA) signs RSA certificates for hosts or users. This central
CA is responsible for relaying trust, including the revocations of individual hosts or users.

For example, you can generate X.509 certificates using the openssl command and the NSS certutil
command. Because Libreswan reads user certificates from the NSS database using the certificates'
nickname in the leftcert= configuration option, provide a nickname when you create a certificate.

If you use a custom CA certificate, you must import it to the Network Security Services (NSS) database.
213
Red Hat Enterprise Linux 8 System Design Guide

If you use a custom CA certificate, you must import it to the Network Security Services (NSS) database.
You can import any certificate in the PKCS #12 format to the Libreswan NSS database by using the
ipsec import command.


WARNING

Libreswan requires an Internet Key Exchange (IKE) peer ID as a subject alternative


name (SAN) for every peer certificate as described in section 3.1 of RFC 4945 .
Disabling this check by changing the require-id-on-certificated= option can make
the system vulnerable to man-in-the-middle attacks.

Use the authby=rsasig connection option for authentication based on X.509 certificates using RSA
with SHA-1 and SHA-2. You can further limit it for ECDSA digital signatures using SHA-2 by setting
authby= to ecdsa and RSA Probabilistic Signature Scheme (RSASSA-PSS) digital signatures based
authentication with SHA-2 through authby=rsa-sha2. The default value is authby=rsasig,ecdsa.

The certificates and the authby= signature methods should match. This increases interoperability and
preserves authentication in one digital signature system.

NULL authentication
NULL authentication is used to gain mesh encryption without authentication. It protects against passive
attacks but not against active attacks. However, because IKEv2 allows asymmetric authentication
methods, NULL authentication can also be used for internet-scale opportunistic IPsec. In this model,
clients authenticate the server, but servers do not authenticate the client. This model is similar to secure
websites using TLS. Use authby=null for NULL authentication.

Protection against quantum computers


In addition to the previously mentioned authentication methods, you can use the Post-quantum Pre-
shared Key (PPK) method to protect against possible attacks by quantum computers. Individual clients
or groups of clients can use their own PPK by specifying a PPK ID that corresponds to an out-of-band
configured pre-shared key.

Using IKEv1 with pre-shared keys protects against quantum attackers. The redesign of IKEv2 does not
offer this protection natively. Libreswan offers the use of a Post-quantum Pre-shared Key (PPK) to
protect IKEv2 connections against quantum attacks.

To enable optional PPK support, add ppk=yes to the connection definition. To require PPK, add
ppk=insist. Then, each client can be given a PPK ID with a secret value that is communicated out-of-
band (and preferably quantum-safe). The PPK’s should be very strong in randomness and not based on
dictionary words. The PPK ID and PPK data are stored in the ipsec.secrets file, for example:

@west @east : PPKS "user1" "thestringismeanttobearandomstr"

The PPKS option refers to static PPKs. This experimental function uses one-time-pad-based Dynamic
PPKs. Upon each connection, a new part of the one-time pad is used as the PPK. When used, that part
of the dynamic PPK inside the file is overwritten with zeros to prevent re-use. If there is no more one-
time-pad material left, the connection fails. See the ipsec.secrets(5) man page for more information.

214
CHAPTER 14. SECURING NETWORKS


WARNING

The implementation of dynamic PPKs is provided as an unsupported Technology


Preview. Use with caution.

14.3.3. Installing Libreswan


Before you can set a VPN through the Libreswan IPsec/IKE implementation, you must install the
corresponding packages, start the ipsec service, and allow the service in your firewall.

Prerequisites

The AppStream repository is enabled.

Procedure

1. Install the libreswan packages:

# yum install libreswan

2. If you are re-installing Libreswan, remove its old database files and create a new database:

# systemctl stop ipsec


# rm /etc/ipsec.d/*db
# ipsec initnss

3. Start the ipsec service, and enable the service to be started automatically on boot:

# systemctl enable ipsec --now

4. Configure the firewall to allow 500 and 4500/UDP ports for the IKE, ESP, and AH protocols by
adding the ipsec service:

# firewall-cmd --add-service="ipsec"
# firewall-cmd --runtime-to-permanent

14.3.4. Creating a host-to-host VPN


You can configure Libreswan to create a host-to-host IPsec VPN between two hosts referred to as left
and right using authentication by raw RSA keys.

Prerequisites

Libreswan is installed and the ipsec service is started on each node.

Procedure

1. Generate a raw RSA key pair on each host:

215
Red Hat Enterprise Linux 8 System Design Guide

# ipsec newhostkey

2. The previous step returned the generated key’s ckaid. Use that ckaid with the following
command on left, for example:

# ipsec showhostkey --left --ckaid 2d3ea57b61c9419dfd6cf43a1eb6cb306c0e857d

The output of the previous command generated the leftrsasigkey= line required for the
configuration. Do the same on the second host (right):

# ipsec showhostkey --right --ckaid a9e1f6ce9ecd3608c24e8f701318383f41798f03

3. In the /etc/ipsec.d/ directory, create a new my_host-to-host.conf file. Write the RSA host keys
from the output of the ipsec showhostkey commands in the previous step to the new file. For
example:

conn mytunnel
leftid=@west
left=192.1.2.23
leftrsasigkey=0sAQOrlo+hOafUZDlCQmXFrje/oZm [...] W2n417C/4urYHQkCvuIQ==
rightid=@east
right=192.1.2.45
rightrsasigkey=0sAQO3fwC6nSSGgt64DWiYZzuHbc4 [...] D/v8t5YTQ==
authby=rsasig

4. After importing keys, restart the ipsec service:

# systemctl restart ipsec

5. Load the connection:

# ipsec auto --add mytunnel

6. Establish the tunnel:

# ipsec auto --up mytunnel

7. To automatically start the tunnel when the ipsec service is started, add the following line to the
connection definition:

auto=start

14.3.5. Configuring a site-to-site VPN


To create a site-to-site IPsec VPN, by joining two networks, an IPsec tunnel between the two hosts, is
created. The hosts thus act as the end points, which are configured to permit traffic from one or more
subnets to pass through. Therefore you can think of the host as gateways to the remote portion of the
network.

The configuration of the site-to-site VPN only differs from the host-to-host VPN in that one or more
networks or subnets must be specified in the configuration file.

Prerequisites

216
CHAPTER 14. SECURING NETWORKS

Prerequisites

A host-to-host VPN is already configured.

Procedure

1. Copy the file with the configuration of your host-to-host VPN to a new file, for example:

# cp /etc/ipsec.d/my_host-to-host.conf /etc/ipsec.d/my_site-to-site.conf

2. Add the subnet configuration to the file created in the previous step, for example:

conn mysubnet
also=mytunnel
leftsubnet=192.0.1.0/24
rightsubnet=192.0.2.0/24
auto=start

conn mysubnet6
also=mytunnel
leftsubnet=2001:db8:0:1::/64
rightsubnet=2001:db8:0:2::/64
auto=start

# the following part of the configuration file is the same for both host-to-host and site-to-site
connections:

conn mytunnel
leftid=@west
left=192.1.2.23
leftrsasigkey=0sAQOrlo+hOafUZDlCQmXFrje/oZm [...] W2n417C/4urYHQkCvuIQ==
rightid=@east
right=192.1.2.45
rightrsasigkey=0sAQO3fwC6nSSGgt64DWiYZzuHbc4 [...] D/v8t5YTQ==
authby=rsasig

14.3.6. Configuring a remote access VPN


Road warriors are traveling users with mobile clients and a dynamically assigned IP address. The mobile
clients authenticate using X.509 certificates.

The following example shows configuration for IKEv2, and it avoids using the IKEv1 XAUTH protocol.

On the server:

conn roadwarriors
ikev2=insist
# support (roaming) MOBIKE clients (RFC 4555)
mobike=yes
fragmentation=yes
left=1.2.3.4
# if access to the LAN is given, enable this, otherwise use 0.0.0.0/0
# leftsubnet=10.10.0.0/16
leftsubnet=0.0.0.0/0
leftcert=gw.example.com

217
Red Hat Enterprise Linux 8 System Design Guide

leftid=%fromcert
leftxauthserver=yes
leftmodecfgserver=yes
right=%any
# trust our own Certificate Agency
rightca=%same
# pick an IP address pool to assign to remote users
# 100.64.0.0/16 prevents RFC1918 clashes when remote users are behind NAT
rightaddresspool=100.64.13.100-100.64.13.254
# if you want remote clients to use some local DNS zones and servers
modecfgdns="1.2.3.4, 5.6.7.8"
modecfgdomains="internal.company.com, corp"
rightxauthclient=yes
rightmodecfgclient=yes
authby=rsasig
# optionally, run the client X.509 ID through pam to allow or deny client
# pam-authorize=yes
# load connection, do not initiate
auto=add
# kill vanished roadwarriors
dpddelay=1m
dpdtimeout=5m
dpdaction=clear

On the mobile client, the road warrior’s device, use a slight variation of the previous configuration:

conn to-vpn-server
ikev2=insist
# pick up our dynamic IP
left=%defaultroute
leftsubnet=0.0.0.0/0
leftcert=myname.example.com
leftid=%fromcert
leftmodecfgclient=yes
# right can also be a DNS hostname
right=1.2.3.4
# if access to the remote LAN is required, enable this, otherwise use 0.0.0.0/0
# rightsubnet=10.10.0.0/16
rightsubnet=0.0.0.0/0
fragmentation=yes
# trust our own Certificate Agency
rightca=%same
authby=rsasig
# allow narrowing to the server’s suggested assigned IP and remote subnet
narrowing=yes
# support (roaming) MOBIKE clients (RFC 4555)
mobike=yes
# initiate connection
auto=start

14.3.7. Configuring a mesh VPN


A mesh VPN network, which is also known as an any-to-any VPN, is a network where all nodes
communicate using IPsec. The configuration allows for exceptions for nodes that cannot use IPsec. The
mesh VPN network can be configured in two ways:

218
CHAPTER 14. SECURING NETWORKS

To require IPsec.

To prefer IPsec but allow a fallback to clear-text communication.

Authentication between the nodes can be based on X.509 certificates or on DNS Security Extensions
(DNSSEC).

You can use any regular IKEv2 authentication method for opportunistic IPsec, because these
connections are regular Libreswan configurations, except for the opportunistic IPsec that is defined by
right=%opportunisticgroup entry. A common authentication method is for hosts to authenticate each
other based on X.509 certificates using a commonly shared certification authority (CA). Cloud
deployments typically issue certificates for each node in the cloud as part of the standard procedure.

IMPORTANT

Do not use PreSharedKey (PSK) authentication because one compromised host would
result in group PSK secret being compromised as well.

You can use NULL authentication to deploy encryption between nodes without authentication, which
protects only against passive attackers.

The following procedure uses X.509 certificates. You can generate these certificates by using any kind
of CA management system, such as the Dogtag Certificate System. Dogtag assumes that the
certificates for each node are available in the PKCS #12 format (.p12 files), which contain the private
key, the node certificate, and the Root CA certificate used to validate other nodes' X.509 certificates.

Each node has an identical configuration with the exception of its X.509 certificate. This allows for
adding new nodes without reconfiguring any of the existing nodes in the network. The PKCS #12 files
require a "friendly name", for which we use the name "node" so that the configuration files referencing
the friendly name can be identical for all nodes.

Prerequisites

Libreswan is installed, and the ipsec service is started on each node.

A new NSS database is initialized.

1. If you already have an old NSS database, remove the old database files:

# systemctl stop ipsec


# rm /etc/ipsec.d/*db

2. You can initialize a new database with the following command:

# ipsec initnss

Procedure

1. On each node, import PKCS #12 files. This step requires the password used to generate the
PKCS #12 files:

# ipsec import nodeXXX.p12

2. Create the following three connection definitions for the IPsec required (private), IPsec

219
Red Hat Enterprise Linux 8 System Design Guide

2. Create the following three connection definitions for the IPsec required (private), IPsec
optional (private-or-clear), and No IPsec (clear) profiles:

# cat /etc/ipsec.d/mesh.conf
conn clear
auto=ondemand 1
type=passthrough
authby=never
left=%defaultroute
right=%group

conn private
auto=ondemand
type=transport
authby=rsasig
failureshunt=drop
negotiationshunt=drop
ikev2=insist
left=%defaultroute
leftcert=nodeXXXX
leftid=%fromcert 2
rightid=%fromcert
right=%opportunisticgroup

conn private-or-clear
auto=ondemand
type=transport
authby=rsasig
failureshunt=passthrough
negotiationshunt=passthrough
# left
left=%defaultroute
leftcert=nodeXXXX 3
leftid=%fromcert
leftrsasigkey=%cert
# right
rightrsasigkey=%cert
rightid=%fromcert
right=%opportunisticgroup

1 The auto variable has several options:

You can use the ondemand connection option with opportunistic IPsec to initiate the IPsec
connection, or for explicitly configured connections that do not need to be active all the time. This
option sets up a trap XFRM policy in the kernel, enabling the IPsec connection to begin when it
receives the first packet that matches that policy.

You can effectively configure and manage your IPsec connections, whether you use Opportunistic
IPsec or explicitly configured connections, by using the following options:

The add option


Loads the connection configuration and prepares it for responding to remote initiations.
However, the connection is not automatically initiated from the local side. You can manually
start the IPsec connection by using the command ipsec auto --up.
The start option

Loads the connection configuration and prepares it for responding to remote initiations.

220
CHAPTER 14. SECURING NETWORKS

Loads the connection configuration and prepares it for responding to remote initiations.
Additionally, it immediately initiates a connection to the remote peer. You can use this option
for permanent and always active connections.

2 The leftid and rightid variables identify the right and the left channel of the IPsec tunnel
connection. You can use these variables to obtain the value of the local IP address or the subject
DN of the local certificate, if you have configured one.

3 The leftcert variable defines the nickname of the NSS database that you want to use.

3. Add the IP address of the network to the corresponding category. For example, if all nodes
reside in the 10.15.0.0/16 network, and all nodes must use IPsec encryption:

# echo "10.15.0.0/16" >> /etc/ipsec.d/policies/private

4. To allow certain nodes, for example, 10.15.34.0/24, to work with and without IPsec, add
those nodes to the private-or-clear group:

# echo "10.15.34.0/24" >> /etc/ipsec.d/policies/private-or-clear

5. To define a host, for example, 10.15.1.2, which is not capable of IPsec into the clear group,
use:

# echo "10.15.1.2/32" >> /etc/ipsec.d/policies/clear

You can create the files in the /etc/ipsec.d/policies directory from a template for each
new node, or you can provision them by using Puppet or Ansible.

Note that every node has the same list of exceptions or different traffic flow expectations.
Two nodes, therefore, might not be able to communicate because one requires IPsec and
the other cannot use IPsec.

6. Restart the node to add it to the configured mesh:

# systemctl restart ipsec

Verification

1. Open an IPsec tunnel by using the ping command:

# ping <nodeYYY>

2. Display the NSS database with the imported certification:

# certutil -L -d sql:/etc/ipsec.d

Certificate Nickname Trust Attributes


SSL,S/MIME,JAR/XPI

west u,u,u
ca CT,,

3. See which tunnels are open on the node:

221
Red Hat Enterprise Linux 8 System Design Guide

# ipsec trafficstatus
006 #2: "private#10.15.0.0/16"[1] ...<nodeYYY>, type=ESP, add_time=1691399301,
inBytes=512, outBytes=512, maxBytes=2^63B, id='C=US, ST=NC, O=Example
Organization, CN=east'

Additional resources

ipsec.conf(5) man page on your system

For more information about the authby variable, see 6.2. Authentication methods in Libreswan .

14.3.8. Deploying a FIPS-compliant IPsec VPN


You can deploy a FIPS-compliant IPsec VPN solution with Libreswan. To do so, you can identify which
cryptographic algorithms are available and which are disabled for Libreswan in FIPS mode.

Prerequisites

The AppStream repository is enabled.

Procedure

1. Install the libreswan packages:

# yum install libreswan

2. If you are re-installing Libreswan, remove its old NSS database:

# systemctl stop ipsec


# rm /etc/ipsec.d/*db

3. Start the ipsec service, and enable the service to be started automatically on boot:

# systemctl enable ipsec --now

4. Configure the firewall to allow 500 and 4500 UDP ports for the IKE, ESP, and AH protocols by
adding the ipsec service:

# firewall-cmd --add-service="ipsec"
# firewall-cmd --runtime-to-permanent

5. Switch the system to FIPS mode:

# fips-mode-setup --enable

6. Restart your system to allow the kernel to switch to FIPS mode:

# reboot

Verification

1. Confirm Libreswan is running in FIPS mode:

222
CHAPTER 14. SECURING NETWORKS

# ipsec whack --fipsstatus


000 FIPS mode enabled

2. Alternatively, check entries for the ipsec unit in the systemd journal:

$ journalctl -u ipsec
...
Jan 22 11:26:50 localhost.localdomain pluto[3076]: FIPS Product: YES
Jan 22 11:26:50 localhost.localdomain pluto[3076]: FIPS Kernel: YES
Jan 22 11:26:50 localhost.localdomain pluto[3076]: FIPS Mode: YES

3. To see the available algorithms in FIPS mode:

# ipsec pluto --selftest 2>&1 | head -11


FIPS Product: YES
FIPS Kernel: YES
FIPS Mode: YES
NSS DB directory: sql:/etc/ipsec.d
Initializing NSS
Opening NSS database "sql:/etc/ipsec.d" read-only
NSS initialized
NSS crypto library initialized
FIPS HMAC integrity support [enabled]
FIPS mode enabled for pluto daemon
NSS library is running in FIPS mode
FIPS HMAC integrity verification self-test passed

4. To query disabled algorithms in FIPS mode:

# ipsec pluto --selftest 2>&1 | grep disabled


Encryption algorithm CAMELLIA_CTR disabled; not FIPS compliant
Encryption algorithm CAMELLIA_CBC disabled; not FIPS compliant
Encryption algorithm SERPENT_CBC disabled; not FIPS compliant
Encryption algorithm TWOFISH_CBC disabled; not FIPS compliant
Encryption algorithm TWOFISH_SSH disabled; not FIPS compliant
Encryption algorithm NULL disabled; not FIPS compliant
Encryption algorithm CHACHA20_POLY1305 disabled; not FIPS compliant
Hash algorithm MD5 disabled; not FIPS compliant
PRF algorithm HMAC_MD5 disabled; not FIPS compliant
PRF algorithm AES_XCBC disabled; not FIPS compliant
Integrity algorithm HMAC_MD5_96 disabled; not FIPS compliant
Integrity algorithm HMAC_SHA2_256_TRUNCBUG disabled; not FIPS compliant
Integrity algorithm AES_XCBC_96 disabled; not FIPS compliant
DH algorithm MODP1024 disabled; not FIPS compliant
DH algorithm MODP1536 disabled; not FIPS compliant
DH algorithm DH31 disabled; not FIPS compliant

5. To list all allowed algorithms and ciphers in FIPS mode:

# ipsec pluto --selftest 2>&1 | grep ESP | grep FIPS | sed "s/^.*FIPS//"
{256,192,*128} aes_ccm, aes_ccm_c
{256,192,*128} aes_ccm_b
{256,192,*128} aes_ccm_a
[*192] 3des

223
Red Hat Enterprise Linux 8 System Design Guide

{256,192,*128} aes_gcm, aes_gcm_c


{256,192,*128} aes_gcm_b
{256,192,*128} aes_gcm_a
{256,192,*128} aesctr
{256,192,*128} aes
{256,192,*128} aes_gmac
sha, sha1, sha1_96, hmac_sha1
sha512, sha2_512, sha2_512_256, hmac_sha2_512
sha384, sha2_384, sha2_384_192, hmac_sha2_384
sha2, sha256, sha2_256, sha2_256_128, hmac_sha2_256
aes_cmac
null
null, dh0
dh14
dh15
dh16
dh17
dh18
ecp_256, ecp256
ecp_384, ecp384
ecp_521, ecp521

Additional resources

Using system-wide cryptographic policies

14.3.9. Protecting the IPsec NSS database by a password


By default, the IPsec service creates its Network Security Services (NSS) database with an empty
password during the first start. To enhance security, you can add password protection.

NOTE

In the previous releases of RHEL up to version 6.6, you had to protect the IPsec NSS
database with a password to meet the FIPS 140-2 requirements because the NSS
cryptographic libraries were certified for the FIPS 140-2 Level 2 standard. In RHEL 8,
NIST certified NSS to Level 1 of this standard, and this status does not require password
protection for the database.

Prerequisites

The /etc/ipsec.d/ directory contains NSS database files.

Procedure

1. Enable password protection for the NSS database for Libreswan:

# certutil -N -d sql:/etc/ipsec.d
Enter Password or Pin for "NSS Certificate DB":
Enter a password which will be used to encrypt your keys.
The password should be at least 8 characters long,
and should contain at least one non-alphabetic character.

Enter new password:

224
CHAPTER 14. SECURING NETWORKS

2. Create the /etc/ipsec.d/nsspassword file that containins the password you have set in the
previous step, for example:

# cat /etc/ipsec.d/nsspassword
NSS Certificate DB:_<password>_

The nsspassword file use the following syntax:

<token_1>:<password1>
<token_2>:<password2>

The default NSS software token is NSS Certificate DB. If your system is running in FIPS mode,
the name of the token is NSS FIPS 140-2 Certificate DB.

3. Depending on your scenario, either start or restart the ipsec service after you finish the
nsspassword file:

# systemctl restart ipsec

Verification

1. Check that the ipsec service is running after you have added a non-empty password to its NSS
database:

# systemctl status ipsec


● ipsec.service - Internet Key Exchange (IKE) Protocol Daemon for IPsec
Loaded: loaded (/usr/lib/systemd/system/ipsec.service; enabled; vendor preset: disable>
Active: active (running)...

2. Check that the Journal log contains entries that confirm a successful initialization:

# journalctl -u ipsec
...
pluto[6214]: Initializing NSS using read-write database "sql:/etc/ipsec.d"
pluto[6214]: NSS Password from file "/etc/ipsec.d/nsspassword" for token "NSS Certificate
DB" with length 20 passed to NSS
pluto[6214]: NSS crypto library initialized
...

Additional resources

certutil(1) man page on your system

FIPS 140-2 and FIPS 140-3 in the Compliance Activities and Government Standards
Knowledgebase article.

14.3.10. Configuring an IPsec VPN to use TCP


Libreswan supports TCP encapsulation of IKE and IPsec packets as described in RFC 8229. With this
feature, you can establish IPsec VPNs on networks that prevent traffic transmitted via UDP and
Encapsulating Security Payload (ESP). You can configure VPN servers and clients to use TCP either as a
fallback or as the main VPN transport protocol. Because TCP encapsulation has bigger performance
costs, use TCP as the main VPN protocol only if UDP is permanently blocked in your scenario.

225
Red Hat Enterprise Linux 8 System Design Guide

Prerequisites

A remote-access VPN is already configured.

Procedure

1. Add the following option to the /etc/ipsec.conf file in the config setup section:

listen-tcp=yes

2. To use TCP encapsulation as a fallback option when the first attempt over UDP fails, add the
following two options to the client’s connection definition:

enable-tcp=fallback
tcp-remoteport=4500

Alternatively, if you know that UDP is permanently blocked, use the following options in the
client’s connection configuration:

enable-tcp=yes
tcp-remoteport=4500

Additional resources

IETF RFC 8229: TCP Encapsulation of IKE and IPsec Packets

14.3.11. Configuring automatic detection and usage of ESP hardware offload to


accelerate an IPsec connection
Offloading Encapsulating Security Payload (ESP) to the hardware accelerates IPsec connections over
Ethernet. By default, Libreswan detects if hardware supports this feature and, as a result, enables ESP
hardware offload. In case that the feature was disabled or explicitly enabled, you can switch back to
automatic detection.

Prerequisites

The network card supports ESP hardware offload.

The network driver supports ESP hardware offload.

The IPsec connection is configured and works.

Procedure

1. Edit the Libreswan configuration file in the /etc/ipsec.d/ directory of the connection that should
use automatic detection of ESP hardware offload support.

2. Ensure the nic-offload parameter is not set in the connection’s settings.

3. If you removed nic-offload, restart the ipsec service:

# systemctl restart ipsec

Verification

226
CHAPTER 14. SECURING NETWORKS

Verification

1. Display the tx_ipsec and rx_ipsec counters of the Ethernet device the IPsec connection uses:

# ethtool -S enp1s0 | egrep "_ipsec"


tx_ipsec: 10
rx_ipsec: 10

2. Send traffic through the IPsec tunnel. For example, ping a remote IP address:

# ping -c 5 remote_ip_address

3. Display the tx_ipsec and rx_ipsec counters of the Ethernet device again:

# ethtool -S enp1s0 | egrep "_ipsec"


tx_ipsec: 15
rx_ipsec: 15

If the counter values have increased, ESP hardware offload works.

Additional resources

Configuring a VPN with IPsec

14.3.12. Configuring ESP hardware offload on a bond to accelerate an IPsec


connection
Offloading Encapsulating Security Payload (ESP) to the hardware accelerates IPsec connections. If you
use a network bond for fail-over reasons, the requirements and the procedure to configure ESP
hardware offload are different from those using a regular Ethernet device. For example, in this scenario,
you enable the offload support on the bond, and the kernel applies the settings to the ports of the bond.

Prerequisites

All network cards in the bond support ESP hardware offload. Use the ethtool -k
<interface_name> | grep "esp-hw-offload" command to verify whether each bond port
supports this feature.

The bond is configured and works.

The bond uses the active-backup mode. The bonding driver does not support any other modes
for this feature.

The IPsec connection is configured and works.

Procedure

1. Enable ESP hardware offload support on the network bond:

# nmcli connection modify bond0 ethtool.feature-esp-hw-offload on

This command enables ESP hardware offload support on the bond0 connection.

2. Reactivate the bond0 connection:

227
Red Hat Enterprise Linux 8 System Design Guide

# nmcli connection up bond0

3. Edit the Libreswan configuration file in the /etc/ipsec.d/ directory of the connection that should
use ESP hardware offload, and append the nic-offload=yes statement to the connection entry:

conn example
...
nic-offload=yes

4. Restart the ipsec service:

# systemctl restart ipsec

Verification
The verification methods depend on various aspects, such as the kernel version and driver. For example,
certain drivers provide counters, but their names can vary. See the documentation of your network
driver for details.

The following verification steps work for the ixgbe driver on Red Hat Enterprise Linux 8:

1. Display the active port of the bond:

# grep "Currently Active Slave" /proc/net/bonding/bond0


Currently Active Slave: enp1s0

2. Display the tx_ipsec and rx_ipsec counters of the active port:

# ethtool -S enp1s0 | egrep "_ipsec"


tx_ipsec: 10
rx_ipsec: 10

3. Send traffic through the IPsec tunnel. For example, ping a remote IP address:

# ping -c 5 remote_ip_address

4. Display the tx_ipsec and rx_ipsec counters of the active port again:

# ethtool -S enp1s0 | egrep "_ipsec"


tx_ipsec: 15
rx_ipsec: 15

If the counter values have increased, ESP hardware offload works.

Additional resources

Configuring a network bond

Setting up an IPsec VPN

14.3.13. Configuring VPN connections with IPsec by using RHEL system roles

With the vpn system role, you can configure VPN connections on RHEL systems by using Red Hat

228
CHAPTER 14. SECURING NETWORKS

With the vpn system role, you can configure VPN connections on RHEL systems by using Red Hat
Ansible Automation Platform. You can use it to set up host-to-host, network-to-network, VPN Remote
Access Server, and mesh configurations.

For host-to-host connections, the role sets up a VPN tunnel between each pair of hosts in the list of
vpn_connections using the default parameters, including generating keys as needed. Alternatively, you
can configure it to create an opportunistic mesh configuration between all hosts listed. The role assumes
that the names of the hosts under hosts are the same as the names of the hosts used in the Ansible
inventory, and that you can use those names to configure the tunnels.

NOTE

The vpn RHEL system role currently supports only Libreswan, which is an IPsec
implementation, as the VPN provider.

14.3.13.1. Creating a host-to-host VPN with IPsec by using the vpn RHEL system role

You can use the vpn system role to configure host-to-host connections by running an Ansible playbook
on the control node, which configures all managed nodes listed in an inventory file.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

- name: Host to host VPN


hosts: managed-node-01.example.com, managed-node-02.example.com
roles:
- rhel-system-roles.vpn
vars:
vpn_connections:
- hosts:
managed-node-01.example.com:
managed-node-02.example.com:
vpn_manage_firewall: true
vpn_manage_selinux: true

This playbook configures the connection managed-node-01.example.com-to-managed-node-


02.example.com by using pre-shared key authentication with keys auto-generated by the
system role. Because vpn_manage_firewall and vpn_manage_selinux are both set to true,
the vpn role uses the firewall and selinux roles to manage the ports used by the vpn role.

To configure connections from managed hosts to external hosts that are not listed in the
inventory file, add the following section to the vpn_connections list of hosts:

vpn_connections:
- hosts:
managed-node-01.example.com:

229
Red Hat Enterprise Linux 8 System Design Guide

<external_node>:
hostname: <IP_address_or_hostname>

This configures one additional connection: managed-node-01.example.com-


to-<external_node>

NOTE

The connections are configured only on the managed nodes and not on the
external node.

2. Optional: You can specify multiple VPN connections for the managed nodes by using additional
sections within vpn_connections, for example, a control plane and a data plane:

- name: Multiple VPN


hosts: managed-node-01.example.com, managed-node-02.example.com
roles:
- rhel-system-roles.vpn
vars:
vpn_connections:
- name: control_plane_vpn
hosts:
managed-node-01.example.com:
hostname: 192.0.2.0 # IP for the control plane
managed-node-02.example.com:
hostname: 192.0.2.1
- name: data_plane_vpn
hosts:
managed-node-01.example.com:
hostname: 10.0.0.1 # IP for the data plane
managed-node-02.example.com:
hostname: 10.0.0.2

3. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

4. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

1. On the managed nodes, confirm that the connection is successfully loaded:

# ipsec status | grep <connection_name>

Replace <connection_name> with the name of the connection from this node, for example
managed_node1-to-managed_node2.

NOTE
230
CHAPTER 14. SECURING NETWORKS

NOTE

By default, the role generates a descriptive name for each connection it creates
from the perspective of each system. For example, when creating a connection
between managed_node1 and managed_node2, the descriptive name of this
connection on managed_node1 is managed_node1-to-managed_node2 but
on managed_node2 the connection is named managed_node2-to-
managed_node1.

2. On the managed nodes, confirm that the connection is successfully started:

# ipsec trafficstatus | grep <connection_name>

3. Optional: If a connection does not successfully load, manually add the connection by entering
the following command. This provides more specific information indicating why the connection
failed to establish:

# ipsec auto --add <connection_name>

NOTE

Any errors that may occur during the process of loading and starting the
connection are reported in the /var/log/pluto.log file. Because these logs are
hard to parse, manually add the connection to obtain log messages from the
standard output instead.

Additional resources

/usr/share/ansible/roles/rhel-system-roles.vpn/README.md file

/usr/share/doc/rhel-system-roles/vpn/ directory

14.3.13.2. Creating an opportunistic mesh VPN connection with IPsec by using the vpn RHEL
system role

You can use the vpn system role to configure an opportunistic mesh VPN connection that uses
certificates for authentication by running an Ansible playbook on the control node, which will configure
all the managed nodes listed in an inventory file.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

The IPsec Network Security Services (NSS) crypto library in the /etc/ipsec.d/ directory contains
the necessary certificates.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

231
Red Hat Enterprise Linux 8 System Design Guide

- name: Mesh VPN


hosts: managed-node-01.example.com, managed-node-02.example.com, managed-node-
03.example.com
roles:
- rhel-system-roles.vpn
vars:
vpn_connections:
- opportunistic: true
auth_method: cert
policies:
- policy: private
cidr: default
- policy: private-or-clear
cidr: 198.51.100.0/24
- policy: private
cidr: 192.0.2.0/24
- policy: clear
cidr: 192.0.2.7/32
vpn_manage_firewall: true
vpn_manage_selinux: true

Authentication with certificates is configured by defining the auth_method: cert parameter in


the playbook. By default, the node name is used as the certificate nickname. In this example, this
is managed-node-01.example.com. You can define different certificate names by using the
cert_name attribute in your inventory.

In this example procedure, the control node, which is the system from which you will run the
Ansible playbook, shares the same classless inter-domain routing (CIDR) number as both of the
managed nodes (192.0.2.0/24) and has the IP address 192.0.2.7. Therefore, the control node
falls under the private policy which is automatically created for CIDR 192.0.2.0/24.

To prevent SSH connection loss during the play, a clear policy for the control node is included in
the list of policies. Note that there is also an item in the policies list where the CIDR is equal to
default. This is because this playbook overrides the rule from the default policy to make it
private instead of private-or-clear.

Because vpn_manage_firewall and vpn_manage_selinux are both set to true, the vpn role
uses the firewall and selinux roles to manage the ports used by the vpn role.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Additional resources

/usr/share/ansible/roles/rhel-system-roles.vpn/README.md file

/usr/share/doc/rhel-system-roles/vpn/ directory

232
CHAPTER 14. SECURING NETWORKS

14.3.14. Configuring IPsec connections that opt out of the system-wide crypto
policies

Overriding system-wide crypto-policies for a connection

The RHEL system-wide cryptographic policies create a special connection called %default. This
connection contains the default values for the ikev2, esp, and ike options. However, you can override
the default values by specifying the mentioned option in the connection configuration file.

For example, the following configuration allows connections that use IKEv1 with AES and SHA-1 or SHA-
2, and IPsec (ESP) with either AES-GCM or AES-CBC:

conn MyExample
...
ikev2=never
ike=aes-sha2,aes-sha1;modp2048
esp=aes_gcm,aes-sha2,aes-sha1
...

Note that AES-GCM is available for IPsec (ESP) and for IKEv2, but not for IKEv1.

Disabling system-wide crypto policies for all connections


To disable system-wide crypto policies for all IPsec connections, comment out the following line in the
/etc/ipsec.conf file:

include /etc/crypto-policies/back-ends/libreswan.config

Then add the ikev2=never option to your connection configuration file.

Additional resources

Using system-wide cryptographic policies

14.3.15. Troubleshooting IPsec VPN configurations


Problems related to IPsec VPN configurations most commonly occur due to several main reasons. If you
are encountering such problems, you can check if the cause of the problem corresponds to any of the
following scenarios, and apply the corresponding solution.

Basic connection troubleshooting


Most problems with VPN connections occur in new deployments, where administrators configured
endpoints with mismatched configuration options. Also, a working configuration can suddenly stop
working, often due to newly introduced incompatible values. This could be the result of an administrator
changing the configuration. Alternatively, an administrator may have installed a firmware update or a
package update with different default values for certain options, such as encryption algorithms.

To confirm that an IPsec VPN connection is established:

# ipsec trafficstatus
006 #8: "vpn.example.com"[1] 192.0.2.1, type=ESP, add_time=1595296930, inBytes=5999,
outBytes=3231, id='@vpn.example.com', lease=100.64.13.5/32

If the output is empty or does not show an entry with the connection name, the tunnel is broken.

233
Red Hat Enterprise Linux 8 System Design Guide

To check that the problem is in the connection:

1. Reload the vpn.example.com connection:

# ipsec auto --add vpn.example.com


002 added connection description "vpn.example.com"

2. Next, initiate the VPN connection:

# ipsec auto --up vpn.example.com

Firewall-related problems
The most common problem is that a firewall on one of the IPsec endpoints or on a router between the
endpoints is dropping all Internet Key Exchange (IKE) packets.

For IKEv2, an output similar to the following example indicates a problem with a firewall:

# ipsec auto --up vpn.example.com


181 "vpn.example.com"[1] 192.0.2.2 #15: initiating IKEv2 IKE SA
181 "vpn.example.com"[1] 192.0.2.2 #15: STATE_PARENT_I1: sent v2I1, expected v2R1
010 "vpn.example.com"[1] 192.0.2.2 #15: STATE_PARENT_I1: retransmission; will wait 0.5
seconds for response
010 "vpn.example.com"[1] 192.0.2.2 #15: STATE_PARENT_I1: retransmission; will wait 1
seconds for response
010 "vpn.example.com"[1] 192.0.2.2 #15: STATE_PARENT_I1: retransmission; will wait 2
seconds for
...

For IKEv1, the output of the initiating command looks like:

# ipsec auto --up vpn.example.com


002 "vpn.example.com" #9: initiating Main Mode
102 "vpn.example.com" #9: STATE_MAIN_I1: sent MI1, expecting MR1
010 "vpn.example.com" #9: STATE_MAIN_I1: retransmission; will wait 0.5 seconds for
response
010 "vpn.example.com" #9: STATE_MAIN_I1: retransmission; will wait 1 seconds for
response
010 "vpn.example.com" #9: STATE_MAIN_I1: retransmission; will wait 2 seconds for
response
...

Because the IKE protocol, which is used to set up IPsec, is encrypted, you can troubleshoot only a limited
subset of problems using the tcpdump tool. If a firewall is dropping IKE or IPsec packets, you can try to
find the cause using the tcpdump utility. However, tcpdump cannot diagnose other problems with IPsec
VPN connections.

To capture the negotiation of the VPN and all encrypted data on the eth0 interface:

# tcpdump -i eth0 -n -n esp or udp port 500 or udp port 4500 or tcp port 4500

Mismatched algorithms, protocols, and policies

VPN connections require that the endpoints have matching IKE algorithms, IPsec algorithms, and IP

234
CHAPTER 14. SECURING NETWORKS

VPN connections require that the endpoints have matching IKE algorithms, IPsec algorithms, and IP
address ranges. If a mismatch occurs, the connection fails. If you identify a mismatch by using one of the
following methods, fix it by aligning algorithms, protocols, or policies.

If the remote endpoint is not running IKE/IPsec, you can see an ICMP packet indicating it. For
example:

# ipsec auto --up vpn.example.com


...
000 "vpn.example.com"[1] 192.0.2.2 #16: ERROR: asynchronous network error report on
wlp2s0 (192.0.2.2:500), complainant 198.51.100.1: Connection refused [errno 111, origin
ICMP type 3 code 3 (not authenticated)]
...

Example of mismatched IKE algorithms:

# ipsec auto --up vpn.example.com


...
003 "vpn.example.com"[1] 193.110.157.148 #3: dropping unexpected IKE_SA_INIT message
containing NO_PROPOSAL_CHOSEN notification; message payloads: N; missing payloads:
SA,KE,Ni

Example of mismatched IPsec algorithms:

# ipsec auto --up vpn.example.com


...
182 "vpn.example.com"[1] 193.110.157.148 #5: STATE_PARENT_I2: sent v2I2, expected
v2R2 {auth=IKEv2 cipher=AES_GCM_16_256 integ=n/a prf=HMAC_SHA2_256
group=MODP2048}
002 "vpn.example.com"[1] 193.110.157.148 #6: IKE_AUTH response contained the error
notification NO_PROPOSAL_CHOSEN

A mismatched IKE version could also result in the remote endpoint dropping the request
without a response. This looks identical to a firewall dropping all IKE packets.

Example of mismatched IP address ranges for IKEv2 (called Traffic Selectors - TS):

# ipsec auto --up vpn.example.com


...
1v2 "vpn.example.com" #1: STATE_PARENT_I2: sent v2I2, expected v2R2 {auth=IKEv2
cipher=AES_GCM_16_256 integ=n/a prf=HMAC_SHA2_512 group=MODP2048}
002 "vpn.example.com" #2: IKE_AUTH response contained the error notification
TS_UNACCEPTABLE

Example of mismatched IP address ranges for IKEv1:

# ipsec auto --up vpn.example.com


...
031 "vpn.example.com" #2: STATE_QUICK_I1: 60 second timeout exceeded after 0
retransmits. No acceptable response to our first Quick Mode message: perhaps peer likes
no proposal

When using PreSharedKeys (PSK) in IKEv1, if both sides do not put in the same PSK, the entire
IKE message becomes unreadable:

235
Red Hat Enterprise Linux 8 System Design Guide

# ipsec auto --up vpn.example.com


...
003 "vpn.example.com" #1: received Hash Payload does not match computed value
223 "vpn.example.com" #1: sending notification INVALID_HASH_INFORMATION to
192.0.2.23:500

In IKEv2, the mismatched-PSK error results in an AUTHENTICATION_FAILED message:

# ipsec auto --up vpn.example.com


...
002 "vpn.example.com" #1: IKE SA authentication request rejected by peer:
AUTHENTICATION_FAILED

Maximum transmission unit


Other than firewalls blocking IKE or IPsec packets, the most common cause of networking problems
relates to an increased packet size of encrypted packets. Network hardware fragments packets larger
than the maximum transmission unit (MTU), for example, 1500 bytes. Often, the fragments are lost and
the packets fail to re-assemble. This leads to intermittent failures, when a ping test, which uses small-
sized packets, works but other traffic fails. In this case, you can establish an SSH session but the terminal
freezes as soon as you use it, for example, by entering the 'ls -al /usr' command on the remote host.

To work around the problem, reduce MTU size by adding the mtu=1400 option to the tunnel
configuration file.

Alternatively, for TCP connections, enable an iptables rule that changes the MSS value:

# iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

If the previous command does not solve the problem in your scenario, directly specify a lower size in the
set-mss parameter:

# iptables -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1380

Network address translation (NAT)


When an IPsec host also serves as a NAT router, it could accidentally remap packets. The following
example configuration demonstrates the problem:

conn myvpn
left=172.16.0.1
leftsubnet=10.0.2.0/24
right=172.16.0.2
rightsubnet=192.168.0.0/16

The system with address 172.16.0.1 have a NAT rule:

iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE

If the system on address 10.0.2.33 sends a packet to 192.168.0.1, then the router translates the source
10.0.2.33 to 172.16.0.1 before it applies the IPsec encryption.

Then, the packet with the source address 10.0.2.33 no longer matches the conn myvpn configuration,

236
CHAPTER 14. SECURING NETWORKS

Then, the packet with the source address 10.0.2.33 no longer matches the conn myvpn configuration,
and IPsec does not encrypt this packet.

To solve this problem, insert rules that exclude NAT for target IPsec subnet ranges on the router, in this
example:

iptables -t nat -I POSTROUTING -s 10.0.2.0/24 -d 192.168.0.0/16 -j RETURN

Kernel IPsec subsystem bugs


The kernel IPsec subsystem might fail, for example, when a bug causes a desynchronizing of the IKE user
space and the IPsec kernel. To check for such problems:

$ cat /proc/net/xfrm_stat
XfrmInError 0
XfrmInBufferError 0
...

Any non-zero value in the output of the previous command indicates a problem. If you encounter this
problem, open a new support case, and attach the output of the previous command along with the
corresponding IKE logs.

Libreswan logs
Libreswan logs using the syslog protocol by default. You can use the journalctl command to find log
entries related to IPsec. Because the corresponding entries to the log are sent by the pluto IKE daemon,
search for the “pluto” keyword, for example:

$ journalctl -b | grep pluto

To show a live log for the ipsec service:

$ journalctl -f -u ipsec

If the default level of logging does not reveal your configuration problem, enable debug logs by adding
the plutodebug=all option to the config setup section in the /etc/ipsec.conf file.

Note that debug logging produces a lot of entries, and it is possible that either the journald or syslogd
service rate-limits the syslog messages. To ensure you have complete logs, redirect the logging to a
file. Edit the /etc/ipsec.conf, and add the logfile=/var/log/pluto.log in the config setup section.

Additional resources

Troubleshooting problems by using log files

tcpdump(8) and ipsec.conf(5) man pages.

Using and configuring firewalld

14.3.16. Configuring a VPN connection with control-center


If you use Red Hat Enterprise Linux with a graphical interface, you can configure a VPN connection in the
GNOME control-center.

Prerequisites

237
Red Hat Enterprise Linux 8 System Design Guide

The NetworkManager-libreswan-gnome package is installed.

Procedure

1. Press the Super key, type Settings, and press Enter to open the control-center application.

2. Select the Network entry on the left.

3. Click the + icon.

4. Select VPN.

5. Select the Identity menu entry to see the basic configuration options:
General

Gateway — The name or IP address of the remote VPN gateway.

Authentication

Type

IKEv2 (Certificate)- client is authenticated by certificate. It is more secure (default).

IKEv1 (XAUTH) - client is authenticated by user name and password, or a pre-shared key
(PSK).
The following configuration settings are available under the Advanced section:

Figure 14.1. Advanced options of a VPN connection


238
CHAPTER 14. SECURING NETWORKS

Figure 14.1. Advanced options of a VPN connection

239
Red Hat Enterprise Linux 8 System Design Guide


WARNING

When configuring an IPsec-based VPN connection using the gnome-


control-center application, the Advanced dialog displays the
configuration, but it does not allow any changes. As a consequence,
users cannot change any advanced IPsec options. Use the nm-
connection-editor or nmcli tools instead to perform configuration of
the advanced properties.

Identification

Domain — If required, enter the Domain Name.


Security

Phase1 Algorithms — corresponds to the ike Libreswan parameter — enter the algorithms
to be used to authenticate and set up an encrypted channel.

Phase2 Algorithms — corresponds to the esp Libreswan parameter — enter the algorithms
to be used for the IPsec negotiations.
Check the Disable PFS field to turn off Perfect Forward Secrecy (PFS) to ensure
compatibility with old servers that do not support PFS.

Phase1 Lifetime — corresponds to the ikelifetime Libreswan parameter — how long the key
used to encrypt the traffic will be valid.

Phase2 Lifetime — corresponds to the salifetime Libreswan parameter — how long a


particular instance of a connection should last before expiring.
Note that the encryption key should be changed from time to time for security reasons.

Remote network — corresponds to the rightsubnet Libreswan parameter — the destination


private remote network that should be reached through the VPN.
Check the narrowing field to enable narrowing. Note that it is only effective in IKEv2
negotiation.

Enable fragmentation — corresponds to the fragmentation Libreswan parameter —


whether or not to allow IKE fragmentation. Valid values are yes (default) or no.

Enable Mobike — corresponds to the mobike Libreswan parameter — whether to allow


Mobility and Multihoming Protocol (MOBIKE, RFC 4555) to enable a connection to migrate
its endpoint without needing to restart the connection from scratch. This is used on mobile
devices that switch between wired, wireless, or mobile data connections. The values are no
(default) or yes.

6. Select the IPv4 menu entry:


IPv4 Method

Automatic (DHCP) — Choose this option if the network you are connecting to uses a DHCP
server to assign dynamic IP addresses.

Link-Local Only — Choose this option if the network you are connecting to does not have a
DHCP server and you do not want to assign IP addresses manually. Random addresses will
be assigned as per RFC 3927 with prefix 169.254/16.

240
CHAPTER 14. SECURING NETWORKS

Manual — Choose this option if you want to assign IP addresses manually.

Disable — IPv4 is disabled for this connection.


DNS

In the DNS section, when Automatic is ON, switch it to OFF to enter the IP address of a
DNS server you want to use separating the IPs by comma.

Routes

Note that in the Routes section, when Automatic is ON, routes from DHCP are used, but
you can also add additional static routes. When OFF, only static routes are used.

Address — Enter the IP address of a remote network or host.

Netmask — The netmask or prefix length of the IP address entered above.

Gateway — The IP address of the gateway leading to the remote network or host entered
above.

Metric — A network cost, a preference value to give to this route. Lower values will be
preferred over higher values.
Use this connection only for resources on its network

Select this check box to prevent the connection from becoming the default route. Selecting
this option means that only traffic specifically destined for routes learned automatically over
the connection or entered here manually is routed over the connection.

7. To configure IPv6 settings in a VPN connection, select the IPv6 menu entry:
IPv6 Method

Automatic — Choose this option to use IPv6 Stateless Address AutoConfiguration


(SLAAC) to create an automatic, stateless configuration based on the hardware address
and Router Advertisements (RA).

Automatic, DHCP only — Choose this option to not use RA, but request information from
DHCPv6 directly to create a stateful configuration.

Link-Local Only — Choose this option if the network you are connecting to does not have a
DHCP server and you do not want to assign IP addresses manually. Random addresses will
be assigned as per RFC 4862 with prefix FE80::0.

Manual — Choose this option if you want to assign IP addresses manually.

Disable — IPv6 is disabled for this connection.


Note that DNS, Routes, Use this connection only for resources on its network are
common to IPv4 settings.

8. Once you have finished editing the VPN connection, click the Add button to customize the
configuration or the Apply button to save it for the existing one.

9. Switch the profile to ON to active the VPN connection.

Additional resources

nm-settings-libreswan(5)

241
Red Hat Enterprise Linux 8 System Design Guide

14.3.17. Configuring a VPN connection using nm-connection-editor


If you use Red Hat Enterprise Linux with a graphical interface, you can configure a VPN connection in the
nm-connection-editor application.

Prerequisites

The NetworkManager-libreswan-gnome package is installed.

If you configure an Internet Key Exchange version 2 (IKEv2) connection:

The certificate is imported into the IPsec network security services (NSS) database.

The nickname of the certificate in the NSS database is known.

Procedure

1. Open a terminal, and enter:

$ nm-connection-editor

2. Click the + button to add a new connection.

3. Select the IPsec based VPN connection type, and click Create.

4. On the VPN tab:

a. Enter the host name or IP address of the VPN gateway into the Gateway field, and select
an authentication type. Based on the authentication type, you must enter different
additional information:

IKEv2 (Certifiate) authenticates the client by using a certificate, which is more secure.
This setting requires the nickname of the certificate in the IPsec NSS database

IKEv1 (XAUTH) authenticates the user by using a user name and password (pre-shared
key). This setting requires that you enter the following values:

User name

Password

Group name

Secret

b. If the remote server specifies a local identifier for the IKE exchange, enter the exact string
in the Remote ID field. In the remote server runs Libreswan, this value is set in the server’s
leftid parameter.

242
CHAPTER 14. SECURING NETWORKS

c. Optional: Configure additional settings by clicking the Advanced button. You can configure
the following settings:

Identification

Domain — If required, enter the domain name.

Security

Phase1 Algorithms corresponds to the ike Libreswan parameter. Enter the


algorithms to be used to authenticate and set up an encrypted channel.

Phase2 Algorithms corresponds to the esp Libreswan parameter. Enter the


algorithms to be used for the IPsec negotiations.
Check the Disable PFS field to turn off Perfect Forward Secrecy (PFS) to ensure
compatibility with old servers that do not support PFS.

Phase1 Lifetime corresponds to the ikelifetime Libreswan parameter. This


parameter defines how long the key used to encrypt the traffic is valid.

Phase2 Lifetime corresponds to the salifetime Libreswan parameter. This


parameter defines how long a security association is valid.

Connectivity

Remote network corresponds to the rightsubnet Libreswan parameter and

243
Red Hat Enterprise Linux 8 System Design Guide

Remote network corresponds to the rightsubnet Libreswan parameter and


defines the destination private remote network that should be reached through the
VPN.
Check the narrowing field to enable narrowing. Note that it is only effective in the
IKEv2 negotiation.

Enable fragmentation corresponds to the fragmentation Libreswan parameter


and defines whether or not to allow IKE fragmentation. Valid values are yes
(default) or no.

Enable Mobike corresponds to the mobike Libreswan parameter. The parameter


defines whether to allow Mobility and Multihoming Protocol (MOBIKE) (RFC 4555)
to enable a connection to migrate its endpoint without needing to restart the
connection from scratch. This is used on mobile devices that switch between wired,
wireless or mobile data connections. The values are no (default) or yes.

5. On the IPv4 Settings tab, select the IP assignment method and, optionally, set additional static
addresses, DNS servers, search domains, and routes.

6. Save the connection.

7. Close nm-connection-editor.

NOTE

When you add a new connection by clicking the + button, NetworkManager creates a new
configuration file for that connection and then opens the same dialog that is used for
editing an existing connection. The difference between these dialogs is that an existing
connection profile has a Details menu entry.

Additional resources

nm-settings-libreswan(5) man page on your system

244
CHAPTER 14. SECURING NETWORKS

14.3.18. Additional resources


ipsec(8), ipsec.conf(5), ipsec.secrets(5), ipsec_auto(8), and ipsec_rsasigkey(8) man pages.

/usr/share/doc/libreswan-version/ directory.

The Libreswan Project Wiki .

All Libreswan man pages .

NIST Special Publication 800-77: Guide to IPsec VPNs .

14.4. USING MACSEC TO ENCRYPT LAYER-2 TRAFFIC IN THE SAME


PHYSICAL NETWORK
You can use MACsec to secure the communication between two devices (point-to-point). For example,
your branch office is connected over a Metro-Ethernet connection with the central office, you can
configure MACsec on the two hosts that connect the offices to increase the security.

14.4.1. How MACsec increases security


Media Access Control security (MACsec) is a layer-2 protocol that secures different traffic types over
the Ethernet links, including:

Dynamic host configuration protocol (DHCP)

address resolution protocol (ARP)

IPv4 and IPv6 traffic

Any traffic over IP such as TCP or UDP

MACsec encrypts and authenticates all traffic in LANs, by default with the GCM-AES-128 algorithm, and
uses a pre-shared key to establish the connection between the participant hosts. To change the pre-
shared key, you must update the NM configuration on all network hosts that use MACsec.

A MACsec connection uses an Ethernet device, such as an Ethernet network card, VLAN, or tunnel
device, as a parent. You can either set an IP configuration only on the MACsec device to communicate
with other hosts only by using the encrypted connection, or you can also set an IP configuration on the
parent device. In the latter case, you can use the parent device to communicate with other hosts using an
unencrypted connection and the MACsec device for encrypted connections.

MACsec does not require any special hardware. For example, you can use any switch, except if you want
to encrypt traffic only between a host and a switch. In this scenario, the switch must also support
MACsec.

In other words, you can configure MACsec for two common scenarios:

Host-to-host

Host-to-switch and switch-to-other-hosts

IMPORTANT

You can use MACsec only between hosts being in the same physical or virtual LAN.

245
Red Hat Enterprise Linux 8 System Design Guide

Additional resources

MACsec: a different solution to encrypt network traffic

14.4.2. Configuring a MACsec connection by using nmcli

You can use the nmcli utility to configure Ethernet interfaces to use MACsec. For example, you can
create a MACsec connection between two hosts that are connected over Ethernet.

Procedure

1. On the first host on which you configure MACsec:

Create the connectivity association key (CAK) and connectivity-association key name
(CKN) for the pre-shared key:

a. Create a 16-byte hexadecimal CAK:

# dd if=/dev/urandom count=16 bs=1 2> /dev/null | hexdump -e '1/2 "%04x"'


50b71a8ef0bd5751ea76de6d6c98c03a

b. Create a 32-byte hexadecimal CKN:

# dd if=/dev/urandom count=32 bs=1 2> /dev/null | hexdump -e '1/2 "%04x"'


f2b4297d39da7330910a74abc0449feb45b5c0b9fc23df1430e1898fcf1c4550

2. On both hosts you want to connect over a MACsec connection:

3. Create the MACsec connection:

# nmcli connection add type macsec con-name macsec0 ifname macsec0


connection.autoconnect yes macsec.parent enp1s0 macsec.mode psk macsec.mka-
cak 50b71a8ef0bd5751ea76de6d6c98c03a macsec.mka-ckn
f2b4297d39da7330910a74abc0449feb45b5c0b9fc23df1430e1898fcf1c4550

Use the CAK and CKN generated in the previous step in the macsec.mka-cak and
macsec.mka-ckn parameters. The values must be the same on every host in the MACsec-
protected network.

4. Configure the IP settings on the MACsec connection.

a. Configure the IPv4 settings. For example, to set a static IPv4 address, network mask,
default gateway, and DNS server to the macsec0 connection, enter:

# nmcli connection modify macsec0 ipv4.method manual ipv4.addresses


'192.0.2.1/24' ipv4.gateway '192.0.2.254' ipv4.dns '192.0.2.253'

b. Configure the IPv6 settings. For example, to set a static IPv6 address, network mask,
default gateway, and DNS server to the macsec0 connection, enter:

# nmcli connection modify macsec0 ipv6.method manual ipv6.addresses


'2001:db8:1::1/32' ipv6.gateway '2001:db8:1::fffe' ipv6.dns '2001:db8:1::fffd'

5. Activate the connection:

246
CHAPTER 14. SECURING NETWORKS

# nmcli connection up macsec0

Verification

1. Verify that the traffic is encrypted:

# tcpdump -nn -i enp1s0

2. Optional: Display the unencrypted traffic:

# tcpdump -nn -i macsec0

3. Display MACsec statistics:

# ip macsec show

4. Display individual counters for each type of protection: integrity-only (encrypt off) and
encryption (encrypt on)

# ip -s macsec show

Additional resources

MACsec: a different solution to encrypt network traffic

14.5. USING AND CONFIGURING FIREWALLD


A firewall is a way to protect machines from any unwanted traffic from outside. It enables users to
control incoming network traffic on host machines by defining a set of firewall rules. These rules are used
to sort the incoming traffic and either block it or allow through.

firewalld is a firewall service daemon that provides a dynamic customizable host-based firewall with a
D-Bus interface. Being dynamic, it enables creating, changing, and deleting the rules without the
necessity to restart the firewall daemon each time the rules are changed.

firewalld uses the concepts of zones and services, that simplify the traffic management. Zones are
predefined sets of rules. Network interfaces and sources can be assigned to a zone. The traffic allowed
depends on the network your computer is connected to and the security level this network is assigned.
Firewall services are predefined rules that cover all necessary settings to allow incoming traffic for a
specific service and they apply within a zone.

Services use one or more ports or addresses for network communication. Firewalls filter communication
based on ports. To allow network traffic for a service, its ports must be open. firewalld blocks all traffic
on ports that are not explicitly set as open. Some zones, such as trusted, allow all traffic by default.

Note that firewalld with nftables backend does not support passing custom nftables rules to firewalld,
using the --direct option.

14.5.1. When to use firewalld, nftables, or iptables


The following is a brief overview in which scenario you should use one of the following utilities:

firewalld: Use the firewalld utility for simple firewall use cases. The utility is easy to use and

247
Red Hat Enterprise Linux 8 System Design Guide

firewalld: Use the firewalld utility for simple firewall use cases. The utility is easy to use and
covers the typical use cases for these scenarios.

nftables: Use the nftables utility to set up complex and performance-critical firewalls, such as
for a whole network.

iptables: The iptables utility on Red Hat Enterprise Linux uses the nf_tables kernel API instead
of the legacy back end. The nf_tables API provides backward compatibility so that scripts that
use iptables commands still work on Red Hat Enterprise Linux. For new firewall scripts, Red Hat
recommends to use nftables.

IMPORTANT

To prevent the different firewall-related services (firewalld, nftables, or iptables) from


influencing each other, run only one of them on a RHEL host, and disable the other
services.

14.5.2. Firewall zones


You can use the ⁠firewalld utility to separate networks into different zones according to the level of trust
that you have with the interfaces and traffic within that network. A connection can only be part of one
zone, but you can use that zone for many network connections.

firewalld follows strict principles in regards to zones:

1. Traffic ingresses only one zone.

2. Traffic egresses only one zone.

3. A zone defines a level of trust.

4. Intrazone traffic (within the same zone) is allowed by default.

5. Interzone traffic (from zone to zone) is denied by default.

Principles 4 and 5 are a consequence of principle 3.

Principle 4 is configurable through the zone option --remove-forward. Principle 5 is configurable by


adding new policies.

NetworkManager notifies firewalld of the zone of an interface. You can assign zones to interfaces with
the following utilities:

NetworkManager

firewall-config utility

firewall-cmd utility

The RHEL web console

The RHEL web console, firewall-config, and firewall-cmd can only edit the appropriate
NetworkManager configuration files. If you change the zone of the interface using the web console,
firewall-cmd, or firewall-config, the request is forwarded to NetworkManager and is not handled by
⁠firewalld.

The /usr/lib/firewalld/zones/ directory stores the predefined zones, and you can instantly apply them to

248
CHAPTER 14. SECURING NETWORKS

The /usr/lib/firewalld/zones/ directory stores the predefined zones, and you can instantly apply them to
any available network interface. These files are copied to the /etc/firewalld/zones/ directory only after
they are modified. The default settings of the predefined zones are as follows:

block

Suitable for: Any incoming network connections are rejected with an icmp-host-prohibited
message for IPv4 and icmp6-adm-prohibited for IPv6.

Accepts: Only network connections initiated from within the system.

dmz

Suitable for: Computers in your DMZ that are publicly-accessible with limited access to your
internal network.

Accepts: Only selected incoming connections.

drop
Suitable for: Any incoming network packets are dropped without any notification.

Accepts: Only outgoing network connections.

external

Suitable for: External networks with masquerading enabled, especially for routers. Situations
when you do not trust the other computers on the network.

Accepts: Only selected incoming connections.

home

Suitable for: Home environment where you mostly trust the other computers on the network.

Accepts: Only selected incoming connections.

internal

Suitable for: Internal networks where you mostly trust the other computers on the network.

Accepts: Only selected incoming connections.

public

Suitable for: Public areas where you do not trust other computers on the network.

Accepts: Only selected incoming connections.

trusted

Accepts: All network connections.

work
Suitable for: Work environment where you mostly trust the other computers on the network.

Accepts: Only selected incoming connections.

249
Red Hat Enterprise Linux 8 System Design Guide

One of these zones is set as the default zone. When interface connections are added to
NetworkManager, they are assigned to the default zone. On installation, the default zone in firewalld is
the public zone. You can change the default zone.

NOTE

Make network zone names self-explanatory to help users understand them quickly.

To avoid any security problems, review the default zone configuration and disable any unnecessary
services according to your needs and risk assessments.

Additional resources

firewalld.zone(5) man page on your system

14.5.3. Firewall policies


The firewall policies specify the desired security state of your network. They outline rules and actions to
take for different types of traffic. Typically, the policies contain rules for the following types of traffic:

Incoming traffic

Outgoing traffic

Forward traffic

Specific services and applications

Network address translations (NAT)

Firewall policies use the concept of firewall zones. Each zone is associated with a specific set of firewall
rules that determine the traffic allowed. Policies apply firewall rules in a stateful, unidirectional manner.
This means you only consider one direction of the traffic. The traffic return path is implicitly allowed due
to stateful filtering of firewalld.

Policies are associated with an ingress zone and an egress zone. The ingress zone is where the traffic
originated (received). The egress zone is where the traffic leaves (sent).

The firewall rules defined in a policy can reference the firewall zones to apply consistent configurations
across multiple network interfaces.

14.5.4. Firewall rules


You can use the firewall rules to implement specific configurations for allowing or blocking network
traffic. As a result, you can control the flow of network traffic to protect your system from security
threats.

Firewall rules typically define certain criteria based on various attributes. The attributes can be as:

Source IP addresses

Destination IP addresses

Transfer Protocols (TCP, UDP, …​)

250
CHAPTER 14. SECURING NETWORKS

Ports

Network interfaces

The firewalld utility organizes the firewall rules into zones (such as public, internal, and others) and
policies. Each zone has its own set of rules that determine the level of traffic freedom for network
interfaces associated with a particular zone.

14.5.5. Zone configuration files


A firewalld zone configuration file contains the information for a zone. These are the zone description,
services, ports, protocols, icmp-blocks, masquerade, forward-ports and rich language rules in an XML
file format. The file name has to be zone-name.xml where the length of zone-name is currently limited
to 17 chars. The zone configuration files are located in the /usr/lib/firewalld/zones/ and
/etc/firewalld/zones/ directories.

The following example shows a configuration that allows one service (SSH) and one port range, for both
the TCP and UDP protocols:

<?xml version="1.0" encoding="utf-8"?>


<zone>
<short>My Zone</short>
<description>Here you can describe the characteristic features of the zone.</description>
<service name="ssh"/>
<port protocol="udp" port="1025-65535"/>
<port protocol="tcp" port="1025-65535"/>
</zone>

Additional resources

firewalld.zone manual page

14.5.6. Predefined firewalld services


The firewalld service is a predefined set of firewall rules that define access to a specific application or
network service. Each service represents a combination of the following elements:

Local port

Network protocol

Associated firewall rules

Source ports and destinations

Firewall helper modules that load automatically if a service is enabled

A service simplifies packet filtering and saves you time because it achieves several tasks at once. For
example, firewalld can perform the following tasks at once:

Open a port

Define network protocol

Enable packet forwarding

251
Red Hat Enterprise Linux 8 System Design Guide

Service configuration options and generic file information are described in the firewalld.service(5) man
page on your system. The services are specified by means of individual XML configuration files, which
are named in the following format: service-name.xml. Protocol names are preferred over service or
application names in firewalld.

You can configure firewalld in the following ways:

Use utilities:

firewall-config - graphical utility

firewall-cmd - command-line utility

firewall-offline-cmd - command-line utility

Edit the XML files in the /etc/firewalld/services/ directory.


If you do not add or change the service, no corresponding XML file exists in
/etc/firewalld/services/. You can use the files in /usr/lib/firewalld/services/ as templates.

Additional resources

firewalld.service(5) man page on your system

14.5.7. Working with firewalld zones


Zones represent a concept to manage incoming traffic more transparently. The zones are connected to
networking interfaces or assigned a range of source addresses. You manage firewall rules for each zone
independently, which enables you to define complex firewall settings and apply them to the traffic.

14.5.7.1. Customizing firewall settings for a specific zone to enhance security

You can strengthen your network security by modifying the firewall settings and associating a specific
network interface or connection with a particular firewall zone. By defining granular rules and restrictions
for a zone, you can control inbound and outbound traffic based on your intended security levels.

For example, you can achieve the following benefits:

Protection of sensitive data

Prevention of unauthorized access

Mitigation of potential network threats

Prerequisites

The firewalld service is running.

Procedure

1. List the available firewall zones:

# firewall-cmd --get-zones

The firewall-cmd --get-zones command displays all zones that are available on the system, but

252
CHAPTER 14. SECURING NETWORKS

The firewall-cmd --get-zones command displays all zones that are available on the system, but
it does not show any details for particular zones. To see more detailed information for all zones,
use the firewall-cmd --list-all-zones command.

2. Choose the zone you want to use for this configuration.

3. Modify firewall settings for the chosen zone. For example, to allow the SSH service and remove
the ftp service:

# firewall-cmd --add-service=ssh --zone=<your_chosen_zone>


# firewall-cmd --remove-service=ftp --zone=<same_chosen_zone>

4. Assign a network interface to the firewall zone:

a. List the available network interfaces:

# firewall-cmd --get-active-zones

Activity of a zone is determined by the presence of network interfaces or source address


ranges that match its configuration. The default zone is active for unclassified traffic but is
not always active if no traffic matches its rules.

b. Assign a network interface to the chosen zone:

# firewall-cmd --zone=<your_chosen_zone> --change-interface=<interface_name> -


-permanent

Assigning a network interface to a zone is more suitable for applying consistent firewall
settings to all traffic on a particular interface (physical or virtual).

The firewall-cmd command, when used with the --permanent option, often involves
updating NetworkManager connection profiles to make changes to the firewall
configuration permanent. This integration between firewalld and NetworkManager ensures
consistent network and firewall settings.

Verification

1. Display the updated settings for your chosen zone:

# firewall-cmd --zone=<your_chosen_zone> --list-all

The command output displays all zone settings including the assigned services, network
interface, and network connections (sources).

14.5.7.2. Changing the default zone

System administrators assign a zone to a networking interface in its configuration files. If an interface is
not assigned to a specific zone, it is assigned to the default zone. After each restart of the firewalld
service, firewalld loads the settings for the default zone and makes it active. Note that settings for all
other zones are preserved and ready to be used.

Typically, zones are assigned to interfaces by NetworkManager according to the connection.zone


setting in NetworkManager connection profiles. Also, after a reboot NetworkManager manages
assignments for "activating" those zones.

253
Red Hat Enterprise Linux 8 System Design Guide

Prerequisites

The firewalld service is running.

Procedure
To set up the default zone:

1. Display the current default zone:

# firewall-cmd --get-default-zone

2. Set the new default zone:

# firewall-cmd --set-default-zone <zone_name>

NOTE

Following this procedure, the setting is a permanent setting, even without the --
permanent option.

14.5.7.3. Assigning a network interface to a zone

It is possible to define different sets of rules for different zones and then change the settings quickly by
changing the zone for the interface that is being used. With multiple interfaces, a specific zone can be
set for each of them to distinguish traffic that is coming through them.

Procedure
To assign the zone to a specific interface:

1. List the active zones and the interfaces assigned to them:

# firewall-cmd --get-active-zones

2. Assign the interface to a different zone:

# firewall-cmd --zone=zone_name --change-interface=interface_name --permanent

14.5.7.4. Assigning a zone to a connection using nmcli

You can add a firewalld zone to a NetworkManager connection using the nmcli utility.

Procedure

1. Assign the zone to the NetworkManager connection profile:

# nmcli connection modify profile connection.zone zone_name

2. Activate the connection:

# nmcli connection up profile

254
CHAPTER 14. SECURING NETWORKS

14.5.7.5. Manually assigning a zone to a network connection in a connection profile file

If you cannot use the nmcli utility to modify a connection profile, you can manually edit the
corresponding file of the profile to assign a firewalld zone.

NOTE

Modifying the connection profile with the nmcli utility to assign a firewalld zone is more
efficient. For details, see Assigning a network interface to a zone .

Procedure

1. Determine the path to the connection profile and its format:

# nmcli -f NAME,FILENAME connection


NAME FILENAME
enp1s0 /etc/NetworkManager/system-connections/enp1s0.nmconnection
enp7s0 /etc/sysconfig/network-scripts/ifcfg-enp7s0

NetworkManager uses separate directories and file names for the different connection profile
formats:

Profiles in /etc/NetworkManager/system-
connections/<connection_name>.nmconnection files use the keyfile format.

Profiles in /etc/sysconfig/network-scripts/ifcfg-<interface_name> files use the ifcfg


format.

2. Depending on the format, update the corresponding file:

If the file uses the keyfile format, append zone=<name> to the [connection] section of the
/etc/NetworkManager/system-connections/<connection_name>.nmconnection file:

[connection]
...
zone=internal

If the file uses the ifcfg format, append ZONE=<name> to the /etc/sysconfig/network-
scripts/ifcfg-<interface_name> file:

ZONE=internal

3. Reload the connection profiles:

# nmcli connection reload

4. Reactivate the connection profiles

# nmcli connection up <profile_name>

Verification

Display the zone of the interface, for example:

255
Red Hat Enterprise Linux 8 System Design Guide

# firewall-cmd --get-zone-of-interface enp1s0


internal

14.5.7.6. Manually assigning a zone to a network connection in an ifcfg file

When the connection is managed by NetworkManager, it must be aware of a zone that it uses. For
every network connection profile, a zone can be specified, which provides the flexibility of various
firewall settings according to the location of the computer with portable devices. Thus, zones and
settings can be specified for different locations, such as company or home.

Procedure

To set a zone for a connection, edit the /etc/sysconfig/network-


scripts/ifcfg-connection_name file and add a line that assigns a zone to this connection:

ZONE=zone_name

14.5.7.7. Creating a new zone

To use custom zones, create a new zone and use it just like a predefined zone. New zones require the --
permanent option, otherwise the command does not work.

Prerequisites

The firewalld service is running.

Procedure

1. Create a new zone:

# firewall-cmd --permanent --new-zone=zone-name

2. Make the new zone usable:

# firewall-cmd --reload

The command applies recent changes to the firewall configuration without interrupting network
services that are already running.

Verification

Check if the new zone is added to your permanent settings:

# firewall-cmd --get-zones --permanent

14.5.7.8. Enabling zones by using the web console

You can apply predefined and existing firewall zones on a particular interface or a range of IP addresses
through the RHEL web console.

Prerequisites

256
CHAPTER 14. SECURING NETWORKS

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Networking.

3. Click on the Edit rules and zones button.

If you do not see the Edit rules and zones button, log in to the web console with the
administrator privileges.

4. In the Firewall section, click Add new zone.

5. In the Add zone dialog box, select a zone from the Trust level options.
The web console displays all zones predefined in the firewalld service.

6. In the Interfaces part, select an interface or interfaces on which the selected zone is applied.

7. In the Allowed Addresses part, you can select whether the zone is applied on:

the whole subnet

or a range of IP addresses in the following format:

192.168.1.0

192.168.1.0/24

192.168.1.0/24, 192.168.1.0

8. Click on the Add zone button.

257
Red Hat Enterprise Linux 8 System Design Guide

Verification

Check the configuration in the Firewall section:

14.5.7.9. Disabling zones by using the web console

You can disable a firewall zone in your firewall configuration by using the web console.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Networking.

258
CHAPTER 14. SECURING NETWORKS

3. Click on the Edit rules and zones button.

If you do not see the Edit rules and zones button, log in to the web console with the
administrator privileges.

4. Click on the Options icon at the zone you want to remove.

5. Click Delete.

The zone is now disabled and the interface does not include opened services and ports which were
configured in the zone.

14.5.7.10. Using zone targets to set default behavior for incoming traffic

For every zone, you can set a default behavior that handles incoming traffic that is not further specified.
Such behavior is defined by setting the target of the zone. There are four options:

ACCEPT: Accepts all incoming packets except those disallowed by specific rules.

REJECT: Rejects all incoming packets except those allowed by specific rules. When firewalld
rejects packets, the source machine is informed about the rejection.

DROP: Drops all incoming packets except those allowed by specific rules. When firewalld drops
packets, the source machine is not informed about the packet drop.

default: Similar behavior as for REJECT, but with special meanings in certain scenarios.

Prerequisites

The firewalld service is running.

Procedure
To set a target for a zone:

1. List the information for the specific zone to see the default target:

# firewall-cmd --zone=zone-name --list-all

259
Red Hat Enterprise Linux 8 System Design Guide

2. Set a new target in the zone:

# firewall-cmd --permanent --zone=zone-name --set-target=


<default|ACCEPT|REJECT|DROP>

Additional resources

firewall-cmd(1) man page on your system

14.5.8. Controlling network traffic using firewalld

The firewalld package installs a large number of predefined service files and you can add more or
customize them. You can then use these service definitions to open or close ports for services without
knowing the protocol and port numbers they use.

14.5.8.1. Controlling traffic with predefined services using the CLI

The most straightforward method to control traffic is to add a predefined service to firewalld. This
opens all necessary ports and modifies other settings according to the service definition file .

Prerequisites

The firewalld service is running.

Procedure

1. Check that the service in firewalld is not already allowed:

# firewall-cmd --list-services
ssh dhcpv6-client

The command lists the services that are enabled in the default zone.

2. List all predefined services in firewalld:

# firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client bitcoin bitcoin-rpc
bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine condor-collector ctdb dhcp dhcpv6
dhcpv6-client dns docker-registry ...

The command displays a list of available services for the default zone.

3. Add the service to the list of services that firewalld allows:

# firewall-cmd --add-service=<service_name>

The command adds the specified service to the default zone.

4. Make the new settings persistent:

# firewall-cmd --runtime-to-permanent

The command applies these runtime changes to the permanent configuration of the firewall. By

260
CHAPTER 14. SECURING NETWORKS

The command applies these runtime changes to the permanent configuration of the firewall. By
default, it applies these changes to the configuration of the default zone.

Verification

1. List all permanent firewall rules:

# firewall-cmd --list-all --permanent


public
target: default
icmp-block-inversion: no
interfaces:
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

The command displays complete configuration with the permanent firewall rules of the default
firewall zone (public).

2. Check the validity of the permanent configuration of the firewalld service.

# firewall-cmd --check-config
success

If the permanent configuration is invalid, the command returns an error with further details:

# firewall-cmd --check-config
Error: INVALID_PROTOCOL: 'public.xml': 'tcpx' not from {'tcp'|'udp'|'sctp'|'dccp'}

You can also manually inspect the permanent configuration files to verify the settings. The main
configuration file is /etc/firewalld/firewalld.conf. The zone-specific configuration files are in the
/etc/firewalld/zones/ directory and the policies are in the /etc/firewalld/policies/ directory.

14.5.8.2. Controlling traffic with predefined services using the GUI

You can control the network traffic with predefined services using a graphical user interface. The
Firewall Configuration application provides an accessible and user-friendly alternative to the command-
line utilities.

Prerequisites

You installed the firewall-config package.

The firewalld service is running.

Procedure

1. To enable or disable a predefined or custom service:

261
Red Hat Enterprise Linux 8 System Design Guide

a. Start the firewall-config utility and select the network zone whose services are to be
configured.

b. Select the Zones tab and then the Services tab below.

c. Select the checkbox for each type of service you want to trust or clear the checkbox to
block a service in the selected zone.

2. To edit a service:

a. Start the firewall-config utility.

b. Select Permanent from the menu labeled Configuration. Additional icons and menu
buttons appear at the bottom of the Services window.

c. Select the service you want to configure.

The Ports, Protocols, and Source Port tabs enable adding, changing, and removing of ports, protocols,
and source port for the selected service. The modules tab is for configuring Netfilter helper modules.
The Destination tab enables limiting traffic to a particular destination address and Internet Protocol
(IPv4 or IPv6).

NOTE

It is not possible to alter service settings in the Runtime mode.

Verification

Press the Super key to enter the Activities overview.

Select the Firewall Configuration utility.

You can also start the graphical firewall configuration utility using the command-line, by
entering the firewall-config command.

View the list of configurations of your firewall:

262
CHAPTER 14. SECURING NETWORKS

The Firewall Configuration window opens. Note that this command can be run as a normal user, but you
are prompted for an administrator password occasionally.

14.5.8.3. Enabling services on the firewall by using the web console

By default, services are added to the default firewall zone. If you use more firewall zones on more
network interfaces, you must select a zone first and then add the service with port.

The RHEL 8 web console displays predefined firewalld services and you can add them to active firewall
zones.

IMPORTANT

The RHEL 8 web console configures the firewalld service.

The web console does not allow generic firewalld rules which are not listed in the web
console.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Networking.

263
Red Hat Enterprise Linux 8 System Design Guide

3. Click on the Edit rules and zones button.

If you do not see the Edit rules and zones button, log in to the web console with the
administrator privileges.

4. In the Firewall section, select a zone for which you want to add the service and click Add
Services.

5. In the Add Services dialog box, find the service you want to enable on the firewall.

6. Enable services according to your scenario:

7. Click Add Services.

At this point, the RHEL 8 web console displays the service in the zone’s list of Services.

14.5.8.4. Configuring custom ports by using the web console

You can add configure custom ports for services through the RHEL web console.

264
CHAPTER 14. SECURING NETWORKS

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

The firewalld service is running.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Networking.

3. Click on the Edit rules and zones button.

If you do not see the Edit rules and zones button, log in to the web console with the
administrative privileges.

4. In the Firewall section, select a zone for which you want to configure a custom port and click
Add Services.

5. In the Add services dialog box, click on the Custom Ports radio button.

6. In the TCP and UDP fields, add ports according to examples. You can add ports in the following
formats:

Port numbers such as 22

Range of port numbers such as 5900-5910

Aliases such as nfs, rsync

NOTE

You can add multiple values into each field. Values must be separated with the
comma and without the space, for example: 8080,8081,http

265
Red Hat Enterprise Linux 8 System Design Guide

7. After adding the port number in the TCP filed, the UDP filed, or both, verify the service name in
the Name field.
The Name field displays the name of the service for which is this port reserved. You can rewrite
the name if you are sure that this port is free to use and no server needs to communicate on this
port.

8. In the Name field, add a name for the service including defined ports.

9. Click on the Add Ports button.

To verify the settings, go to the Firewall page and find the service in the list of zone’s Services.

14.5.8.5. Configuring firewalld to allow hosting a secure web server

Ports are logical services that enable an operating system to receive and distinguish network traffic and
forward it to system services. The system services are represented by a daemon that listens on the port
and waits for any traffic coming to this port.

Normally, system services listen on standard ports that are reserved for them. The httpd daemon, for
example, listens on port 80. However, system administrators can directly specify the port number
instead of the service name.

266
CHAPTER 14. SECURING NETWORKS

You can use the firewalld service to configure access to a secure web server for hosting your data.

Prerequisites

The firewalld service is running.

Procedure

1. Check the currently active firewall zone:

# firewall-cmd --get-active-zones

2. Add the HTTPS service to the appropriate zone:

# firewall-cmd --zone=<zone_name> --add-service=https --permanent

3. Reload the firewall configuration:

# firewall-cmd --reload

Verification

1. Check if the port is open in firewalld:

If you opened the port by specifying the port number, enter:

# firewall-cmd --zone=<zone_name> --list-all

If you opened the port by specifying a service definition, enter:

# firewall-cmd --zone=<zone_name> --list-services

14.5.8.6. Closing unused or unnecessary ports to enhance network security

When an open port is no longer needed, you can use the firewalld utility to close it.

IMPORTANT

Close all unnecessary ports to reduce the potential attack surface and minimize the risk
of unauthorized access or exploitation of vulnerabilities.

Procedure

1. List all allowed ports:

# firewall-cmd --list-ports

By default, this command lists the ports that are enabled in the default zone.

NOTE
267
Red Hat Enterprise Linux 8 System Design Guide

NOTE

This command will only give you a list of ports that are opened as ports. You will
not be able to see any open ports that are opened as a service. For that case,
consider using the --list-all option instead of --list-ports.

2. Remove the port from the list of allowed ports to close it for the incoming traffic:

# firewall-cmd --remove-port=port-number/port-type

This command removes a port from a zone. If you do not specify a zone, it will remove the port
from the default zone.

3. Make the new settings persistent:

# firewall-cmd --runtime-to-permanent

Without specifying a zone, this command applies runtime changes to the permanent
configuration of the default zone.

Verification

1. List the active zones and choose the zone you want to inspect:

# firewall-cmd --get-active-zones

2. List the currently open ports in the selected zone to check if the unused or unnecessary ports
are closed:

# firewall-cmd --zone=<zone_to_inspect> --list-ports

14.5.8.7. Controlling traffic through the CLI

You can use the firewall-cmd command to:

disable networking traffic

enable networking traffic

As a result, you can for example enhance your system defenses, ensure data privacy or optimize network
resources.

IMPORTANT

Enabling panic mode stops all networking traffic. For this reason, it should be used only
when you have the physical access to the machine or if you are logged in using a serial
console.

Procedure

1. To immediately disable networking traffic, switch panic mode on:

# firewall-cmd --panic-on

268
CHAPTER 14. SECURING NETWORKS

2. Switching off panic mode reverts the firewall to its permanent settings. To switch panic mode
off, enter:

# firewall-cmd --panic-off

Verification

To see whether panic mode is switched on or off, use:

# firewall-cmd --query-panic

14.5.8.8. Controlling traffic with protocols using GUI

To permit traffic through the firewall using a certain protocol, you can use the GUI.

Prerequisites

You installed the firewall-config package

Procedure

1. Start the firewall-config tool and select the network zone whose settings you want to change.

2. Select the Protocols tab and click the Add button on the right-hand side. The Protocol window
opens.

3. Either select a protocol from the list or select the Other Protocol check box and enter the
protocol in the field.

14.5.9. Using zones to manage incoming traffic depending on a source


You can use zones to manage incoming traffic based on its source. Incoming traffic in this context is any
data that is destined for your system, or passes through the host running firewalld. The source typically
refers to the IP address or network range from which the traffic originates. As a result, you can sort
incoming traffic and assign it to different zones to allow or disallow services that can be reached by that
traffic.

Matching by source address takes precedence over matching by interface name. When you add a source
to a zone, the firewall will prioritize the source-based rules for incoming traffic over interface-based
rules. This means that if incoming traffic matches a source address specified for a particular zone, the
zone associated with that source address will determine how the traffic is handled, regardless of the
interface through which it arrives. On the other hand, interface-based rules are generally a fallback for
traffic that does not match specific source-based rules. These rules apply to traffic, for which the source
is not explicitly associated with a zone. This allows you to define a default behavior for traffic that does
not have a specific source-defined zone.

14.5.9.1. Adding a source

To route incoming traffic into a specific zone, add the source to that zone. The source can be an IP
address or an IP mask in the classless inter-domain routing (CIDR) notation.

NOTE
269
Red Hat Enterprise Linux 8 System Design Guide

NOTE

In case you add multiple zones with an overlapping network range, they are ordered
alphanumerically by zone name and only the first one is considered.

To set the source in the current zone:

# firewall-cmd --add-source=<source>

To set the source IP address for a specific zone:

# firewall-cmd --zone=zone-name --add-source=<source>

The following procedure allows all incoming traffic from 192.168.2.15 in the trusted zone:

Procedure

1. List all available zones:

# firewall-cmd --get-zones

2. Add the source IP to the trusted zone in the permanent mode:

# firewall-cmd --zone=trusted --add-source=192.168.2.15

3. Make the new settings persistent:

# firewall-cmd --runtime-to-permanent

14.5.9.2. Removing a source

When you remove a source from a zone, the traffic which originates from the source is no longer
directed through the rules specified for that source. Instead, the traffic falls back to the rules and
settings of the zone associated with the interface from which it originates, or goes to the default zone.

Procedure

1. List allowed sources for the required zone:

# firewall-cmd --zone=zone-name --list-sources

2. Remove the source from the zone permanently:

# firewall-cmd --zone=zone-name --remove-source=<source>

3. Make the new settings persistent:

# firewall-cmd --runtime-to-permanent

14.5.9.3. Removing a source port

270
CHAPTER 14. SECURING NETWORKS

By removing a source port you disable sorting the traffic based on a port of origin.

Procedure

To remove a source port:

# firewall-cmd --zone=zone-name --remove-source-port=<port-


name>/<tcp|udp|sctp|dccp>

14.5.9.4. Using zones and sources to allow a service for only a specific domain

To allow traffic from a specific network to use a service on a machine, use zones and source. The
following procedure allows only HTTP traffic from the 192.0.2.0/24 network while any other traffic is
blocked.


WARNING

When you configure this scenario, use a zone that has the default target. Using a
zone that has the target set to ACCEPT is a security risk, because for traffic from
192.0.2.0/24, all network connections would be accepted.

Procedure

1. List all available zones:

# firewall-cmd --get-zones
block dmz drop external home internal public trusted work

2. Add the IP range to the internal zone to route the traffic originating from the source through
the zone:

# firewall-cmd --zone=internal --add-source=192.0.2.0/24

3. Add the http service to the internal zone:

# firewall-cmd --zone=internal --add-service=http

4. Make the new settings persistent:

# firewall-cmd --runtime-to-permanent

Verification

Check that the internal zone is active and that the service is allowed in it:

# firewall-cmd --zone=internal --list-all


internal (active)
target: default

271
Red Hat Enterprise Linux 8 System Design Guide

icmp-block-inversion: no
interfaces:
sources: 192.0.2.0/24
services: cockpit dhcpv6-client mdns samba-client ssh http
...

Additional resources

firewalld.zones(5) man page on your system

14.5.10. Filtering forwarded traffic between zones


firewalld enables you to control the flow of network data between different firewalld zones. By defining
rules and policies, you can manage how traffic is allowed or blocked when it moves between these zones.

The policy objects feature provides forward and output filtering in firewalld. You can use firewalld to
filter traffic between different zones to allow access to locally hosted VMs to connect the host.

14.5.10.1. The relationship between policy objects and zones

Policy objects allow the user to attach firewalld’s primitives such as services, ports, and rich rules to the
policy. You can apply the policy objects to traffic that passes between zones in a stateful and
unidirectional manner.

# firewall-cmd --permanent --new-policy myOutputPolicy

# firewall-cmd --permanent --policy myOutputPolicy --add-ingress-zone HOST

# firewall-cmd --permanent --policy myOutputPolicy --add-egress-zone ANY

HOST and ANY are the symbolic zones used in the ingress and egress zone lists.

The HOST symbolic zone allows policies for the traffic originating from or has a destination to
the host running firewalld.

The ANY symbolic zone applies policy to all the current and future zones. ANY symbolic zone
acts as a wildcard for all zones.

14.5.10.2. Using priorities to sort policies

Multiple policies can apply to the same set of traffic, therefore, priorities should be used to create an
order of precedence for the policies that may be applied.

To set a priority to sort the policies:

# firewall-cmd --permanent --policy mypolicy --set-priority -500

In the above example -500 is a lower priority value but has higher precedence. Thus, -500 will execute
before -100.

Lower numerical priority values have higher precedence and are applied first.

14.5.10.3. Using policy objects to filter traffic between locally hosted containers and a
network physically connected to the host

272
CHAPTER 14. SECURING NETWORKS

The policy objects feature allows users to filter traffic between Podman and firewalld zones.

NOTE

Red Hat recommends blocking all traffic by default and opening the selective services
needed for the Podman utility.

Procedure

1. Create a new firewall policy:

# firewall-cmd --permanent --new-policy podmanToAny

2. Block all traffic from Podman to other zones and allow only necessary services on Podman:

# firewall-cmd --permanent --policy podmanToAny --set-target REJECT


# firewall-cmd --permanent --policy podmanToAny --add-service dhcp
# firewall-cmd --permanent --policy podmanToAny --add-service dns
# firewall-cmd --permanent --policy podmanToAny --add-service https

3. Create a new Podman zone:

# firewall-cmd --permanent --new-zone=podman

4. Define the ingress zone for the policy:

# firewall-cmd --permanent --policy podmanToHost --add-ingress-zone podman

5. Define the egress zone for all other zones:

# firewall-cmd --permanent --policy podmanToHost --add-egress-zone ANY

Setting the egress zone to ANY means that you filter from Podman to other zones. If you want
to filter to the host, then set the egress zone to HOST.

6. Restart the firewalld service:

# systemctl restart firewalld

Verification

Verify the Podman firewall policy to other zones:

# firewall-cmd --info-policy podmanToAny


podmanToAny (active)
...
target: REJECT
ingress-zones: podman
egress-zones: ANY
services: dhcp dns https
...

273
Red Hat Enterprise Linux 8 System Design Guide

14.5.10.4. Setting the default target of policy objects

You can specify --set-target options for policies. The following targets are available:

ACCEPT - accepts the packet

DROP - drops the unwanted packets

REJECT - rejects unwanted packets with an ICMP reply

CONTINUE (default) - packets will be subject to rules in following policies and zones.

# firewall-cmd --permanent --policy mypolicy --set-target CONTINUE

Verification

Verify information about the policy

# firewall-cmd --info-policy mypolicy

14.5.10.5. Using DNAT to forward HTTPS traffic to a different host

If your web server runs in a DMZ with private IP addresses, you can configure destination network
address translation (DNAT) to enable clients on the internet to connect to this web server. In this case,
the host name of the web server resolves to the public IP address of the router. When a client
establishes a connection to a defined port on the router, the router forwards the packets to the internal
web server.

Prerequisites

The DNS server resolves the host name of the web server to the router’s IP address.

You know the following settings:

The private IP address and port number that you want to forward

The IP protocol to be used

The destination IP address and port of the web server where you want to redirect the
packets

Procedure

1. Create a firewall policy:

# firewall-cmd --permanent --new-policy <example_policy>

The policies, as opposed to zones, allow packet filtering for input, output, and forwarded traffic.
This is important, because forwarding traffic to endpoints on locally run web servers, containers,
or virtual machines requires such capability.

2. Configure symbolic zones for the ingress and egress traffic to also enable the router itself to
connect to its local IP address and forward this traffic:

274
CHAPTER 14. SECURING NETWORKS

# firewall-cmd --permanent --policy=<example_policy> --add-ingress-zone=HOST


# firewall-cmd --permanent --policy=<example_policy> --add-egress-zone=ANY

The --add-ingress-zone=HOST option refers to packets generated locally and transmitted out
of the local host. The --add-egress-zone=ANY option refers to traffic moving to any zone.

3. Add a rich rule that forwards traffic to the web server:

# firewall-cmd --permanent --policy=<example_policy> --add-rich-rule='rule


family="ipv4" destination address="192.0.2.1" forward-port port="443" protocol="tcp"
to-port="443" to-addr="192.51.100.20"'

The rich rule forwards TCP traffic from port 443 on the IP address of the router (192.0.2.1) to
port 443 of the IP address of the web server (192.51.100.20).

4. Reload the firewall configuration files:

# firewall-cmd --reload
success

5. Activate routing of 127.0.0.0/8 in the kernel:

For persistent changes, run:

# echo "net.ipv4.conf.all.route_localnet=1" > /etc/sysctl.d/90-enable-route-


localnet.conf

The command persistently configures the route_localnet kernel parameter and ensures
that the setting is preserved after the system reboots.

For applying the settings immediately without a system reboot, run:

# sysctl -p /etc/sysctl.d/90-enable-route-localnet.conf

The sysctl command is useful for applying on-the-fly changes, however the configuration
will not persist across system reboots.

Verification

1. Connect to the IP address of the router and to the port that you have forwarded to the web
server:

# curl https://192.0.2.1:443

2. Optional: Verify that the net.ipv4.conf.all.route_localnet kernel parameter is active:

# sysctl net.ipv4.conf.all.route_localnet
net.ipv4.conf.all.route_localnet = 1

3. Verify that <example_policy> is active and contains the settings you need, especially the
source IP address and port, protocol to be used, and the destination IP address and port:

# firewall-cmd --info-policy=<example_policy>
example_policy (active)

275
Red Hat Enterprise Linux 8 System Design Guide

priority: -1
target: CONTINUE
ingress-zones: HOST
egress-zones: ANY
services:
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
rule family="ipv4" destination address="192.0.2.1" forward-port port="443" protocol="tcp" to-
port="443" to-addr="192.51.100.20"

Additional resources

firewall-cmd(1), firewalld.policies(5), firewalld.richlanguage(5), sysctl(8), and sysctl.conf(5)


man pages on your system

Using configuration files in /etc/sysctl.d/ to adjust kernel parameters

14.5.11. Configuring NAT using firewalld


With firewalld, you can configure the following network address translation (NAT) types:

Masquerading

Destination NAT (DNAT)

Redirect

14.5.11.1. Network address translation types

These are the different network address translation (NAT) types:

Masquerading
Use one of these NAT types to change the source IP address of packets. For example, Internet
Service Providers (ISPs) do not route private IP ranges, such as 10.0.0.0/8. If you use private IP
ranges in your network and users should be able to reach servers on the internet, map the source IP
address of packets from these ranges to a public IP address.
Masquerading automatically uses the IP address of the outgoing interface. Therefore, use
masquerading if the outgoing interface uses a dynamic IP address.

Destination NAT (DNAT)


Use this NAT type to rewrite the destination address and port of incoming packets. For example, if
your web server uses an IP address from a private IP range and is, therefore, not directly accessible
from the internet, you can set a DNAT rule on the router to redirect incoming traffic to this server.
Redirect
This type is a special case of DNAT that redirects packets to a different port on the local machine.
For example, if a service runs on a different port than its standard port, you can redirect incoming
traffic from the standard port to this specific port.

276
CHAPTER 14. SECURING NETWORKS

14.5.11.2. Configuring IP address masquerading

You can enable IP masquerading on your system. IP masquerading hides individual machines behind a
gateway when accessing the internet.

Procedure

1. To check if IP masquerading is enabled (for example, for the external zone), enter the following
command as root:

# firewall-cmd --zone=external --query-masquerade

The command prints yes with exit status 0 if enabled. It prints no with exit status 1 otherwise. If
zone is omitted, the default zone will be used.

2. To enable IP masquerading, enter the following command as root:

# firewall-cmd --zone=external --add-masquerade

3. To make this setting persistent, pass the --permanent option to the command.

4. To disable IP masquerading, enter the following command as root:

# firewall-cmd --zone=external --remove-masquerade

To make this setting permanent, pass the --permanent option to the command.

14.5.11.3. Using DNAT to forward incoming HTTP traffic

You can use destination network address translation (DNAT) to direct incoming traffic from one
destination address and port to another. Typically, this is useful for redirecting incoming requests from
an external network interface to specific internal servers or services.

Prerequisites

The firewalld service is running.

Procedure

1. Create the /etc/sysctl.d/90-enable-IP-forwarding.conf file with the following content:

net.ipv4.ip_forward=1

This setting enables IP forwarding in the kernel. It makes the internal RHEL server act as a router
and forward packets from network to network.

2. Load the setting from the /etc/sysctl.d/90-enable-IP-forwarding.conf file:

# sysctl -p /etc/sysctl.d/90-enable-IP-forwarding.conf

3. Forward incoming HTTP traffic:

# firewall-cmd --zone=public --add-forward-


port=port=80:proto=tcp:toaddr=198.51.100.10:toport=8080 --permanent

277
Red Hat Enterprise Linux 8 System Design Guide

The previous command defines a DNAT rule with the following settings:

--zone=public - The firewall zone for which you configure the DNAT rule. You can adjust
this to whatever zone you need.

--add-forward-port - The option that indicates you are adding a port-forwarding rule.

port=80 - The external destination port.

proto=tcp - The protocol indicating that you forward TCP traffic.

toaddr=198.51.100.10 - The destination IP address.

toport=8080 - The destination port of the internal server.

--permanent - The option that makes the DNAT rule persistent across reboots.

4. Reload the firewall configuration to apply the changes:

# firewall-cmd --reload

Verification

Verify the DNAT rule for the firewall zone that you used:

# firewall-cmd --list-forward-ports --zone=public


port=80:proto=tcp:toport=8080:toaddr=198.51.100.10

Alternatively, view the corresponding XML configuration file:

# cat /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
<short>Public</short>
<description>For use in public areas. You do not trust the other computers on networks to
not harm your computer. Only selected incoming connections are accepted.</description>
<service name="ssh"/>
<service name="dhcpv6-client"/>
<service name="cockpit"/>
<forward-port port="80" protocol="tcp" to-port="8080" to-addr="198.51.100.10"/>
<forward/>
</zone>

Additional resources

Configuring kernel parameters at runtime

firewall-cmd(1) manual page

14.5.11.4. Redirecting traffic from a non-standard port to make the web service accessible
on a standard port

You can use the redirect mechanism to make the web service that internally runs on a non-standard port
accessible without requiring users to specify the port in the URL. As a result, the URLs are simpler and

278
CHAPTER 14. SECURING NETWORKS

provide better browsing experience, while a non-standard port is still used internally or for specific
requirements.

Prerequisites

The firewalld service is running.

Procedure

1. Create the /etc/sysctl.d/90-enable-IP-forwarding.conf file with the following content:

net.ipv4.ip_forward=1

This setting enables IP forwarding in the kernel.

2. Load the setting from the /etc/sysctl.d/90-enable-IP-forwarding.conf file:

# sysctl -p /etc/sysctl.d/90-enable-IP-forwarding.conf

3. Create the NAT redirect rule:

# firewall-cmd --zone=public --add-forward-


port=port=<standard_port>:proto=tcp:toport=<non_standard_port> --permanent

The previous command defines the NAT redirect rule with the following settings:

--zone=public - The firewall zone, for which you configure the rule. You can adjust this to
whatever zone you need.

--add-forward-port=port=<non_standard_port> - The option that indicates you are


adding a port-forwarding (redirecting) rule with source port on which you initially receive the
incoming traffic.

proto=tcp - The protocol indicating that you redirect TCP traffic.

toport=<standard_port> - The destination port, to which the incoming traffic should be


redirected after being received on the source port.

--permanent - The option that makes the rule persist across reboots.

4. Reload the firewall configuration to apply the changes:

# firewall-cmd --reload

Verification

Verify the redirect rule for the firewall zone that you used:

# firewall-cmd --list-forward-ports
port=8080:proto=tcp:toport=80:toaddr=

Alternatively, view the corresponding XML configuration file:

# cat /etc/firewalld/zones/public.xml

279
Red Hat Enterprise Linux 8 System Design Guide

<?xml version="1.0" encoding="utf-8"?>


<zone>
<short>Public</short>
<description>For use in public areas. You do not trust the other computers on networks to
not harm your computer. Only selected incoming connections are accepted.</description>
<service name="ssh"/>
<service name="dhcpv6-client"/>
<service name="cockpit"/>
<forward-port port="8080" protocol="tcp" to-port="80"/>
<forward/>
</zone>

Additional resources

Configuring kernel parameters at runtime

firewall-cmd(1) manual page

14.5.12. Managing ICMP requests


The Internet Control Message Protocol (ICMP) is a supporting protocol that is used by various
network devices for testing, troubleshooting, and diagnostics. ICMP differs from transport protocols
such as TCP and UDP because it is not used to exchange data between systems.

You can use the ICMP messages, especially echo-request and echo-reply, to reveal information about a
network and misuse such information for various kinds of fraudulent activities. Therefore, firewalld
enables controlling the ICMP requests to protect your network information.

14.5.12.1. Configuring ICMP filtering

You can use ICMP filtering to define which ICMP types and codes you want the firewall to permit or
deny from reaching your system. ICMP types and codes are specific categories and subcategories of
ICMP messages.

ICMP filtering helps, for example, in the following areas:

Security enhancement - Block potentially harmful ICMP types and codes to reduce your attack
surface.

Network performance - Permit only necessary ICMP types to optimize network performance
and prevent potential network congestion caused by excessive ICMP traffic.

Troubleshooting control - Maintain essential ICMP functionality for network troubleshooting


and block ICMP types that represent potential security risk.

Prerequisites

The firewalld service is running.

Procedure

1. List available ICMP types and codes:

# firewall-cmd --get-icmptypes
address-unreachable bad-header beyond-scope communication-prohibited destination-

280
CHAPTER 14. SECURING NETWORKS

unreachable echo-reply echo-request failed-policy fragmentation-needed host-precedence-


violation host-prohibited host-redirect host-unknown host-unreachable
...

From this predefined list, select which ICMP types and codes to allow or block.

2. Filter specific ICMP types by:

Allowing ICMP types:

# firewall-cmd --zone=<target-zone> --remove-icmp-block=echo-request --


permanent

The command removes any existing blocking rules for the echo requests ICMP type.

Blocking ICMP types:

# firewall-cmd --zone=<target-zone> --add-icmp-block=redirect --permanent

The command ensures that the redirect messages ICMP type is blocked by the firewall.

3. Reload the firewall configuration to apply the changes:

# firewall-cmd --reload

Verification

Verify your filtering rules are in effect:

# firewall-cmd --list-icmp-blocks
redirect

The command output displays the ICMP types and codes that you allowed or blocked.

Additional resources

firewall-cmd(1) manual page

14.5.13. Setting and controlling IP sets using firewalld

IP sets are a RHEL feature for grouping of IP addresses and networks into sets to achieve more flexible
and efficient firewall rule management.

The IP sets are valuable in scenarios when you need to for example:

Handle large lists of IP addresses

Implement dynamic updates to those large lists of IP addresses

Create custom IP-based policies to enhance network security and control

281
Red Hat Enterprise Linux 8 System Design Guide


WARNING

Red Hat recommends using the firewall-cmd command to create and manage IP
sets.

14.5.13.1. Configuring dynamic updates for allowlisting with IP sets

You can make near real-time updates to flexibly allow specific IP addresses or ranges in the IP sets even
in unpredictable conditions. These updates can be triggered by various events, such as detection of
security threats or changes in the network behavior. Typically, such a solution leverages automation to
reduce manual effort and improve security by responding quickly to the situation.

Prerequisites

The firewalld service is running.

Procedure

1. Create an IP set with a meaningful name:

# firewall-cmd --permanent --new-ipset=allowlist --type=hash:ip

The new IP set called allowlist contains IP addresses that you want your firewall to allow.

2. Add a dynamic update to the IP set:

# firewall-cmd --permanent --ipset=allowlist --add-entry=198.51.100.10

This configuration updates the allowlist IP set with a newly added IP address that is allowed to
pass network traffic by your firewall.

3. Create a firewall rule that references the previously created IP set:

# firewall-cmd --permanent --zone=public --add-source=ipset:allowlist

Without this rule, the IP set would not have any impact on network traffic. The default firewall
policy would prevail.

4. Reload the firewall configuration to apply the changes:

# firewall-cmd --reload

Verification

1. List all IP sets:

# firewall-cmd --get-ipsets
allowlist

282
CHAPTER 14. SECURING NETWORKS

2. List the active rules:

# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp0s1
sources: ipset:allowlist
services: cockpit dhcpv6-client ssh
ports:
protocols:
...

The sources section of the command-line output provides insights to what origins of traffic
(hostnames, interfaces, IP sets, subnets, and others) are permitted or denied access to a
particular firewall zone. In this case, the IP addresses contained in the allowlist IP set are
allowed to pass traffic through the firewall for the public zone.

3. Explore the contents of your IP set:

# cat /etc/firewalld/ipsets/allowlist.xml
<?xml version="1.0" encoding="utf-8"?>
<ipset type="hash:ip">
<entry>198.51.100.10</entry>
</ipset>

Next steps

Use a script or a security utility to fetch your threat intelligence feeds and update allowlist
accordingly in an automated fashion.

Additional resources

firewall-cmd(1) manual page

14.5.14. Prioritizing rich rules


By default, rich rules are organized based on their rule action. For example, deny rules have precedence
over allow rules. The priority parameter in rich rules provides administrators fine-grained control over
rich rules and their execution order. When using the priority parameter, rules are sorted first by their
priority values in ascending order. When more rules have the same priority, their order is determined by
the rule action, and if the action is also the same, the order may be undefined.

14.5.14.1. How the priority parameter organizes rules into different chains

You can set the priority parameter in a rich rule to any number between -32768 and 32767, and lower
numerical values have higher precedence.

The firewalld service organizes rules based on their priority value into different chains:

Priority lower than 0: the rule is redirected into a chain with the _pre suffix.

Priority higher than 0: the rule is redirected into a chain with the _post suffix.

Priority equals 0: based on the action, the rule is redirected into a chain with the _log, _deny, or

283
Red Hat Enterprise Linux 8 System Design Guide

Priority equals 0: based on the action, the rule is redirected into a chain with the _log, _deny, or
_allow the action.

Inside these sub-chains, firewalld sorts the rules based on their priority value.

14.5.14.2. Setting the priority of a rich rule

The following is an example of how to create a rich rule that uses the priority parameter to log all traffic
that is not allowed or denied by other rules. You can use this rule to flag unexpected traffic.

Procedure

Add a rich rule with a very low precedence to log all traffic that has not been matched by other
rules:

# firewall-cmd --add-rich-rule='rule priority=32767 log prefix="UNEXPECTED: " limit


value="5/m"'

The command additionally limits the number of log entries to 5 per minute.

Verification

Display the nftables rule that the command in the previous step created:

# nft list chain inet firewalld filter_IN_public_post


table inet firewalld {
chain filter_IN_public_post {
log prefix "UNEXPECTED: " limit rate 5/minute
}
}

14.5.15. Configuring firewall lockdown


Local applications or services are able to change the firewall configuration if they are running as root (for
example, libvirt). With this feature, the administrator can lock the firewall configuration so that either no
applications or only applications that are added to the lockdown allow list are able to request firewall
changes. The lockdown settings default to disabled. If enabled, the user can be sure that there are no
unwanted configuration changes made to the firewall by local applications or services.

14.5.15.1. Configuring lockdown using CLI

You can enable or disable the lockdown feature using the command line.

Procedure

1. To query whether lockdown is enabled:

# firewall-cmd --query-lockdown

2. Manage lockdown configuration by either:

Enabling lockdown:

# firewall-cmd --lockdown-on

284
CHAPTER 14. SECURING NETWORKS

Disabling lockdown:

# firewall-cmd --lockdown-off

14.5.15.2. Overview of lockdown allowlist configuration files

The default allowlist configuration file contains the NetworkManager context and the default context
of libvirt. The user ID 0 is also on the list.

The allowlist configuration files are stored in the /etc/firewalld/ directory.

<?xml version="1.0" encoding="utf-8"?>


<whitelist>
<command name="/usr/bin/python3 -s /usr/bin/firewall-config"/>
<selinux context="system_u:system_r:NetworkManager_t:s0"/>
<selinux context="system_u:system_r:virtd_t:s0-s0:c0.c1023"/>
<user id="0"/>
</whitelist>

Following is an example allowlist configuration file enabling all commands for the firewall-cmd utility, for
a user called user whose user ID is 815:

<?xml version="1.0" encoding="utf-8"?>


<whitelist>
<command name="/usr/libexec/platform-python -s /bin/firewall-cmd*"/>
<selinux context="system_u:system_r:NetworkManager_t:s0"/>
<user id="815"/>
<user name="user"/>
</whitelist>

This example shows both user id and user name, but only one option is required. Python is the
interpreter and is prepended to the command line.

In Red Hat Enterprise Linux, all utilities are placed in the /usr/bin/ directory and the /bin/ directory is
sym-linked to the /usr/bin/ directory. In other words, although the path for firewall-cmd when entered
as root might resolve to /bin/firewall-cmd, /usr/bin/firewall-cmd can now be used. All new scripts
should use the new location. But be aware that if scripts that run as root are written to use the
/bin/firewall-cmd path, then that command path must be added in the allowlist in addition to the
/usr/bin/firewall-cmd path traditionally used only for non- root users.

The * at the end of the name attribute of a command means that all commands that start with this string
match. If the * is not there then the absolute command including arguments must match.

14.5.16. Enabling traffic forwarding between different interfaces or sources within a


firewalld zone
Intra-zone forwarding is a firewalld feature that enables traffic forwarding between interfaces or
sources within a firewalld zone.

14.5.16.1. The difference between intra-zone forwarding and zones with the default target
set to ACCEPT

With intra-zone forwarding enabled, the traffic within a single firewalld zone can flow from one interface

285
Red Hat Enterprise Linux 8 System Design Guide

With intra-zone forwarding enabled, the traffic within a single firewalld zone can flow from one interface
or source to another interface or source. The zone specifies the trust level of interfaces and sources. If
the trust level is the same, the traffic stays inside the same zone.

NOTE

Enabling intra-zone forwarding in the default zone of firewalld, applies only to the
interfaces and sources added to the current default zone.

firewalld uses different zones to manage incoming and outgoing traffic. Each zone has its own set of
rules and behaviors. For example, the trusted zone, allows all forwarded traffic by default.

Other zones can have different default behaviors. In standard zones, forwarded traffic is typically
dropped by default when the target of the zone is set to default.

To control how the traffic is forwarded between different interfaces or sources within a zone, make sure
you understand and configure the target of the zone accordingly.

14.5.16.2. Using intra-zone forwarding to forward traffic between an Ethernet and Wi-Fi
network

You can use intra-zone forwarding to forward traffic between interfaces and sources within the same
firewalld zone. This feature brings the following benefits:

Seamless connectivity between wired and wireless devices (you can forward traffic between an
Ethernet network connected to enp1s0 and a Wi-Fi network connected to wlp0s20)

Support for flexible work environments

Shared resources that are accessible and used by multiple devices or users within a network
(such as printers, databases, network-attached storage, and others)

Efficient internal networking (such as smooth communication, reduced latency, resource


accessibility, and others)

You can enable this functionality for individual firewalld zones.

Procedure

1. Enable packet forwarding in the kernel:

# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf


# sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

2. Ensure that interfaces between which you want to enable intra-zone forwarding are assigned
only to the internal zone:

# firewall-cmd --get-active-zones

3. If the interface is currently assigned to a zone other than internal, reassign it:

# firewall-cmd --zone=internal --change-interface=interface_name --permanent

4. Add the enp1s0 and wlp0s20 interfaces to the internal zone:

286
CHAPTER 14. SECURING NETWORKS

# firewall-cmd --zone=internal --add-interface=enp1s0 --add-interface=wlp0s20

5. Enable intra-zone forwarding:

# firewall-cmd --zone=internal --add-forward

Verification
The following Verification require that the nmap-ncat package is installed on both hosts.

1. Log in to a host that is on the same network as the enp1s0 interface of the host on which you
enabled zone forwarding.

2. Start an echo service with ncat to test connectivity:

# ncat -e /usr/bin/cat -l 12345

3. Log in to a host that is in the same network as the wlp0s20 interface.

4. Connect to the echo server running on the host that is in the same network as the enp1s0:

# ncat <other_host> 12345

5. Type something and press Enter. Verify the text is sent back.

Additional resources

firewalld.zones(5) man page on your system

14.5.17. Configuring firewalld by using RHEL system roles

RHEL system roles is a set of contents for the Ansible automation utility. This content together with the
Ansible automation utility provides a consistent configuration interface to remotely manage multiple
systems at once.

The rhel-system-roles package contains the rhel-system-roles.firewall RHEL system role. This role
was introduced for automated configurations of the firewalld service.

With the firewall RHEL system role you can configure many different firewalld parameters, for
example:

Zones

The services for which packets should be allowed

Granting, rejection, or dropping of traffic access to ports

Forwarding of ports or port ranges for a zone

14.5.17.1. Resetting the firewalld settings by using the firewall RHEL system role

Over time, updates to your firewall configuration can accumulate to the point, where they could lead to
unintended security risks. With the firewall RHEL system role, you can reset the firewalld settings to
their default state in an automated fashion. This way you can efficiently remove any unintentional or

287
Red Hat Enterprise Linux 8 System Design Guide

insecure firewall rules and simplify their management.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Reset firewalld example
hosts: managed-node-01.example.com
tasks:
- name: Reset firewalld
ansible.builtin.include_role:
name: rhel-system-roles.firewall
vars:
firewall:
- previous: replaced

The settings specified in the example playbook include the following:

previous: replaced
Removes all existing user-defined settings and resets the firewalld settings to defaults. If
you combine the previous:replaced parameter with other settings, the firewall role
removes all existing settings before applying new ones.
For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.firewall/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

Run this command on the control node to remotely check that all firewall configuration on your
managed node was reset to its default values:

# ansible managed-node-01.example.com -m ansible.builtin.command -a 'firewall-cmd


--list-all-zones'

288
CHAPTER 14. SECURING NETWORKS

Additional resources

/usr/share/ansible/roles/rhel-system-roles.firewall/README.md file

/usr/share/doc/rhel-system-roles/firewall/ directory

14.5.17.2. Forwarding incoming traffic in firewalld from one local port to a different local
port by using the firewall RHEL system role

You can use the firewall RHEL system role to remotely configure forwarding of incoming traffic from
one local port to a different local port.

For example, if you have an environment where multiple services co-exist on the same machine and
need the same default port, there are likely to become port conflicts. These conflicts can disrupt
services and cause a downtime. With the firewall RHEL system role, you can efficiently forward traffic
to alternative ports to ensure that your services can run simultaneously without modification to their
configuration.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Configure firewalld
hosts: managed-node-01.example.com
tasks:
- name: Forward incoming traffic on port 8080 to 443
ansible.builtin.include_role:
name: rhel-system-roles.firewall
vars:
firewall:
- forward_port: 8080/tcp;443;
state: enabled
runtime: true
permanent: true

The settings specified in the example playbook include the following:

forward_port: 8080/tcp;443
Traffic coming to the local port 8080 using the TCP protocol is forwarded to the port 443.
runtime: true
Enables changes in the runtime configuration. The default is set to true.
For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.firewall/README.md file on the control node.

289
Red Hat Enterprise Linux 8 System Design Guide

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

On the control node, run the following command to remotely check the forwarded-ports on your
managed node:

# ansible managed-node-01.example.com -m ansible.builtin.command -a 'firewall-cmd


--list-forward-ports'
managed-node-01.example.com | CHANGED | rc=0 >>
port=8080:proto=tcp:toport=443:toaddr=

Additional resources

/usr/share/ansible/roles/rhel-system-roles.firewall/README.md file

/usr/share/doc/rhel-system-roles/firewall/ directory

14.5.17.3. Configuring a firewalld DMZ zone by using the firewall RHEL system role

As a system administrator, you can use the firewall RHEL system role to configure a dmz zone on the
enp1s0 interface to permit HTTPS traffic to the zone. In this way, you enable external users to access
your web servers.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Configure firewalld
hosts: managed-node-01.example.com
tasks:
- name: Creating a DMZ with access to HTTPS port and masquerading for hosts in DMZ
ansible.builtin.include_role:
name: rhel-system-roles.firewall
vars:
firewall:

290
CHAPTER 14. SECURING NETWORKS

- zone: dmz
interface: enp1s0
service: https
state: enabled
runtime: true
permanent: true

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.firewall/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

On the control node, run the following command to remotely check the information about the
dmz zone on your managed node:

# ansible managed-node-01.example.com -m ansible.builtin.command -a 'firewall-cmd


--zone=dmz --list-all'
managed-node-01.example.com | CHANGED | rc=0 >>
dmz (active)
target: default
icmp-block-inversion: no
interfaces: enp1s0
sources:
services: https ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:

Additional resources

/usr/share/ansible/roles/rhel-system-roles.firewall/README.md file

/usr/share/doc/rhel-system-roles/firewall/ directory

14.6. GETTING STARTED WITH NFTABLES


The nftables framework classifies packets and it is the successor to the iptables, ip6tables, arptables,
ebtables, and ipset utilities. It offers numerous improvements in convenience, features, and
performance over previous packet-filtering tools, most notably:

291
Red Hat Enterprise Linux 8 System Design Guide

Built-in lookup tables instead of linear processing

A single framework for both the IPv4 and IPv6 protocols

All rules applied atomically instead of fetching, updating, and storing a complete rule set

Support for debugging and tracing in the rule set (nftrace) and monitoring trace events (in the
nft tool)

More consistent and compact syntax, no protocol-specific extensions

A Netlink API for third-party applications

The nftables framework uses tables to store chains. The chains contain individual rules for performing
actions. The nft utility replaces all tools from the previous packet-filtering frameworks. You can use the
libnftnl library for low-level interaction with nftables Netlink API through the libmnl library.

To display the effect of rule set changes, use the nft list ruleset command. Because these utilities add
tables, chains, rules, sets, and other objects to the nftables rule set, be aware that nftables rule-set
operations, such as the nft flush ruleset command, might affect rule sets installed using the iptables
command.

14.6.1. Creating and managing nftables tables, chains, and rules


You can display nftables rule sets and manage them.

14.6.1.1. Basics of nftables tables

A table in nftables is a namespace that contains a collection of chains, rules, sets, and other objects.

Each table must have an address family assigned. The address family defines the packet types that this
table processes. You can set one of the following address families when you create a table:

ip: Matches only IPv4 packets. This is the default if you do not specify an address family.

ip6: Matches only IPv6 packets.

inet: Matches both IPv4 and IPv6 packets.

arp: Matches IPv4 address resolution protocol (ARP) packets.

bridge: Matches packets that pass through a bridge device.

netdev: Matches packets from ingress.

If you want to add a table, the format to use depends on your firewall script:

In scripts in native syntax, use:

table <table_address_family> <table_name> {


}

In shell scripts, use:

nft add table <table_address_family> <table_name>

292
CHAPTER 14. SECURING NETWORKS

14.6.1.2. Basics of nftables chains

Tables consist of chains which in turn are containers for rules. The following two rule types exists:

Base chain: You can use base chains as an entry point for packets from the networking stack.

Regular chain: You can use regular chains as a jump target to better organize rules.

If you want to add a base chain to a table, the format to use depends on your firewall script:

In scripts in native syntax, use:

table <table_address_family> <table_name> {


chain <chain_name> {
type <type> hook <hook> priority <priority>
policy <policy> ;
}
}

In shell scripts, use:

nft add chain <table_address_family> <table_name> <chain_name> { type <type> hook


<hook> priority <priority> \; policy <policy> \; }

To avoid that the shell interprets the semicolons as the end of the command, place the \ escape
character in front of the semicolons.

Both examples create base chains. To create a regular chain, do not set any parameters in the curly
brackets.

Chain types
The following are the chain types and an overview with which address families and hooks you can use
them:

Type Address families Hooks Description

filter all all Standard chain type

nat ip, ip6, inet prerouting, input, Chains of this type perform native address
output, translation based on connection tracking
postrouting entries. Only the first packet traverses this
chain type.

route ip, ip6 output Accepted packets that traverse this chain type
cause a new route lookup if relevant parts of
the IP header have changed.

Chain priorities
The priority parameter specifies the order in which packets traverse chains with the same hook value.
You can set this parameter to an integer value or use a standard priority name.

The following matrix is an overview of the standard priority names and their numeric values, and with
which address families and hooks you can use them:

293
Red Hat Enterprise Linux 8 System Design Guide

Textual value Numeric value Address families Hooks

raw -300 ip, ip6, inet all

mangle -150 ip, ip6, inet all

dstnat -100 ip, ip6, inet prerouting

-300 bridge prerouting

filter 0 ip, ip6, inet , arp, netdev all

-200 bridge all

security 50 ip, ip6, inet all

srcnat 100 ip, ip6, inet postrouting

300 bridge postrouting

out 100 bridge output

Chain policies
The chain policy defines whether nftables should accept or drop packets if rules in this chain do not
specify any action. You can set one of the following policies in a chain:

accept (default)

drop

14.6.1.3. Basics of nftables rules

Rules define actions to perform on packets that pass a chain that contains this rule. If the rule also
contains matching expressions, nftables performs the actions only if all previous expressions apply.

If you want to add a rule to a chain, the format to use depends on your firewall script:

In scripts in native syntax, use:

table <table_address_family> <table_name> {


chain <chain_name> {
type <type> hook <hook> priority <priority> ; policy <policy> ;
<rule>
}
}

In shell scripts, use:

nft add rule <table_address_family> <table_name> <chain_name> <rule>

This shell command appends the new rule at the end of the chain. If you prefer to add a rule at
294
CHAPTER 14. SECURING NETWORKS

This shell command appends the new rule at the end of the chain. If you prefer to add a rule at
the beginning of the chain, use the nft insert command instead of nft add.

14.6.1.4. Managing tables, chains, and rules using nft commands

To manage an nftables firewall on the command line or in shell scripts, use the nft utility.

IMPORTANT

The commands in this procedure do not represent a typical workflow and are not
optimized. This procedure only demonstrates how to use nft commands to manage
tables, chains, and rules in general.

Procedure

1. Create a table named nftables_svc with the inet address family so that the table can process
both IPv4 and IPv6 packets:

# nft add table inet nftables_svc

2. Add a base chain named INPUT, that processes incoming network traffic, to the inet
nftables_svc table:

# nft add chain inet nftables_svc INPUT { type filter hook input priority filter \; policy
accept \; }

To avoid that the shell interprets the semicolons as the end of the command, escape the
semicolons using the \ character.

3. Add rules to the INPUT chain. For example, allow incoming TCP traffic on port 22 and 443, and,
as the last rule of the INPUT chain, reject other incoming traffic with an Internet Control
Message Protocol (ICMP) port unreachable message:

# nft add rule inet nftables_svc INPUT tcp dport 22 accept


# nft add rule inet nftables_svc INPUT tcp dport 443 accept
# nft add rule inet nftables_svc INPUT reject with icmpx type port-unreachable

If you enter the nft add rule commands as shown, nft adds the rules in the same order to the
chain as you run the commands.

4. Display the current rule set including handles:

# nft -a list table inet nftables_svc


table inet nftables_svc { # handle 13
chain INPUT { # handle 1
type filter hook input priority filter; policy accept;
tcp dport 22 accept # handle 2
tcp dport 443 accept # handle 3
reject # handle 4
}
}

5. Insert a rule before the existing rule with handle 3. For example, to insert a rule that allows TCP
traffic on port 636, enter:

295
Red Hat Enterprise Linux 8 System Design Guide

# nft insert rule inet nftables_svc INPUT position 3 tcp dport 636 accept

6. Append a rule after the existing rule with handle 3. For example, to insert a rule that allows TCP
traffic on port 80, enter:

# nft add rule inet nftables_svc INPUT position 3 tcp dport 80 accept

7. Display the rule set again with handles. Verify that the later added rules have been added to the
specified positions:

# nft -a list table inet nftables_svc


table inet nftables_svc { # handle 13
chain INPUT { # handle 1
type filter hook input priority filter; policy accept;
tcp dport 22 accept # handle 2
tcp dport 636 accept # handle 5
tcp dport 443 accept # handle 3
tcp dport 80 accept # handle 6
reject # handle 4
}
}

8. Remove the rule with handle 6:

# nft delete rule inet nftables_svc INPUT handle 6

To remove a rule, you must specify the handle.

9. Display the rule set, and verify that the removed rule is no longer present:

# nft -a list table inet nftables_svc


table inet nftables_svc { # handle 13
chain INPUT { # handle 1
type filter hook input priority filter; policy accept;
tcp dport 22 accept # handle 2
tcp dport 636 accept # handle 5
tcp dport 443 accept # handle 3
reject # handle 4
}
}

10. Remove all remaining rules from the INPUT chain:

# nft flush chain inet nftables_svc INPUT

11. Display the rule set, and verify that the INPUT chain is empty:

# nft list table inet nftables_svc


table inet nftables_svc {
chain INPUT {
type filter hook input priority filter; policy accept
}
}

296
CHAPTER 14. SECURING NETWORKS

12. Delete the INPUT chain:

# nft delete chain inet nftables_svc INPUT

You can also use this command to delete chains that still contain rules.

13. Display the rule set, and verify that the INPUT chain has been deleted:

# nft list table inet nftables_svc


table inet nftables_svc {
}

14. Delete the nftables_svc table:

# nft delete table inet nftables_svc

You can also use this command to delete tables that still contain chains.

NOTE

To delete the entire rule set, use the nft flush ruleset command instead of
manually deleting all rules, chains, and tables in separate commands.

Additional resources

nft(8) man page on your system

14.6.2. Migrating from iptables to nftables


If your firewall configuration still uses iptables rules, you can migrate your iptables rules to nftables.

14.6.2.1. When to use firewalld, nftables, or iptables

The following is a brief overview in which scenario you should use one of the following utilities:

firewalld: Use the firewalld utility for simple firewall use cases. The utility is easy to use and
covers the typical use cases for these scenarios.

nftables: Use the nftables utility to set up complex and performance-critical firewalls, such as
for a whole network.

iptables: The iptables utility on Red Hat Enterprise Linux uses the nf_tables kernel API instead
of the legacy back end. The nf_tables API provides backward compatibility so that scripts that
use iptables commands still work on Red Hat Enterprise Linux. For new firewall scripts, Red Hat
recommends to use nftables.

IMPORTANT

To prevent the different firewall-related services (firewalld, nftables, or iptables) from


influencing each other, run only one of them on a RHEL host, and disable the other
services.

14.6.2.2. Concepts in the nftables framework

297
Red Hat Enterprise Linux 8 System Design Guide

Compared to the iptables framework, nftables offers a more modern, efficient, and flexible alternative.
There are several concepts and features that provide advanced capabilities and improvements over
iptables. These enhancements simplify the rule management and improve performance to make
nftables a modern alternative for complex and high-performance networking environments.

The nftables framework contains the following components:

Tables and namespaces


In nftables, tables represent organizational units or namespaces that group together related firewall
chains, sets, flowtables, and other objects. In nftables, tables provide a more flexible way to structure
firewall rules and related components. While in iptables, the tables were more rigidly defined with
specific purposes.
Table families
Each table in nftables is associated with a specific family ( ip, ip6, inet, arp, bridge, or netdev). This
association determines which packets the table can process. For example, a table in the ip family
handles only IPv4 packets. On the other hand, inet is a special case of table family. It offers a unified
approach across protocols, because it can process both IPv4 and IPv6 packets. Another case of a
special table family is netdev, because it is used for rules that apply directly to network devices,
enabling filtering at the device level.
Base chains
Base chains in nftables are highly configurable entry-points in the packet processing pipeline that
enable users to specify the following:

Type of chain, for example "filter"

The hook point in the packet processing path, for example "input", "output", "forward"

Priority of the chain

This flexibility enables precise control over when and how the rules are applied to packets as they
pass through the network stack. A special case of a chain is the route chain, which is used to
influence the routing decisions made by the kernel, based on packet headers.

Virtual machine for rule processing


The nftables framework uses an internal virtual machine to process rules. This virtual machine
executes instructions that are similar to assembly language operations (loading data into registers,
performing comparisons, and so on). Such a mechanism allows for highly flexible and efficient rule
processing.

Enhancements in nftables can be introduced as new instructions for that virtual machine. This typically
requires a new kernel module and updates to the libnftnl library and the nft command-line utility.

Alternatively, you can introduce new features by combining existing instructions in innovative ways
without a need for kernel modifications. The syntax of nftables rules reflects the flexibility of the
underlying virtual machine. For example, the rule meta mark set tcp dport map { 22: 1, 80: 2 } sets a
packet’s firewall mark to 1 if the TCP destination port is 22, and to 2 if the port is 80. This demonstrates
how complex logic can be expressed concisely.

Lessons learned and enhancements


The nftables framework integrates and extends the functionality of the ipset utility, which is used in
iptables for bulk matching on IP addresses, ports, other data types and, most importantly,
combinations thereof. This integration makes it easier to manage large and dynamic sets of data

298
CHAPTER 14. SECURING NETWORKS

directly within nftables. Next, nftables natively supports matching packets based on multiple values
or ranges for any data type, which enhances its capability to handle complex filtering requirements.
With nftables you can manipulate any field within a packet.

In nftables, sets can be either named or anonymous. The named sets can be referenced by multiple
rules and modified dynamically. The anonymous sets are defined inline within a rule and are immutable.
Sets can contain elements that are combinations of different types, for example IP address and port
number pairs. This feature provides greater flexibility in matching complex criteria. To manage sets, the
kernel can select the most appropriate backend based on the specific requirements (performance,
memory efficiency, and others). Sets can also function as maps with key-value pairs. The value part can
be used as data points (values to write into packet headers), or as verdicts or chains to jump to. This
enables complex and dynamic rule behaviors, known as "verdict maps".

Flexible rule format


The structure of nftables rules is straightforward. The conditions and actions are applied sequentially
from left to right. This intuitive format simplifies rule creating and troubleshooting.

Conditions in a rule are logically connected (with the AND operator) together, which means that all
conditions must be evaluated as "true" for the rule to match. If any condition fails, the evaluation moves
to the next rule.

Actions in nftables can be final, such as drop or accept, which stop further rule processing for the
packet. Non-terminal actions, such as counter log meta mark set 0x3, perform specific tasks (counting
packets, logging, setting a mark, and others), but allow subsequent rules to be evaluated.

Additional resources

nft(8) man page

What comes after iptables? Its successor, of course: nftables

Firewalld: The Future is nftables

14.6.2.3. Concepts in the deprecated iptables framework

Similar to the actively-maintained nftables framework, the deprecated iptables framework enables you
to perform a variety of packet filtering tasks, logging and auditing, NAT-related configuration tasks, and
more.

The iptables framework is structured into multiple tables, where each table is designed for a specific
purpose:

filter
The default table, ensures general packet filtering
nat
For Network Address Translation (NAT), includes altering the source and destination addresses of
packets
mangle
For specific packet alteration, enables you to do modification of packet headers for advanced routing
decisions
raw
For configurations that need to happen before connection tracking

These tables are implemented as separate kernel modules, where each table offers a fixed set of builtin
299
Red Hat Enterprise Linux 8 System Design Guide

These tables are implemented as separate kernel modules, where each table offers a fixed set of builtin
chains such as INPUT, OUTPUT, and FORWARD. A chain is a sequence of rules that packets are
evaluated against. These chains hook into specific points in the packet processing flow in the kernel. The
chains have the same names across different tables, however their order of execution is determined by
their respective hook priorities. The priorities are managed internally by the kernel to make sure that the
rules are applied in the correct sequence.

Originally, iptables was designed to process IPv4 traffic. However, with the inception of the IPv6
protocol, the ip6tables utility needed to be introduced to provide comparable functionality (as
iptables) and enable users to create and manage firewall rules for IPv6 packets. With the same logic,
the arptables utility was created to process Address Resolution Protocol (ARP) and the ebtables utility
was developed to handle Ethernet bridging frames. These tools ensure that you can apply the packet
filtering abilities of iptables across various network protocols and provide comprehensive network
coverage.

To enhance the functionality of iptables, the extensions started to be developed. The functionality
extensions are typically implemented as kernel modules that are paired with user-space dynamic shared
objects (DSOs). The extensions introduce "matches" and "targets" that you can use in firewall rules to
perform more sophisticated operations. Extensions can enable complex matches and targets. For
instance you can match on, or manipulate specific layer 4 protocol header values, perform rate-limiting,
enforce quotas, and so on. Some extensions are designed to address limitations in the default iptables
syntax, for example the "multiport" match extension. This extension allows a single rule to match
multiple, non-consecutive ports to simplify rule definitions, and thereby reducing the number of
individual rules required.

An ipset is a special kind of functionality extension to iptables. It is a kernel-level data structure that is
used together with iptables to create collections of IP addresses, port numbers, and other network-
related elements that you can match against packets. These sets significantly streamline, optimize, and
accelerate the process of writing and managing firewall rules.

Additional resources

iptables(8) man page

14.6.2.4. Converting iptables and ip6tables rule sets to nftables

Use the iptables-restore-translate and ip6tables-restore-translate utilities to translate iptables and


ip6tables rule sets to nftables.

Prerequisites

The nftables and iptables packages are installed.

The system has iptables and ip6tables rules configured.

Procedure

1. Write the iptables and ip6tables rules to a file:

# iptables-save >/root/iptables.dump
# ip6tables-save >/root/ip6tables.dump

2. Convert the dump files to nftables instructions:

# iptables-restore-translate -f /root/iptables.dump > /etc/nftables/ruleset-migrated-

300
CHAPTER 14. SECURING NETWORKS

from-iptables.nft
# ip6tables-restore-translate -f /root/ip6tables.dump > /etc/nftables/ruleset-migrated-
from-ip6tables.nft

3. Review and, if needed, manually update the generated nftables rules.

4. To enable the nftables service to load the generated files, add the following to the
/etc/sysconfig/nftables.conf file:

include "/etc/nftables/ruleset-migrated-from-iptables.nft"
include "/etc/nftables/ruleset-migrated-from-ip6tables.nft"

5. Stop and disable the iptables service:

# systemctl disable --now iptables

If you used a custom script to load the iptables rules, ensure that the script no longer starts
automatically and reboot to flush all tables.

6. Enable and start the nftables service:

# systemctl enable --now nftables

Verification

Display the nftables rule set:

# nft list ruleset

Additional resources

Automatically loading nftables rules when the system boots

14.6.2.5. Converting single iptables and ip6tables rules to nftables

Red Hat Enterprise Linux provides the iptables-translate and ip6tables-translate utilities to convert an
iptables or ip6tables rule into the equivalent one for nftables.

Prerequisites

The nftables package is installed.

Procedure

Use the iptables-translate or ip6tables-translate utility instead of iptables or ip6tables to


display the corresponding nftables rule, for example:

# iptables-translate -A INPUT -s 192.0.2.0/24 -j ACCEPT


nft add rule ip filter INPUT ip saddr 192.0.2.0/24 counter accept

Note that some extensions lack translation support. In these cases, the utility prints the
untranslated rule prefixed with the # sign, for example:

301
Red Hat Enterprise Linux 8 System Design Guide

# iptables-translate -A INPUT -j CHECKSUM --checksum-fill


nft # -A INPUT -j CHECKSUM --checksum-fill

Additional resources

iptables-translate --help

14.6.2.6. Comparison of common iptables and nftables commands

The following is a comparison of common iptables and nftables commands:

Listing all rules:

iptables nftables

iptables-save nft list ruleset

Listing a certain table and chain:

iptables nftables

iptables -L nft list table ip filter

iptables -L INPUT nft list chain ip filter INPUT

iptables -t nat -L PREROUTING nft list chain ip nat PREROUTING

The nft command does not pre-create tables and chains. They exist only if a user created them
manually.

Listing rules generated by firewalld:

# nft list table inet firewalld


# nft list table ip firewalld
# nft list table ip6 firewalld

14.6.3. Writing and executing nftables scripts


The major benefit of using the nftables framework is that the execution of scripts is atomic. This means
that the system either applies the whole script or prevents the execution if an error occurs. This
guarantees that the firewall is always in a consistent state.

Additionally, with the nftables script environment, you can:

Add comments

Define variables

Include other rule-set files

When you install the nftables package, Red Hat Enterprise Linux automatically creates *.nft scripts in

302
CHAPTER 14. SECURING NETWORKS

When you install the nftables package, Red Hat Enterprise Linux automatically creates *.nft scripts in
the /etc/nftables/ directory. These scripts contain commands that create tables and empty chains for
different purposes.

14.6.3.1. Supported nftables script formats

You can write scripts in the nftables scripting environment in the following formats:

The same format as the nft list ruleset command displays the rule set:

#!/usr/sbin/nft -f

# Flush the rule set


flush ruleset

table inet example_table {


chain example_chain {
# Chain for incoming packets that drops all packets that
# are not explicitly allowed by any rule in this chain
type filter hook input priority 0; policy drop;

# Accept connections to port 22 (ssh)


tcp dport ssh accept
}
}

The same syntax as for nft commands:

#!/usr/sbin/nft -f

# Flush the rule set


flush ruleset

# Create a table
add table inet example_table

# Create a chain for incoming packets that drops all packets


# that are not explicitly allowed by any rule in this chain
add chain inet example_table example_chain { type filter hook input priority 0 ; policy drop ; }

# Add a rule that accepts connections to port 22 (ssh)


add rule inet example_table example_chain tcp dport ssh accept

14.6.3.2. Running nftables scripts

You can run an nftables script either by passing it to the nft utility or by executing the script directly.

Procedure

To run an nftables script by passing it to the nft utility, enter:

# nft -f /etc/nftables/<example_firewall_script>.nft

To run an nftables script directly:

a. For the single time that you perform this:


303
Red Hat Enterprise Linux 8 System Design Guide

a. For the single time that you perform this:

i. Ensure that the script starts with the following shebang sequence:

#!/usr/sbin/nft -f

IMPORTANT

If you omit the -f parameter, the nft utility does not read the script and
displays: Error: syntax error, unexpected newline, expecting string.

ii. Optional: Set the owner of the script to root:

# chown root /etc/nftables/<example_firewall_script>.nft

iii. Make the script executable for the owner:

# chmod u+x /etc/nftables/<example_firewall_script>.nft

b. Run the script:

# /etc/nftables/<example_firewall_script>.nft

If no output is displayed, the system executed the script successfully.

IMPORTANT

Even if nft executes the script successfully, incorrectly placed rules, missing parameters,
or other problems in the script can cause that the firewall behaves not as expected.

Additional resources

chown(1) and chmod(1) man pages on your system

Automatically loading nftables rules when the system boots

14.6.3.3. Using comments in nftables scripts

The nftables scripting environment interprets everything to the right of a # character to the end of a
line as a comment.

Comments can start at the beginning of a line, or next to a command:

...
# Flush the rule set
flush ruleset

add table inet example_table # Create a table


...

14.6.3.4. Using variables in nftables script

To define a variable in an nftables script, use the define keyword. You can store single values and
304
CHAPTER 14. SECURING NETWORKS

To define a variable in an nftables script, use the define keyword. You can store single values and
anonymous sets in a variable. For more complex scenarios, use sets or verdict maps.

Variables with a single value


The following example defines a variable named INET_DEV with the value enp1s0:

define INET_DEV = enp1s0

You can use the variable in the script by entering the $ sign followed by the variable name:

...
add rule inet example_table example_chain iifname $INET_DEV tcp dport ssh accept
...

Variables that contain an anonymous set


The following example defines a variable that contains an anonymous set:

define DNS_SERVERS = { 192.0.2.1, 192.0.2.2 }

You can use the variable in the script by writing the $ sign followed by the variable name:

add rule inet example_table example_chain ip daddr $DNS_SERVERS accept

NOTE

Curly braces have special semantics when you use them in a rule because they indicate
that the variable represents a set.

Additional resources

Using sets in nftables commands

Using verdict maps in nftables commands

14.6.3.5. Including files in nftables scripts

In the nftables scripting environment, you can include other scripts by using the include statement.

If you specify only a file name without an absolute or relative path, nftables includes files from the
default search path, which is set to /etc on Red Hat Enterprise Linux.

Example 14.1. Including files from the default search directory

To include a file from the default search directory:

include "example.nft"

Example 14.2. Including all *.nft files from a directory

305
Red Hat Enterprise Linux 8 System Design Guide

To include all files ending with *.nft that are stored in the /etc/nftables/rulesets/ directory:

include "/etc/nftables/rulesets/*.nft"

Note that the include statement does not match files beginning with a dot.

Additional resources

The Include files section in the nft(8) man page on your system

14.6.3.6. Automatically loading nftables rules when the system boots

The nftables systemd service loads firewall scripts that are included in the /etc/sysconfig/nftables.conf
file.

Prerequisites

The nftables scripts are stored in the /etc/nftables/ directory.

Procedure

1. Edit the /etc/sysconfig/nftables.conf file.

If you modified the *.nft scripts that were created in /etc/nftables/ with the installation of
the nftables package, uncomment the include statement for these scripts.

If you wrote new scripts, add include statements to include these scripts. For example, to
load the /etc/nftables/example.nft script when the nftables service starts, add:

include "/etc/nftables/_example_.nft"

2. Optional: Start the nftables service to load the firewall rules without rebooting the system:

# systemctl start nftables

3. Enable the nftables service.

# systemctl enable nftables

Additional resources

Supported nftables script formats

14.6.4. Configuring NAT using nftables


With nftables, you can configure the following network address translation (NAT) types:

Masquerading

Source NAT (SNAT)

Destination NAT (DNAT)

306
CHAPTER 14. SECURING NETWORKS

Redirect

IMPORTANT

You can only use real interface names in iifname and oifname parameters, and
alternative names (altname) are not supported.

14.6.4.1. NAT types

These are the different network address translation (NAT) types:

Masquerading and source NAT (SNAT)


Use one of these NAT types to change the source IP address of packets. For example, Internet
Service Providers (ISPs) do not route private IP ranges, such as 10.0.0.0/8. If you use private IP
ranges in your network and users should be able to reach servers on the internet, map the source IP
address of packets from these ranges to a public IP address.
Masquerading and SNAT are very similar to one another. The differences are:

Masquerading automatically uses the IP address of the outgoing interface. Therefore, use
masquerading if the outgoing interface uses a dynamic IP address.

SNAT sets the source IP address of packets to a specified IP and does not dynamically look
up the IP of the outgoing interface. Therefore, SNAT is faster than masquerading. Use SNAT
if the outgoing interface uses a fixed IP address.

Destination NAT (DNAT)


Use this NAT type to rewrite the destination address and port of incoming packets. For example, if
your web server uses an IP address from a private IP range and is, therefore, not directly accessible
from the internet, you can set a DNAT rule on the router to redirect incoming traffic to this server.
Redirect
This type is a special case of DNAT that redirects packets to the local machine depending on the
chain hook. For example, if a service runs on a different port than its standard port, you can redirect
incoming traffic from the standard port to this specific port.

14.6.4.2. Configuring masquerading using nftables

Masquerading enables a router to dynamically change the source IP of packets sent through an
interface to the IP address of the interface. This means that if the interface gets a new IP assigned,
nftables automatically uses the new IP when replacing the source IP.

Replace the source IP of packets leaving the host through the ens3 interface to the IP set on ens3.

Procedure

1. Create a table:

# nft add table nat

2. Add the prerouting and postrouting chains to the table:

# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }

IMPORTANT
307
Red Hat Enterprise Linux 8 System Design Guide

IMPORTANT

Even if you do not add a rule to the prerouting chain, the nftables framework
requires this chain to match incoming packet replies.

Note that you must pass the -- option to the nft command to prevent the shell from interpreting
the negative priority value as an option of the nft command.

3. Add a rule to the postrouting chain that matches outgoing packets on the ens3 interface:

# nft add rule nat postrouting oifname "ens3" masquerade

14.6.4.3. Configuring source NAT using nftables

On a router, Source NAT (SNAT) enables you to change the IP of packets sent through an interface to a
specific IP address. The router then replaces the source IP of outgoing packets.

Procedure

1. Create a table:

# nft add table nat

2. Add the prerouting and postrouting chains to the table:

# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }

IMPORTANT

Even if you do not add a rule to the postrouting chain, the nftables framework
requires this chain to match outgoing packet replies.

Note that you must pass the -- option to the nft command to prevent the shell from interpreting
the negative priority value as an option of the nft command.

3. Add a rule to the postrouting chain that replaces the source IP of outgoing packets through
ens3 with 192.0.2.1:

# nft add rule nat postrouting oifname "ens3" snat to 192.0.2.1

Additional resources

Forwarding incoming packets on a specific local port to a different host

14.6.4.4. Configuring destination NAT using nftables

Destination NAT (DNAT) enables you to redirect traffic on a router to a host that is not directly
accessible from the internet.

For example, with DNAT the router redirects incoming traffic sent to port 80 and 443 to a web server
with the IP address 192.0.2.1.

Procedure

308
CHAPTER 14. SECURING NETWORKS

Procedure

1. Create a table:

# nft add table nat

2. Add the prerouting and postrouting chains to the table:

# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }

IMPORTANT

Even if you do not add a rule to the postrouting chain, the nftables framework
requires this chain to match outgoing packet replies.

Note that you must pass the -- option to the nft command to prevent the shell from interpreting
the negative priority value as an option of the nft command.

3. Add a rule to the prerouting chain that redirects incoming traffic to port 80 and 443 on the
ens3 interface of the router to the web server with the IP address 192.0.2.1:

# nft add rule nat prerouting iifname ens3 tcp dport { 80, 443 } dnat to 192.0.2.1

4. Depending on your environment, add either a SNAT or masquerading rule to change the source
address for packets returning from the web server to the sender:

a. If the ens3 interface uses a dynamic IP addresses, add a masquerading rule:

# nft add rule nat postrouting oifname "ens3" masquerade

b. If the ens3 interface uses a static IP address, add a SNAT rule. For example, if the ens3
uses the 198.51.100.1 IP address:

# nft add rule nat postrouting oifname "ens3" snat to 198.51.100.1

5. Enable packet forwarding:

# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf


# sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

Additional resources

NAT types

14.6.4.5. Configuring a redirect using nftables

The redirect feature is a special case of destination network address translation (DNAT) that redirects
packets to the local machine depending on the chain hook.

For example, you can redirect incoming and forwarded traffic sent to port 22 of the local host to port
2222.

Procedure

309
Red Hat Enterprise Linux 8 System Design Guide

Procedure

1. Create a table:

# nft add table nat

2. Add the prerouting chain to the table:

# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }

Note that you must pass the -- option to the nft command to prevent the shell from interpreting
the negative priority value as an option of the nft command.

3. Add a rule to the prerouting chain that redirects incoming traffic on port 22 to port 2222:

# nft add rule nat prerouting tcp dport 22 redirect to 2222

Additional resources

NAT types

14.6.4.6. Configuring flowtable by using nftables

The nftables utility uses the netfilter framework to provide network address translation (NAT) for
network traffic and provides the fastpath feature-based flowtable mechanism to accelerate packet
forwarding.

The flowtable mechanism has the following features:

Uses connection tracking to bypass the classic packet forwarding path.

Avoids revisiting the routing table by bypassing the classic packet processing.

Works only with TCP and UDP protocols.

Hardware independent software fast path.

Procedure

1. Add an example-table table of inet family:

# nft add table inet <example-table>

2. Add an example-flowtable flowtable with ingress hook and filter as a priority type:

# nft add flowtable inet <example-table> <example-flowtable> { hook ingress priority


filter \; devices = { enp1s0, enp7s0 } \; }

3. Add an example-forwardchain flow to the flowtable from a packet processing table:

# nft add chain inet <example-table> <example-forwardchain> { type filter hook


forward priority filter \; }

This command adds a flowtable of filter type with forward hook and filter priority.

310
CHAPTER 14. SECURING NETWORKS

4. Add a rule with established connection tracking state to offload example-flowtable flow:

# nft add rule inet <example-table> <example-forwardchain> ct state established flow


add @<example-flowtable>

Verification

Verify the properties of example-table:

# nft list table inet <example-table>


table inet example-table {
flowtable example-flowtable {
hook ingress priority filter
devices = { enp1s0, enp7s0 }
}

chain example-forwardchain {
type filter hook forward priority filter; policy accept;
ct state established flow add @example-flowtable
}
}

Additional resources

nft(8) man page on your system

14.6.5. Using sets in nftables commands


The nftables framework natively supports sets. You can use sets, for example, if a rule should match
multiple IP addresses, port numbers, interfaces, or any other match criteria.

14.6.5.1. Using anonymous sets in nftables

An anonymous set contains comma-separated values enclosed in curly brackets, such as { 22, 80, 443 },
that you use directly in a rule. You can use anonymous sets also for IP addresses and any other match
criteria.

The drawback of anonymous sets is that if you want to change the set, you must replace the rule. For a
dynamic solution, use named sets as described in Using named sets in nftables .

Prerequisites

The example_chain chain and the example_table table in the inet family exists.

Procedure

1. For example, to add a rule to example_chain in example_table that allows incoming traffic to
port 22, 80, and 443:

# nft add rule inet example_table example_chain tcp dport { 22, 80, 443 } accept

2. Optional: Display all chains and their rules in example_table:

311
Red Hat Enterprise Linux 8 System Design Guide

# nft list table inet example_table


table inet example_table {
chain example_chain {
type filter hook input priority filter; policy accept;
tcp dport { ssh, http, https } accept
}
}

14.6.5.2. Using named sets in nftables

The nftables framework supports mutable named sets. A named set is a list or range of elements that
you can use in multiple rules within a table. Another benefit over anonymous sets is that you can update
a named set without replacing the rules that use the set.

When you create a named set, you must specify the type of elements the set contains. You can set the
following types:

ipv4_addr for a set that contains IPv4 addresses or ranges, such as 192.0.2.1 or 192.0.2.0/24.

ipv6_addr for a set that contains IPv6 addresses or ranges, such as 2001:db8:1::1 or
2001:db8:1::1/64.

ether_addr for a set that contains a list of media access control (MAC) addresses, such as
52:54:00:6b:66:42.

inet_proto for a set that contains a list of internet protocol types, such as tcp.

inet_service for a set that contains a list of internet services, such as ssh.

mark for a set that contains a list of packet marks. Packet marks can be any positive 32-bit
integer value (0 to 2147483647).

Prerequisites

The example_chain chain and the example_table table exists.

Procedure

1. Create an empty set. The following examples create a set for IPv4 addresses:

To create a set that can store multiple individual IPv4 addresses:

# nft add set inet example_table example_set { type ipv4_addr \; }

To create a set that can store IPv4 address ranges:

# nft add set inet example_table example_set { type ipv4_addr \; flags interval \; }

IMPORTANT

To prevent the shell from interpreting the semicolons as the end of the
command, you must escape the semicolons with a backslash.

2. Optional: Create rules that use the set. For example, the following command adds a rule to the

312
CHAPTER 14. SECURING NETWORKS

2. Optional: Create rules that use the set. For example, the following command adds a rule to the
example_chain in the example_table that will drop all packets from IPv4 addresses in
example_set.

# nft add rule inet example_table example_chain ip saddr @example_set drop

Because example_set is still empty, the rule has currently no effect.

3. Add IPv4 addresses to example_set:

If you create a set that stores individual IPv4 addresses, enter:

# nft add element inet example_table example_set { 192.0.2.1, 192.0.2.2 }

If you create a set that stores IPv4 ranges, enter:

# nft add element inet example_table example_set { 192.0.2.0-192.0.2.255 }

When you specify an IP address range, you can alternatively use the Classless Inter-Domain
Routing (CIDR) notation, such as 192.0.2.0/24 in the above example.

14.6.5.3. Additional resources

The Sets section in the nft(8) man page on your system

14.6.6. Using verdict maps in nftables commands


Verdict maps, which are also known as dictionaries, enable nft to perform an action based on packet
information by mapping match criteria to an action.

14.6.6.1. Using anonymous maps in nftables

An anonymous map is a { match_criteria : action } statement that you use directly in a rule. The
statement can contain multiple comma-separated mappings.

The drawback of an anonymous map is that if you want to change the map, you must replace the rule.
For a dynamic solution, use named maps as described in Using named maps in nftables .

For example, you can use an anonymous map to route both TCP and UDP packets of the IPv4 and IPv6
protocol to different chains to count incoming TCP and UDP packets separately.

Procedure

1. Create a new table:

# nft add table inet example_table

2. Create the tcp_packets chain in example_table:

# nft add chain inet example_table tcp_packets

3. Add a rule to tcp_packets that counts the traffic in this chain:

# nft add rule inet example_table tcp_packets counter

313
Red Hat Enterprise Linux 8 System Design Guide

4. Create the udp_packets chain in example_table

# nft add chain inet example_table udp_packets

5. Add a rule to udp_packets that counts the traffic in this chain:

# nft add rule inet example_table udp_packets counter

6. Create a chain for incoming traffic. For example, to create a chain named incoming_traffic in
example_table that filters incoming traffic:

# nft add chain inet example_table incoming_traffic { type filter hook input priority 0 \;
}

7. Add a rule with an anonymous map to incoming_traffic:

# nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump
tcp_packets, udp : jump udp_packets }

The anonymous map distinguishes the packets and sends them to the different counter chains
based on their protocol.

8. To list the traffic counters, display example_table:

# nft list table inet example_table


table inet example_table {
chain tcp_packets {
counter packets 36379 bytes 2103816
}

chain udp_packets {
counter packets 10 bytes 1559
}

chain incoming_traffic {
type filter hook input priority filter; policy accept;
ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
}
}

The counters in the tcp_packets and udp_packets chain display both the number of received
packets and bytes.

14.6.6.2. Using named maps in nftables

The nftables framework supports named maps. You can use these maps in multiple rules within a table.
Another benefit over anonymous maps is that you can update a named map without replacing the rules
that use it.

When you create a named map, you must specify the type of elements:

ipv4_addr for a map whose match part contains an IPv4 address, such as 192.0.2.1.

314
CHAPTER 14. SECURING NETWORKS

ipv6_addr for a map whose match part contains an IPv6 address, such as 2001:db8:1::1.

ether_addr for a map whose match part contains a media access control (MAC) address, such
as 52:54:00:6b:66:42.

inet_proto for a map whose match part contains an internet protocol type, such as tcp.

inet_service for a map whose match part contains an internet services name port number, such
as ssh or 22.

mark for a map whose match part contains a packet mark. A packet mark can be any positive
32-bit integer value (0 to 2147483647).

counter for a map whose match part contains a counter value. The counter value can be any
positive 64-bit integer value.

quota for a map whose match part contains a quota value. The quota value can be any positive
64-bit integer value.

For example, you can allow or drop incoming packets based on their source IP address. Using a named
map, you require only a single rule to configure this scenario while the IP addresses and actions are
dynamically stored in the map.

Procedure

1. Create a table. For example, to create a table named example_table that processes IPv4
packets:

# nft add table ip example_table

2. Create a chain. For example, to create a chain named example_chain in example_table:

# nft add chain ip example_table example_chain { type filter hook input priority 0 \; }

IMPORTANT

To prevent the shell from interpreting the semicolons as the end of the
command, you must escape the semicolons with a backslash.

3. Create an empty map. For example, to create a map for IPv4 addresses:

# nft add map ip example_table example_map { type ipv4_addr : verdict \; }

4. Create rules that use the map. For example, the following command adds a rule to
example_chain in example_table that applies actions to IPv4 addresses which are both
defined in example_map:

# nft add rule example_table example_chain ip saddr vmap @example_map

5. Add IPv4 addresses and corresponding actions to example_map:

# nft add element ip example_table example_map { 192.0.2.1 : accept, 192.0.2.2 : drop }

This example defines the mappings of IPv4 addresses to actions. In combination with the rule
315
Red Hat Enterprise Linux 8 System Design Guide

This example defines the mappings of IPv4 addresses to actions. In combination with the rule
created above, the firewall accepts packet from 192.0.2.1 and drops packets from 192.0.2.2.

6. Optional: Enhance the map by adding another IP address and action statement:

# nft add element ip example_table example_map { 192.0.2.3 : accept }

7. Optional: Remove an entry from the map:

# nft delete element ip example_table example_map { 192.0.2.1 }

8. Optional: Display the rule set:

# nft list ruleset


table ip example_table {
map example_map {
type ipv4_addr : verdict
elements = { 192.0.2.2 : drop, 192.0.2.3 : accept }
}

chain example_chain {
type filter hook input priority filter; policy accept;
ip saddr vmap @example_map
}
}

14.6.6.3. Additional resources

The Maps section in the nft(8) man page on your system

14.6.7. Example: Protecting a LAN and DMZ using an nftables script


Use the nftables framework on a RHEL router to write and install a firewall script that protects the
network clients in an internal LAN and a web server in a DMZ from unauthorized access from the
internet and from other networks.

IMPORTANT

This example is only for demonstration purposes and describes a scenario with specific
requirements.

Firewall scripts highly depend on the network infrastructure and security requirements.
Use this example to learn the concepts of nftables firewalls when you write scripts for
your own environment.

14.6.7.1. Network conditions

The network in this example has the following conditions:

The router is connected to the following networks:

The internet through interface enp1s0

The internal LAN through interface enp7s0

316
CHAPTER 14. SECURING NETWORKS

The DMZ through enp8s0

The internet interface of the router has both a static IPv4 address (203.0.113.1) and IPv6
address (2001:db8:a::1) assigned.

The clients in the internal LAN use only private IPv4 addresses from the range 10.0.0.0/24.
Consequently, traffic from the LAN to the internet requires source network address translation
(SNAT).

The administrator PCs in the internal LAN use the IP addresses 10.0.0.100 and 10.0.0.200.

The DMZ uses public IP addresses from the ranges 198.51.100.0/24 and 2001:db8:b::/56.

The web server in the DMZ uses the IP addresses 198.51.100.5 and 2001:db8:b::5.

The router acts as a caching DNS server for hosts in the LAN and DMZ.

14.6.7.2. Security requirements to the firewall script

The following are the requirements to the nftables firewall in the example network:

The router must be able to:

Recursively resolve DNS queries.

Perform all connections on the loopback interface.

Clients in the internal LAN must be able to:

Query the caching DNS server running on the router.

Access the HTTPS server in the DMZ.

Access any HTTPS server on the internet.

The PCs of the administrators must be able to access the router and every server in the DMZ
using SSH.

The web server in the DMZ must be able to:

Query the caching DNS server running on the router.

Access HTTPS servers on the internet to download updates.

Hosts on the internet must be able to:

Access the HTTPS servers in the DMZ.

Additionally, the following security requirements exists:

Connection attempts that are not explicitly allowed should be dropped.

Dropped packets should be logged.

14.6.7.3. Configuring logging of dropped packets to a file

By default, systemd logs kernel messages, such as for dropped packets, to the journal. Additionally, you

317
Red Hat Enterprise Linux 8 System Design Guide

By default, systemd logs kernel messages, such as for dropped packets, to the journal. Additionally, you
can configure the rsyslog service to log such entries to a separate file. To ensure that the log file does
not grow infinitely, configure a rotation policy.

Prerequisites

The rsyslog package is installed.

The rsyslog service is running.

Procedure

1. Create the /etc/rsyslog.d/nftables.conf file with the following content:

:msg, startswith, "nft drop" -/var/log/nftables.log


& stop

Using this configuration, the rsyslog service logs dropped packets to the /var/log/nftables.log
file instead of /var/log/messages.

2. Restart the rsyslog service:

# systemctl restart rsyslog

3. Create the /etc/logrotate.d/nftables file with the following content to rotate


/var/log/nftables.log if the size exceeds 10 MB:

/var/log/nftables.log {
size +10M
maxage 30
sharedscripts
postrotate
/usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
endscript
}

The maxage 30 setting defines that logrotate removes rotated logs older than 30 days during
the next rotation operation.

Additional resources

rsyslog.conf(5) and logrotate(8) man pages on your system

14.6.7.4. Writing and activating the nftables script

This example is an nftables firewall script that runs on a RHEL router and protects the clients in an
internal LAN and a web server in a DMZ. For details about the network and the requirements for the
firewall used in the example, see Network conditions and Security requirements to the firewall script .

318
CHAPTER 14. SECURING NETWORKS


WARNING

This nftables firewall script is only for demonstration purposes. Do not use it
without adapting it to your environments and security requirements.

Prerequisites

The network is configured as described in Network conditions.

Procedure

1. Create the /etc/nftables/firewall.nft script with the following content:

# Remove all rules


flush ruleset

# Table for both IPv4 and IPv6 rules


table inet nftables_svc {

# Define variables for the interface name


define INET_DEV = enp1s0
define LAN_DEV = enp7s0
define DMZ_DEV = enp8s0

# Set with the IPv4 addresses of admin PCs


set admin_pc_ipv4 {
type ipv4_addr
elements = { 10.0.0.100, 10.0.0.200 }
}

# Chain for incoming trafic. Default policy: drop


chain INPUT {
type filter hook input priority filter
policy drop

# Accept packets in established and related state, drop invalid packets


ct state vmap { established:accept, related:accept, invalid:drop }

# Accept incoming traffic on loopback interface


iifname lo accept

# Allow request from LAN and DMZ to local DNS server


iifname { $LAN_DEV, $DMZ_DEV } meta l4proto { tcp, udp } th dport 53 accept

# Allow admins PCs to access the router using SSH


iifname $LAN_DEV ip saddr @admin_pc_ipv4 tcp dport 22 accept

# Last action: Log blocked packets

319
Red Hat Enterprise Linux 8 System Design Guide

# (packets that were not accepted in previous rules in this chain)


log prefix "nft drop IN : "
}

# Chain for outgoing traffic. Default policy: drop


chain OUTPUT {
type filter hook output priority filter
policy drop

# Accept packets in established and related state, drop invalid packets


ct state vmap { established:accept, related:accept, invalid:drop }

# Accept outgoing traffic on loopback interface


oifname lo accept

# Allow local DNS server to recursively resolve queries


oifname $INET_DEV meta l4proto { tcp, udp } th dport 53 accept

# Last action: Log blocked packets


log prefix "nft drop OUT: "
}

# Chain for forwarding traffic. Default policy: drop


chain FORWARD {
type filter hook forward priority filter
policy drop

# Accept packets in established and related state, drop invalid packets


ct state vmap { established:accept, related:accept, invalid:drop }

# IPv4 access from LAN and internet to the HTTPS server in the DMZ
iifname { $LAN_DEV, $INET_DEV } oifname $DMZ_DEV ip daddr 198.51.100.5 tcp dport
443 accept

# IPv6 access from internet to the HTTPS server in the DMZ


iifname $INET_DEV oifname $DMZ_DEV ip6 daddr 2001:db8:b::5 tcp dport 443 accept

# Access from LAN and DMZ to HTTPS servers on the internet


iifname { $LAN_DEV, $DMZ_DEV } oifname $INET_DEV tcp dport 443 accept

# Last action: Log blocked packets


log prefix "nft drop FWD: "
}

# Postrouting chain to handle SNAT


chain postrouting {
type nat hook postrouting priority srcnat; policy accept;

# SNAT for IPv4 traffic from LAN to internet


iifname $LAN_DEV oifname $INET_DEV snat ip to 203.0.113.1
}
}

320
CHAPTER 14. SECURING NETWORKS

2. Include the /etc/nftables/firewall.nft script in the /etc/sysconfig/nftables.conf file:

include "/etc/nftables/firewall.nft"

3. Enable IPv4 forwarding:

# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf


# sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

4. Enable and start the nftables service:

# systemctl enable --now nftables

Verification

1. Optional: Verify the nftables rule set:

# nft list ruleset


...

2. Try to perform an access that the firewall prevents. For example, try to access the router using
SSH from the DMZ:

# ssh router.example.com
ssh: connect to host router.example.com port 22: Network is unreachable

3. Depending on your logging settings, search:

The systemd journal for the blocked packets:

# journalctl -k -g "nft drop"


Oct 14 17:27:18 router kernel: nft drop IN : IN=enp8s0 OUT= MAC=...
SRC=198.51.100.5 DST=198.51.100.1 ... PROTO=TCP SPT=40464 DPT=22 ... SYN ...

The /var/log/nftables.log file for the blocked packets:

Oct 14 17:27:18 router kernel: nft drop IN : IN=enp8s0 OUT= MAC=...


SRC=198.51.100.5 DST=198.51.100.1 ... PROTO=TCP SPT=40464 DPT=22 ... SYN ...

14.6.8. Configuring port forwarding using nftables


Port forwarding enables administrators to forward packets sent to a specific destination port to a
different local or remote port.

For example, if your web server does not have a public IP address, you can set a port forwarding rule on
your firewall that forwards incoming packets on port 80 and 443 on the firewall to the web server. With
this firewall rule, users on the internet can access the web server using the IP or host name of the
firewall.

14.6.8.1. Forwarding incoming packets to a different local port

You can use nftables to forward packets. For example, you can forward incoming IPv4 packets on port

321
Red Hat Enterprise Linux 8 System Design Guide

You can use nftables to forward packets. For example, you can forward incoming IPv4 packets on port
8022 to port 22 on the local system.

Procedure

1. Create a table named nat with the ip address family:

# nft add table ip nat

2. Add the prerouting and postrouting chains to the table:

# nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }

NOTE

Pass the -- option to the nft command to prevent the shell from interpreting the
negative priority value as an option of the nft command.

3. Add a rule to the prerouting chain that redirects incoming packets on port 8022 to the local
port 22:

# nft add rule ip nat prerouting tcp dport 8022 redirect to :22

14.6.8.2. Forwarding incoming packets on a specific local port to a different host

You can use a destination network address translation (DNAT) rule to forward incoming packets on a
local port to a remote host. This enables users on the internet to access a service that runs on a host
with a private IP address.

For example, you can forward incoming IPv4 packets on the local port 443 to the same port number on
the remote system with the 192.0.2.1 IP address.

Prerequisites

You are logged in as the root user on the system that should forward the packets.

Procedure

1. Create a table named nat with the ip address family:

# nft add table ip nat

2. Add the prerouting and postrouting chains to the table:

# nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
# nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }

NOTE

Pass the -- option to the nft command to prevent the shell from interpreting the
negative priority value as an option of the nft command.

322
CHAPTER 14. SECURING NETWORKS

3. Add a rule to the prerouting chain that redirects incoming packets on port 443 to the same port
on 192.0.2.1:

# nft add rule ip nat prerouting tcp dport 443 dnat to 192.0.2.1

4. Add a rule to the postrouting chain to masquerade outgoing traffic:

# nft add rule ip nat postrouting daddr 192.0.2.1 masquerade

5. Enable packet forwarding:

# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf


# sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf

14.6.9. Using nftables to limit the amount of connections


You can use nftables to limit the number of connections or to block IP addresses that attempt to
establish a given amount of connections to prevent them from using too many system resources.

14.6.9.1. Limiting the number of connections by using nftables

By using the ct count parameter of the nft utility, you can limit the number of simultaneous connections
per IP address. For example, you can use this feature to configure that each source IP address can only
establish two parallel SSH connections to a host.

Procedure

1. Create the filter table with the inet address family:

# nft add table inet filter

2. Add the input chain to the inet filter table:

# nft add chain inet filter input { type filter hook input priority 0 \; }

3. Create a dynamic set for IPv4 addresses:

# nft add set inet filter limit-ssh { type ipv4_addr\; flags dynamic \;}

4. Add a rule to the input chain that allows only two simultaneous incoming connections to the
SSH port (22) from an IPv4 address and rejects all further connections from the same IP:

# nft add rule inet filter input tcp dport ssh ct state new add @limit-ssh { ip saddr ct
count over 2 } counter reject

Verification

1. Establish more than two new simultaneous SSH connections from the same IP address to the
host. Nftables refuses connections to the SSH port if two connections are already established.

2. Display the limit-ssh meter:

323
Red Hat Enterprise Linux 8 System Design Guide

# nft list set inet filter limit-ssh


table inet filter {
set limit-ssh {
type ipv4_addr
size 65535
flags dynamic
elements = { 192.0.2.1 ct count over 2 , 192.0.2.2 ct count over 2 }
}
}

The elements entry displays addresses that currently match the rule. In this example, elements
lists IP addresses that have active connections to the SSH port. Note that the output does not
display the number of active connections or if connections were rejected.

14.6.9.2. Blocking IP addresses that attempt more than ten new incoming TCP connections
within one minute

You can temporarily block hosts that are establishing more than ten IPv4 TCP connections within one
minute.

Procedure

1. Create the filter table with the ip address family:

# nft add table ip filter

2. Add the input chain to the filter table:

# nft add chain ip filter input { type filter hook input priority 0 \; }

3. Add a rule that drops all packets from source addresses that attempt to establish more than ten
TCP connections within one minute:

# nft add rule ip filter input ip protocol tcp ct state new, untracked meter ratemeter { ip
saddr timeout 5m limit rate over 10/minute } drop

The timeout 5m parameter defines that nftables automatically removes entries after five
minutes to prevent that the meter fills up with stale entries.

Verification

To display the meter’s content, enter:

# nft list meter ip filter ratemeter


table ip filter {
meter ratemeter {
type ipv4_addr
size 65535
flags dynamic,timeout
elements = { 192.0.2.1 limit rate over 10/minute timeout 5m expires 4m58s224ms }
}
}

324
CHAPTER 14. SECURING NETWORKS

14.6.10. Debugging nftables rules


The nftables framework provides different options for administrators to debug rules and if packets
match them.

14.6.10.1. Creating a rule with a counter

To identify if a rule is matched, you can use a counter.

For more information about a procedure that adds a counter to an existing rule, see Adding a
counter to an existing rule in Configuring and managing networking

Prerequisites

The chain to which you want to add the rule exists.

Procedure

1. Add a new rule with the counter parameter to the chain. The following example adds a rule with
a counter that allows TCP traffic on port 22 and counts the packets and traffic that match this
rule:

# nft add rule inet example_table example_chain tcp dport 22 counter accept

2. To display the counter values:

# nft list ruleset


table inet example_table {
chain example_chain {
type filter hook input priority filter; policy accept;
tcp dport ssh counter packets 6872 bytes 105448565 accept
}
}

14.6.10.2. Adding a counter to an existing rule

To identify if a rule is matched, you can use a counter.

For more information about a procedure that adds a new rule with a counter, see Creating a rule
with the counter in Configuring and managing networking

Prerequisites

The rule to which you want to add the counter exists.

Procedure

1. Display the rules in the chain including their handles:

# nft --handle list chain inet example_table example_chain


table inet example_table {
chain example_chain { # handle 1
type filter hook input priority filter; policy accept;

325
Red Hat Enterprise Linux 8 System Design Guide

tcp dport ssh accept # handle 4


}
}

2. Add the counter by replacing the rule but with the counter parameter. The following example
replaces the rule displayed in the previous step and adds a counter:

# nft replace rule inet example_table example_chain handle 4 tcp dport 22 counter
accept

3. To display the counter values:

# nft list ruleset


table inet example_table {
chain example_chain {
type filter hook input priority filter; policy accept;
tcp dport ssh counter packets 6872 bytes 105448565 accept
}
}

14.6.10.3. Monitoring packets that match an existing rule

The tracing feature in nftables in combination with the nft monitor command enables administrators to
display packets that match a rule. You can enable tracing for a rule an use it to monitoring packets that
match this rule.

Prerequisites

The rule to which you want to add the counter exists.

Procedure

1. Display the rules in the chain including their handles:

# nft --handle list chain inet example_table example_chain


table inet example_table {
chain example_chain { # handle 1
type filter hook input priority filter; policy accept;
tcp dport ssh accept # handle 4
}
}

2. Add the tracing feature by replacing the rule but with the meta nftrace set 1 parameters. The
following example replaces the rule displayed in the previous step and enables tracing:

# nft replace rule inet example_table example_chain handle 4 tcp dport 22 meta nftrace
set 1 accept

3. Use the nft monitor command to display the tracing. The following example filters the output of
the command to display only entries that contain inet example_table example_chain:

# nft monitor | grep "inet example_table example_chain"


trace id 3c5eb15e inet example_table example_chain packet: iif "enp1s0" ether saddr

326
CHAPTER 14. SECURING NETWORKS

52:54:00:17:ff:e4 ether daddr 52:54:00:72:2f:6e ip saddr 192.0.2.1 ip daddr 192.0.2.2 ip dscp


cs0 ip ecn not-ect ip ttl 64 ip id 49710 ip protocol tcp ip length 60 tcp sport 56728 tcp dport
ssh tcp flags == syn tcp window 64240
trace id 3c5eb15e inet example_table example_chain rule tcp dport ssh nftrace set 1 accept
(verdict accept)
...


WARNING

Depending on the number of rules with tracing enabled and the amount of
matching traffic, the nft monitor command can display a lot of output. Use
grep or other utilities to filter the output.

14.6.11. Backing up and restoring the nftables rule set


You can backup nftables rules to a file and later restoring them. Also, administrators can use a file with
the rules to, for example, transfer the rules to a different server.

14.6.11.1. Backing up the nftables rule set to a file

You can use the nft utility to back up the nftables rule set to a file.

Procedure

To backup nftables rules:

In a format produced by nft list ruleset format:

# nft list ruleset > file.nft

In JSON format:

# nft -j list ruleset > file.json

14.6.11.2. Restoring the nftables rule set from a file

You can restore the nftables rule set from a file.

Procedure

To restore nftables rules:

If the file to restore is in the format produced by nft list ruleset or contains nft commands
directly:

# nft -f file.nft

If the file to restore is in JSON format:

327
Red Hat Enterprise Linux 8 System Design Guide

# nft -j -f file.json

14.6.12. Additional resources


Using nftables in Red Hat Enterprise Linux 8

What comes after iptables? Its successor, of course: nftables

Firewalld: The Future is nftables

328
PART IV. DESIGN OF HARD DISK

PART IV. DESIGN OF HARD DISK

329
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 15. OVERVIEW OF AVAILABLE FILE SYSTEMS


Choosing the file system that is appropriate for your application is an important decision due to the
large number of options available and the trade-offs involved.

The following sections describe the file systems that Red Hat Enterprise Linux 8 includes by default, and
recommendations on the most suitable file system for your application.

15.1. TYPES OF FILE SYSTEMS


Red Hat Enterprise Linux 8 supports a variety of file systems (FS). Different types of file systems solve
different kinds of problems, and their usage is application specific. At the most general level, available
file systems can be grouped into the following major types:

Table 15.1. Types of file systems and their use cases

Type File system Attributes and use cases

Disk or local FS XFS XFS is the default file system in RHEL. Red Hat
recommends deploying XFS as your local file system
unless there are specific reasons to do otherwise: for
example, compatibility or corner cases around
performance.

ext4 ext4 has the benefit of familiarity in Linux, having


evolved from the older ext2 and ext3 file systems. In
many cases, it rivals XFS on performance. Support
limits for ext4 filesystem and file sizes are lower than
those on XFS.

Network or client-and- NFS Use NFS to share files between multiple systems on
server FS the same network.

SMB Use SMB for file sharing with Microsoft Windows


systems.

Shared storage or GFS2 GFS2 provides shared write access to members of a


shared disk FS compute cluster. The emphasis is on stability and
reliability, with the functional experience of a local
file system as possible. SAS Grid, Tibco MQ, IBM
Websphere MQ, and Red Hat Active MQ have been
deployed successfully on GFS2.

Volume-managing FS Stratis (Technology Stratis is a volume manager built on a combination of


Preview) XFS and LVM. The purpose of Stratis is to emulate
capabilities offered by volume-managing file systems
like Btrfs and ZFS. It is possible to build this stack
manually, but Stratis reduces configuration
complexity, implements best practices, and
consolidates error information.

330
CHAPTER 15. OVERVIEW OF AVAILABLE FILE SYSTEMS

15.2. LOCAL FILE SYSTEMS


Local file systems are file systems that run on a single, local server and are directly attached to storage.

For example, a local file system is the only choice for internal SATA or SAS disks, and is used when your
server has internal hardware RAID controllers with local drives. Local file systems are also the most
common file systems used on SAN attached storage when the device exported on the SAN is not
shared.

All local file systems are POSIX-compliant and are fully compatible with all supported Red Hat
Enterprise Linux releases. POSIX-compliant file systems provide support for a well-defined set of
system calls, such as read(), write(), and seek().

When considering a file system choice, choose a file system based on how large the file system needs to
be, what unique features it must have, and how it performs under your workload.

Available local file systems

XFS

ext4

15.3. THE XFS FILE SYSTEM


XFS is a highly scalable, high-performance, robust, and mature 64-bit journaling file system that
supports very large files and file systems on a single host. It is the default file system in Red Hat
Enterprise Linux 8. XFS was originally developed in the early 1990s by SGI and has a long history of
running on extremely large servers and storage arrays.

The features of XFS include:

Reliability

Metadata journaling, which ensures file system integrity after a system crash by keeping a
record of file system operations that can be replayed when the system is restarted and the
file system remounted

Extensive run-time metadata consistency checking

Scalable and fast repair utilities

Quota journaling. This avoids the need for lengthy quota consistency checks after a crash.

Scalability and performance

Supported file system size up to 1024 TiB

Ability to support a large number of concurrent operations

B-tree indexing for scalability of free space management

Sophisticated metadata read-ahead algorithms

Optimizations for streaming video workloads

Allocation schemes

331
Red Hat Enterprise Linux 8 System Design Guide

Extent-based allocation

Stripe-aware allocation policies

Delayed allocation

Space pre-allocation

Dynamically allocated inodes

Other features

Reflink-based file copies

Tightly integrated backup and restore utilities

Online defragmentation

Online file system growing

Comprehensive diagnostics capabilities

Extended attributes (xattr). This allows the system to associate several additional
name/value pairs per file.

Project or directory quotas. This allows quota restrictions over a directory tree.

Subsecond timestamps

Performance characteristics
XFS has a high performance on large systems with enterprise workloads. A large system is one with a
relatively high number of CPUs, multiple HBAs, and connections to external disk arrays. XFS also
performs well on smaller systems that have a multi-threaded, parallel I/O workload.

XFS has a relatively low performance for single threaded, metadata-intensive workloads: for example, a
workload that creates or deletes large numbers of small files in a single thread.

15.4. THE EXT4 FILE SYSTEM


The ext4 file system is the fourth generation of the ext file system family. It was the default file system
in Red Hat Enterprise Linux 6.

The ext4 driver can read and write to ext2 and ext3 file systems, but the ext4 file system format is not
compatible with ext2 and ext3 drivers.

ext4 adds several new and improved features, such as:

Supported file system size up to 50 TiB

Extent-based metadata

Delayed allocation

Journal checksumming

332
CHAPTER 15. OVERVIEW OF AVAILABLE FILE SYSTEMS

Large storage support

The extent-based metadata and the delayed allocation features provide a more compact and efficient
way to track utilized space in a file system. These features improve file system performance and reduce
the space consumed by metadata. Delayed allocation allows the file system to postpone selection of the
permanent location for newly written user data until the data is flushed to disk. This enables higher
performance since it can allow for larger, more contiguous allocations, allowing the file system to make
decisions with much better information.

File system repair time using the fsck utility in ext4 is much faster than in ext2 and ext3. Some file
system repairs have demonstrated up to a six-fold increase in performance.

15.5. COMPARISON OF XFS AND EXT4


XFS is the default file system in RHEL. This section compares the usage and features of XFS and ext4.

Metadata error behavior


In ext4, you can configure the behavior when the file system encounters metadata errors. The
default behavior is to simply continue the operation. When XFS encounters an unrecoverable
metadata error, it shuts down the file system and returns the EFSCORRUPTED error.
Quotas
In ext4, you can enable quotas when creating the file system or later on an existing file system. You
can then configure the quota enforcement using a mount option.
XFS quotas are not a remountable option. You must activate quotas on the initial mount.

Running the quotacheck command on an XFS file system has no effect. The first time you turn on
quota accounting, XFS checks quotas automatically.

File system resize


XFS has no utility to reduce the size of a file system. You can only increase the size of an XFS file
system. In comparison, ext4 supports both extending and reducing the size of a file system.
Inode numbers
The ext4 file system does not support more than 232 inodes.
XFS supports dynamic inode allocation. The amount of space inodes can consume on an XFS
filesystem is calculated as a percentage of the total filesystem space. To prevent the system from
running out of inodes, an administrator can tune this percentage after the filesystem has been
created, given there is free space left on the file system.

Certain applications cannot properly handle inode numbers larger than 232 on an XFS file system.
These applications might cause the failure of 32-bit stat calls with the EOVERFLOW return value.
Inode number exceed 232 under the following conditions:

The file system is larger than 1 TiB with 256-byte inodes.

The file system is larger than 2 TiB with 512-byte inodes.

If your application fails with large inode numbers, mount the XFS file system with the -o inode32
option to enforce inode numbers below 232. Note that using inode32 does not affect inodes that are
already allocated with 64-bit numbers.

IMPORTANT
333
Red Hat Enterprise Linux 8 System Design Guide

IMPORTANT

Do not use the inode32 option unless a specific environment requires it. The inode32
option changes allocation behavior. As a consequence, the ENOSPC error might
occur if no space is available to allocate inodes in the lower disk blocks.

15.6. CHOOSING A LOCAL FILE SYSTEM


To choose a file system that meets your application requirements, you must understand the target
system on which you will deploy the file system. In general, use XFS unless you have a specific use case
for ext4.

XFS
For large-scale deployments, use XFS, particularly when handling large files (hundreds of
megabytes) and high I/O concurrency. XFS performs optimally in environments with high bandwidth
(greater than 200MB/s) and more than 1000 IOPS. However, it consumes more CPU resources for
metadata operations compared to ext4 and does not support file system shrinking.
ext4
For smaller systems or environments with limited I/O bandwidth, ext4 might be a better fit. It
performs better in single-threaded, lower I/O workloads and environments with lower throughput
requirements. ext4 also supports offline shrinking, which can be beneficial if resizing the file system is
a requirement.

Benchmark your application’s performance on your target server and storage system to ensure the
selected file system meets your performance and scalability requirements.

Table 15.2. Summary of local file system recommendations

Scenario Recommended file system

No special use case XFS

Large server XFS

Large storage devices XFS

Large files XFS

Multi-threaded I/O XFS

Single-threaded I/O ext4

Limited I/O capability (under 1000 IOPS) ext4

Limited bandwidth (under 200MB/s) ext4

CPU-bound workload ext4

Support for offline shrinking ext4

334
CHAPTER 15. OVERVIEW OF AVAILABLE FILE SYSTEMS

15.7. NETWORK FILE SYSTEMS


Network file systems, also referred to as client/server file systems, enable client systems to access files
that are stored on a shared server. This makes it possible for multiple users on multiple systems to share
files and storage resources.

Such file systems are built from one or more servers that export a set of file systems to one or more
clients. The client nodes do not have access to the underlying block storage, but rather interact with the
storage using a protocol that allows for better access control.

Available network file systems

The most common client/server file system for RHEL customers is the NFS file system.
RHEL provides both an NFS server component to export a local file system over the network
and an NFS client to import these file systems.

RHEL also includes a CIFS client that supports the popular Microsoft SMB file servers for
Windows interoperability. The userspace Samba server provides Windows clients with a
Microsoft SMB service from a RHEL server.

15.8. SHARED STORAGE FILE SYSTEMS


Shared storage file systems, sometimes referred to as cluster file systems, give each server in the
cluster direct access to a shared block device over a local storage area network (SAN).

Comparison with network file systems


Like client/server file systems, shared storage file systems work on a set of servers that are all
members of a cluster. Unlike NFS, however, no single server provides access to data or metadata to
other members: each member of the cluster has direct access to the same storage device (the
shared storage ), and all cluster member nodes access the same set of files.
Concurrency
Cache coherency is key in a clustered file system to ensure data consistency and integrity. There
must be a single version of all files in a cluster visible to all nodes within a cluster. The file system
must prevent members of the cluster from updating the same storage block at the same time and
causing data corruption. In order to do that, shared storage file systems use a cluster wide-locking
mechanism to arbitrate access to the storage as a concurrency control mechanism. For example,
before creating a new file or writing to a file that is opened on multiple servers, the file system
component on the server must obtain the correct lock.
The requirement of cluster file systems is to provide a highly available service like an Apache web
server. Any member of the cluster will see a fully coherent view of the data stored in their shared disk
file system, and all updates will be arbitrated correctly by the locking mechanisms.

Performance characteristics
Shared disk file systems do not always perform as well as local file systems running on the same
system due to the computational cost of the locking overhead. Shared disk file systems perform well
with workloads where each node writes almost exclusively to a particular set of files that are not
shared with other nodes or where a set of files is shared in an almost exclusively read-only manner
across a set of nodes. This results in a minimum of cross-node cache invalidation and can maximize
performance.
Setting up a shared disk file system is complex, and tuning an application to perform well on a shared
disk file system can be challenging.

Available shared storage file systems

335
Red Hat Enterprise Linux 8 System Design Guide

Red Hat Enterprise Linux provides the GFS2 file system. GFS2 comes tightly integrated with
the Red Hat Enterprise Linux High Availability Add-On and the Resilient Storage Add-On.

Red Hat Enterprise Linux supports GFS2 on clusters that range in size from 2 to 16 nodes.

15.9. CHOOSING BETWEEN NETWORK AND SHARED STORAGE FILE


SYSTEMS
When choosing between network and shared storage file systems, consider the following points:

NFS-based network file systems are an extremely common and popular choice for
environments that provide NFS servers.

Network file systems can be deployed using very high-performance networking technologies
like Infiniband or 10 Gigabit Ethernet. This means that you should not turn to shared storage file
systems just to get raw bandwidth to your storage. If the speed of access is of prime
importance, then use NFS to export a local file system like XFS.

Shared storage file systems are not easy to set up or to maintain, so you should deploy them
only when you cannot provide your required availability with either local or network file systems.

A shared storage file system in a clustered environment helps reduce downtime by eliminating
the steps needed for unmounting and mounting that need to be done during a typical fail-over
scenario involving the relocation of a high-availability service.

Red Hat recommends that you use network file systems unless you have a specific use case for shared
storage file systems. Use shared storage file systems primarily for deployments that need to provide
high-availability services with minimum downtime and have stringent service-level requirements.

15.10. VOLUME-MANAGING FILE SYSTEMS


Volume-managing file systems integrate the entire storage stack for the purposes of simplicity and in-
stack optimization.

Available volume-managing file systems

Red Hat Enterprise Linux 8 provides the Stratis volume manager as a Technology Preview.
Stratis uses XFS for the file system layer and integrates it with LVM, Device Mapper, and
other components.

Stratis was first released in Red Hat Enterprise Linux 8.0. It is conceived to fill the gap created when
Red Hat deprecated Btrfs. Stratis 1.0 is an intuitive, command line-based volume manager that can
perform significant storage management operations while hiding the complexity from the user:

Volume management

Pool creation

Thin storage pools

Snapshots

Automated read cache

Stratis offers powerful features, but currently lacks certain capabilities of other offerings that it

336
CHAPTER 15. OVERVIEW OF AVAILABLE FILE SYSTEMS

Stratis offers powerful features, but currently lacks certain capabilities of other offerings that it
might be compared to, such as Btrfs or ZFS. Most notably, it does not support CRCs with self healing.

337
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 16. MOUNTING AN SMB SHARE


The Server Message Block (SMB) protocol implements an application-layer network protocol used to
access resources on a server, such as file shares and shared printers.

NOTE

In the context of SMB, you can find mentions about the Common Internet File System
(CIFS) protocol, which is a dialect of SMB. Both the SMB and CIFS protocol are
supported, and the kernel module and utilities involved in mounting SMB and CIFS shares
both use the name cifs.

The cifs-utils package provides utilities to:

Mount SMB and CIFS shares

Manage NT LAN Manager (NTLM) credentials in the kernel’s keyring

Set and display Access Control Lists (ACL) in a security descriptor on SMB and CIFS shares

16.1. SUPPORTED SMB PROTOCOL VERSIONS


The cifs.ko kernel module supports the following SMB protocol versions:

SMB 1


WARNING

The SMB1 protocol is deprecated due to known security issues, and is only
safe to use on a private network. The main reason that SMB1 is still
provided as a supported option is that currently it is the only SMB protocol
version that supports UNIX extensions. If you do not need to use UNIX
extensions on SMB, Red Hat strongly recommends using SMB2 or later.

SMB 2.0

SMB 2.1

SMB 3.0

SMB 3.1.1

NOTE

Depending on the protocol version, not all SMB features are implemented.

16.2. UNIX EXTENSIONS SUPPORT

Samba uses the CAP_UNIX capability bit in the SMB protocol to provide the UNIX extensions feature.
338
CHAPTER 16. MOUNTING AN SMB SHARE

Samba uses the CAP_UNIX capability bit in the SMB protocol to provide the UNIX extensions feature.
These extensions are also supported by the cifs.ko kernel module. However, both Samba and the kernel
module support UNIX extensions only in the SMB 1 protocol.

Prerequisites

The cifs-utils package is installed.

Procedure

1. Set the server min protocol parameter in the [global] section in the /etc/samba/smb.conf file
to NT1.

2. Mount the share using the SMB 1 protocol by providing the -o vers=1.0 option to the mount
command. For example:

# mount -t cifs -o vers=1.0,username=<user_name> //<server_name>/<share_name>


/mnt/

By default, the kernel module uses SMB 2 or the highest later protocol version supported by the
server. Passing the -o vers=1.0 option to the mount command forces that the kernel module
uses the SMB 1 protocol that is required for using UNIX extensions.

Verification

Display the options of the mounted share:

# mount
...
//<server_name>/<share_name> on /mnt type cifs (...,unix,...)

If the unix entry is displayed in the list of mount options, UNIX extensions are enabled.

16.3. MANUALLY MOUNTING AN SMB SHARE


If you only require an SMB share to be temporary mounted, you can mount it manually using the mount
utility.

NOTE

Manually mounted shares are not mounted automatically again when you reboot the
system. To configure that Red Hat Enterprise Linux automatically mounts the share when
the system boots, see Mounting an SMB share automatically when the system boots .

Prerequisites

The cifs-utils package is installed.

Procedure

Use the mount utility with the -t cifs parameter to mount an SMB share:

# mount -t cifs -o username=<user_name> //<server_name>/<share_name> /mnt/


Password for <user_name>@//<server_name>/<share_name>: password

339
Red Hat Enterprise Linux 8 System Design Guide

In the -o parameter, you can specify options that are used to mount the share. For details, see
the OPTIONS section in the mount.cifs(8) man page and Frequently used mount options .

Example 16.1. Mounting a share using an encrypted SMB 3.0 connection

To mount the \\server\example\ share as the DOMAIN\Administrator user over an


encrypted SMB 3.0 connection into the /mnt/ directory:

# mount -t cifs -o username=DOMAIN\Administrator,seal,vers=3.0 //server/example


/mnt/
Password for DOMAIN\Administrator@//server_name/share_name: password

Verification

List the content of the mounted share:

# ls -l /mnt/
total 4
drwxr-xr-x. 2 root root 8748 Dec 4 16:27 test.txt
drwxr-xr-x. 17 root root 4096 Dec 4 07:43 Demo-Directory

16.4. MOUNTING AN SMB SHARE AUTOMATICALLY WHEN THE


SYSTEM BOOTS
If access to a mounted SMB share is permanently required on a server, mount the share automatically at
boot time.

Prerequisites

The cifs-utils package is installed.

Procedure

1. Add an entry for the share to the /etc/fstab file. For example:

//<server_name>/<share_name> /mnt cifs credentials=/root/smb.cred 0 0

IMPORTANT

To enable the system to mount a share automatically, you must store the user
name, password, and domain name in a credentials file. For details, see Creating
a credentials file to authenticate to an SMB share

In the fourth field of the row in the /etc/fstab, specify mount options, such as the path to the
credentials file. For details, see the OPTIONS section in the mount.cifs(8) man page and
Frequently used mount options .

Verification

Mount the share by specifying the mount point:

340
CHAPTER 16. MOUNTING AN SMB SHARE

# mount /mnt/

16.5. CREATING A CREDENTIALS FILE TO AUTHENTICATE TO AN SMB


SHARE
In certain situations, such as when mounting a share automatically at boot time, a share should be
mounted without entering the user name and password. To implement this, create a credentials file.

Prerequisites

The cifs-utils package is installed.

Procedure

1. Create a file, such as /root/smb.cred, and specify the user name, password, and domain name
that file:

username=user_name
password=password
domain=domain_name

2. Set the permissions to only allow the owner to access the file:

# chown user_name /root/smb.cred


# chmod 600 /root/smb.cred

You can now pass the credentials=file_name mount option to the mount utility or use it in the
/etc/fstab file to mount the share without being prompted for the user name and password.

16.6. PERFORMING A MULTI-USER SMB MOUNT


The credentials you provide to mount a share determine the access permissions on the mount point by
default. For example, if you use the DOMAIN\example user when you mount a share, all operations on
the share will be executed as this user, regardless which local user performs the operation.

However, in certain situations, the administrator wants to mount a share automatically when the system
boots, but users should perform actions on the share’s content using their own credentials. The
multiuser mount options lets you configure this scenario.

IMPORTANT

To use the multiuser mount option, you must additionally set the sec mount option to a
security type that supports providing credentials in a non-interactive way, such as krb5 or
the ntlmssp option with a credentials file. For details, see Accessing a share as a user .

The root user mounts the share using the multiuser option and an account that has minimal access to
the contents of the share. Regular users can then provide their user name and password to the current
session’s kernel keyring using the cifscreds utility. If the user accesses the content of the mounted
share, the kernel uses the credentials from the kernel keyring instead of the one initially used to mount
the share.

Using this feature consists of the following steps:

341
Red Hat Enterprise Linux 8 System Design Guide

Mount a share with the multiuser option.

Optionally, verify if the share was successfully mounted with the multiuser option.

Access the share as a user .

Prerequisites

The cifs-utils package is installed.

16.6.1. Mounting a share with the multiuser option


Before users can access the share with their own credentials, mount the share as the root user using an
account with limited permissions.

Procedure
To mount a share automatically with the multiuser option when the system boots:

1. Create the entry for the share in the /etc/fstab file. For example:

//server_name/share_name /mnt cifs multiuser,sec=ntlmssp,credentials=/root/smb.cred


00

2. Mount the share:

# mount /mnt/

If you do not want to mount the share automatically when the system boots, mount it manually by
passing -o multiuser,sec=security_type to the mount command. For details about mounting an SMB
share manually, see Manually mounting an SMB share .

16.6.2. Verifying if an SMB share is mounted with the multiuser option


To verify if a share is mounted with the multiuser option, display the mount options.

Procedure

# mount
...
//server_name/share_name on /mnt type cifs (sec=ntlmssp,multiuser,...)

If the multiuser entry is displayed in the list of mount options, the feature is enabled.

16.6.3. Accessing a share as a user


If an SMB share is mounted with the multiuser option, users can provide their credentials for the server
to the kernel’s keyring:

# cifscreds add -u SMB_user_name server_name


Password: password

When the user performs operations in the directory that contains the mounted SMB share, the server

342
CHAPTER 16. MOUNTING AN SMB SHARE

When the user performs operations in the directory that contains the mounted SMB share, the server
applies the file system permissions for this user, instead of the one initially used when the share was
mounted.

NOTE

Multiple users can perform operations using their own credentials on the mounted share
at the same time.

16.7. FREQUENTLY USED SMB MOUNT OPTIONS


When you mount an SMB share, the mount options determine:

How the connection will be established with the server. For example, which SMB protocol
version is used when connecting to the server.

How the share will be mounted into the local file system. For example, if the system overrides
the remote file and directory permissions to enable multiple local users to access the content
on the server.

To set multiple options in the fourth field of the /etc/fstab file or in the -o parameter of a mount
command, separate them with commas. For example, see Mounting a share with the multiuser option .

The following list gives frequently used mount options:

Option Description

credentials=file_name Sets the path to the credentials file. See Authenticating to an SMB share
using a credentials file.

dir_mode=mode Sets the directory mode if the server does not support CIFS UNIX extensions.

file_mode=mode Sets the file mode if the server does not support CIFS UNIX extensions.

password=password Sets the password used to authenticate to the SMB server. Alternatively,
specify a credentials file using the credentials option.

seal Enables encryption support for connections using SMB 3.0 or a later
protocol version. Therefore, use seal together with the vers mount option
set to 3.0 or later. See the example in Manually mounting an SMB share.

sec=security_mode Sets the security mode, such as ntlmsspi, to enable NTLMv2 password
hashing and enabled packet signing. For a list of supported values, see the
option’s description in the mount.cifs(8) man page on your system.

If the server does not support the ntlmv2 security mode, use sec=ntlmssp,
which is the default.

For security reasons, do not use the insecure ntlm security mode.

username=user_name Sets the user name used to authenticate to the SMB server. Alternatively,
specify a credentials file using the credentials option.

343
Red Hat Enterprise Linux 8 System Design Guide

Option Description

vers=SMB_protocol_version Sets the SMB protocol version used for the communication with the server.

For a complete list, see the OPTIONS section in the mount.cifs(8) man page on your system.

344
CHAPTER 17. OVERVIEW OF PERSISTENT NAMING ATTRIBUTES

CHAPTER 17. OVERVIEW OF PERSISTENT NAMING


ATTRIBUTES
As a system administrator, you need to refer to storage volumes using persistent naming attributes to
build storage setups that are reliable over multiple system boots.

17.1. DISADVANTAGES OF NON-PERSISTENT NAMING ATTRIBUTES


Red Hat Enterprise Linux provides a number of ways to identify storage devices. It is important to use
the correct option to identify each device when used in order to avoid inadvertently accessing the wrong
device, particularly when installing to or reformatting drives.

Traditionally, non-persistent names in the form of /dev/sd(major number)(minor number) are used on
Linux to refer to storage devices. The major and minor number range and associated sd names are
allocated for each device when it is detected. This means that the association between the major and
minor number range and associated sd names can change if the order of device detection changes.

Such a change in the ordering might occur in the following situations:

The parallelization of the system boot process detects storage devices in a different order with
each system boot.

A disk fails to power up or respond to the SCSI controller. This results in it not being detected by
the normal device probe. The disk is not accessible to the system and subsequent devices will
have their major and minor number range, including the associated sd names shifted down. For
example, if a disk normally referred to as sdb is not detected, a disk that is normally referred to
as sdc would instead appear as sdb.

A SCSI controller (host bus adapter, or HBA) fails to initialize, causing all disks connected to that
HBA to not be detected. Any disks connected to subsequently probed HBAs are assigned
different major and minor number ranges, and different associated sd names.

The order of driver initialization changes if different types of HBAs are present in the system.
This causes the disks connected to those HBAs to be detected in a different order. This might
also occur if HBAs are moved to different PCI slots on the system.

Disks connected to the system with Fibre Channel, iSCSI, or FCoE adapters might be
inaccessible at the time the storage devices are probed, due to a storage array or intervening
switch being powered off, for example. This might occur when a system reboots after a power
failure, if the storage array takes longer to come online than the system take to boot. Although
some Fibre Channel drivers support a mechanism to specify a persistent SCSI target ID to
WWPN mapping, this does not cause the major and minor number ranges, and the associated sd
names to be reserved; it only provides consistent SCSI target ID numbers.

These reasons make it undesirable to use the major and minor number range or the associated sd
names when referring to devices, such as in the /etc/fstab file. There is the possibility that the wrong
device will be mounted and data corruption might result.

Occasionally, however, it is still necessary to refer to the sd names even when another mechanism is
used, such as when errors are reported by a device. This is because the Linux kernel uses sd names (and
also SCSI host/channel/target/LUN tuples) in kernel messages regarding the device.

17.2. FILE SYSTEM AND DEVICE IDENTIFIERS

File system identifiers are tied to the file system itself, while device identifiers are linked to the physical

345
Red Hat Enterprise Linux 8 System Design Guide

File system identifiers are tied to the file system itself, while device identifiers are linked to the physical
block device. Understanding the difference is important for proper storage management.

File system identifiers


File system identifiers are tied to a particular file system created on a block device. The identifier is also
stored as part of the file system. If you copy the file system to a different device, it still carries the same
file system identifier. However, if you rewrite the device, such as by formatting it with the mkfs utility,
the device loses the attribute.

File system identifiers include:

Unique identifier (UUID)

Label

Device identifiers
Device identifiers are tied to a block device: for example, a disk or a partition. If you rewrite the device,
such as by formatting it with the mkfs utility, the device keeps the attribute, because it is not stored in
the file system.

Device identifiers include:

World Wide Identifier (WWID)

Partition UUID

Serial number

Recommendations

Some file systems, such as logical volumes, span multiple devices. Red Hat recommends
accessing these file systems using file system identifiers rather than device identifiers.

17.3. DEVICE NAMES MANAGED BY THE UDEV MECHANISM IN


/DEV/DISK/
The udev mechanism is used for all types of devices in Linux, and is not limited only for storage devices.
It provides different kinds of persistent naming attributes in the /dev/disk/ directory. In the case of
storage devices, Red Hat Enterprise Linux contains udev rules that create symbolic links in the
/dev/disk/ directory. This enables you to refer to storage devices by:

Their content

A unique identifier

Their serial number.

Although udev naming attributes are persistent, in that they do not change on their own across system
reboots, some are also configurable.

17.3.1. File system identifiers

The UUID attribute in /dev/disk/by-uuid/


Entries in this directory provide a symbolic name that refers to the storage device by a unique identifier
(UUID) in the content (that is, the data) stored on the device. For example:

346
CHAPTER 17. OVERVIEW OF PERSISTENT NAMING ATTRIBUTES

/dev/disk/by-uuid/3e6be9de-8139-11d1-9106-a43f08d823a6

You can use the UUID to refer to the device in the /etc/fstab file using the following syntax:

UUID=3e6be9de-8139-11d1-9106-a43f08d823a6

You can configure the UUID attribute when creating a file system, and you can also change it later on.

The Label attribute in /dev/disk/by-label/


Entries in this directory provide a symbolic name that refers to the storage device by a label in the
content (that is, the data) stored on the device.

For example:

/dev/disk/by-label/Boot

You can use the label to refer to the device in the /etc/fstab file using the following syntax:

LABEL=Boot

You can configure the Label attribute when creating a file system, and you can also change it later on.

17.3.2. Device identifiers


The WWID attribute in /dev/disk/by-id/
The World Wide Identifier (WWID) is a persistent, system-independent identifier that the SCSI
Standard requires from all SCSI devices. The WWID identifier is guaranteed to be unique for every
storage device, and independent of the path that is used to access the device. The identifier is a
property of the device but is not stored in the content (that is, the data) on the devices.

This identifier can be obtained by issuing a SCSI Inquiry to retrieve the Device Identification Vital
Product Data (page 0x83) or Unit Serial Number (page 0x80).

Red Hat Enterprise Linux automatically maintains the proper mapping from the WWID-based device
name to a current /dev/sd name on that system. Applications can use the /dev/disk/by-id/ name to
reference the data on the disk, even if the path to the device changes, and even when accessing the
device from different systems.

Example 17.1. WWID mappings

WWID symlink Non-persistent device Note

/dev/disk/by-id/scsi- /dev/sda A device with a page


3600508b400105e210000900000490000 0x83 identifier

/dev/disk/by-id/scsi- /dev/sdb A device with a page


SSEAGATE_ST373453LW_3HW1RHM6 0x80 identifier

/dev/disk/by-id/ata- /dev/sdc3 A disk partition


SAMSUNG_MZNLN256HMHQ-
000L7_S2WDNX0J336519-part3

347
Red Hat Enterprise Linux 8 System Design Guide

In addition to these persistent names provided by the system, you can also use udev rules to implement
persistent names of your own, mapped to the WWID of the storage.

The Partition UUID attribute in /dev/disk/by-partuuid


The Partition UUID (PARTUUID) attribute identifies partitions as defined by GPT partition table.

Example 17.2. Partition UUID mappings

PARTUUID symlink Non-persistent device

/dev/disk/by-partuuid/4cd1448a-01 /dev/sda1

/dev/disk/by-partuuid/4cd1448a-02 /dev/sda2

/dev/disk/by-partuuid/4cd1448a-03 /dev/sda3

The Path attribute in /dev/disk/by-path/


This attribute provides a symbolic name that refers to the storage device by the hardware path used to
access the device.

The Path attribute fails if any part of the hardware path (for example, the PCI ID, target port, or LUN
number) changes. The Path attribute is therefore unreliable. However, the Path attribute may be useful
in one of the following scenarios:

You need to identify a disk that you are planning to replace later.

You plan to install a storage service on a disk in a specific location.

17.4. THE WORLD WIDE IDENTIFIER WITH DM MULTIPATH


You can configure Device Mapper (DM) Multipath to map between the World Wide Identifier (WWID)
and non-persistent device names.

If there are multiple paths from a system to a device, DM Multipath uses the WWID to detect this. DM
Multipath then presents a single "pseudo-device" in the /dev/mapper/wwid directory, such as
/dev/mapper/3600508b400105df70000e00000ac0000.

The command multipath -l shows the mapping to the non-persistent identifiers:

Host:Channel:Target:LUN

/dev/sd name

major:minor number

Example 17.3. WWID mappings in a multipath configuration

An example output of the multipath -l command:

3600508b400105df70000e00000ac0000 dm-2 vendor,product

348
CHAPTER 17. OVERVIEW OF PERSISTENT NAMING ATTRIBUTES

[size=20G][features=1 queue_if_no_path][hwhandler=0][rw]
\_ round-robin 0 [prio=0][active]
\_ 5:0:1:1 sdc 8:32 [active][undef]
\_ 6:0:1:1 sdg 8:96 [active][undef]
\_ round-robin 0 [prio=0][enabled]
\_ 5:0:0:1 sdb 8:16 [active][undef]
\_ 6:0:0:1 sdf 8:80 [active][undef]

DM Multipath automatically maintains the proper mapping of each WWID-based device name to its
corresponding /dev/sd name on the system. These names are persistent across path changes, and they
are consistent when accessing the device from different systems.

When the user_friendly_names feature of DM Multipath is used, the WWID is mapped to a name of the
form /dev/mapper/mpathN. By default, this mapping is maintained in the file /etc/multipath/bindings.
These mpathN names are persistent as long as that file is maintained.

IMPORTANT

If you use user_friendly_names, then additional steps are required to obtain consistent
names in a cluster.

17.5. LIMITATIONS OF THE UDEV DEVICE NAMING CONVENTION


The following are some limitations of the udev naming convention:

It is possible that the device might not be accessible at the time the query is performed
because the udev mechanism might rely on the ability to query the storage device when the
udev rules are processed for a udev event. This is more likely to occur with Fibre Channel, iSCSI
or FCoE storage devices when the device is not located in the server chassis.

The kernel might send udev events at any time, causing the rules to be processed and possibly
causing the /dev/disk/by-*/ links to be removed if the device is not accessible.

There might be a delay between when the udev event is generated and when it is processed,
such as when a large number of devices are detected and the user-space udevd service takes
some amount of time to process the rules for each one. This might cause a delay between when
the kernel detects the device and when the /dev/disk/by-*/ names are available.

External programs such as blkid invoked by the rules might open the device for a brief period of
time, making the device inaccessible for other uses.

The device names managed by the udev mechanism in /dev/disk/ may change between major
releases, requiring you to update the links.

17.6. LISTING PERSISTENT NAMING ATTRIBUTES


You can find out the persistent naming attributes of non-persistent storage devices.

Procedure

To list the UUID and Label attributes, use the lsblk utility:

$ lsblk --fs storage-device

349
Red Hat Enterprise Linux 8 System Design Guide

For example:

Example 17.4. Viewing the UUID and Label of a file system

$ lsblk --fs /dev/sda1

NAME FSTYPE LABEL UUID MOUNTPOINT


sda1 xfs Boot afa5d5e3-9050-48c3-acc1-bb30095f3dc4 /boot

To list the PARTUUID attribute, use the lsblk utility with the --output +PARTUUID option:

$ lsblk --output +PARTUUID

For example:

Example 17.5. Viewing the PARTUUID attribute of a partition

$ lsblk --output +PARTUUID /dev/sda1

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT PARTUUID


sda1 8:1 0 512M 0 part /boot 4cd1448a-01

To list the WWID attribute, examine the targets of symbolic links in the /dev/disk/by-id/
directory. For example:
Example 17.6. Viewing the WWID of all storage devices on the system

$ file /dev/disk/by-id/*

/dev/disk/by-id/ata-QEMU_HARDDISK_QM00001
symbolic link to ../../sda
/dev/disk/by-id/ata-QEMU_HARDDISK_QM00001-part1
symbolic link to ../../sda1
/dev/disk/by-id/ata-QEMU_HARDDISK_QM00001-part2
symbolic link to ../../sda2
/dev/disk/by-id/dm-name-rhel_rhel8-root
symbolic link to ../../dm-0
/dev/disk/by-id/dm-name-rhel_rhel8-swap
symbolic link to ../../dm-1
/dev/disk/by-id/dm-uuid-LVM-
QIWtEHtXGobe5bewlIUDivKOz5ofkgFhP0RMFsNyySVihqEl2cWWbR7MjXJolD6g
symbolic link to ../../dm-1
/dev/disk/by-id/dm-uuid-LVM-
QIWtEHtXGobe5bewlIUDivKOz5ofkgFhXqH2M45hD2H9nAf2qfWSrlRLhzfMyOKd
symbolic link to ../../dm-0
/dev/disk/by-id/lvm-pv-uuid-atlr2Y-vuMo-ueoH-CpMG-4JuH-AhEF-wu4QQm
symbolic link to ../../sda2

17.7. MODIFYING PERSISTENT NAMING ATTRIBUTES

350
CHAPTER 17. OVERVIEW OF PERSISTENT NAMING ATTRIBUTES

You can change the UUID or Label persistent naming attribute of a file system.

NOTE

Changing udev attributes happens in the background and might take a long time. The
udevadm settle command waits until the change is fully registered, which ensures that
your next command will be able to use the new attribute correctly.

In the following commands:

Replace new-uuid with the UUID you want to set; for example, 1cdfbc07-1c90-4984-b5ec-
f61943f5ea50. You can generate a UUID using the uuidgen command.

Replace new-label with a label; for example, backup_data.

Prerequisites

If you are modifying the attributes of an XFS file system, unmount it first.

Procedure

To change the UUID or Label attributes of an XFS file system, use the xfs_admin utility:

# xfs_admin -U new-uuid -L new-label storage-device


# udevadm settle

To change the UUID or Label attributes of an ext4, ext3, or ext2 file system, use the tune2fs
utility:

# tune2fs -U new-uuid -L new-label storage-device


# udevadm settle

To change the UUID or Label attributes of a swap volume, use the swaplabel utility:

# swaplabel --uuid new-uuid --label new-label swap-device


# udevadm settle

351
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 18. GETTING STARTED WITH PARTITIONS


Use disk partitioning to divide a disk into one or more logical areas which enables work on each partition
separately. The hard disk stores information about the location and size of each disk partition in the
partition table. Using the table, each partition then appears as a logical disk to the operating system. You
can then read and write on those individual disks.

For an overview of the advantages and disadvantages to using partitions on block devices, see the
Red Hat Knowledgebase solution What are the advantages and disadvantages to using partitioning on
LUNs, either directly or with LVM in between?.

18.1. CREATING A PARTITION TABLE ON A DISK WITH PARTED


Use the parted utility to format a block device with a partition table more easily.


WARNING

Formatting a block device with a partition table deletes all data stored on the
device.

Procedure

1. Start the interactive parted shell:

# parted block-device

2. Determine if there already is a partition table on the device:

# (parted) print

If the device already contains partitions, they will be deleted in the following steps.

3. Create the new partition table:

# (parted) mklabel table-type

Replace table-type with with the intended partition table type:

msdos for MBR

gpt for GPT

Example 18.1. Creating a GUID Partition Table (GPT) table

To create a GPT table on the disk, use:

# (parted) mklabel gpt

352
CHAPTER 18. GETTING STARTED WITH PARTITIONS

The changes start applying after you enter this command.

4. View the partition table to confirm that it is created:

# (parted) print

5. Exit the parted shell:

# (parted) quit

Additional resources

parted(8) man page on your system

18.2. VIEWING THE PARTITION TABLE WITH PARTED


Display the partition table of a block device to see the partition layout and details about individual
partitions. You can view the partition table on a block device using the parted utility.

Procedure

1. Start the parted utility. For example, the following output lists the device /dev/sda:

# parted /dev/sda

2. View the partition table:

# (parted) print

Model: ATA SAMSUNG MZNLN256 (scsi)


Disk /dev/sda: 256GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number Start End Size Type File system Flags


1 1049kB 269MB 268MB primary xfs boot
2 269MB 34.6GB 34.4GB primary
3 34.6GB 45.4GB 10.7GB primary
4 45.4GB 256GB 211GB extended
5 45.4GB 256GB 211GB logical

3. Optional: Switch to the device you want to examine next:

# (parted) select block-device

For a detailed description of the print command output, see the following:

Model: ATA SAMSUNG MZNLN256 (scsi)


The disk type, manufacturer, model number, and interface.
Disk /dev/sda: 256GB
The file path to the block device and the storage capacity.

353
Red Hat Enterprise Linux 8 System Design Guide

Partition Table: msdos


The disk label type.
Number
The partition number. For example, the partition with minor number 1 corresponds to /dev/sda1.
Start and End
The location on the device where the partition starts and ends.
Type
Valid types are metadata, free, primary, extended, or logical.
File system
The file system type. If the File system field of a device shows no value, this means that its file
system type is unknown. The parted utility cannot recognize the file system on encrypted devices.
Flags
Lists the flags set for the partition. Available flags are boot, root, swap, hidden, raid, lvm, or lba.

Additional resources

parted(8) man page on your system

18.3. CREATING A PARTITION WITH PARTED


As a system administrator, you can create new partitions on a disk by using the parted utility.

NOTE

The required partitions are swap, /boot/, and / (root).

Prerequisites

A partition table on the disk.

If the partition you want to create is larger than 2TiB, format the disk with the GUID Partition
Table (GPT).

Procedure

1. Start the parted utility:

# parted block-device

2. View the current partition table to determine if there is enough free space:

# (parted) print

Resize the partition in case there is not enough free space.

From the partition table, determine:

The start and end points of the new partition.

On MBR, what partition type it should be.

354
CHAPTER 18. GETTING STARTED WITH PARTITIONS

3. Create the new partition:

# (parted) mkpart part-type name fs-type start end

Replace part-type with with primary, logical, or extended. This applies only to the MBR
partition table.

Replace name with an arbitrary partition name. This is required for GPT partition tables.

Replace fs-type with xfs, ext2, ext3, ext4, fat16, fat32, hfs, hfs+, linux-swap, ntfs, or
reiserfs. The fs-type parameter is optional. Note that the parted utility does not create the
file system on the partition.

Replace start and end with the sizes that determine the starting and ending points of the
partition, counting from the beginning of the disk. You can use size suffixes, such as 512MiB,
20GiB, or 1.5TiB. The default size is in megabytes.

Example 18.2. Creating a small primary partition

To create a primary partition from 1024MiB until 2048MiB on an MBR table, use:

# (parted) mkpart primary 1024MiB 2048MiB

The changes start applying after you enter the command.

4. View the partition table to confirm that the created partition is in the partition table with the
correct partition type, file system type, and size:

# (parted) print

5. Exit the parted shell:

# (parted) quit

6. Register the new device node:

# udevadm settle

7. Verify that the kernel recognizes the new partition:

# cat /proc/partitions

Additional resources

parted(8) man page on your system

Creating a partition table on a disk with parted .

Resizing a partition with parted

18.4. SETTING A PARTITION TYPE WITH FDISK

355
Red Hat Enterprise Linux 8 System Design Guide

You can set a partition type or flag, using the fdisk utility.

Prerequisites

A partition on the disk.

Procedure

1. Start the interactive fdisk shell:

# fdisk block-device

2. View the current partition table to determine the minor partition number:

Command (m for help): print

You can see the current partition type in the Type column and its corresponding type ID in the
Id column.

3. Enter the partition type command and select a partition using its minor number:

Command (m for help): type


Partition number (1,2,3 default 3): 2

4. Optional: View the list in hexadecimal codes:

Hex code (type L to list all codes): L

5. Set the partition type:

Hex code (type L to list all codes): 8e

6. Write your changes and exit the fdisk shell:

Command (m for help): write


The partition table has been altered.
Syncing disks.

7. Verify your changes:

# fdisk --list block-device

18.5. RESIZING A PARTITION WITH PARTED


Using the parted utility, extend a partition to use unused disk space, or shrink a partition to use its
capacity for different purposes.

Prerequisites

Back up the data before shrinking a partition.

If the partition you want to create is larger than 2TiB, format the disk with the GUID Partition
356
CHAPTER 18. GETTING STARTED WITH PARTITIONS

If the partition you want to create is larger than 2TiB, format the disk with the GUID Partition
Table (GPT).

If you want to shrink the partition, first shrink the file system so that it is not larger than the
resized partition.

NOTE

XFS does not support shrinking.

Procedure

1. Start the parted utility:

# parted block-device

2. View the current partition table:

# (parted) print

From the partition table, determine:

The minor number of the partition.

The location of the existing partition and its new ending point after resizing.

3. Resize the partition:

# (parted) resizepart 1 2GiB

Replace 1 with the minor number of the partition that you are resizing.

Replace 2 with the size that determines the new ending point of the resized partition,
counting from the beginning of the disk. You can use size suffixes, such as 512MiB, 20GiB,
or 1.5TiB. The default size is in megabytes.

4. View the partition table to confirm that the resized partition is in the partition table with the
correct size:

# (parted) print

5. Exit the parted shell:

# (parted) quit

6. Verify that the kernel registers the new partition:

# cat /proc/partitions

7. Optional: If you extended the partition, extend the file system on it as well.

Additional resources

parted(8) man page.

357
Red Hat Enterprise Linux 8 System Design Guide

18.6. REMOVING A PARTITION WITH PARTED


Using the parted utility, you can remove a disk partition to free up disk space.


WARNING

Removing a partition deletes all data stored on the partition.

Procedure

1. Start the interactive parted shell:

# parted block-device

Replace block-device with the path to the device where you want to remove a partition: for
example, /dev/sda.

2. View the current partition table to determine the minor number of the partition to remove:

(parted) print

3. Remove the partition:

(parted) rm minor-number

Replace minor-number with the minor number of the partition you want to remove.

The changes start applying as soon as you enter this command.

4. Verify that you have removed the partition from the partition table:

(parted) print

5. Exit the parted shell:

(parted) quit

6. Verify that the kernel registers that the partition is removed:

# cat /proc/partitions

7. Remove the partition from the /etc/fstab file, if it is present. Find the line that declares the
removed partition, and remove it from the file.

8. Regenerate mount units so that your system registers the new /etc/fstab configuration:

# systemctl daemon-reload

9. If you have deleted a swap partition or removed pieces of LVM, remove all references to the
358
CHAPTER 18. GETTING STARTED WITH PARTITIONS

9. If you have deleted a swap partition or removed pieces of LVM, remove all references to the
partition from the kernel command line:

a. List active kernel options and see if any option references the removed partition:

# grubby --info=ALL

b. Remove the kernel options that reference the removed partition:

# grubby --update-kernel=ALL --remove-args="option"

10. To register the changes in the early boot system, rebuild the initramfs file system:

# dracut --force --verbose

Additional resources

parted(8) man page on your system

359
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 19. GETTING STARTED WITH XFS


This is an overview of how to create and maintain XFS file systems.

19.1. THE XFS FILE SYSTEM


XFS is a highly scalable, high-performance, robust, and mature 64-bit journaling file system that
supports very large files and file systems on a single host. It is the default file system in Red Hat
Enterprise Linux 8. XFS was originally developed in the early 1990s by SGI and has a long history of
running on extremely large servers and storage arrays.

The features of XFS include:

Reliability

Metadata journaling, which ensures file system integrity after a system crash by keeping a
record of file system operations that can be replayed when the system is restarted and the
file system remounted

Extensive run-time metadata consistency checking

Scalable and fast repair utilities

Quota journaling. This avoids the need for lengthy quota consistency checks after a crash.

Scalability and performance

Supported file system size up to 1024 TiB

Ability to support a large number of concurrent operations

B-tree indexing for scalability of free space management

Sophisticated metadata read-ahead algorithms

Optimizations for streaming video workloads

Allocation schemes

Extent-based allocation

Stripe-aware allocation policies

Delayed allocation

Space pre-allocation

Dynamically allocated inodes

Other features

Reflink-based file copies

Tightly integrated backup and restore utilities

Online defragmentation

360
CHAPTER 19. GETTING STARTED WITH XFS

Online file system growing

Comprehensive diagnostics capabilities

Extended attributes (xattr). This allows the system to associate several additional
name/value pairs per file.

Project or directory quotas. This allows quota restrictions over a directory tree.

Subsecond timestamps

Performance characteristics
XFS has a high performance on large systems with enterprise workloads. A large system is one with a
relatively high number of CPUs, multiple HBAs, and connections to external disk arrays. XFS also
performs well on smaller systems that have a multi-threaded, parallel I/O workload.

XFS has a relatively low performance for single threaded, metadata-intensive workloads: for example, a
workload that creates or deletes large numbers of small files in a single thread.

19.2. COMPARISON OF TOOLS USED WITH EXT4 AND XFS


This section compares which tools to use to accomplish common tasks on the ext4 and XFS file
systems.

Task ext4 XFS

Create a file system mkfs.ext4 mkfs.xfs

File system check e2fsck xfs_repair

Resize a file system resize2fs xfs_growfs

Save an image of a file system e2image xfs_metadump and


xfs_mdrestore

Label or tune a file system tune2fs xfs_admin

Back up a file system dump and restore xfsdump and xfsrestore

Quota management quota xfs_quota

File mapping filefrag xfs_bmap

361
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 20. MOUNTING FILE SYSTEMS


As a system administrator, you can mount file systems on your system to access data on them.

20.1. THE LINUX MOUNT MECHANISM


These are the basic concepts of mounting file systems on Linux.

On Linux, UNIX, and similar operating systems, file systems on different partitions and removable
devices (CDs, DVDs, or USB flash drives for example) can be attached to a certain point (the mount
point) in the directory tree, and then detached again. While a file system is mounted on a directory, the
original content of the directory is not accessible.

Note that Linux does not prevent you from mounting a file system to a directory with a file system
already attached to it.

When mounting, you can identify the device by:

a universally unique identifier (UUID): for example, UUID=34795a28-ca6d-4fd8-a347-


73671d0c19cb

a volume label: for example, LABEL=home

a full path to a non-persistent block device: for example, /dev/sda3

When you mount a file system using the mount command without all required information, that is
without the device name, the target directory, or the file system type, the mount utility reads the
content of the /etc/fstab file to check if the given file system is listed there. The /etc/fstab file contains
a list of device names and the directories in which the selected file systems are set to be mounted as
well as the file system type and mount options. Therefore, when mounting a file system that is specified
in /etc/fstab, the following command syntax is sufficient:

Mounting by the mount point:

# mount directory

Mounting by the block device:

# mount device

Additional resources

mount(8) man page on your system

How to list persistent naming attributes such as the UUID .

20.2. LISTING CURRENTLY MOUNTED FILE SYSTEMS


List all currently mounted file systems on the command line by using the findmnt utility.

Procedure

To list all mounted file systems, use the findmnt utility:

362
CHAPTER 20. MOUNTING FILE SYSTEMS

$ findmnt

To limit the listed file systems only to a certain file system type, add the --types option:

$ findmnt --types fs-type

For example:

Example 20.1. Listing only XFS file systems

$ findmnt --types xfs

TARGET SOURCE FSTYPE OPTIONS


/ /dev/mapper/luks-5564ed00-6aac-4406-bfb4-c59bf5de48b5 xfs rw,relatime
├─/boot /dev/sda1 xfs rw,relatime
└─/home /dev/mapper/luks-9d185660-7537-414d-b727-d92ea036051e xfs rw,relatime

Additional resources

findmnt(8) man page on your system

20.3. MOUNTING A FILE SYSTEM WITH MOUNT


Mount a file system by using the mount utility.

Prerequisites

Verify that no file system is already mounted on your chosen mount point:

$ findmnt mount-point

Procedure

1. To attach a certain file system, use the mount utility:

# mount device mount-point

Example 20.2. Mounting an XFS file system

For example, to mount a local XFS file system identified by UUID:

# mount UUID=ea74bbec-536d-490c-b8d9-5b40bbd7545b /mnt/data

2. If mount cannot recognize the file system type automatically, specify it using the --types
option:

# mount --types type device mount-point

Example 20.3. Mounting an NFS file system

363
Red Hat Enterprise Linux 8 System Design Guide

For example, to mount a remote NFS file system:

# mount --types nfs4 host:/remote-export /mnt/nfs

Additional resources

mount(8) man page on your system

20.4. MOVING A MOUNT POINT


Change the mount point of a mounted file system to a different directory by using the mount utility.

Procedure

1. To change the directory in which a file system is mounted:

# mount --move old-directory new-directory

Example 20.4. Moving a home file system

For example, to move the file system mounted in the /mnt/userdirs/ directory to the /home/
mount point:

# mount --move /mnt/userdirs /home

2. Verify that the file system has been moved as expected:

$ findmnt
$ ls old-directory
$ ls new-directory

Additional resources

mount(8) man page on your system

20.5. UNMOUNTING A FILE SYSTEM WITH UMOUNT


Unmount a file system by using the umount utility.

Procedure

1. Try unmounting the file system using either of the following commands:

By mount point:

# umount mount-point

By device:

364
CHAPTER 20. MOUNTING FILE SYSTEMS

# umount device

If the command fails with an error similar to the following, it means that the file system is in use
because of a process is using resources on it:

umount: /run/media/user/FlashDrive: target is busy.

2. If the file system is in use, use the fuser utility to determine which processes are accessing it.
For example:

$ fuser --mount /run/media/user/FlashDrive

/run/media/user/FlashDrive: 18351

Afterwards, stop the processes using the file system and try unmounting it again.

20.6. MOUNTING AND UNMOUNTING FILE SYSTEMS IN THE WEB


CONSOLE
To be able to use partitions on RHEL systems, you need to mount a file system on the partition as a
device.

NOTE

You also can unmount a file system and the RHEL system will stop using it. Unmounting
the file system enables you to delete, remove, or re-format devices.

Prerequisites

The cockpit-storaged package is installed on your system.

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

If you want to unmount a file system, ensure that the system does not use any file, service, or
application stored in the partition.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click the Storage tab.

3. In the Storage table, select a volume from which you want to delete the partition.

4. In the GPT partitions section, click the menu button, ⋮ next to the partition whose file system
you want to mount or unmount.

5. Click Mount or Unmount.

20.7. COMMON MOUNT OPTIONS

365
Red Hat Enterprise Linux 8 System Design Guide

The following table lists the most common options of the mount utility. You can apply these mount
options using the following syntax:

# mount --options option1,option2,option3 device mount-point

Table 20.1. Common mount options

Option Description

async Enables asynchronous input and output operations on the file system.

auto Enables the file system to be mounted automatically using the mount -a
command.

defaults Provides an alias for the async,auto,dev,exec,nouser,rw,suid options.

exec Allows the execution of binary files on the particular file system.

loop Mounts an image as a loop device.

noauto Default behavior disables the automatic mount of the file system using the
mount -a command.

noexec Disallows the execution of binary files on the particular file system.

nouser Disallows an ordinary user (that is, other than root) to mount and unmount the file
system.

remount Remounts the file system in case it is already mounted.

ro Mounts the file system for reading only.

rw Mounts the file system for both reading and writing.

user Allows an ordinary user (that is, other than root) to mount and unmount the file
system.

366
CHAPTER 21. SHARING A MOUNT ON MULTIPLE MOUNT POINTS

CHAPTER 21. SHARING A MOUNT ON MULTIPLE MOUNT


POINTS
As a system administrator, you can duplicate mount points to make the file systems accessible from
multiple directories.

21.1. TYPES OF SHARED MOUNTS


There are multiple types of shared mounts that you can use. The difference between them is what
happens when you mount another file system under one of the shared mount points. The shared mounts
are implemented using the shared subtrees functionality.

The following mount types are available:

private
This type does not receive or forward any propagation events.
When you mount another file system under either the duplicate or the original mount point, it is not
reflected in the other.

shared
This type creates an exact replica of a given mount point.
When a mount point is marked as a shared mount, any mount within the original mount point is
reflected in it, and vice versa.

This is the default mount type of the root file system.

slave
This type creates a limited duplicate of a given mount point.
When a mount point is marked as a slave mount, any mount within the original mount point is
reflected in it, but no mount within a slave mount is reflected in its original.

unbindable
This type prevents the given mount point from being duplicated whatsoever.

Additional resources

The Shared subtrees article on Linux Weekly News

21.2. CREATING A PRIVATE MOUNT POINT DUPLICATE


Duplicate a mount point as a private mount. File systems that you later mount under the duplicate or the
original mount point are not reflected in the other.

Procedure

1. Create a virtual file system (VFS) node from the original mount point:

# mount --bind original-dir original-dir

2. Mark the original mount point as private:

367
Red Hat Enterprise Linux 8 System Design Guide

# mount --make-private original-dir

Alternatively, to change the mount type for the selected mount point and all mount points
under it, use the --make-rprivate option instead of --make-private.

3. Create the duplicate:

# mount --bind original-dir duplicate-dir

Example 21.1. Duplicating /media into /mnt as a private mount point

1. Create a VFS node from the /media directory:

# mount --bind /media /media

2. Mark the /media directory as private:

# mount --make-private /media

3. Create its duplicate in /mnt:

# mount --bind /media /mnt

4. It is now possible to verify that /media and /mnt share content but none of the mounts within
/media appear in /mnt. For example, if the CD-ROM drive contains non-empty media and
the /media/cdrom/ directory exists, use:

# mount /dev/cdrom /media/cdrom


# ls /media/cdrom
EFI GPL isolinux LiveOS
# ls /mnt/cdrom
#

5. It is also possible to verify that file systems mounted in the /mnt directory are not reflected
in /media. For example, if a non-empty USB flash drive that uses the /dev/sdc1 device is
plugged in and the /mnt/flashdisk/ directory is present, use:

# mount /dev/sdc1 /mnt/flashdisk


# ls /media/flashdisk
# ls /mnt/flashdisk
en-US publican.cfg

Additional resources

mount(8) man page on your system

21.3. CREATING A SHARED MOUNT POINT DUPLICATE


Duplicate a mount point as a shared mount. File systems that you later mount under the original
directory or the duplicate are always reflected in the other.

368
CHAPTER 21. SHARING A MOUNT ON MULTIPLE MOUNT POINTS

Procedure

1. Create a virtual file system (VFS) node from the original mount point:

# mount --bind original-dir original-dir

2. Mark the original mount point as shared:

# mount --make-shared original-dir

Alternatively, to change the mount type for the selected mount point and all mount points
under it, use the --make-rshared option instead of --make-shared.

3. Create the duplicate:

# mount --bind original-dir duplicate-dir

Example 21.2. Duplicating /media into /mnt as a shared mount point

To make the /media and /mnt directories share the same content:

1. Create a VFS node from the /media directory:

# mount --bind /media /media

2. Mark the /media directory as shared:

# mount --make-shared /media

3. Create its duplicate in /mnt:

# mount --bind /media /mnt

4. It is now possible to verify that a mount within /media also appears in /mnt. For example, if
the CD-ROM drive contains non-empty media and the /media/cdrom/ directory exists, use:

# mount /dev/cdrom /media/cdrom


# ls /media/cdrom
EFI GPL isolinux LiveOS
# ls /mnt/cdrom
EFI GPL isolinux LiveOS

5. Similarly, it is possible to verify that any file system mounted in the /mnt directory is
reflected in /media. For example, if a non-empty USB flash drive that uses the /dev/sdc1
device is plugged in and the /mnt/flashdisk/ directory is present, use:

# mount /dev/sdc1 /mnt/flashdisk


# ls /media/flashdisk
en-US publican.cfg
# ls /mnt/flashdisk
en-US publican.cfg

369
Red Hat Enterprise Linux 8 System Design Guide

Additional resources

mount(8) man page on your system

21.4. CREATING A SLAVE MOUNT POINT DUPLICATE


Duplicate a mount point as a slave mount type. File systems that you later mount under the original
mount point are reflected in the duplicate but not the other way around.

Procedure

1. Create a virtual file system (VFS) node from the original mount point:

# mount --bind original-dir original-dir

2. Mark the original mount point as shared:

# mount --make-shared original-dir

Alternatively, to change the mount type for the selected mount point and all mount points
under it, use the --make-rshared option instead of --make-shared.

3. Create the duplicate and mark it as the slave type:

# mount --bind original-dir duplicate-dir


# mount --make-slave duplicate-dir

Example 21.3. Duplicating /media into /mnt as a slave mount point

This example shows how to get the content of the /media directory to appear in /mnt as well, but
without any mounts in the /mnt directory to be reflected in /media.

1. Create a VFS node from the /media directory:

# mount --bind /media /media

2. Mark the /media directory as shared:

# mount --make-shared /media

3. Create its duplicate in /mnt and mark it as slave:

# mount --bind /media /mnt


# mount --make-slave /mnt

4. Verify that a mount within /media also appears in /mnt. For example, if the CD-ROM drive
contains non-empty media and the /media/cdrom/ directory exists, use:

# mount /dev/cdrom /media/cdrom


# ls /media/cdrom
EFI GPL isolinux LiveOS
# ls /mnt/cdrom
EFI GPL isolinux LiveOS

370
CHAPTER 21. SHARING A MOUNT ON MULTIPLE MOUNT POINTS

5. Also verify that file systems mounted in the /mnt directory are not reflected in /media. For
example, if a non-empty USB flash drive that uses the /dev/sdc1 device is plugged in and
the /mnt/flashdisk/ directory is present, use:

# mount /dev/sdc1 /mnt/flashdisk


# ls /media/flashdisk
# ls /mnt/flashdisk
en-US publican.cfg

Additional resources

mount(8) man page on your system

21.5. PREVENTING A MOUNT POINT FROM BEING DUPLICATED


Mark a mount point as unbindable so that it is not possible to duplicate it in another mount point.

Procedure

To change the type of a mount point to an unbindable mount, use:

# mount --bind mount-point mount-point


# mount --make-unbindable mount-point

Alternatively, to change the mount type for the selected mount point and all mount points
under it, use the --make-runbindable option instead of --make-unbindable.

Any subsequent attempt to make a duplicate of this mount fails with the following error:

# mount --bind mount-point duplicate-dir

mount: wrong fs type, bad option, bad superblock on mount-point,


missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so

Example 21.4. Preventing /media from being duplicated

To prevent the /media directory from being shared, use:

# mount --bind /media /media


# mount --make-unbindable /media

Additional resources

mount(8) man page on your system

371
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 22. PERSISTENTLY MOUNTING FILE SYSTEMS


As a system administrator, you can persistently mount file systems to configure non-removable storage.

22.1. THE /ETC/FSTAB FILE


Use the /etc/fstab configuration file to control persistent mount points of file systems. Each line in the
/etc/fstab file defines a mount point of a file system.

It includes six fields separated by white space:

1. The block device identified by a persistent attribute or a path in the /dev directory.

2. The directory where the device will be mounted.

3. The file system on the device.

4. Mount options for the file system, which includes the defaults option to mount the partition at
boot time with default options. The mount option field also recognizes the systemd mount unit
options in the x-systemd.option format.

5. Backup option for the dump utility.

6. Check order for the fsck utility.

NOTE

The systemd-fstab-generator dynamically converts the entries from the /etc/fstab file
to the systemd-mount units. The systemd auto mounts LVM volumes from /etc/fstab
during manual activation unless the systemd-mount unit is masked.

Example 22.1. The /boot file system in/etc/fstab

Block device Mount File system Options Backup Check


point

UUID=ea74bbec-536d- /boot xfs defaults 0 0


490c-b8d9-
5b40bbd7545b

The systemd service automatically generates mount units from entries in /etc/fstab.

Additional resources

fstab(5) and systemd.mount(5) man pages on your system

22.2. ADDING A FILE SYSTEM TO /ETC/FSTAB


Configure persistent mount point for a file system in the /etc/fstab configuration file.

372
CHAPTER 22. PERSISTENTLY MOUNTING FILE SYSTEMS

Procedure

1. Find out the UUID attribute of the file system:

$ lsblk --fs storage-device

For example:

Example 22.2. Viewing the UUID of a partition

$ lsblk --fs /dev/sda1

NAME FSTYPE LABEL UUID MOUNTPOINT


sda1 xfs Boot ea74bbec-536d-490c-b8d9-5b40bbd7545b /boot

2. If the mount point directory does not exist, create it:

# mkdir --parents mount-point

3. As root, edit the /etc/fstab file and add a line for the file system, identified by the UUID.
For example:

Example 22.3. The /boot mount point in /etc/fstab

UUID=ea74bbec-536d-490c-b8d9-5b40bbd7545b /boot xfs defaults 0 0

4. Regenerate mount units so that your system registers the new configuration:

# systemctl daemon-reload

5. Try mounting the file system to verify that the configuration works:

# mount mount-point

Additional resources

Overview of persistent naming attributes

373
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 23. MOUNTING FILE SYSTEMS ON DEMAND


As a system administrator, you can configure file systems, such as NFS, to mount automatically on
demand.

23.1. THE AUTOFS SERVICE


The autofs service can mount and unmount file systems automatically (on-demand), therefore saving
system resources. It can be used to mount file systems such as NFS, AFS, SMBFS, CIFS, and local file
systems.

One drawback of permanent mounting using the /etc/fstab configuration is that, regardless of how
infrequently a user accesses the mounted file system, the system must dedicate resources to keep the
mounted file system in place. This might affect system performance when, for example, the system is
maintaining NFS mounts to many systems at one time.

An alternative to /etc/fstab is to use the kernel-based autofs service. It consists of the following
components:

A kernel module that implements a file system, and

A user-space service that performs all of the other functions.

Additional resources

autofs(8) man page on your system

23.2. THE AUTOFS CONFIGURATION FILES


This section describes the usage and syntax of configuration files used by the autofs service.

The master map file


The autofs service uses /etc/auto.master (master map) as its default primary configuration file. This can
be changed to use another supported network source and name using the autofs configuration in the
/etc/autofs.conf configuration file in conjunction with the Name Service Switch (NSS) mechanism.

All on-demand mount points must be configured in the master map. Mount point, host name, exported
directory, and options can all be specified in a set of files (or other supported network sources) rather
than configuring them manually for each host.

The master map file lists mount points controlled by autofs, and their corresponding configuration files
or network sources known as automount maps. The format of the master map is as follows:

mount-point map-name options

The variables used in this format are:

mount-point
The autofs mount point; for example, /mnt/data.
map-file
The map source file, which contains a list of mount points and the file system location from which
those mount points should be mounted.

374
CHAPTER 23. MOUNTING FILE SYSTEMS ON DEMAND

options
If supplied, these apply to all entries in the given map, if they do not themselves have options
specified.

Example 23.1. The /etc/auto.master file

The following is a sample line from /etc/auto.master file:

/mnt/data /etc/auto.data

Map files
Map files configure the properties of individual on-demand mount points.

The automounter creates the directories if they do not exist. If the directories exist before the
automounter was started, the automounter will not remove them when it exits. If a timeout is specified,
the directory is automatically unmounted if the directory is not accessed for the timeout period.

The general format of maps is similar to the master map. However, the options field appears between
the mount point and the location instead of at the end of the entry as in the master map:

mount-point options location

The variables used in this format are:

mount-point
This refers to the autofs mount point. This can be a single directory name for an indirect mount or
the full path of the mount point for direct mounts. Each direct and indirect map entry key (mount-
point) can be followed by a space separated list of offset directories (subdirectory names each
beginning with /) making them what is known as a multi-mount entry.
options
When supplied, these options are appended to the master map entry options, if any, or used instead
of the master map options if the configuration entry append_options is set to no.
location
This refers to the file system location such as a local file system path (preceded with the Sun map
format escape character : for map names beginning with /), an NFS file system or other valid file
system location.

Example 23.2. A map file

The following is a sample from a map file; for example, /etc/auto.misc:

payroll -fstype=nfs4 personnel:/exports/payroll


sales -fstype=xfs :/dev/hda4

The first column in the map file indicates the autofs mount point: sales and payroll from the server
called personnel. The second column indicates the options for the autofs mount. The third column
indicates the source of the mount.

Following the given configuration, the autofs mount points will be /home/payroll and /home/sales.
The -fstype= option is often omitted and is not needed if the file system is NFS, including mounts for
NFSv4 if the system default is NFSv4 for NFS mounts.

375
Red Hat Enterprise Linux 8 System Design Guide

Using the given configuration, if a process requires access to an autofs unmounted directory such as
/home/payroll/2006/July.sxc, the autofs service automatically mounts the directory.

The amd map format


The autofs service recognizes map configuration in the amd format as well. This is useful if you want to
reuse existing automounter configuration written for the am-utils service, which has been removed from
Red Hat Enterprise Linux.

However, Red Hat recommends using the simpler autofs format described in the previous sections.

Additional resources

autofs(5), autofs.conf(5), and auto.master(5) man pages on your system

/usr/share/doc/autofs/README.amd-maps file

23.3. CONFIGURING AUTOFS MOUNT POINTS


Configure on-demand mount points by using the autofs service.

Prerequisites

Install the autofs package:

# yum install autofs

Start and enable the autofs service:

# systemctl enable --now autofs

Procedure

1. Create a map file for the on-demand mount point, located at /etc/auto.identifier. Replace
identifier with a name that identifies the mount point.

2. In the map file, enter the mount point, options, and location fields as described in The autofs
configuration files section.

3. Register the map file in the master map file, as described in The autofs configuration files
section.

4. Allow the service to re-read the configuration, so it can manage the newly configured autofs
mount:

# systemctl reload autofs.service

5. Try accessing content in the on-demand directory:

# ls automounted-directory

23.4. AUTOMOUNTING NFS SERVER USER HOME DIRECTORIES WITH


376
CHAPTER 23. MOUNTING FILE SYSTEMS ON DEMAND

23.4. AUTOMOUNTING NFS SERVER USER HOME DIRECTORIES WITH


AUTOFS SERVICE
Configure the autofs service to mount user home directories automatically.

Prerequisites

The autofs package is installed.

The autofs service is enabled and running.

Procedure

1. Specify the mount point and location of the map file by editing the /etc/auto.master file on a
server on which you need to mount user home directories. To do so, add the following line into
the /etc/auto.master file:

/home /etc/auto.home

2. Create a map file with the name of /etc/auto.home on a server on which you need to mount
user home directories, and edit the file with the following parameters:

* -fstype=nfs,rw,sync host.example.com:/home/&

You can skip fstype parameter, as it is nfs by default. For more information, see autofs(5) man
page on your system.

3. Reload the autofs service:

# systemctl reload autofs

23.5. OVERRIDING OR AUGMENTING AUTOFS SITE CONFIGURATION


FILES
It is sometimes useful to override site defaults for a specific mount point on a client system.

Example 23.3. Initial conditions

For example, consider the following conditions:

Automounter maps are stored in NIS and the /etc/nsswitch.conf file has the following
directive:

automount: files nis

The auto.master file contains:

+auto.master

The NIS auto.master map file contains:

/home auto.home

377
Red Hat Enterprise Linux 8 System Design Guide

The NIS auto.home map contains:

beth fileserver.example.com:/export/home/beth
joe fileserver.example.com:/export/home/joe
* fileserver.example.com:/export/home/&

The autofs configuration option BROWSE_MODE is set to yes:

BROWSE_MODE="yes"

The file map /etc/auto.home does not exist.

Procedure
This section describes the examples of mounting home directories from a different server and
augmenting auto.home with only selected entries.

Example 23.4. Mounting home directories from a different server

Given the preceding conditions, let’s assume that the client system needs to override the NIS map
auto.home and mount home directories from a different server.

In this case, the client needs to use the following /etc/auto.master map:

/home ​/etc/auto.home
+auto.master

The /etc/auto.home map contains the entry:

* host.example.com:/export/home/&

Because the automounter only processes the first occurrence of a mount point, the /home directory
contains the content of /etc/auto.home instead of the NIS auto.home map.

Example 23.5. Augmenting auto.home with only selected entries

Alternatively, to augment the site-wide auto.home map with just a few entries:

1. Create an /etc/auto.home file map, and in it put the new entries. At the end, include the NIS
auto.home map. Then the /etc/auto.home file map looks similar to:

mydir someserver:/export/mydir
+auto.home

2. With these NIS auto.home map conditions, listing the content of the /home directory
outputs:

$ ls /home

beth joe mydir

378
CHAPTER 23. MOUNTING FILE SYSTEMS ON DEMAND

This last example works as expected because autofs does not include the contents of a file map of
the same name as the one it is reading. As such, autofs moves on to the next map source in the
nsswitch configuration.

23.6. USING LDAP TO STORE AUTOMOUNTER MAPS


Configure autofs to store automounter maps in LDAP configuration rather than in autofs map files.

Prerequisites

LDAP client libraries must be installed on all systems configured to retrieve automounter maps
from LDAP. On Red Hat Enterprise Linux, the openldap package should be installed
automatically as a dependency of the autofs package.

Procedure

1. To configure LDAP access, modify the /etc/openldap/ldap.conf file. Ensure that the BASE,
URI, and schema options are set appropriately for your site.

2. The most recently established schema for storing automount maps in LDAP is described by the
rfc2307bis draft. To use this schema, set it in the /etc/autofs.conf configuration file by
removing the comment characters from the schema definition. For example:
Example 23.6. Setting autofs configuration

DEFAULT_MAP_OBJECT_CLASS="automountMap"
DEFAULT_ENTRY_OBJECT_CLASS="automount"
DEFAULT_MAP_ATTRIBUTE="automountMapName"
DEFAULT_ENTRY_ATTRIBUTE="automountKey"
DEFAULT_VALUE_ATTRIBUTE="automountInformation"

3. Ensure that all other schema entries are commented in the configuration. The automountKey
attribute of the rfc2307bis schema replaces the cn attribute of the rfc2307 schema. Following
is an example of an LDAP Data Interchange Format (LDIF) configuration:
Example 23.7. LDIF Configuration

# auto.master, example.com
dn: automountMapName=auto.master,dc=example,dc=com
objectClass: top
objectClass: automountMap
automountMapName: auto.master

# /home, auto.master, example.com


dn: automountMapName=auto.master,dc=example,dc=com
objectClass: automount
automountKey: /home
automountInformation: auto.home

# auto.home, example.com
dn: automountMapName=auto.home,dc=example,dc=com
objectClass: automountMap
automountMapName: auto.home

379
Red Hat Enterprise Linux 8 System Design Guide

# foo, auto.home, example.com


dn: automountKey=foo,automountMapName=auto.home,dc=example,dc=com
objectClass: automount
automountKey: foo
automountInformation: filer.example.com:/export/foo

# /, auto.home, example.com
dn: automountKey=/,automountMapName=auto.home,dc=example,dc=com
objectClass: automount
automountKey: /
automountInformation: filer.example.com:/export/&

Additional resources

The rfc2307bis draft

23.7. USING SYSTEMD.AUTOMOUNT TO MOUNT A FILE SYSTEM ON


DEMAND WITH /ETC/FSTAB
Mount a file system on demand using the automount systemd units when mount point is defined in
/etc/fstab. You have to add an automount unit for each mount and enable it.

Procedure

1. Add desired fstab entry as documented in Persistently mounting file systems . For example:

/dev/disk/by-id/da875760-edb9-4b82-99dc-5f4b1ff2e5f4 /mount/point xfs defaults 0 0

2. Add x-systemd.automount to the options field of entry created in the previous step.

3. Load newly created units so that your system registers the new configuration:

# systemctl daemon-reload

4. Start the automount unit:

# systemctl start mount-point.automount

Verification

1. Check that mount-point.automount is running:

# systemctl status mount-point.automount

2. Check that automounted directory has desired content:

# ls /mount/point

Additional resources

380
CHAPTER 23. MOUNTING FILE SYSTEMS ON DEMAND

systemd.automount(5) and systemd.mount(5) man pages on your system

Managing systemd

23.8. USING SYSTEMD.AUTOMOUNT TO MOUNT A FILE SYSTEM ON-


DEMAND WITH A MOUNT UNIT
Mount a file system on-demand using the automount systemd units when mount point is defined by a
mount unit. You have to add an automount unit for each mount and enable it.

Procedure

1. Create a mount unit. For example:

mount-point.mount
[Mount]
What=/dev/disk/by-uuid/f5755511-a714-44c1-a123-cfde0e4ac688
Where=/mount/point
Type=xfs

2. Create a unit file with the same name as the mount unit, but with extension .automount.

3. Open the file and create an [Automount] section. Set the Where= option to the mount path:

[Automount]
Where=/mount/point
[Install]
WantedBy=multi-user.target

4. Load newly created units so that your system registers the new configuration:

# systemctl daemon-reload

5. Enable and start the automount unit instead:

# systemctl enable --now mount-point.automount

Verification

1. Check that mount-point.automount is running:

# systemctl status mount-point.automount

2. Check that automounted directory has desired content:

# ls /mount/point

Additional resources

systemd.automount(5) and systemd.mount(5) man pages on your system

Managing systemd

381
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 24. USING SSSD COMPONENT FROM IDM TO


CACHE THE AUTOFS MAPS
The System Security Services Daemon (SSSD) is a system service to access remote service directories
and authentication mechanisms. The data caching is useful in case of the slow network connection. To
configure the SSSD service to cache the autofs map, follow the procedures below in this section.

24.1. CONFIGURING AUTOFS MANUALLY TO USE IDM SERVER AS AN


LDAP SERVER
Configure autofs to use IdM server as an LDAP server.

Procedure

1. Edit the /etc/autofs.conf file to specify the schema attributes that autofs searches for:

#
# Other common LDAP naming
#
map_object_class = "automountMap"
entry_object_class = "automount"
map_attribute = "automountMapName"
entry_attribute = "automountKey"
value_attribute = "automountInformation"

NOTE

User can write the attributes in both lower and upper cases in the
/etc/autofs.conf file.

2. Optional: Specify the LDAP configuration. There are two ways to do this. The simplest is to let
the automount service discover the LDAP server and locations on its own:

ldap_uri = "ldap:///dc=example,dc=com"

This option requires DNS to contain SRV records for the discoverable servers.

Alternatively, explicitly set which LDAP server to use and the base DN for LDAP searches:

ldap_uri = "ldap://ipa.example.com"
search_base = "cn=location,cn=automount,dc=example,dc=com"

3. Edit the /etc/autofs_ldap_auth.conf file so that autofs allows client authentication with the IdM
LDAP server.

Change authrequired to yes.

Set the principal to the Kerberos host principal for the IdM LDAP server,
host/FQDN@REALM. The principal name is used to connect to the IdM directory as part of
GSS client authentication.

<autofs_ldap_sasl_conf

382
CHAPTER 24. USING SSSD COMPONENT FROM IDM TO CACHE THE AUTOFS MAPS

usetls="no"
tlsrequired="no"
authrequired="yes"
authtype="GSSAPI"
clientprinc="host/[email protected]"
/>

For more information about host principal, see Using canonicalized DNS host names in IdM .

If necessary, run klist -k to get the exact host principal information.

24.2. CONFIGURING SSSD TO CACHE AUTOFS MAPS


The SSSD service can be used to cache autofs maps stored on an IdM server without having to
configure autofs to use the IdM server at all.

Prerequisites

The sssd package is installed.

Procedure

1. Open the SSSD configuration file:

# vim /etc/sssd/sssd.conf

2. Add the autofs service to the list of services handled by SSSD.

[sssd]
domains = ldap
services = nss,pam,autofs

3. Create a new [autofs] section. You can leave this blank, because the default settings for an
autofs service work with most infrastructures.

[nss]

[pam]

[sudo]

[autofs]

[ssh]

[pac]

For more information, see the sssd.conf man page on your system.

4. Optional: Set a search base for the autofs entries. By default, this is the LDAP search base, but
a subtree can be specified in the ldap_autofs_search_base parameter.

[domain/EXAMPLE]

383
Red Hat Enterprise Linux 8 System Design Guide

ldap_search_base = "dc=example,dc=com"
ldap_autofs_search_base = "ou=automount,dc=example,dc=com"

5. Restart SSSD service:

# systemctl restart sssd.service

6. Check the /etc/nsswitch.conf file, so that SSSD is listed as a source for automount
configuration:

automount: sss files

7. Restart autofs service:

# systemctl restart autofs.service

8. Test the configuration by listing a user’s /home directory, assuming there is a master map entry
for /home:

# ls /home/userName

If this does not mount the remote file system, check the /var/log/messages file for errors. If
necessary, increase the debug level in the /etc/sysconfig/autofs file by setting the logging
parameter to debug.

384
CHAPTER 25. SETTING READ-ONLY PERMISSIONS FOR THE ROOT FILE SYSTEM

CHAPTER 25. SETTING READ-ONLY PERMISSIONS FOR THE


ROOT FILE SYSTEM
Sometimes, you need to mount the root file system (/) with read-only permissions. Example use cases
include enhancing security or ensuring data integrity after an unexpected system power-off.

25.1. FILES AND DIRECTORIES THAT ALWAYS RETAIN WRITE


PERMISSIONS
For the system to function properly, some files and directories need to retain write permissions. When
the root file system is mounted in read-only mode, these files are mounted in RAM using the tmpfs
temporary file system.

The default set of such files and directories is read from the /etc/rwtab file. Note that the readonly-root
package is required to have this file present in your system.

dirs /var/cache/man
dirs /var/gdm
<content truncated>

empty /tmp
empty /var/cache/foomatic
<content truncated>

files /etc/adjtime
files /etc/ntp.conf
<content truncated>

Entries in the /etc/rwtab file follow this format:

copy-method path

In this syntax:

Replace copy-method with one of the keywords specifying how the file or directory is copied to
tmpfs.

Replace path with the path to the file or directory.

The /etc/rwtab file recognizes the following ways in which a file or directory can be copied to tmpfs:

empty
An empty path is copied to tmpfs. For example:

empty /tmp

dirs
A directory tree is copied to tmpfs, empty. For example:

dirs /var/run

files

385
Red Hat Enterprise Linux 8 System Design Guide

A file or a directory tree is copied to tmpfs intact. For example:

files /etc/resolv.conf

The same format applies when adding custom paths to /etc/rwtab.d/.

25.2. CONFIGURING THE ROOT FILE SYSTEM TO MOUNT WITH READ-


ONLY PERMISSIONS ON BOOT
With this procedure, the root file system is mounted read-only on all following boots.

Procedure

1. In the /etc/sysconfig/readonly-root file, set the READONLY option to yes to mount the file
systems as read-only:

READONLY=yes

2. Add the ro option in the root entry ( /) in the /etc/fstab file:

/dev/mapper/luks-c376919e... / xfs x-systemd.device-timeout=0,ro 1 1

3. Enable the ro kernel option:

# grubby --update-kernel=ALL --args="ro"

4. Ensure that the rw kernel option is disabled:

# grubby --update-kernel=ALL --remove-args="rw"

5. If you need to add files and directories to be mounted with write permissions in the tmpfs file
system, create a text file in the /etc/rwtab.d/ directory and put the configuration there.
For example, to mount the /etc/example/file file with write permissions, add this line to the
/etc/rwtab.d/example file:

files /etc/example/file

IMPORTANT

Changes made to files and directories in tmpfs do not persist across boots.

6. Reboot the system to apply the changes.

Troubleshooting

If you mount the root file system with read-only permissions by mistake, you can remount it with
read-and-write permissions again using the following command:

# mount -o remount,rw /

386
CHAPTER 26. MANAGING STORAGE DEVICES

CHAPTER 26. MANAGING STORAGE DEVICES

26.1. SETTING UP STRATIS FILE SYSTEMS


Stratis runs as a service to manage pools of physical storage devices, simplifying local storage
management with ease of use while helping you set up and manage complex storage configurations.

IMPORTANT

Stratis is a Technology Preview feature only. Technology Preview features are not
supported with Red Hat production service level agreements (SLAs) and might not be
functionally complete. Red Hat does not recommend using them in production. These
features provide early access to upcoming product features, enabling customers to test
functionality and provide feedback during the development process. For more
information about the support scope of Red Hat Technology Preview features, see
https://access.redhat.com/support/offerings/techpreview.

26.1.1. What is Stratis


Stratis is a local storage-management solution for Linux. It is focused on simplicity and ease of use, and
gives you access to advanced storage features.

Stratis makes the following activities easier:

Initial configuration of storage

Making changes later

Using advanced storage features

Stratis is a local storage management system that supports advanced storage features. The central
concept of Stratis is a storage pool. This pool is created from one or more local disks or partitions, and
file systems are created from the pool.

The pool enables many useful features, such as:

File system snapshots

Thin provisioning

Tiering

Encryption

Additional resources

Stratis website

26.1.2. Components of a Stratis volume


Learn about the components that comprise a Stratis volume.

Externally, Stratis presents the following volume components in the command-line interface and the
API:

387
Red Hat Enterprise Linux 8 System Design Guide

blockdev
Block devices, such as a disk or a disk partition.
pool
Composed of one or more block devices.
A pool has a fixed total size, equal to the size of the block devices.

The pool contains most Stratis layers, such as the non-volatile data cache using the dm-cache
target.

Stratis creates a /dev/stratis/my-pool/ directory for each pool. This directory contains links to
devices that represent Stratis file systems in the pool.

filesystem
Each pool can contain one or more file systems, which store files.
File systems are thinly provisioned and do not have a fixed total size. The actual size of a file system
grows with the data stored on it. If the size of the data approaches the virtual size of the file system,
Stratis grows the thin volume and the file system automatically.

The file systems are formatted with XFS.

IMPORTANT

Stratis tracks information about file systems created using Stratis that XFS is not
aware of, and changes made using XFS do not automatically create updates in Stratis.
Users must not reformat or reconfigure XFS file systems that are managed by Stratis.

Stratis creates links to file systems at the /dev/stratis/my-pool/my-fs path.

NOTE

Stratis uses many Device Mapper devices, which show up in dmsetup listings and the
/proc/partitions file. Similarly, the lsblk command output reflects the internal workings
and layers of Stratis.

26.1.3. Block devices usable with Stratis


Storage devices that can be used with Stratis.

Supported devices
Stratis pools have been tested to work on these types of block devices:

LUKS

LVM logical volumes

MD RAID

DM Multipath

iSCSI

HDDs and SSDs

388
CHAPTER 26. MANAGING STORAGE DEVICES

NVMe devices

Unsupported devices
Because Stratis contains a thin-provisioning layer, Red Hat does not recommend placing a Stratis pool
on block devices that are already thinly-provisioned.

26.1.4. Installing Stratis


Install the required packages for Stratis.

Procedure

1. Install packages that provide the Stratis service and command-line utilities:

# yum install stratisd stratis-cli

2. Verify that the stratisd service is enabled:

# systemctl enable --now stratisd

26.1.5. Creating an unencrypted Stratis pool


You can create an unencrypted Stratis pool from one or more block devices.

Prerequisites

Stratis is installed. For more information, see Installing Stratis.

The stratisd service is running.

The block devices on which you are creating a Stratis pool are not in use and are not mounted.

Each block device on which you are creating a Stratis pool is at least 1 GB.

On the IBM Z architecture, the /dev/dasd* block devices must be partitioned. Use the partition
device for creating the Stratis pool.

For information about partitioning DASD devices, see Configuring a Linux instance on IBM Z

NOTE

You cannot encrypt an unencrypted Stratis pool.

Procedure

1. Erase any file system, partition table, or RAID signatures that exist on each block device that
you want to use in the Stratis pool:

# wipefs --all block-device

where block-device is the path to the block device; for example, /dev/sdb.

2. Create the new unencrypted Stratis pool on the selected block device:

389
Red Hat Enterprise Linux 8 System Design Guide

# stratis pool create my-pool block-device

where block-device is the path to an empty or wiped block device.

NOTE

Specify multiple block devices on a single line:

# stratis pool create my-pool block-device-1 block-device-2

3. Verify that the new Stratis pool was created:

# stratis pool list

26.1.6. Creating an unencrypted Stratis pool by using the web console


You can use the web console to create an unencrypted Stratis pool from one or more block devices.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

The stratisd service is running.

The block devices on which you are creating a Stratis pool are not in use and are not mounted.

Each block device on which you are creating a Stratis pool is at least 1 GB.

NOTE

You cannot encrypt an unencrypted Stratis pool after it is created.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Storage.

3. In the Storage table, click the menu button.

4. From the drop-down menu, select Create Stratis pool.

390
CHAPTER 26. MANAGING STORAGE DEVICES

5. In the Create Stratis pool dialog box, enter a name for the Stratis pool.

6. Select the Block devices from which you want to create the Stratis pool.

7. Optional: If you want to specify the maximum size for each file system that is created in pool,
select Manage filesystem sizes.

8. Click Create.

Verification

Go to the Storage section and verify that you can see the new Stratis pool in the Devices table.

26.1.7. Creating an encrypted Stratis pool

391
Red Hat Enterprise Linux 8 System Design Guide

To secure your data, you can create an encrypted Stratis pool from one or more block devices.

When you create an encrypted Stratis pool, the kernel keyring is used as the primary encryption
mechanism. After subsequent system reboots this kernel keyring is used to unlock the encrypted Stratis
pool.

When creating an encrypted Stratis pool from one or more block devices, note the following:

Each block device is encrypted using the cryptsetup library and implements the LUKS2 format.

Each Stratis pool can either have a unique key or share the same key with other pools. These
keys are stored in the kernel keyring.

The block devices that comprise a Stratis pool must be either all encrypted or all unencrypted. It
is not possible to have both encrypted and unencrypted block devices in the same Stratis pool.

Block devices added to the data tier of an encrypted Stratis pool are automatically encrypted.

Prerequisites

Stratis v2.1.0 or later is installed. For more information, see Installing Stratis.

The stratisd service is running.

The block devices on which you are creating a Stratis pool are not in use and are not mounted.

The block devices on which you are creating a Stratis pool are at least 1GB in size each.

On the IBM Z architecture, the /dev/dasd* block devices must be partitioned. Use the partition
in the Stratis pool.

For information about partitioning DASD devices, see link:Configuring a Linux instance on IBM Z .

Procedure

1. Erase any file system, partition table, or RAID signatures that exist on each block device that
you want to use in the Stratis pool:

# wipefs --all block-device

where block-device is the path to the block device; for example, /dev/sdb.

2. If you have not created a key set already, run the following command and follow the prompts to
create a key set to use for the encryption.

# stratis key set --capture-key key-description

where key-description is a reference to the key that gets created in the kernel keyring.

3. Create the encrypted Stratis pool and specify the key description to use for the encryption. You
can also specify the key path using the --keyfile-path option instead of using the key-
description option.

# stratis pool create --key-desc key-description my-pool block-device

where

392
CHAPTER 26. MANAGING STORAGE DEVICES

key-description
References the key that exists in the kernel keyring, which you created in the previous step.
my-pool
Specifies the name of the new Stratis pool.
block-device
Specifies the path to an empty or wiped block device.

NOTE

Specify multiple block devices on a single line:

# stratis pool create --key-desc key-description my-pool block-device-1


block-device-2

4. Verify that the new Stratis pool was created:

# stratis pool list

26.1.8. Creating an encrypted Stratis pool by using the web console


To secure your data, you can use the web console to create an encrypted Stratis pool from one or more
block devices.

When creating an encrypted Stratis pool from one or more block devices, note the following:

Each block device is encrypted using the cryptsetup library and implements the LUKS2 format.

Each Stratis pool can either have a unique key or share the same key with other pools. These
keys are stored in the kernel keyring.

The block devices that comprise a Stratis pool must be either all encrypted or all unencrypted. It
is not possible to have both encrypted and unencrypted block devices in the same Stratis pool.

Block devices added to the data tier of an encrypted Stratis pool are automatically encrypted.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

Stratis v2.1.0 or later is installed.

The stratisd service is running.

The block devices on which you are creating a Stratis pool are not in use and are not mounted.

Each block device on which you are creating a Stratis pool is at least 1 GB.

Procedure

1. Log in to the RHEL 8 web console.

393
Red Hat Enterprise Linux 8 System Design Guide

For details, see Logging in to the web console .

2. Click Storage.

3. In the Storage table, click the menu button.

4. From the drop-down menu, select Create Stratis pool.

5. In the Create Stratis pool dialog box, enter a name for the Stratis pool.

6. Select the Block devices from which you want to create the Stratis pool.

7. Select the type of encryption, you can use a passphrase, a Tang keyserver, or both:

Passphrase:

i. Enter a passphrase.

394
CHAPTER 26. MANAGING STORAGE DEVICES

ii. Confirm the passphrase

Tang keyserver:

i. Enter the keyserver address. For more information, see Deploying a Tang server with
SELinux in enforcing mode.

8. Optional: If you want to specify the maximum size for each file system that is created in pool,
select Manage filesystem sizes.

9. Click Create.

Verification

Go to the Storage section and verify that you can see the new Stratis pool in the Devices table.

26.1.9. Renaming a Stratis pool by using the web console


You can use the web console to rename an existing Stratis pool.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

Stratis is installed.
The web console detects and installs Stratis by default. However, for manually installing Stratis,
see Installing Stratis.

The stratisd service is running.

A Stratis pool is created.

Procedure

1. Log in to the RHEL 8 web console.

2. Click Storage.

3. In the Storage table, click the Stratis pool you want to rename.

4. On the Stratis pool page, click edit next to the Name field.

395
Red Hat Enterprise Linux 8 System Design Guide

5. In the Rename Stratis pool dialog box, enter a new name.

6. Click Rename.

26.1.10. Setting overprovisioning mode in Stratis filesystem


A storage stack can reach a state of overprovision. If the file system size becomes bigger than the pool
backing it, the pool becomes full. To prevent this, disable overprovisioning, which ensures that the size
of all filesystems on the pool does not exceed the available physical storage provided by the pool. If you
use Stratis for critical applications or the root filesystem, this mode prevents certain failure cases.

If you enable overprovisioning, an API signal notifies you when your storage has been fully allocated. The
notification serves as a warning to the user to inform them that when all the remaining pool space fills up,
Stratis has no space left to extend to.

Prerequisites

Stratis is installed. For more information, see Installing Stratis.

Procedure
To set up the pool correctly, you have two possibilities:

1. Create a pool from one or more block devices:

# stratis pool create pool-name /dev/sdb

2. Set overprovisioning mode in the existing pool:

# stratis pool overprovision pool-name <yes|no>

If set to "yes", you enable overprovisioning to the pool. This means that the sum of the
logical sizes of the Stratis filesystems, supported by the pool, can exceed the amount of
available data space.

396
CHAPTER 26. MANAGING STORAGE DEVICES

Verification

1. Run the following to view the full list of Stratis pools:

# stratis pool list

Name Total Physical Properties UUID Alerts


pool-name 1.42 TiB / 23.96 MiB / 1.42 TiB ~Ca,~Cr,~Op cb7cb4d8-9322-4ac4-a6fd-
eb7ae9e1e540

2. Check if there is an indication of the pool overprovisioning mode flag in the stratis pool list
output. The " ~ " is a math symbol for "NOT", so ~Op means no-overprovisioning.

3. Optional: Run the following to check overprovisioning on a specific pool:

# stratis pool overprovision pool-name yes

# stratis pool list

Name Total Physical Properties UUID Alerts


pool-name 1.42 TiB / 23.96 MiB / 1.42 TiB ~Ca,~Cr,~Op cb7cb4d8-9322-4ac4-a6fd-
eb7ae9e1e540

Additional resources

The Stratis Storage webpage.

26.1.11. Binding a Stratis pool to NBDE


Binding an encrypted Stratis pool to Network Bound Disk Encryption (NBDE) requires a Tang server.
When a system containing the Stratis pool reboots, it connects with the Tang server to automatically
unlock the encrypted pool without you having to provide the kernel keyring description.

NOTE

Binding a Stratis pool to a supplementary Clevis encryption mechanism does not remove
the primary kernel keyring encryption.

Prerequisites

Stratis v2.3.0 or later is installed. For more information, see Installing Stratis.

The stratisd service is running.

You have created an encrypted Stratis pool, and you have the key description of the key that
was used for the encryption. For more information, see Creating an encrypted Stratis pool .

You can connect to the Tang server. For more information, see Deploying a Tang server with
SELinux in enforcing mode

Procedure

Bind an encrypted Stratis pool to NBDE:

397
Red Hat Enterprise Linux 8 System Design Guide

# stratis pool bind nbde --trust-url my-pool tang-server

where

my-pool
Specifies the name of the encrypted Stratis pool.
tang-server
Specifies the IP address or URL of the Tang server.

Additional resources

Configuring automated unlocking of encrypted volumes using policy-based decryption

26.1.12. Binding a Stratis pool to TPM


When you bind an encrypted Stratis pool to the Trusted Platform Module (TPM) 2.0, the system
containing the pool reboots, and the pool is automatically unlocked without you having to provide the
kernel keyring description.

Prerequisites

Stratis v2.3.0 or later is installed. For more information, see Installing Stratis.

The stratisd service is running.

You have created an encrypted Stratis pool. For more information, see Creating an encrypted
Stratis pool.

Procedure

Bind an encrypted Stratis pool to TPM:

# stratis pool bind tpm my-pool key-description

where

my-pool
Specifies the name of the encrypted Stratis pool.
key-description
References the key that exists in the kernel keyring, which was generated when you created
the encrypted Stratis pool.

26.1.13. Unlocking an encrypted Stratis pool with kernel keyring


After a system reboot, your encrypted Stratis pool or the block devices that comprise it might not be
visible. You can unlock the pool using the kernel keyring that was used to encrypt the pool.

Prerequisites

Stratis v2.1.0 is installed. For more information, see Installing Stratis.

The stratisd service is running.

398
CHAPTER 26. MANAGING STORAGE DEVICES

You have created an encrypted Stratis pool. For more information, see Creating an encrypted
Stratis pool.

Procedure

1. Re-create the key set using the same key description that was used previously:

# stratis key set --capture-key key-description

where key-description references the key that exists in the kernel keyring, which was generated
when you created the encrypted Stratis pool.

2. Verify that the Stratis pool is visible:

# stratis pool list

26.1.14. Unbinding a Stratis pool from supplementary encryption


When you unbind an encrypted Stratis pool from a supported supplementary encryption mechanism, the
primary kernel keyring encryption remains in place. This is not true for pools that are created with Clevis
encryption from the start.

Prerequisites

Stratis v2.3.0 or later is installed on your system. For more information, see Installing Stratis.

You have created an encrypted Stratis pool. For more information, see Creating an encrypted
Stratis pool.

The encrypted Stratis pool is bound to a supported supplementary encryption mechanism.

Procedure

Unbind an encrypted Stratis pool from a supplementary encryption mechanism:

# stratis pool unbind clevis my-pool

where

my-pool specifies the name of the Stratis pool you want to unbind.

Additional resources

Binding an encrypted Stratis pool to NBDE

Binding an encrypted Stratis pool to TPM

26.1.15. Starting and stopping Stratis pool


You can start and stop Stratis pools. This gives you the option to dissasemble or bring down all the
objects that were used to construct the pool, such as filesystems, cache devices, thin pool, and
encrypted devices. Note that if the pool actively uses any device or filesystem, it might issue a warning
and not be able to stop.

399
Red Hat Enterprise Linux 8 System Design Guide

The stopped state is recorded in the pool’s metadata. These pools do not start on the following boot,
until the pool receives a start command.

Prerequisites

Stratis is installed. For more information, see Installing Stratis.

The stratisd service is running.

You have created either an unencrypted or an encrypted Stratis pool. See Creating an
unencrypted Stratis pool

or Creating an encrypted Stratis pool .

Procedure

Use the following command to start the Stratis pool. The --unlock-method option specifies the
method of unlocking the pool if it is encrypted:

# stratis pool start pool-uuid --unlock-method <keyring|clevis>

Alternatively, use the following command to stop the Stratis pool. This tears down the storage
stack but leaves all metadata intact:

# stratis pool stop pool-name

Verification

Use the following command to list all pools on the system:

# stratis pool list

Use the following command to list all not previously started pools. If the UUID is specified, the
command prints detailed information about the pool corresponding to the UUID:

# stratis pool list --stopped --uuid UUID

26.1.16. Creating a Stratis file system


Create a Stratis file system on an existing Stratis pool.

Prerequisites

Stratis is installed. For more information, see Installing Stratis.

The stratisd service is running.

You have created a Stratis pool. See Creating an unencrypted Stratis pool

or Creating an encrypted Stratis pool .

Procedure

400
CHAPTER 26. MANAGING STORAGE DEVICES

1. To create a Stratis file system on a pool, use:

# stratis filesystem create --size number-and-unit my-pool my-fs

where

number-and-unit
Specifies the size of a file system. The specification format must follow the standard size
specification format for input, that is B, KiB, MiB, GiB, TiB or PiB.
my-pool
Specifies the name of the Stratis pool.
my-fs
Specifies an arbitrary name for the file system.
For example:

Example 26.1. Creating a Stratis file system

# stratis filesystem create --size 10GiB pool1 filesystem1

Verification

List file systems within the pool to check if the Stratis filesystem is created:

# stratis fs list my-pool

Additional resources

Mounting a Stratis file system

26.1.17. Creating a file system on a Stratis pool by using the web console
You can use the web console to create a file system on an existing Stratis pool.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

The stratisd service is running.

A Stratis pool is created.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Storage.

401
Red Hat Enterprise Linux 8 System Design Guide

3. Click the Stratis pool on which you want to create a file system.

4. On the Stratis pool page, scroll to the Stratis filesystems section and click Create new
filesystem.

5. In the Create filesystem dialog box, enter a Name for the file system.

6. Enter the Mount point for the file system.

7. Select the Mount option.

8. In the At boot drop-down menu, select when you want to mount your file system.

9. Create the file system:

If you want to create and mount the file system, click Create and mount.

If you want to only create the file system, click Create only.

402
CHAPTER 26. MANAGING STORAGE DEVICES

Verification

The new file system is visible on the Stratis pool page under the Stratis filesystems tab.

26.1.18. Mounting a Stratis file system


Mount an existing Stratis file system to access the content.

Prerequisites

Stratis is installed. For more information, see Installing Stratis.

The stratisd service is running.

You have created a Stratis file system. For more information, see Creating a Stratis filesystem .

Procedure

To mount the file system, use the entries that Stratis maintains in the /dev/stratis/ directory:

# mount /dev/stratis/my-pool/my-fs mount-point

The file system is now mounted on the mount-point directory and ready to use.

Additional resources

Creating a Stratis file system

26.1.19. Setting up non-root Stratis filesystems in /etc/fstab using a systemd service


You can manage setting up non-root filesystems in /etc/fstab using a systemd service.

Prerequisites

Stratis is installed. See Installing Stratis.

The stratisd service is running.

You have created a Stratis file system. See Creating a Stratis filesystem .

Procedure

As root, edit the /etc/fstab file and add a line to set up non-root filesystems:

/dev/stratis/my-pool/my-fs mount-point xfs defaults,x-systemd.requires=stratis-fstab-


[email protected],[email protected] dump-value
fsck_value

Additional resources

Persistently mounting file systems

26.2. EXTENDING A STRATIS VOLUME WITH ADDITIONAL BLOCK


403
Red Hat Enterprise Linux 8 System Design Guide

26.2. EXTENDING A STRATIS VOLUME WITH ADDITIONAL BLOCK


DEVICES
You can attach additional block devices to a Stratis pool to provide more storage capacity for Stratis file
systems.

IMPORTANT

Stratis is a Technology Preview feature only. Technology Preview features are not
supported with Red Hat production service level agreements (SLAs) and might not be
functionally complete. Red Hat does not recommend using them in production. These
features provide early access to upcoming product features, enabling customers to test
functionality and provide feedback during the development process. For more
information about the support scope of Red Hat Technology Preview features, see
https://access.redhat.com/support/offerings/techpreview.

26.2.1. Components of a Stratis volume


Learn about the components that comprise a Stratis volume.

Externally, Stratis presents the following volume components in the command-line interface and the
API:

blockdev
Block devices, such as a disk or a disk partition.
pool
Composed of one or more block devices.
A pool has a fixed total size, equal to the size of the block devices.

The pool contains most Stratis layers, such as the non-volatile data cache using the dm-cache
target.

Stratis creates a /dev/stratis/my-pool/ directory for each pool. This directory contains links to
devices that represent Stratis file systems in the pool.

filesystem
Each pool can contain one or more file systems, which store files.
File systems are thinly provisioned and do not have a fixed total size. The actual size of a file system
grows with the data stored on it. If the size of the data approaches the virtual size of the file system,
Stratis grows the thin volume and the file system automatically.

The file systems are formatted with XFS.

IMPORTANT

Stratis tracks information about file systems created using Stratis that XFS is not
aware of, and changes made using XFS do not automatically create updates in Stratis.
Users must not reformat or reconfigure XFS file systems that are managed by Stratis.

Stratis creates links to file systems at the /dev/stratis/my-pool/my-fs path.

NOTE
404
CHAPTER 26. MANAGING STORAGE DEVICES

NOTE

Stratis uses many Device Mapper devices, which show up in dmsetup listings and the
/proc/partitions file. Similarly, the lsblk command output reflects the internal workings
and layers of Stratis.

26.2.2. Adding block devices to a Stratis pool


This procedure adds one or more block devices to a Stratis pool to be usable by Stratis file systems.

Prerequisites

Stratis is installed. See Installing Stratis.

The stratisd service is running.

The block devices that you are adding to the Stratis pool are not in use and not mounted.

The block devices that you are adding to the Stratis pool are at least 1 GiB in size each.

Procedure

To add one or more block devices to the pool, use:

# stratis pool add-data my-pool device-1 device-2 device-n

Additional resources

stratis(8) man page on your system

26.2.3. Adding a block device to a Stratis pool by using the web console
You can use the web console to add a block device to an existing Stratis pool. You can also add caches
as a block device.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

The stratisd service is running.

A Stratis pool is created.

The block devices on which you are creating a Stratis pool are not in use and are not mounted.

Each block device on which you are creating a Stratis pool is at least 1 GB.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Storage.

405
Red Hat Enterprise Linux 8 System Design Guide

3. In the Storage table, click the Stratis pool to which you want to add a block device.

4. On the Stratis pool page, click Add block devices.

5. In the Add block devices dialog box, select the Tier, whether you want to add a block device as
data or cache.

6. Optional: If you are adding the block device to a Stratis pool that is encrypted with a passphrase,
then you must enter the passphrase.

7. Under Block devices, select the devices you want to add to the pool.

8. Click Add.

26.2.4. Additional resources


The Stratis Storage website

26.3. MONITORING STRATIS FILE SYSTEMS


As a Stratis user, you can view information about Stratis volumes on your system to monitor their state
and free space.

IMPORTANT
406
CHAPTER 26. MANAGING STORAGE DEVICES

IMPORTANT

Stratis is a Technology Preview feature only. Technology Preview features are not
supported with Red Hat production service level agreements (SLAs) and might not be
functionally complete. Red Hat does not recommend using them in production. These
features provide early access to upcoming product features, enabling customers to test
functionality and provide feedback during the development process. For more
information about the support scope of Red Hat Technology Preview features, see
https://access.redhat.com/support/offerings/techpreview.

26.3.1. Stratis sizes reported by different utilities


This section explains the difference between Stratis sizes reported by standard utilities such as df and
the stratis utility.

Standard Linux utilities such as df report the size of the XFS file system layer on Stratis, which is 1 TiB.
This is not useful information, because the actual storage usage of Stratis is less due to thin provisioning,
and also because Stratis automatically grows the file system when the XFS layer is close to full.

IMPORTANT

Regularly monitor the amount of data written to your Stratis file systems, which is
reported as the Total Physical Used value. Make sure it does not exceed the Total Physical
Size value.

Additional resources

stratis(8) man page on your system

26.3.2. Displaying information about Stratis volumes


This procedure lists statistics about your Stratis volumes, such as the total, used, and free size or file
systems and block devices belonging to a pool.

Prerequisites

Stratis is installed. See Installing Stratis.

The stratisd service is running.

Procedure

To display information about all block devices used for Stratis on your system:

# stratis blockdev

Pool Name Device Node Physical Size State Tier


my-pool /dev/sdb 9.10 TiB In-use Data

To display information about all Stratis pools on your system:

# stratis pool

Name Total Physical Size Total Physical Used

407
Red Hat Enterprise Linux 8 System Design Guide

my-pool 9.10 TiB 598 MiB

To display information about all Stratis file systems on your system:

# stratis filesystem

Pool Name Name Used Created Device


my-pool my-fs 546 MiB Nov 08 2018 08:03 /dev/stratis/my-pool/my-fs

Additional resources

stratis(8) man page on your system

26.3.3. Viewing a Stratis pool by using the web console


You can use the web console to view an existing Stratis pool and the file systems it contains.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

The stratisd service is running.

You have an existing Stratis pool.

Procedure

1. Log in to the RHEL 8 web console.

2. Click Storage.

3. In the Storage table, click the Stratis pool you want to view.
The Stratis pool page displays all the information about the pool and the file systems that you
created in the pool.

408
CHAPTER 26. MANAGING STORAGE DEVICES

26.3.4. Additional resources


The Stratis Storage website

26.4. USING SNAPSHOTS ON STRATIS FILE SYSTEMS


You can use snapshots on Stratis file systems to capture file system state at arbitrary times and restore
it in the future.

IMPORTANT

Stratis is a Technology Preview feature only. Technology Preview features are not
supported with Red Hat production service level agreements (SLAs) and might not be
functionally complete. Red Hat does not recommend using them in production. These
features provide early access to upcoming product features, enabling customers to test
functionality and provide feedback during the development process. For more
information about the support scope of Red Hat Technology Preview features, see
https://access.redhat.com/support/offerings/techpreview.

26.4.1. Characteristics of Stratis snapshots


In Stratis, a snapshot is a regular Stratis file system created as a copy of another Stratis file system. The
snapshot initially contains the same file content as the original file system, but can change as the
snapshot is modified. Whatever changes you make to the snapshot will not be reflected in the original
file system.

The current snapshot implementation in Stratis is characterized by the following:

A snapshot of a file system is another file system.

A snapshot and its origin are not linked in lifetime. A snapshotted file system can live longer than
the file system it was created from.

409
Red Hat Enterprise Linux 8 System Design Guide

A file system does not have to be mounted to create a snapshot from it.

Each snapshot uses around half a gigabyte of actual backing storage, which is needed for the
XFS log.

26.4.2. Creating a Stratis snapshot


This procedure creates a Stratis file system as a snapshot of an existing Stratis file system.

Prerequisites

Stratis is installed. See Installing Stratis.

The stratisd service is running.

You have created a Stratis file system. See Creating a Stratis filesystem .

Procedure

To create a Stratis snapshot, use:

# stratis fs snapshot my-pool my-fs my-fs-snapshot

Additional resources

stratis(8) man page on your system

26.4.3. Accessing the content of a Stratis snapshot


This procedure mounts a snapshot of a Stratis file system to make it accessible for read and write
operations.

Prerequisites

Stratis is installed. See Installing Stratis.

The stratisd service is running.

You have created a Stratis snapshot. See Creating a Stratis filesystem .

Procedure

To access the snapshot, mount it as a regular file system from the /dev/stratis/my-pool/
directory:

# mount /dev/stratis/my-pool/my-fs-snapshot mount-point

Additional resources

Mounting a Stratis file system

mount(8) man page on your system

410
CHAPTER 26. MANAGING STORAGE DEVICES

26.4.4. Reverting a Stratis file system to a previous snapshot


This procedure reverts the content of a Stratis file system to the state captured in a Stratis snapshot.

Prerequisites

Stratis is installed. See Installing Stratis.

The stratisd service is running.

You have created a Stratis snapshot. See Creating a Stratis snapshot .

Procedure

1. Optional: Back up the current state of the file system to be able to access it later:

# stratis filesystem snapshot my-pool my-fs my-fs-backup

2. Unmount and remove the original file system:

# umount /dev/stratis/my-pool/my-fs
# stratis filesystem destroy my-pool my-fs

3. Create a copy of the snapshot under the name of the original file system:

# stratis filesystem snapshot my-pool my-fs-snapshot my-fs

4. Mount the snapshot, which is now accessible with the same name as the original file system:

# mount /dev/stratis/my-pool/my-fs mount-point

The content of the file system named my-fs is now identical to the snapshot my-fs-snapshot.

Additional resources

stratis(8) man page on your system

26.4.5. Removing a Stratis snapshot


This procedure removes a Stratis snapshot from a pool. Data on the snapshot are lost.

Prerequisites

Stratis is installed. See Installing Stratis.

The stratisd service is running.

You have created a Stratis snapshot. See Creating a Stratis snapshot .

Procedure

1. Unmount the snapshot:

411
Red Hat Enterprise Linux 8 System Design Guide

# umount /dev/stratis/my-pool/my-fs-snapshot

2. Destroy the snapshot:

# stratis filesystem destroy my-pool my-fs-snapshot

Additional resources

stratis(8) man page on your system

26.4.6. Additional resources


The Stratis Storage website

26.5. REMOVING STRATIS FILE SYSTEMS


You can remove an existing Stratis file system, or a Stratis pool, by destroying data on them.

IMPORTANT

Stratis is a Technology Preview feature only. Technology Preview features are not
supported with Red Hat production service level agreements (SLAs) and might not be
functionally complete. Red Hat does not recommend using them in production. These
features provide early access to upcoming product features, enabling customers to test
functionality and provide feedback during the development process. For more
information about the support scope of Red Hat Technology Preview features, see
https://access.redhat.com/support/offerings/techpreview.

26.5.1. Components of a Stratis volume


Learn about the components that comprise a Stratis volume.

Externally, Stratis presents the following volume components in the command-line interface and the
API:

blockdev
Block devices, such as a disk or a disk partition.
pool
Composed of one or more block devices.
A pool has a fixed total size, equal to the size of the block devices.

The pool contains most Stratis layers, such as the non-volatile data cache using the dm-cache
target.

Stratis creates a /dev/stratis/my-pool/ directory for each pool. This directory contains links to
devices that represent Stratis file systems in the pool.

filesystem
Each pool can contain one or more file systems, which store files.

File systems are thinly provisioned and do not have a fixed total size. The actual size of a file system
412
CHAPTER 26. MANAGING STORAGE DEVICES

File systems are thinly provisioned and do not have a fixed total size. The actual size of a file system
grows with the data stored on it. If the size of the data approaches the virtual size of the file system,
Stratis grows the thin volume and the file system automatically.

The file systems are formatted with XFS.

IMPORTANT

Stratis tracks information about file systems created using Stratis that XFS is not
aware of, and changes made using XFS do not automatically create updates in Stratis.
Users must not reformat or reconfigure XFS file systems that are managed by Stratis.

Stratis creates links to file systems at the /dev/stratis/my-pool/my-fs path.

NOTE

Stratis uses many Device Mapper devices, which show up in dmsetup listings and the
/proc/partitions file. Similarly, the lsblk command output reflects the internal workings
and layers of Stratis.

26.5.2. Removing a Stratis file system


This procedure removes an existing Stratis file system. Data stored on it are lost.

Prerequisites

Stratis is installed. See Installing Stratis.

The stratisd service is running.

You have created a Stratis file system. See Creating a Stratis filesystem .

Procedure

1. Unmount the file system:

# umount /dev/stratis/my-pool/my-fs

2. Destroy the file system:

# stratis filesystem destroy my-pool my-fs

3. Verify that the file system no longer exists:

# stratis filesystem list my-pool

Additional resources

stratis(8) man page on your system

26.5.3. Deleting a file system from a Stratis pool by using the web console

413
Red Hat Enterprise Linux 8 System Design Guide

You can use the web console to delete a file system from an existing Stratis pool.

NOTE

Deleting a Stratis pool file system erases all the data it contains.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

Stratis is installed.
The web console detects and installs Stratis by default. However, for manually installing Stratis,
see Installing Stratis.

The stratisd service is running.

You have an existing Stratis pool.

You have created a file system on the Stratis pool.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Storage.

3. In the Storage table, click the Stratis pool from which you want to delete a file system.

4. On the Stratis pool page, scroll to the Stratis filesystems section and click the menu button ⋮
next to the file system you want to delete.

5. From the drop-down menu, select delete.

414
CHAPTER 26. MANAGING STORAGE DEVICES

6. In the Confirm deletion dialog box, click Delete.

26.5.4. Removing a Stratis pool


This procedure removes an existing Stratis pool. Data stored on it are lost.

Prerequisites

Stratis is installed. See Installing Stratis.

The stratisd service is running.

You have created a Stratis pool:

To create an unencrypted pool, see Creating an unencrypted Stratis pool

To create an encrypted pool, see Creating an encrypted Stratis pool .

Procedure

1. List file systems on the pool:

# stratis filesystem list my-pool

2. Unmount all file systems on the pool:

# umount /dev/stratis/my-pool/my-fs-1 \
/dev/stratis/my-pool/my-fs-2 \
/dev/stratis/my-pool/my-fs-n

3. Destroy the file systems:

# stratis filesystem destroy my-pool my-fs-1 my-fs-2

4. Destroy the pool:

# stratis pool destroy my-pool

5. Verify that the pool no longer exists:

415
Red Hat Enterprise Linux 8 System Design Guide

# stratis pool list

Additional resources

stratis(8) man page on your system

26.5.5. Deleting a Stratis pool by using the web console


You can use the web console to delete an existing Stratis pool.

NOTE

Deleting a Stratis pool erases all the data it contains.

Prerequisites

You have installed the RHEL 8 web console.


For instructions, see Installing and enabling the web console .

The stratisd service is running.

You have an existing Stratis pool.

Procedure

1. Log in to the RHEL 8 web console.


For details, see Logging in to the web console .

2. Click Storage.

3. In the Storage table, click the menu button, ⋮, next to the Stratis pool you want to delete.

4. From the drop-down menu, select Delete pool.

5. In the Permanently delete pool dialog box, click Delete.

26.5.6. Additional resources


The Stratis Storage website

26.6. GETTING STARTED WITH SWAP


Use the swap space to provide temporary storage for inactive processes and data, and prevent out-of-
memory errors when physical memory is full. The swap space acts as an extension to the physical
memory and allows the system to continue running smoothly even when physical memory is exhausted.
Note that using swap space can slow down system performance, so optimizing the use of physical
memory, before relying on swap space, can be more favorable.

26.6.1. Overview of swap space


Swap space in Linux is used when the amount of physical memory (RAM) is full. If the system needs more
memory resources and the RAM is full, inactive pages in memory are moved to the swap space. While
swap space can help machines with a small amount of RAM, it should not be considered a replacement

416
CHAPTER 26. MANAGING STORAGE DEVICES

for more RAM.

Swap space is located on hard drives, which have a slower access time than physical memory. Swap
space can be a dedicated swap partition (recommended), a swap file, or a combination of swap partitions
and swap files.

In years past, the recommended amount of swap space increased linearly with the amount of RAM in the
system. However, modern systems often include hundreds of gigabytes of RAM. As a consequence,
recommended swap space is considered a function of system memory workload, not system memory.

Adding swap space


The following are the different ways to add a swap space:

Extending swap on an LVM2 logical volume

Creating an LVM2 logical volume for swap

Creating a swap file

Creating a partition with parted


For example, you may upgrade the amount of RAM in your system from 1 GB to 2 GB, but
there is only 2 GB of swap space. It might be advantageous to increase the amount of swap
space to 4 GB if you perform memory-intense operations or run applications that require a
large amount of memory.

Removing swap space


The following are the different ways to remove a swap space:

Reducing swap on an LVM2 logical volume

Removing an LVM2 logical volume for swap

Removing a swap file

Removing a partition with parted


For example, you have downgraded the amount of RAM in your system from 1 GB to 512 MB,
but there is 2 GB of swap space still assigned. It might be advantageous to reduce the
amount of swap space to 1 GB, since the larger 2 GB could be wasting disk space.

26.6.2. Recommended system swap space


The recommended size of a swap partition depends on the amount of RAM in your system and whether
you want sufficient memory for your system to hibernate. The recommended swap partition size is set
automatically during installation. To allow for hibernation, however, you need to edit the swap space in
the custom partitioning stage.

The following recommendations are especially important on systems with low memory, such as 1 GB or
less. Failure to allocate sufficient swap space on these systems can cause issues, such as instability or
even render the installed system unbootable.

Table 26.1. Recommended swap space

417
Red Hat Enterprise Linux 8 System Design Guide

Amount of RAM in the system Recommended swap space Recommended swap space if
allowing for hibernation

⩽ 2 GB 2 times the amount of RAM 3 times the amount of RAM

> 2 GB – 8 GB Equal to the amount of RAM 2 times the amount of RAM

> 8 GB – 64 GB At least 4 GB 1.5 times the amount of RAM

> 64 GB At least 4 GB Hibernation not recommended

For border values such as 2 GB, 8 GB, or 64 GB of system RAM, choose swap size based on your needs
or preference. If your system resources allow for it, increasing the swap space can lead to better
performance.

Note that distributing swap space over multiple storage devices also improves swap space performance,
particularly on systems with fast drives, controllers, and interfaces.

IMPORTANT

File systems and LVM2 volumes assigned as swap space should not be in use when being
modified. Any attempts to modify swap fail if a system process or the kernel is using swap
space. Use the free and cat /proc/swaps commands to verify how much and where swap
is in use.

Resizing swap space requires temporarily removing it from the system. This can be
problematic if running applications rely on the additional swap space and might run into
low-memory situations. Preferably, perform swap resizing from rescue mode, see Debug
boot options. When prompted to mount the file system, select Skip.

26.6.3. Creating an LVM2 logical volume for swap


You can create an LVM2 logical volume for swap. Assuming /dev/VolGroup00/LogVol02 is the swap
volume you want to add.

Prerequisites

You have enough disk space.

Procedure

1. Create the LVM2 logical volume of size 2 GB:

# lvcreate VolGroup00 -n LogVol02 -L 2G

2. Format the new swap space:

# mkswap /dev/VolGroup00/LogVol02

3. Add the following entry to the /etc/fstab file:

418
CHAPTER 26. MANAGING STORAGE DEVICES

/dev/VolGroup00/LogVol02 none swap defaults 0 0

4. Regenerate mount units so that your system registers the new configuration:

# systemctl daemon-reload

5. Activate swap on the logical volume:

# swapon -v /dev/VolGroup00/LogVol02

Verification

To test if the swap logical volume was successfully created and activated, inspect active swap
space by using the following command:

# cat /proc/swaps
total used free shared buff/cache available
Mem: 30Gi 1.2Gi 28Gi 12Mi 994Mi 28Gi
Swap: 22Gi 0B 22Gi

# free -h
total used free shared buff/cache available
Mem: 30Gi 1.2Gi 28Gi 12Mi 995Mi 28Gi
Swap: 17Gi 0B 17Gi

26.6.4. Creating a swap file


You can create a swap file to create a temporary storage space on a solid-state drive or hard disk when
the system runs low on memory.

Prerequisites

You have enough disk space.

Procedure

1. Determine the size of the new swap file in megabytes and multiply by 1024 to determine the
number of blocks. For example, the block size of a 64 MB swap file is 65536.

2. Create an empty file:

# dd if=/dev/zero of=/swapfile bs=1024 count=65536

Replace 65536 with the value equal to the required block size.

3. Set up the swap file with the command:

# mkswap /swapfile

4. Change the security of the swap file so it is not world readable.

# chmod 0600 /swapfile

419
Red Hat Enterprise Linux 8 System Design Guide

5. Edit the /etc/fstab file with the following entries to enable the swap file at boot time:

/swapfile none swap defaults 0 0

The next time the system boots, it activates the new swap file.

6. Regenerate mount units so that your system registers the new /etc/fstab configuration:

# systemctl daemon-reload

7. Activate the swap file immediately:

# swapon /swapfile

Verification

To test if the new swap file was successfully created and activated, inspect active swap space by
using the following command:

$ cat /proc/swaps
$ free -h

26.6.5. Extending swap on an LVM2 logical volume


You can extend swap space on an existing LVM2 logical volume. Assuming /dev/VolGroup00/LogVol01
is the volume you want to extend by 2 GB.

Prerequisites

You have sufficient disk space.

Procedure

1. Disable swapping for the associated logical volume:

# swapoff -v /dev/VolGroup00/LogVol01

2. Resize the LVM2 logical volume by 2 GB:

# lvresize /dev/VolGroup00/LogVol01 -L +2G

3. Format the new swap space:

# mkswap /dev/VolGroup00/LogVol01

4. Enable the extended logical volume:

# swapon -v /dev/VolGroup00/LogVol01

Verification

To test if the swap logical volume was successfully extended and activated, inspect active swap
420
CHAPTER 26. MANAGING STORAGE DEVICES

To test if the swap logical volume was successfully extended and activated, inspect active swap
space:

# cat /proc/swaps
Filename Type Size Used Priority
/dev/dm-1 partition 16322556 0 -2
/dev/dm-4 partition 7340028 0 -3

# free -h
total used free shared buff/cache available
Mem: 30Gi 1.2Gi 28Gi 12Mi 994Mi 28Gi
Swap: 22Gi 0B 22Gi

26.6.6. Reducing swap on an LVM2 logical volume


You can reduce swap on an LVM2 logical volume. Assuming /dev/VolGroup00/LogVol01 is the volume
you want to reduce.

Procedure

1. Disable swapping for the associated logical volume:

# swapoff -v /dev/VolGroup00/LogVol01

2. Clean the swap signature:

# wipefs -a /dev/VolGroup00/LogVol01

3. Reduce the LVM2 logical volume by 512 MB:

# lvreduce /dev/VolGroup00/LogVol01 -L -512M

4. Format the new swap space:

# mkswap /dev/VolGroup00/LogVol01

5. Activate swap on the logical volume:

# swapon -v /dev/VolGroup00/LogVol01

Verification

To test if the swap logical volume was successfully reduced, inspect active swap space by using
the following command:

$ cat /proc/swaps
$ free -h

26.6.7. Removing an LVM2 logical volume for swap

You can remove an LVM2 logical volume for swap. Assuming /dev/VolGroup00/LogVol02 is the swap
421
Red Hat Enterprise Linux 8 System Design Guide

You can remove an LVM2 logical volume for swap. Assuming /dev/VolGroup00/LogVol02 is the swap
volume you want to remove.

Procedure

1. Disable swapping for the associated logical volume:

# swapoff -v /dev/VolGroup00/LogVol02

2. Remove the LVM2 logical volume:

# lvremove /dev/VolGroup00/LogVol02

3. Remove the following associated entry from the /etc/fstab file:

/dev/VolGroup00/LogVol02 none swap defaults 0 0

4. Regenerate mount units to register the new configuration:

# systemctl daemon-reload

Verification

Test if the logical volume was successfully removed, inspect active swap space by using the
following command:

$ cat /proc/swaps
$ free -h

26.6.8. Removing a swap file


You can remove a swap file.

Procedure

1. Disable the /swapfile swap file:

# swapoff -v /swapfile

2. Remove its entry from the /etc/fstab file accordingly.

3. Regenerate mount units so that your system registers the new configuration:

# systemctl daemon-reload

4. Remove the actual file:

# rm /swapfile

26.7. MANAGING LOCAL STORAGE BY USING RHEL SYSTEM ROLES

To manage LVM and local file systems (FS) by using Ansible, you can use the storage role, which is one
422
CHAPTER 26. MANAGING STORAGE DEVICES

To manage LVM and local file systems (FS) by using Ansible, you can use the storage role, which is one
of the RHEL system roles available in RHEL 8.

Using the storage role enables you to automate administration of file systems on disks and logical
volumes on multiple machines and across all versions of RHEL starting with RHEL 7.7.

For more information about RHEL system roles and how to apply them, see Introduction to
RHEL system roles.

26.7.1. Creating an XFS file system on a block device by using the storage RHEL
system role
The example Ansible playbook applies the storage role to create an XFS file system on a block device
using the default parameters.

NOTE

The storage role can create a file system only on an unpartitioned, whole disk or a logical
volume (LV). It cannot create the file system on a partition.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- hosts: managed-node-01.example.com
roles:
- rhel-system-roles.storage
vars:
storage_volumes:
- name: barefs
type: disk
disks:
- sdb
fs_type: xfs

The volume name (barefs in the example) is currently arbitrary. The storage role identifies
the volume by the disk device listed under the disks: attribute.

You can omit the fs_type: xfs line because XFS is the default file system in RHEL 8.

To create the file system on an LV, provide the LVM setup under the disks: attribute,
including the enclosing volume group. For details, see Creating or resizing a logical volume
by using the storage RHEL system role.
Do not provide the path to the LV device.

2. Validate the playbook syntax:

423
Red Hat Enterprise Linux 8 System Design Guide

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

26.7.2. Persistently mounting a file system by using the storage RHEL system role

The example Ansible applies the storage role to immediately and persistently mount an XFS file system.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- hosts: managed-node-01.example.com
roles:
- rhel-system-roles.storage
vars:
storage_volumes:
- name: barefs
type: disk
disks:
- sdb
fs_type: xfs
mount_point: /mnt/data
mount_user: somebody
mount_group: somegroup
mount_mode: 0755

This playbook adds the file system to the /etc/fstab file, and mounts the file system
immediately.

If the file system on the /dev/sdb device or the mount point directory do not exist, the
playbook creates them.

2. Validate the playbook syntax:

424
CHAPTER 26. MANAGING STORAGE DEVICES

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

26.7.3. Creating or resizing a logical volume by using the storage RHEL system role

Use the storage role to perform the following tasks:

To create an LVM logical volume in a volume group consisting of many disks

To resize an existing file system on LVM

To express an LVM volume size in percentage of the pool’s total size

If the volume group does not exist, the role creates it. If a logical volume exists in the volume group, it is
resized if the size does not match what is specified in the playbook.

If you are reducing a logical volume, to prevent data loss you must ensure that the file system on that
logical volume is not using the space in the logical volume that is being reduced.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Manage local storage
hosts: managed-node-01.example.com
tasks:
- name: Create logical volume
ansible.builtin.include_role:
name: rhel-system-roles.storage
vars:
storage_pools:
- name: myvg
disks:

425
Red Hat Enterprise Linux 8 System Design Guide

- sda
- sdb
- sdc
volumes:
- name: mylv
size: 2G
fs_type: ext4
mount_point: /mnt/data

The settings specified in the example playbook include the following:

size: <size>
You must specify the size by using units (for example, GiB) or percentage (for example,
60%).

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.storage/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

Verify that specified volume has been created or resized to the requested size:

# ansible managed-node-01.example.com -m command -a 'lvs myvg'

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

26.7.4. Enabling online block discard by using the storage RHEL system role

You can mount an XFS file system with the online block discard option to automatically discard unused
blocks.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

426
CHAPTER 26. MANAGING STORAGE DEVICES

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Manage local storage
hosts: managed-node-01.example.com
tasks:
- name: Enable online block discard
ansible.builtin.include_role:
name: rhel-system-roles.storage
vars:
storage_volumes:
- name: barefs
type: disk
disks:
- sdb
fs_type: xfs
mount_point: /mnt/data
mount_options: discard

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.storage/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

Verify that online block discard option is enabled:

# ansible managed-node-01.example.com -m command -a 'findmnt /mnt/data'

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

26.7.5. Creating and mounting an Ext4 file system by using the storage RHEL system
role
The example Ansible playbook applies the storage role to create and mount an Ext4 file system.

Prerequisites

427
Red Hat Enterprise Linux 8 System Design Guide

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- hosts: managed-node-01.example.com
roles:
- rhel-system-roles.storage
vars:
storage_volumes:
- name: barefs
type: disk
disks:
- sdb
fs_type: ext4
fs_label: label-name
mount_point: /mnt/data

The playbook creates the file system on the /dev/sdb disk.

The playbook persistently mounts the file system at the /mnt/data directory.

The label of the file system is label-name.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

26.7.6. Creating and mounting an Ext3 file system by using the storage RHEL system
role
The example Ansible playbook applies the storage role to create and mount an Ext3 file system.

Prerequisites

428
CHAPTER 26. MANAGING STORAGE DEVICES

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- hosts: all
roles:
- rhel-system-roles.storage
vars:
storage_volumes:
- name: barefs
type: disk
disks:
- sdb
fs_type: ext3
fs_label: label-name
mount_point: /mnt/data
mount_user: somebody
mount_group: somegroup
mount_mode: 0755

The playbook creates the file system on the /dev/sdb disk.

The playbook persistently mounts the file system at the /mnt/data directory.

The label of the file system is label-name.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

26.7.7. Creating a swap volume by using the storage RHEL system role

This section provides an example Ansible playbook. This playbook applies the storage role to create a
swap volume, if it does not exist, or to modify the swap volume, if it already exist, on a block device by
using the default parameters.

429
Red Hat Enterprise Linux 8 System Design Guide

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Create a disk device with swap
hosts: managed-node-01.example.com
roles:
- rhel-system-roles.storage
vars:
storage_volumes:
- name: swap_fs
type: disk
disks:
- /dev/sdb
size: 15 GiB
fs_type: swap

The volume name (swap_fs in the example) is currently arbitrary. The storage role identifies
the volume by the disk device listed under the disks: attribute.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

26.7.8. Configuring a RAID volume by using the storage RHEL system role

With the storage system role, you can configure a RAID volume on RHEL by using Red Hat Ansible
Automation Platform and Ansible-Core. Create an Ansible playbook with the parameters to configure a
RAID volume to suit your requirements.

430
CHAPTER 26. MANAGING STORAGE DEVICES


WARNING

Device names might change in certain circumstances, for example, when you add a
new disk to a system. Therefore, to prevent data loss, use persistent naming
attributes in the playbook. For more information about persistent naming attributes,
see Overview of persistent naming attributes.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Manage local storage
hosts: managed-node-01.example.com
tasks:
- name: Create a RAID on sdd, sde, sdf, and sdg
ansible.builtin.include_role:
name: rhel-system-roles.storage
vars:
storage_safe_mode: false
storage_volumes:
- name: data
type: raid
disks: [sdd, sde, sdf, sdg]
raid_level: raid0
raid_chunk_size: 32 KiB
mount_point: /mnt/data
state: present

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.storage/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

431
Red Hat Enterprise Linux 8 System Design Guide

Verification

Verify that the array was correctly created:

# ansible managed-node-01.example.com -m command -a 'mdadm --detail


/dev/md/data'

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

Managing RAID

26.7.9. Configuring an LVM pool with RAID by using the storage RHEL system role

With the storage system role, you can configure an LVM pool with RAID on RHEL by using Red Hat
Ansible Automation Platform. You can set up an Ansible playbook with the available parameters to
configure an LVM pool with RAID.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Manage local storage
hosts: managed-node-01.example.com
tasks:
- name: Configure LVM pool with RAID
ansible.builtin.include_role:
name: rhel-system-roles.storage
vars:
storage_safe_mode: false
storage_pools:
- name: my_pool
type: lvm
disks: [sdh, sdi]
raid_level: raid1
volumes:
- name: my_volume
size: "1 GiB"
mount_point: "/mnt/app/shared"
fs_type: xfs
state: present

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-

432
CHAPTER 26. MANAGING STORAGE DEVICES

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.storage/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

Verify that your pool is on RAID:

# ansible managed-node-01.example.com -m command -a 'lsblk'

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

Managing RAID

26.7.10. Configuring a stripe size for RAID LVM volumes by using the storage RHEL
system role
With the storage system role, you can configure a stripe size for RAID LVM volumes on RHEL by using
Red Hat Ansible Automation Platform. You can set up an Ansible playbook with the available parameters
to configure an LVM pool with RAID.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Manage local storage
hosts: managed-node-01.example.com
tasks:
- name: Configure stripe size for RAID LVM volumes
ansible.builtin.include_role:
name: rhel-system-roles.storage

433
Red Hat Enterprise Linux 8 System Design Guide

vars:
storage_safe_mode: false
storage_pools:
- name: my_pool
type: lvm
disks: [sdh, sdi]
volumes:
- name: my_volume
size: "1 GiB"
mount_point: "/mnt/app/shared"
fs_type: xfs
raid_level: raid0
raid_stripe_size: "256 KiB"
state: present

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.storage/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Verification

Verify that stripe size is set to the required size:

# ansible managed-node-01.example.com -m command -a 'lvs -o+stripesize


/dev/my_pool/my_volume'

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

Managing RAID

26.7.11. Configuring an LVM-VDO volume by using the storage RHEL system role

You can use the storage RHEL system role to create a VDO volume on LVM (LVM-VDO) with enabled
compression and deduplication.

NOTE

Because of the storage system role use of LVM-VDO, only one volume can be created
per pool.

434
CHAPTER 26. MANAGING STORAGE DEVICES

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Manage local storage
hosts: managed-node-01.example.com
tasks:
- name: Create LVM-VDO volume under volume group 'myvg'
ansible.builtin.include_role:
name: rhel-system-roles.storage
vars:
storage_pools:
- name: myvg
disks:
- /dev/sdb
volumes:
- name: mylv1
compression: true
deduplication: true
vdo_pool_size: 10 GiB
size: 30 GiB
mount_point: /mnt/app/shared

The settings specified in the example playbook include the following:

vdo_pool_size: <size>
The actual size that the volume takes on the device. You can specify the size in human-
readable format, such as 10 GiB. If you do not specify a unit, it defaults to bytes.
size: <size>
The virtual size of VDO volume.

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.storage/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

435
Red Hat Enterprise Linux 8 System Design Guide

Verification

View the current status of compression and deduplication:

$ ansible managed-node-01.example.com -m command -a 'lvs -


o+vdo_compression,vdo_compression_state,vdo_deduplication,vdo_index_state'
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
VDOCompression VDOCompressionState VDODeduplication VDOIndexState
mylv1 myvg vwi-a-v--- 3.00t vpool0 enabled
online enabled online

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

26.7.12. Creating a LUKS2 encrypted volume by using the storage RHEL system role

You can use the storage role to create and configure a volume encrypted with LUKS by running an
Ansible playbook.

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

Procedure

1. Store your sensitive variables in an encrypted file:

a. Create the vault:

$ ansible-vault create vault.yml


New Vault password: <vault_password>
Confirm New Vault password: <vault_password>

b. After the ansible-vault create command opens an editor, enter the sensitive data in the
<key>: <value> format:

luks_password: <password>

c. Save the changes, and close the editor. Ansible encrypts the data in the vault.

2. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Manage local storage
hosts: managed-node-01.example.com
vars_files:
- vault.yml

436
CHAPTER 26. MANAGING STORAGE DEVICES

tasks:
- name: Create and configure a volume encrypted with LUKS
ansible.builtin.include_role:
name: rhel-system-roles.storage
vars:
storage_volumes:
- name: barefs
type: disk
disks:
- sdb
fs_type: xfs
fs_label: <label>
mount_point: /mnt/data
encryption: true
encryption_password: "{{ luks_password }}"

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.storage/README.md file on the control node.

3. Validate the playbook syntax:

$ ansible-playbook --ask-vault-pass --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

4. Run the playbook:

$ ansible-playbook --ask-vault-pass ~/playbook.yml

Verification

1. Find the luksUUID value of the LUKS encrypted volume:

# ansible managed-node-01.example.com -m command -a 'cryptsetup luksUUID


/dev/sdb'

4e4e7970-1822-470e-b55a-e91efe5d0f5c

2. View the encryption status of the volume:

# ansible managed-node-01.example.com -m command -a 'cryptsetup status luks-


4e4e7970-1822-470e-b55a-e91efe5d0f5c'

/dev/mapper/luks-4e4e7970-1822-470e-b55a-e91efe5d0f5c is active and is in use.


type: LUKS2
cipher: aes-xts-plain64
keysize: 512 bits
key location: keyring
device: /dev/sdb
...

3. Verify the created LUKS encrypted volume:

437
Red Hat Enterprise Linux 8 System Design Guide

# ansible managed-node-01.example.com -m command -a 'cryptsetup luksDump


/dev/sdb'

LUKS header information


Version: 2
Epoch: 3
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: 4e4e7970-1822-470e-b55a-e91efe5d0f5c
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)

Data segments:
0: crypt
offset: 16777216 [bytes]
length: (whole device)
cipher: aes-xts-plain64
sector: 512 [bytes]
...

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

Encrypting block devices by using LUKS

Ansible vault

26.7.13. Creating shared LVM devices using the storage RHEL system role

You can use the storage RHEL system role to create shared LVM devices if you want your multiple
systems to access the same storage at the same time.

This can bring the following notable benefits:

Resource sharing

Flexibility in managing storage resources

Simplification of storage management tasks

Prerequisites

You have prepared the control node and the managed nodes

You are logged in to the control node as a user who can run playbooks on the managed nodes.

The account you use to connect to the managed nodes has sudo permissions on them.

lvmlockd is configured on the managed node. For more information, see Configuring LVM to
share SAN disks among multiple machines.

Procedure

438
CHAPTER 26. MANAGING STORAGE DEVICES

Procedure

1. Create a playbook file, for example ~/playbook.yml, with the following content:

---
- name: Manage local storage
hosts: managed-node-01.example.com
become: true
tasks:
- name: Create shared LVM device
ansible.builtin.include_role:
name: rhel-system-roles.storage
vars:
storage_pools:
- name: vg1
disks: /dev/vdb
type: lvm
shared: true
state: present
volumes:
- name: lv1
size: 4g
mount_point: /opt/test1
storage_safe_mode: false
storage_use_partitions: true

For details about all variables used in the playbook, see the /usr/share/ansible/roles/rhel-
system-roles.storage/README.md file on the control node.

2. Validate the playbook syntax:

$ ansible-playbook --syntax-check ~/playbook.yml

Note that this command only validates the syntax and does not protect against a wrong but valid
configuration.

3. Run the playbook:

$ ansible-playbook ~/playbook.yml

Additional resources

/usr/share/ansible/roles/rhel-system-roles.storage/README.md file

/usr/share/doc/rhel-system-roles/storage/ directory

439
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 27. DEDUPLICATING AND COMPRESSING


STORAGE

27.1. DEPLOYING VDO


As a system administrator, you can use VDO to create deduplicated and compressed storage pools.

27.1.1. Introduction to VDO


Virtual Data Optimizer (VDO) provides inline data reduction for Linux in the form of deduplication,
compression, and thin provisioning. When you set up a VDO volume, you specify a block device on which
to construct your VDO volume and the amount of logical storage you plan to present.

When hosting active VMs or containers, Red Hat recommends provisioning storage at a 10:1
logical to physical ratio: that is, if you are utilizing 1 TB of physical storage, you would present it
as 10 TB of logical storage.

For object storage, such as the type provided by Ceph, Red Hat recommends using a 3:1 logical
to physical ratio: that is, 1 TB of physical storage would present as 3 TB logical storage.

In either case, you can simply put a file system on top of the logical device presented by VDO and then
use it directly or as part of a distributed cloud storage architecture.

Because VDO is thinly provisioned, the file system and applications only see the logical space in use and
are not aware of the actual physical space available. Use scripting to monitor the actual available space
and generate an alert if use exceeds a threshold: for example, when the VDO volume is 80% full.

27.1.2. VDO deployment scenarios


You can deploy VDO in a variety of ways to provide deduplicated storage for:

both block and file access

both local and remote storage

Because VDO exposes its deduplicated storage as a standard Linux block device, you can use it with
standard file systems, iSCSI and FC target drivers, or as unified storage.

NOTE

Deployment of VDO volumes on top of Ceph RADOS Block Device (RBD) is currently
supported. However, the deployment of Red Hat Ceph Storage cluster components on
top of VDO volumes is currently not supported.

KVM
You can deploy VDO on a KVM server configured with Direct Attached Storage.

440
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

File systems
You can create file systems on top of VDO and expose them to NFS or CIFS users with the NFS server
or Samba.

Placement of VDO on iSCSI


You can export the entirety of the VDO storage target as an iSCSI target to remote iSCSI initiators.

When creating a VDO volume on iSCSI, you can place the VDO volume above or below the iSCSI layer.
Although there are many considerations to be made, some guidelines are provided here to help you
select the method that best suits your environment.

When placing the VDO volume on the iSCSI server (target) below the iSCSI layer:

The VDO volume is transparent to the initiator, similar to other iSCSI LUNs. Hiding the thin
provisioning and space savings from the client makes the appearance of the LUN easier to
monitor and maintain.

441
Red Hat Enterprise Linux 8 System Design Guide

There is decreased network traffic because there are no VDO metadata reads or writes, and
read verification for the dedupe advice does not occur across the network.

The memory and CPU resources being used on the iSCSI target can result in better
performance. For example, the ability to host an increased number of hypervisors because the
volume reduction is happening on the iSCSI target.

If the client implements encryption on the initiator and there is a VDO volume below the target,
you will not realize any space savings.

When placing the VDO volume on the iSCSI client (initiator) above the iSCSI layer:

There is a potential for lower network traffic across the network in ASYNC mode if achieving
high rates of space savings.

You can directly view and control the space savings and monitor usage.

If you want to encrypt the data, for example, using dm-crypt, you can implement VDO on top of
the crypt and take advantage of space efficiency.

LVM
On more feature-rich systems, you can use LVM to provide multiple logical unit numbers (LUNs) that
are all backed by the same deduplicated storage pool.

In the following diagram, the VDO target is registered as a physical volume so that it can be managed by
LVM. Multiple logical volumes (LV1 to LV4) are created out of the deduplicated storage pool. In this way,
VDO can support multiprotocol unified block or file access to the underlying deduplicated storage pool.

Deduplicated unified storage design enables for multiple file systems to collectively use the same
deduplication domain through the LVM tools. Also, file systems can take advantage of LVM snapshot,
copy-on-write, and shrink or grow features, all on top of VDO.

Encryption
Device Mapper (DM) mechanisms such as DM Crypt are compatible with VDO. Encrypting VDO volumes
helps ensure data security, and any file systems above VDO are still deduplicated.

442
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

IMPORTANT

Applying the encryption layer above VDO results in little if any data deduplication.
Encryption makes duplicate blocks different before VDO can deduplicate them.

Always place the encryption layer below VDO.

27.1.3. Components of a VDO volume


VDO uses a block device as a backing store, which can include an aggregation of physical storage
consisting of one or more disks, partitions, or even flat files. When a storage management tool creates a
VDO volume, VDO reserves volume space for the UDS index and VDO volume. The UDS index and the
VDO volume interact together to provide deduplicated block storage.

Figure 27.1. VDO disk organization

The VDO solution consists of the following components:

kvdo
A kernel module that loads into the Linux Device Mapper layer provides a deduplicated, compressed,
and thinly provisioned block storage volume.
The kvdo module exposes a block device. You can access this block device directly for block storage
or present it through a Linux file system, such as XFS or ext4.

When kvdo receives a request to read a logical block of data from a VDO volume, it maps the
requested logical block to the underlying physical block and then reads and returns the requested
data.

When kvdo receives a request to write a block of data to a VDO volume, it first checks whether the
request is a DISCARD or TRIM request or whether the data is uniformly zero. If either of these
conditions is true, kvdo updates its block map and acknowledges the request. Otherwise, VDO
processes and optimizes the data.

443
Red Hat Enterprise Linux 8 System Design Guide

uds
A kernel module that communicates with the Universal Deduplication Service (UDS) index on the
volume and analyzes data for duplicates. For each new piece of data, UDS quickly determines if that
piece is identical to any previously stored piece of data. If the index finds a match, the storage system
can then internally reference the existing item to avoid storing the same information more than once.
The UDS index runs inside the kernel as the uds kernel module.

Command line tools


For configuring and managing optimized storage.

27.1.4. The physical and logical size of a VDO volume


VDO utilizes physical, available physical, and logical size in the following ways:

Physical size
This is the same size as the underlying block device. VDO uses this storage for:

User data, which might be deduplicated and compressed

VDO metadata, such as the UDS index

Available physical size


This is the portion of the physical size that VDO is able to use for user data
It is equivalent to the physical size minus the size of the metadata, minus the remainder after dividing
the volume into slabs by the given slab size.

Logical Size
This is the provisioned size that the VDO volume presents to applications. It is usually larger than the
available physical size. If the --vdoLogicalSize option is not specified, then the provisioning of the
logical volume is now provisioned to a 1:1 ratio. For example, if a VDO volume is put on top of a 20
GB block device, then 2.5 GB is reserved for the UDS index (if the default index size is used). The
remaining 17.5 GB is provided for the VDO metadata and user data. As a result, the available storage
to consume is not more than 17.5 GB, and can be less due to metadata that makes up the actual VDO
volume.
VDO currently supports any logical size up to 254 times the size of the physical volume with an
absolute maximum logical size of 4PB.

Figure 27.2. VDO disk organization

In this figure, the VDO deduplicated storage target sits completely on top of the block device, meaning
the physical size of the VDO volume is the same size as the underlying block device.

Additional resources

For more information about how much storage VDO metadata requires on block devices of
444
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

For more information about how much storage VDO metadata requires on block devices of
different sizes, see Section 27.1.6.4, “Examples of VDO requirements by physical size” .

27.1.5. Slab size in VDO


The physical storage of the VDO volume is divided into a number of slabs. Each slab is a contiguous
region of the physical space. All of the slabs for a given volume have the same size, which can be any
power of 2 multiple of 128 MB up to 32 GB.

The default slab size is 2 GB to facilitate evaluating VDO on smaller test systems. A single VDO volume
can have up to 8192 slabs. Therefore, in the default configuration with 2 GB slabs, the maximum allowed
physical storage is 16 TB. When using 32 GB slabs, the maximum allowed physical storage is 256 TB.
VDO always reserves at least one entire slab for metadata, and therefore, the reserved slab cannot be
used for storing user data.

Slab size has no effect on the performance of the VDO volume.

Table 27.1. Recommended VDO slab sizes by physical volume size

Physical volume size Recommended slab size

10–99 GB 1 GB

100 GB – 1 TB 2 GB

2–256 TB 32 GB

The minimal disk usage for a VDO volume using default settings of 2 GB slab size and 0.25 dense index,
requires approx 4.7 GB. This provides slightly less than 2 GB of physical data to write at 0%
deduplication or compression.

Here, the minimal disk usage is the sum of the default slab size and dense index.

You can control the slab size by providing the --vdosettings 'vdo_slab_size_mb=size-in-megabytes'
option to the lvcreate command.

27.1.6. VDO requirements


VDO has certain requirements on its placement and your system resources.

27.1.6.1. VDO memory requirements

Each VDO volume has two distinct memory requirements:

The VDO module


VDO requires a fixed 38 MB of RAM and several variable amounts:

1.15 MB of RAM for each 1 MB of configured block map cache size. The block map cache
requires a minimum of 150MB RAM.

1.6 MB of RAM for each 1 TB of logical space.

268 MB of RAM for each 1 TB of physical storage managed by the volume.

445
Red Hat Enterprise Linux 8 System Design Guide

The UDS index


The Universal Deduplication Service (UDS) requires a minimum of 250 MB of RAM, which is also the
default amount that deduplication uses. You can configure the value when formatting a VDO volume,
because the value also affects the amount of storage that the index needs.
The memory required for the UDS index is determined by the index type and the required size of the
deduplication window:

Index type Deduplication window Note

Dense 1 TB per 1 GB of RAM A 1 GB dense index is generally sufficient for up to


4 TB of physical storage.

Sparse 10 TB per 1 GB of RAM A 1 GB sparse index is generally sufficient for up to


40 TB of physical storage.

NOTE

The minimal disk usage for a VDO volume using default settings of 2 GB slab size and
0.25 dense index, requires approx 4.7 GB. This provides slightly less than 2 GB of
physical data to write at 0% deduplication or compression.

Here, the minimal disk usage is the sum of the default slab size and dense index.

The UDS Sparse Indexing feature is the recommended mode for VDO. It relies on the temporal
locality of data and attempts to retain only the most relevant index entries in memory. With the
sparse index, UDS can maintain a deduplication window that is ten times larger than with dense, while
using the same amount of memory.

Although the sparse index provides the greatest coverage, the dense index provides more
deduplication advice. For most workloads, given the same amount of memory, the difference in
deduplication rates between dense and sparse indexes is negligible.

Additional resources

Examples of VDO requirements by physical size

27.1.6.2. VDO storage space requirements

You can configure a VDO volume to use up to 256 TB of physical storage. Only a certain part of the
physical storage is usable to store data.

VDO requires storage for two types of VDO metadata and for the UDS index. Use the following
calculations to determine the usable size of a VDO-managed volume:

The first type of VDO metadata uses approximately 1 MB for each 4 GB of physical storage plus
an additional 1 MB per slab.

The second type of VDO metadata consumes approximately 1.25 MB for each 1 GB of logical
storage, rounded up to the nearest slab.

The amount of storage required for the UDS index depends on the type of index and the

446
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

The amount of storage required for the UDS index depends on the type of index and the
amount of RAM allocated to the index. For each 1 GB of RAM, a dense UDS index uses 17 GB of
storage, and a sparse UDS index will use 170 GB of storage.

Additional resources

Examples of VDO requirements by physical size

Slab size in VDO

27.1.6.3. Placement of VDO in the storage stack

Place storage layers either above, or under the Virtual Data Optimizer (VDO), to fit the placement
requirements.

A VDO volume is a thin-provisioned block device. You can prevent running out of physical space by
placing the volume above a storage layer that you can expand at a later time. Examples of such
expandable storage are Logical Volume Manager (LVM) volumes, or Multiple Device Redundant Array
Inexpensive or Independent Disks (MD RAID) arrays.

You can place thick provisioned layers above VDO. There are two aspects of thick provisioned layers
that you must consider:

Writing new data to unused logical space on a thick device. When using VDO, or other thin-
provisioned storage, the device can report that it is out of space during this kind of write.

Overwriting used logical space on a thick device with new data. When using VDO, overwriting
data can also result in a report of the device being out of space.

These limitations affect all layers above the VDO layer. If you do not monitor the VDO device, you can
unexpectedly run out of physical space on the thick-provisioned volumes above VDO.

See the following examples of supported and unsupported VDO volume configurations.

Figure 27.3. Supported VDO volume configurations

Figure 27.4. Unsupported VDO volume configurations


447
Red Hat Enterprise Linux 8 System Design Guide

Figure 27.4. Unsupported VDO volume configurations

Additional resources

For more information about stacking VDO with LVM layers, see the Stacking LVM volumes
article.

27.1.6.4. Examples of VDO requirements by physical size

The following tables provide approximate system requirements of VDO based on the physical size of
the underlying volume. Each table lists requirements appropriate to the intended deployment, such as
primary storage or backup storage.

The exact numbers depend on your configuration of the VDO volume.

Primary storage deployment


In the primary storage case, the UDS index is between 0.01% to 25% the size of the physical size.

Table 27.2. Storage and memory requirements for primary storage

Physical size RAM usage: UDS RAM usage: VDO Disk usage Index type

10GB–1TB 250MB 472MB 2.5GB Dense

2–10TB 1GB 3GB 10GB Dense

250MB 22GB Sparse

11–50TB 2GB 14GB 170GB Sparse

448
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

Physical size RAM usage: UDS RAM usage: VDO Disk usage Index type

51–100TB 3GB 27GB 255GB Sparse

101–256TB 12GB 69GB 1020GB Sparse

Backup storage deployment


In the backup storage case, the UDS index covers the size of the backup set but is not bigger than
the physical size. If you expect the backup set or the physical size to grow in the future, factor this
into the index size.

Table 27.3. Storage and memory requirements for backup storage

Physical size RAM usage: UDS RAM usage: VDO Disk usage Index type

10GB–1TB 250MB 472MB 2.5 GB Dense

2–10TB 2GB 3GB 170GB Sparse

11–50TB 10GB 14GB 850GB Sparse

51–100TB 20GB 27GB 1700GB Sparse

101–256TB 26GB 69GB 3400GB Sparse

27.1.7. Installing VDO


You can install the VDO software necessary to create, mount, and manage VDO volumes.

Procedure

Install the VDO software:

# yum install lvm2 kmod-kvdo vdo

27.1.8. Creating a VDO volume


This procedure creates a VDO volume on a block device.

Prerequisites

Install the VDO software. See Section 27.1.7, “Installing VDO”.

Use expandable storage as the backing block device. For more information, see Section 27.1.6.3,
“Placement of VDO in the storage stack”.

Procedure

In all the following steps, replace vdo-name with the identifier you want to use for your VDO volume; for
449
Red Hat Enterprise Linux 8 System Design Guide

In all the following steps, replace vdo-name with the identifier you want to use for your VDO volume; for
example, vdo1. You must use a different name and device for each instance of VDO on the system.

1. Find a persistent name for the block device where you want to create the VDO volume. For
more information about persistent names, see Chapter 17, Overview of persistent naming
attributes.
If you use a non-persistent device name, then VDO might fail to start properly in the future if
the device name changes.

2. Create the VDO volume:

# vdo create \
--name=vdo-name \
--device=block-device \
--vdoLogicalSize=logical-size

Replace block-device with the persistent name of the block device where you want to
create the VDO volume. For example, /dev/disk/by-id/scsi-
3600508b1001c264ad2af21e903ad031f.

Replace logical-size with the amount of logical storage that the VDO volume should
present:

For active VMs or container storage, use logical size that is ten times the physical size
of your block device. For example, if your block device is 1TB in size, use 10T here.

For object storage, use logical size that is three times the physical size of your block
device. For example, if your block device is 1TB in size, use 3T here.

If the physical block device is larger than 16TiB, add the --vdoSlabSize=32G option to
increase the slab size on the volume to 32GiB.
Using the default slab size of 2GiB on block devices larger than 16TiB results in the vdo
create command failing with the following error:

vdo: ERROR - vdoformat: formatVDO failed on '/dev/device': VDO Status: Exceeds


maximum number of slabs supported

Example 27.1. Creating VDO for container storage

For example, to create a VDO volume for container storage on a 1TB block device, you might
use:

# vdo create \
--name=vdo1 \
--device=/dev/disk/by-id/scsi-3600508b1001c264ad2af21e903ad031f \
--vdoLogicalSize=10T

IMPORTANT

If a failure occurs when creating the VDO volume, remove the volume to clean up.
See Removing an unsuccessfully created VDO volume for details.

3. Create a file system on top of the VDO volume:

450
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

For the XFS file system:

# mkfs.xfs -K /dev/mapper/vdo-name

For the ext4 file system:

# mkfs.ext4 -E nodiscard /dev/mapper/vdo-name

NOTE

The purpose of the -K and -E nodiscard options on a freshly created VDO


volume is to not spend time sending requests, as it has no effect on an un-
allocated block. A fresh VDO volume starts out 100% un-allocated.

4. Use the following command to wait for the system to register the new device node:

# udevadm settle

Next steps

1. Mount the file system. See Section 27.1.9, “Mounting a VDO volume” for details.

2. Enable the discard feature for the file system on your VDO device. See Section 27.1.10,
“Enabling periodic block discard” for details.

Additional resources

vdo(8) man page on your system

27.1.9. Mounting a VDO volume


This procedure mounts a file system on a VDO volume, either manually or persistently.

Prerequisites

A VDO volume has been created on your system. For instructions, see Section 27.1.8, “Creating
a VDO volume”.

Procedure

To mount the file system on the VDO volume manually, use:

# mount /dev/mapper/vdo-name mount-point

To configure the file system to mount automatically at boot, add a line to the /etc/fstab file:

For the XFS file system:

/dev/mapper/vdo-name mount-point xfs defaults 0 0

For the ext4 file system:

451
Red Hat Enterprise Linux 8 System Design Guide

/dev/mapper/vdo-name mount-point ext4 defaults 0 0

If the VDO volume is located on a block device that requires network, such as iSCSI, add the
_netdev mount option.

Additional resources

vdo(8) man page on your system

For iSCSI and other block devices requiring network, see the systemd.mount(5) man page for
information about the _netdev mount option.

27.1.10. Enabling periodic block discard


You can enable a systemd timer to regularly discard unused blocks on all supported file systems.

Procedure

Enable and start the systemd timer:

# systemctl enable --now fstrim.timer


Created symlink /etc/systemd/system/timers.target.wants/fstrim.timer →
/usr/lib/systemd/system/fstrim.timer.

Verification

Verify the status of the timer:

# systemctl status fstrim.timer


fstrim.timer - Discard unused blocks once a week
Loaded: loaded (/usr/lib/systemd/system/fstrim.timer; enabled; vendor preset: disabled)
Active: active (waiting) since Wed 2023-05-17 13:24:41 CEST; 3min 15s ago
Trigger: Mon 2023-05-22 01:20:46 CEST; 4 days left
Docs: man:fstrim

May 17 13:24:41 localhost.localdomain systemd[1]: Started Discard unused blocks once a


week.

27.1.11. Monitoring VDO


This procedure describes how to obtain usage and efficiency information from a VDO volume.

Prerequisites

Install the VDO software. See Installing VDO.

Procedure

Use the vdostats utility to get information about a VDO volume:

# vdostats --human-readable

Device 1K-blocks Used Available Use% Space saving%

452
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

/dev/mapper/node1osd1 926.5G 21.0G 905.5G 2% 73%


/dev/mapper/node1osd2 926.5G 28.2G 898.3G 3% 64%

Additional resources

vdostats(8) man page on your system

27.2. MAINTAINING VDO


After deploying a VDO volume, you can perform certain tasks to maintain or optimize it. Some of the
following tasks are required for the correct functioning of VDO volumes.

Prerequisites

VDO is installed and deployed. See Section 27.1, “Deploying VDO” .

27.2.1. Managing free space on VDO volumes


VDO is a thinly provisioned block storage target. Because of that, you must actively monitor and manage
space usage on VDO volumes.

27.2.1.1. The physical and logical size of a VDO volume

VDO utilizes physical, available physical, and logical size in the following ways:

Physical size
This is the same size as the underlying block device. VDO uses this storage for:

User data, which might be deduplicated and compressed

VDO metadata, such as the UDS index

Available physical size


This is the portion of the physical size that VDO is able to use for user data
It is equivalent to the physical size minus the size of the metadata, minus the remainder after dividing
the volume into slabs by the given slab size.

Logical Size
This is the provisioned size that the VDO volume presents to applications. It is usually larger than the
available physical size. If the --vdoLogicalSize option is not specified, then the provisioning of the
logical volume is now provisioned to a 1:1 ratio. For example, if a VDO volume is put on top of a 20
GB block device, then 2.5 GB is reserved for the UDS index (if the default index size is used). The
remaining 17.5 GB is provided for the VDO metadata and user data. As a result, the available storage
to consume is not more than 17.5 GB, and can be less due to metadata that makes up the actual VDO
volume.
VDO currently supports any logical size up to 254 times the size of the physical volume with an
absolute maximum logical size of 4PB.

Figure 27.5. VDO disk organization


453
Red Hat Enterprise Linux 8 System Design Guide

Figure 27.5. VDO disk organization

In this figure, the VDO deduplicated storage target sits completely on top of the block device, meaning
the physical size of the VDO volume is the same size as the underlying block device.

Additional resources

For more information about how much storage VDO metadata requires on block devices of
different sizes, see Section 27.1.6.4, “Examples of VDO requirements by physical size” .

27.2.1.2. Thin provisioning in VDO

VDO is a thinly provisioned block storage target. The amount of physical space that a VDO volume uses
might differ from the size of the volume that is presented to users of the storage. You can make use of
this disparity to save on storage costs.

Out-of-space conditions
Take care to avoid unexpectedly running out of storage space, if the data written does not achieve the
expected rate of optimization.

Whenever the number of logical blocks (virtual storage) exceeds the number of physical blocks (actual
storage), it becomes possible for file systems and applications to unexpectedly run out of space. For
that reason, storage systems using VDO must provide you with a way of monitoring the size of the free
pool on the VDO volume.

You can determine the size of this free pool by using the vdostats utility. The default output of this
utility lists information for all running VDO volumes in a format similar to the Linux df utility. For example:

Device 1K-blocks Used Available Use%


/dev/mapper/vdo-name 211812352 105906176 105906176 50%

When the physical storage capacity of a VDO volume is almost full, VDO reports a warning in the system
log, similar to the following:

Oct 2 17:13:39 system lvm[13863]: Monitoring VDO pool vdo-name.


Oct 2 17:27:39 system lvm[13863]: WARNING: VDO pool vdo-name is now 80.69% full.
Oct 2 17:28:19 system lvm[13863]: WARNING: VDO pool vdo-name is now 85.25% full.
Oct 2 17:29:39 system lvm[13863]: WARNING: VDO pool vdo-name is now 90.64% full.
Oct 2 17:30:29 system lvm[13863]: WARNING: VDO pool vdo-name is now 96.07% full.

NOTE

These warning messages appear only when the lvm2-monitor service is running. It is
enabled by default.

How to prevent out-of-space conditions

454
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

If the size of free pool drops below a certain level, you can take action by:

Deleting data. This reclaims space whenever the deleted data is not duplicated. Deleting data
frees the space only after discards are issued.

Adding physical storage

IMPORTANT

Monitor physical space on your VDO volumes to prevent out-of-space situations.


Running out of physical blocks might result in losing recently written, unacknowledged
data on the VDO volume.

Thin provisioning and the TRIM and DISCARD commands


To benefit from the storage savings of thin provisioning, the physical storage layer needs to know when
data is deleted. File systems that work with thinly provisioned storage send TRIM or DISCARD
commands to inform the storage system when a logical block is no longer required.

Several methods of sending the TRIM or DISCARD commands are available:

With the discard mount option, the file systems can send these commands whenever a block is
deleted.

You can send the commands in a controlled manner by using utilities such as fstrim. These
utilities tell the file system to detect which logical blocks are unused and send the information to
the storage system in the form of a TRIM or DISCARD command.

The need to use TRIM or DISCARD on unused blocks is not unique to VDO. Any thinly provisioned
storage system has the same challenge.

27.2.1.3. Monitoring VDO

This procedure describes how to obtain usage and efficiency information from a VDO volume.

Prerequisites

Install the VDO software. See Installing VDO.

Procedure

Use the vdostats utility to get information about a VDO volume:

# vdostats --human-readable

Device 1K-blocks Used Available Use% Space saving%


/dev/mapper/node1osd1 926.5G 21.0G 905.5G 2% 73%
/dev/mapper/node1osd2 926.5G 28.2G 898.3G 3% 64%

Additional resources

vdostats(8) man page on your system

27.2.1.4. Reclaiming space for VDO on file systems

455
Red Hat Enterprise Linux 8 System Design Guide

This procedure reclaims storage space on a VDO volume that hosts a file system.

VDO cannot reclaim space unless file systems communicate that blocks are free using the DISCARD,
TRIM, or UNMAP commands.

Procedure

If the file system on your VDO volume supports discard operations, enable them. See
Discarding unused blocks .

For file systems that do not use DISCARD, TRIM, or UNMAP, you can manually reclaim free
space. Store a file consisting of binary zeros to fill the free space and then delete that file.

27.2.1.5. Reclaiming space for VDO without a file system

This procedure reclaims storage space on a VDO volume that is used as a block storage target without a
file system.

Procedure

Use the blkdiscard utility.


For example, a single VDO volume can be carved up into multiple subvolumes by deploying LVM
on top of it. Before deprovisioning a logical volume, use the blkdiscard utility to free the space
previously used by that logical volume.

LVM supports the REQ_DISCARD command and forwards the requests to VDO at the
appropriate logical block addresses in order to free the space. If you use other volume
managers, they also need to support REQ_DISCARD, or equivalently, UNMAP for SCSI devices
or TRIM for ATA devices.

Additional resources

blkdiscard(8) man page on your system

27.2.1.6. Reclaiming space for VDO on Fibre Channel or Ethernet network

This procedure reclaims storage space on VDO volumes (or portions of volumes) that are provisioned to
hosts on a Fibre Channel storage fabric or an Ethernet network using SCSI target frameworks such as
LIO or SCST.

Procedure

SCSI initiators can use the UNMAP command to free space on thinly provisioned storage
targets, but the SCSI target framework needs to be configured to advertise support for this
command. This is typically done by enabling thin provisioning on these volumes.
Verify support for UNMAP on Linux-based SCSI initiators by running the following command:

# sg_vpd --page=0xb0 /dev/device

In the output, verify that the Maximum unmap LBA count value is greater than zero.

27.2.2. Starting or stopping VDO volumes


You can start or stop a given VDO volume, or all VDO volumes, and their associated UDS indexes.

456
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

27.2.2.1. Started and activated VDO volumes

During the system boot, the vdo systemd unit automatically starts all VDO devices that are configured
as activated.

The vdo systemd unit is installed and enabled by default when the vdo package is installed. This unit
automatically runs the vdo start --all command at system startup to bring up all activated VDO
volumes.

You can also create a VDO volume that does not start automatically by adding the --activate=disabled
option to the vdo create command.

The starting order


Some systems might place LVM volumes both above VDO volumes and below them. On these systems,
it is necessary to start services in the right order:

1. The lower layer of LVM must start first. In most systems, starting this layer is configured
automatically when the LVM package is installed.

2. The vdo systemd unit must start then.

3. Finally, additional scripts must run in order to start LVM volumes or other services on top of the
running VDO volumes.

How long it takes to stop a volume


Stopping a VDO volume takes time based on the speed of your storage device and the amount of data
that the volume needs to write:

The volume always writes around 1GiB for every 1GiB of the UDS index.

The volume additionally writes the amount of data equal to the block map cache size plus up to
8MiB per slab.

The volume must finish processing all outstanding IO requests.

27.2.2.2. Starting a VDO volume

This procedure starts a given VDO volume or all VDO volumes on your system.

Procedure

To start a given VDO volume, use:

# vdo start --name=my-vdo

To start all VDO volumes, use:

# vdo start --all

Additional resources

vdo(8) man page on your system

27.2.2.3. Stopping a VDO volume

457
Red Hat Enterprise Linux 8 System Design Guide

This procedure stops a given VDO volume or all VDO volumes on your system.

Procedure

1. Stop the volume.

To stop a given VDO volume, use:

# vdo stop --name=my-vdo

To stop all VDO volumes, use:

# vdo stop --all

2. Wait for the volume to finish writing data to the disk.

Additional resources

vdo(8) man page on your system

27.2.2.4. Additional resources

If restarted after an unclean shutdown, VDO performs a rebuild to verify the consistency of its
metadata and repairs it if necessary. See Section 27.2.5, “Recovering a VDO volume after an
unclean shutdown” for more information about the rebuild process.

27.2.3. Automatically starting VDO volumes at system boot


You can configure VDO volumes so that they start automatically at system boot. You can also disable
the automatic start.

27.2.3.1. Started and activated VDO volumes

During the system boot, the vdo systemd unit automatically starts all VDO devices that are configured
as activated.

The vdo systemd unit is installed and enabled by default when the vdo package is installed. This unit
automatically runs the vdo start --all command at system startup to bring up all activated VDO
volumes.

You can also create a VDO volume that does not start automatically by adding the --activate=disabled
option to the vdo create command.

The starting order


Some systems might place LVM volumes both above VDO volumes and below them. On these systems,
it is necessary to start services in the right order:

1. The lower layer of LVM must start first. In most systems, starting this layer is configured
automatically when the LVM package is installed.

2. The vdo systemd unit must start then.

3. Finally, additional scripts must run in order to start LVM volumes or other services on top of the
running VDO volumes.

458
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

How long it takes to stop a volume


Stopping a VDO volume takes time based on the speed of your storage device and the amount of data
that the volume needs to write:

The volume always writes around 1GiB for every 1GiB of the UDS index.

The volume additionally writes the amount of data equal to the block map cache size plus up to
8MiB per slab.

The volume must finish processing all outstanding IO requests.

27.2.3.2. Activating a VDO volume

This procedure activates a VDO volume to enable it to start automatically.

Procedure

To activate a specific volume:

# vdo activate --name=my-vdo

To activate all volumes:

# vdo activate --all

Additional resources

vdo(8) man page on your system

27.2.3.3. Deactivating a VDO volume

This procedure deactivates a VDO volume to prevent it from starting automatically.

Procedure

To deactivate a specific volume:

# vdo deactivate --name=my-vdo

To deactivate all volumes:

# vdo deactivate --all

Additional resources

vdo(8) man page on your system

27.2.4. Selecting a VDO write mode


You can configure write mode for a VDO volume, based on what the underlying block device requires.
By default, VDO selects write mode automatically.

459
Red Hat Enterprise Linux 8 System Design Guide

27.2.4.1. VDO write modes

VDO supports the following write modes:

sync
When VDO is in sync mode, the layers above it assume that a write command writes data to
persistent storage. As a result, it is not necessary for the file system or application, for example, to
issue FLUSH or force unit access (FUA) requests to cause the data to become persistent at critical
points.
VDO must be set to sync mode only when the underlying storage guarantees that data is written to
persistent storage when the write command completes. That is, the storage must either have no
volatile write cache, or have a write through cache.

async
When VDO is in async mode, VDO does not guarantee that the data is written to persistent storage
when a write command is acknowledged. The file system or application must issue FLUSH or FUA
requests to ensure data persistence at critical points in each transaction.
VDO must be set to async mode if the underlying storage does not guarantee that data is written to
persistent storage when the write command completes; that is, when the storage has a volatile write
back cache.

async-unsafe
This mode has the same properties as async but it is not compliant with Atomicity, Consistency,
Isolation, Durability (ACID). Compared to async, async-unsafe has a better performance.


WARNING

When an application or a file system that assumes ACID compliance operates on


top of the VDO volume, async-unsafe mode might cause unexpected data loss.

auto
The auto mode automatically selects sync or async based on the characteristics of each device.
This is the default option.

27.2.4.2. The internal processing of VDO write modes

The write modes for VDO are sync and async. The following information describes the operations of
these modes.

If the kvdo module is operating in synchronous ( synch) mode:

1. It temporarily writes the data in the request to the allocated block and then acknowledges the
request.

2. Once the acknowledgment is complete, an attempt is made to deduplicate the block by


computing a MurmurHash-3 signature of the block data, which is sent to the VDO index.

3. If the VDO index contains an entry for a block with the same signature, kvdo reads the

460
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

3. If the VDO index contains an entry for a block with the same signature, kvdo reads the
indicated block and does a byte-by-byte comparison of the two blocks to verify that they are
identical.

4. If they are indeed identical, then kvdo updates its block map so that the logical block points to
the corresponding physical block and releases the allocated physical block.

5. If the VDO index did not contain an entry for the signature of the block being written, or the
indicated block does not actually contain the same data, kvdo updates its block map to make
the temporary physical block permanent.

If kvdo is operating in asynchronous ( async) mode:

1. Instead of writing the data, it will immediately acknowledge the request.

2. It will then attempt to deduplicate the block in same manner as described above.

3. If the block turns out to be a duplicate, kvdo updates its block map and releases the allocated
block. Otherwise, it writes the data in the request to the allocated block and updates the block
map to make the physical block permanent.

27.2.4.3. Checking the write mode on a VDO volume

This procedure lists the active write mode on a selected VDO volume.

Procedure

Use the following command to see the write mode used by a VDO volume:

# vdo status --name=my-vdo

The output lists:

The configured write policy, which is the option selected from sync, async, or auto

The write policy, which is the particular write mode that VDO applied, that is either sync or
async

27.2.4.4. Checking for a volatile cache

This procedure determines if a block device has a volatile cache or not. You can use the information to
choose between the sync and async VDO write modes.

Procedure

1. Use either of the following methods to determine if a device has a writeback cache:

Read the /sys/block/block-device/device/scsi_disk/identifier/cache_type sysfs file. For


example:

$ cat '/sys/block/sda/device/scsi_disk/7:0:0:0/cache_type'

write back

461
Red Hat Enterprise Linux 8 System Design Guide

$ cat '/sys/block/sdb/device/scsi_disk/1:2:0:0/cache_type'

None

Alternatively, you can find whether the above mentioned devices have a write cache or not
in the kernel boot log:

sd 7:0:0:0: [sda] Write cache: enabled, read cache: enabled, does not support DPO or
FUA
sd 1:2:0:0: [sdb] Write cache: disabled, read cache: disabled, supports DPO and FUA

2. In the previous examples:

Device sda indicates that it has a writeback cache. Use async mode for it.

Device sdb indicates that it does not have a writeback cache. Use sync mode for it.

You should configure VDO to use the sync write mode if the cache_type value is None or
write through.

27.2.4.5. Setting a VDO write mode

This procedure sets a write mode for a VDO volume, either for an existing one or when creating a new
volume.

IMPORTANT

Using an incorrect write mode might result in data loss after a power failure, a system
crash, or any unexpected loss of contact with the disk.

Prerequisites

Determine which write mode is correct for your device. See Section 27.2.4.4, “Checking for a
volatile cache”.

Procedure

You can set a write mode either on an existing VDO volume or when creating a new volume:

To modify an existing VDO volume, use:

# vdo changeWritePolicy --writePolicy=sync|async|async-unsafe|auto \


--name=vdo-name

To specify a write mode when creating a VDO volume, add the --


writePolicy=sync|async|async-unsafe|auto option to the vdo create command.

27.2.5. Recovering a VDO volume after an unclean shutdown


You can recover a VDO volume after an unclean shutdown to enable it to continue operating. The task is
mostly automated. Additionally, you can clean up after a VDO volume was unsuccessfully created
because of a failure in the process.

462
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

27.2.5.1. VDO write modes

VDO supports the following write modes:

sync
When VDO is in sync mode, the layers above it assume that a write command writes data to
persistent storage. As a result, it is not necessary for the file system or application, for example, to
issue FLUSH or force unit access (FUA) requests to cause the data to become persistent at critical
points.
VDO must be set to sync mode only when the underlying storage guarantees that data is written to
persistent storage when the write command completes. That is, the storage must either have no
volatile write cache, or have a write through cache.

async
When VDO is in async mode, VDO does not guarantee that the data is written to persistent storage
when a write command is acknowledged. The file system or application must issue FLUSH or FUA
requests to ensure data persistence at critical points in each transaction.
VDO must be set to async mode if the underlying storage does not guarantee that data is written to
persistent storage when the write command completes; that is, when the storage has a volatile write
back cache.

async-unsafe
This mode has the same properties as async but it is not compliant with Atomicity, Consistency,
Isolation, Durability (ACID). Compared to async, async-unsafe has a better performance.


WARNING

When an application or a file system that assumes ACID compliance operates on


top of the VDO volume, async-unsafe mode might cause unexpected data loss.

auto
The auto mode automatically selects sync or async based on the characteristics of each device.
This is the default option.

27.2.5.2. VDO volume recovery

When a VDO volume restarts after an unclean shutdown, VDO performs the following actions:

Verifies the consistency of the metadata on the volume.

Rebuilds a portion of the metadata to repair it if necessary.

Rebuilds are automatic and do not require user intervention.

VDO might rebuild different writes depending on the active write mode:

sync

If VDO was running on synchronous storage and write policy was set to sync, all data written to the

463
Red Hat Enterprise Linux 8 System Design Guide

If VDO was running on synchronous storage and write policy was set to sync, all data written to the
volume are fully recovered.
async
If the write policy was async, some writes might not be recovered if they were not made durable. This
is done by sending VDO a FLUSH command or a write I/O tagged with the FUA (force unit access)
flag. You can accomplish this from user mode by invoking a data integrity operation like fsync,
fdatasync, sync, or umount.

In either mode, some writes that were either unacknowledged or not followed by a flush might also be
rebuilt.

Automatic and manual recovery


When a VDO volume enters recovering operating mode, VDO automatically rebuilds the unclean VDO
volume after the it comes back online. This is called online recovery.

If VDO cannot recover a VDO volume successfully, it places the volume in read-only operating mode
that persists across volume restarts. You need to fix the problem manually by forcing a rebuild.

Additional resources

For more information about automatic and manual recovery and VDO operating modes, see
Section 27.2.5.3, “VDO operating modes” .

27.2.5.3. VDO operating modes

This section describes the modes that indicate whether a VDO volume is operating normally or is
recovering from an error.

You can display the current operating mode of a VDO volume using the vdostats --verbose device
command. See the Operating mode attribute in the output.

normal
This is the default operating mode. VDO volumes are always in normal mode, unless either of the
following states forces a different mode. A newly created VDO volume starts in normal mode.
recovering
When a VDO volume does not save all of its metadata before shutting down, it automatically enters
recovering mode the next time that it starts up. The typical reasons for entering this mode are
sudden power loss or a problem from the underlying storage device.
In recovering mode, VDO is fixing the references counts for each physical block of data on the
device. Recovery usually does not take very long. The time depends on how large the VDO volume is,
how fast the underlying storage device is, and how many other requests VDO is handling
simultaneously. The VDO volume functions normally with the following exceptions:

Initially, the amount of space available for write requests on the volume might be limited. As
more of the metadata is recovered, more free space becomes available.

Data written while the VDO volume is recovering might fail to deduplicate against data
written before the crash if that data is in a portion of the volume that has not yet been
recovered. VDO can compress data while recovering the volume. You can still read or
overwrite compressed blocks.

During an online recovery, certain statistics are unavailable: for example, blocks in use and
blocks free . These statistics become available when the rebuild is complete.

Response times for reads and writes might be slower than usual due to the ongoing recovery

464
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

Response times for reads and writes might be slower than usual due to the ongoing recovery
work

You can safely shut down the VDO volume in recovering mode. If the recovery does not finish
before shutting down, the device enters recovering mode again the next time that it starts up.

The VDO volume automatically exits recovering mode and moves to normal mode when it has fixed
all the reference counts. No administrator action is necessary. For details, see Section 27.2.5.4,
“Recovering a VDO volume online”.

read-only
When a VDO volume encounters a fatal internal error, it enters read-only mode. Events that might
cause read-only mode include metadata corruption or the backing storage device becoming read-
only. This mode is an error state.
In read-only mode, data reads work normally but data writes always fail. The VDO volume stays in
read-only mode until an administrator fixes the problem.

You can safely shut down a VDO volume in read-only mode. The mode usually persists after the
VDO volume is restarted. In rare cases, the VDO volume is not able to record the read-only state to
the backing storage device. In these cases, VDO attempts to do a recovery instead.

Once a volume is in read-only mode, there is no guarantee that data on the volume has not been lost
or corrupted. In such cases, Red Hat recommends copying the data out of the read-only volume and
possibly restoring the volume from backup.

If the risk of data corruption is acceptable, it is possible to force an offline rebuild of the VDO volume
metadata so the volume can be brought back online and made available. The integrity of the rebuilt
data cannot be guaranteed. For details, see Section 27.2.5.5, “Forcing an offline rebuild of a VDO
volume metadata”.

27.2.5.4. Recovering a VDO volume online

This procedure performs an online recovery on a VDO volume to recover metadata after an unclean
shutdown.

Procedure

1. If the VDO volume is not already started, start it:

# vdo start --name=my-vdo

No additional steps are necessary. The recovery runs in the background.

2. If you rely on volume statistics like blocks in use and blocks free , wait until they are available.

27.2.5.5. Forcing an offline rebuild of a VDO volume metadata

This procedure performs a forced offline rebuild of a VDO volume metadata to recover after an unclean
shutdown.

465
Red Hat Enterprise Linux 8 System Design Guide


WARNING

This procedure might cause data loss on the volume.

Prerequisites

The VDO volume is started.

Procedure

1. Check if the volume is in read-only mode. See the operating mode attribute in the command
output:

# vdo status --name=my-vdo

If the volume is not in read-only mode, it is not necessary to force an offline rebuild. Perform an
online recovery as described in Section 27.2.5.4, “Recovering a VDO volume online” .

2. Stop the volume if it is running:

# vdo stop --name=my-vdo

3. Restart the volume with the --forceRebuild option:

# vdo start --name=my-vdo --forceRebuild

27.2.5.6. Removing an unsuccessfully created VDO volume

This procedure cleans up a VDO volume in an intermediate state. A volume is left in an intermediate
state if a failure occurs when creating the volume. This might happen when, for example:

The system crashes

Power fails

The administrator interrupts a running vdo create command

Procedure

To clean up, remove the unsuccessfully created volume with the --force option:

# vdo remove --force --name=my-vdo

The --force option is required because the administrator might have caused a conflict by
changing the system configuration since the volume was unsuccessfully created.

Without the --force option, the vdo remove command fails with the following message:

[...]

466
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

A previous operation failed.


Recovery from the failure either failed or was interrupted.
Add '--force' to 'remove' to perform the following cleanup.
Steps to clean up VDO my-vdo:
umount -f /dev/mapper/my-vdo
udevadm settle
dmsetup remove my-vdo
vdo: ERROR - VDO volume my-vdo previous operation (create) is incomplete

27.2.6. Optimizing the UDS index


You can configure certain settings of the UDS index to optimize it on your system.

IMPORTANT

You cannot change the properties of the UDS index after creating the VDO volume.

27.2.6.1. Components of a VDO volume

VDO uses a block device as a backing store, which can include an aggregation of physical storage
consisting of one or more disks, partitions, or even flat files. When a storage management tool creates a
VDO volume, VDO reserves volume space for the UDS index and VDO volume. The UDS index and the
VDO volume interact together to provide deduplicated block storage.

Figure 27.6. VDO disk organization

The VDO solution consists of the following components:

kvdo
A kernel module that loads into the Linux Device Mapper layer provides a deduplicated, compressed,
and thinly provisioned block storage volume.
The kvdo module exposes a block device. You can access this block device directly for block storage
or present it through a Linux file system, such as XFS or ext4.

When kvdo receives a request to read a logical block of data from a VDO volume, it maps the
requested logical block to the underlying physical block and then reads and returns the requested
data.

When kvdo receives a request to write a block of data to a VDO volume, it first checks whether the
request is a DISCARD or TRIM request or whether the data is uniformly zero. If either of these
conditions is true, kvdo updates its block map and acknowledges the request. Otherwise, VDO
processes and optimizes the data.

uds
A kernel module that communicates with the Universal Deduplication Service (UDS) index on the
volume and analyzes data for duplicates. For each new piece of data, UDS quickly determines if that

467
Red Hat Enterprise Linux 8 System Design Guide

piece is identical to any previously stored piece of data. If the index finds a match, the storage system
can then internally reference the existing item to avoid storing the same information more than once.
The UDS index runs inside the kernel as the uds kernel module.

Command line tools


For configuring and managing optimized storage.

27.2.6.2. The UDS index

VDO uses a high-performance deduplication index called UDS to detect duplicate blocks of data as they
are being stored.

The UDS index provides the foundation of the VDO product. For each new piece of data, it quickly
determines if that piece is identical to any previously stored piece of data. If the index finds match, the
storage system can then internally reference the existing item to avoid storing the same information
more than once.

The UDS index runs inside the kernel as the uds kernel module.

The deduplication window is the number of previously written blocks that the index remembers. The size
of the deduplication window is configurable. For a given window size, the index requires a specific
amount of RAM and a specific amount of disk space. The size of the window is usually determined by
specifying the size of the index memory using the --indexMem=size option. VDO then determines the
amount of disk space to use automatically.

The UDS index consists of two parts:

A compact representation is used in memory that contains at most one entry per unique block.

An on-disk component that records the associated block names presented to the index as they
occur, in order.

UDS uses an average of 4 bytes per entry in memory, including cache.

The on-disk component maintains a bounded history of data passed to UDS. UDS provides
deduplication advice for data that falls within this deduplication window, containing the names of the
most recently seen blocks. The deduplication window allows UDS to index data as efficiently as possible
while limiting the amount of memory required to index large data repositories. Despite the bounded
nature of the deduplication window, most datasets which have high levels of deduplication also exhibit a
high degree of temporal locality — in other words, most deduplication occurs among sets of blocks that
were written at about the same time. Furthermore, in general, data being written is more likely to
duplicate data that was recently written than data that was written a long time ago. Therefore, for a
given workload over a given time interval, deduplication rates will often be the same whether UDS
indexes only the most recent data or all the data.

Because duplicate data tends to exhibit temporal locality, it is rarely necessary to index every block in
the storage system. Were this not so, the cost of index memory would outstrip the savings of reduced
storage costs from deduplication. Index size requirements are more closely related to the rate of data
ingestion. For example, consider a storage system with 100 TB of total capacity but with an ingestion
rate of 1 TB per week. With a deduplication window of 4 TB, UDS can detect most redundancy among the
data written within the last month.

27.2.6.3. Recommended UDS index configuration

This section describes the recommended options to use with the UDS index, based on your intended use

468
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

This section describes the recommended options to use with the UDS index, based on your intended use
case.

In general, Red Hat recommends using a sparse UDS index for all production use cases. This is an
extremely efficient indexing data structure, requiring approximately one-tenth of a byte of RAM per
block in its deduplication window. On disk, it requires approximately 72 bytes of disk space per block.
The minimum configuration of this index uses 256 MB of RAM and approximately 25 GB of space on
disk.

To use this configuration, specify the --sparseIndex=enabled --indexMem=0.25 options to the vdo
create command. This configuration results in a deduplication window of 2.5 TB (meaning it will
remember a history of 2.5 TB). For most use cases, a deduplication window of 2.5 TB is appropriate for
deduplicating storage pools that are up to 10 TB in size.

The default configuration of the index, however, is to use a dense index. This index is considerably less
efficient (by a factor of 10) in RAM, but it has much lower (also by a factor of 10) minimum required disk
space, making it more convenient for evaluation in constrained environments.

In general, a deduplication window that is one quarter of the physical size of a VDO volume is a
recommended configuration. However, this is not an actual requirement. Even small deduplication
windows (compared to the amount of physical storage) can find significant amounts of duplicate data in
many use cases. Larger windows may also be used, but it in most cases, there will be little additional
benefit to doing so.

Additional resources

Speak with your Red Hat Technical Account Manager representative for additional guidelines on
tuning this important system parameter.

27.2.7. Enabling or disabling deduplication in VDO


In some instances, you might want to temporarily disable deduplication of data being written to a VDO
volume while still retaining the ability to read to and write from the volume. Disabling deduplication
prevents subsequent writes from being deduplicated, but the data that was already deduplicated
remains so.

27.2.7.1. Deduplication in VDO

Deduplication is a technique for reducing the consumption of storage resources by eliminating multiple
copies of duplicate blocks.

Instead of writing the same data more than once, VDO detects each duplicate block and records it as a
reference to the original block. VDO maintains a mapping from logical block addresses, which are used
by the storage layer above VDO, to physical block addresses, which are used by the storage layer under
VDO.

After deduplication, multiple logical block addresses can be mapped to the same physical block address.
These are called shared blocks. Block sharing is invisible to users of the storage, who read and write
blocks as they would if VDO were not present.

When a shared block is overwritten, VDO allocates a new physical block for storing the new block data to
ensure that other logical block addresses that are mapped to the shared physical block are not modified.

27.2.7.2. Enabling deduplication on a VDO volume

This procedure restarts the associated UDS index and informs the VDO volume that deduplication is

469
Red Hat Enterprise Linux 8 System Design Guide

This procedure restarts the associated UDS index and informs the VDO volume that deduplication is
active again.

NOTE

Deduplication is enabled by default.

Procedure

To restart deduplication on a VDO volume, use the following command:

# vdo enableDeduplication --name=my-vdo

27.2.7.3. Disabling deduplication on a VDO volume

This procedure stops the associated UDS index and informs the VDO volume that deduplication is no
longer active.

Procedure

To stop deduplication on a VDO volume, use the following command:

# vdo disableDeduplication --name=my-vdo

You can also disable deduplication when creating a new VDO volume by adding the --
deduplication=disabled option to the vdo create command.

27.2.8. Enabling or disabling compression in VDO


VDO provides data compression. Disabling it can maximize performance and speed up processing of
data that is unlikely to compress. Re-enabling it can increase space savings.

27.2.8.1. Compression in VDO

In addition to block-level deduplication, VDO also provides inline block-level compression using the
HIOPS Compression™ technology.

VDO volume compression is on by default.

While deduplication is the optimal solution for virtual machine environments and backup applications,
compression works very well with structured and unstructured file formats that do not typically exhibit
block-level redundancy, such as log files and databases.

Compression operates on blocks that have not been identified as duplicates. When VDO sees unique
data for the first time, it compresses the data. Subsequent copies of data that have already been stored
are deduplicated without requiring an additional compression step.

The compression feature is based on a parallelized packaging algorithm that enables it to handle many
compression operations at once. After first storing the block and responding to the requestor, a best-fit
packing algorithm finds multiple blocks that, when compressed, can fit into a single physical block. After
it is determined that a particular physical block is unlikely to hold additional compressed blocks, it is
written to storage and the uncompressed blocks are freed and reused.

By performing the compression and packaging operations after having already responded to the

470
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

By performing the compression and packaging operations after having already responded to the
requestor, using compression imposes a minimal latency penalty.

27.2.8.2. Enabling compression on a VDO volume

This procedure enables compression on a VDO volume to increase space savings.

NOTE

Compression is enabled by default.

Procedure

To start it again, use the following command:

# vdo enableCompression --name=my-vdo

27.2.8.3. Disabling compression on a VDO volume

This procedure stops compression on a VDO volume to maximize performance or to speed processing
of data that is unlikely to compress.

Procedure

To stop compression on an existing VDO volume, use the following command:

# vdo disableCompression --name=my-vdo

Alternatively, you can disable compression by adding the --compression=disabled option to


the vdo create command when creating a new volume.

27.2.9. Increasing the size of a VDO volume


You can increase the physical size of a VDO volume to utilize more underlying storage capacity, or the
logical size to provide more capacity on the volume.

27.2.9.1. The physical and logical size of a VDO volume

VDO utilizes physical, available physical, and logical size in the following ways:

Physical size
This is the same size as the underlying block device. VDO uses this storage for:

User data, which might be deduplicated and compressed

VDO metadata, such as the UDS index

Available physical size


This is the portion of the physical size that VDO is able to use for user data
It is equivalent to the physical size minus the size of the metadata, minus the remainder after dividing
the volume into slabs by the given slab size.

471
Red Hat Enterprise Linux 8 System Design Guide

Logical Size
This is the provisioned size that the VDO volume presents to applications. It is usually larger than the
available physical size. If the --vdoLogicalSize option is not specified, then the provisioning of the
logical volume is now provisioned to a 1:1 ratio. For example, if a VDO volume is put on top of a 20
GB block device, then 2.5 GB is reserved for the UDS index (if the default index size is used). The
remaining 17.5 GB is provided for the VDO metadata and user data. As a result, the available storage
to consume is not more than 17.5 GB, and can be less due to metadata that makes up the actual VDO
volume.
VDO currently supports any logical size up to 254 times the size of the physical volume with an
absolute maximum logical size of 4PB.

Figure 27.7. VDO disk organization

In this figure, the VDO deduplicated storage target sits completely on top of the block device, meaning
the physical size of the VDO volume is the same size as the underlying block device.

Additional resources

For more information about how much storage VDO metadata requires on block devices of
different sizes, see Section 27.1.6.4, “Examples of VDO requirements by physical size” .

27.2.9.2. Thin provisioning in VDO

VDO is a thinly provisioned block storage target. The amount of physical space that a VDO volume uses
might differ from the size of the volume that is presented to users of the storage. You can make use of
this disparity to save on storage costs.

Out-of-space conditions
Take care to avoid unexpectedly running out of storage space, if the data written does not achieve the
expected rate of optimization.

Whenever the number of logical blocks (virtual storage) exceeds the number of physical blocks (actual
storage), it becomes possible for file systems and applications to unexpectedly run out of space. For
that reason, storage systems using VDO must provide you with a way of monitoring the size of the free
pool on the VDO volume.

You can determine the size of this free pool by using the vdostats utility. The default output of this
utility lists information for all running VDO volumes in a format similar to the Linux df utility. For example:

Device 1K-blocks Used Available Use%


/dev/mapper/vdo-name 211812352 105906176 105906176 50%

When the physical storage capacity of a VDO volume is almost full, VDO reports a warning in the system
log, similar to the following:

472
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

Oct 2 17:13:39 system lvm[13863]: Monitoring VDO pool vdo-name.


Oct 2 17:27:39 system lvm[13863]: WARNING: VDO pool vdo-name is now 80.69% full.
Oct 2 17:28:19 system lvm[13863]: WARNING: VDO pool vdo-name is now 85.25% full.
Oct 2 17:29:39 system lvm[13863]: WARNING: VDO pool vdo-name is now 90.64% full.
Oct 2 17:30:29 system lvm[13863]: WARNING: VDO pool vdo-name is now 96.07% full.

NOTE

These warning messages appear only when the lvm2-monitor service is running. It is
enabled by default.

How to prevent out-of-space conditions


If the size of free pool drops below a certain level, you can take action by:

Deleting data. This reclaims space whenever the deleted data is not duplicated. Deleting data
frees the space only after discards are issued.

Adding physical storage

IMPORTANT

Monitor physical space on your VDO volumes to prevent out-of-space situations.


Running out of physical blocks might result in losing recently written, unacknowledged
data on the VDO volume.

Thin provisioning and the TRIM and DISCARD commands


To benefit from the storage savings of thin provisioning, the physical storage layer needs to know when
data is deleted. File systems that work with thinly provisioned storage send TRIM or DISCARD
commands to inform the storage system when a logical block is no longer required.

Several methods of sending the TRIM or DISCARD commands are available:

With the discard mount option, the file systems can send these commands whenever a block is
deleted.

You can send the commands in a controlled manner by using utilities such as fstrim. These
utilities tell the file system to detect which logical blocks are unused and send the information to
the storage system in the form of a TRIM or DISCARD command.

The need to use TRIM or DISCARD on unused blocks is not unique to VDO. Any thinly provisioned
storage system has the same challenge.

27.2.9.3. Increasing the logical size of a VDO volume

This procedure increases the logical size of a given VDO volume. It enables you to initially create VDO
volumes that have a logical size small enough to be safe from running out of space. After some period of
time, you can evaluate the actual rate of data reduction, and if sufficient, you can grow the logical size of
the VDO volume to take advantage of the space savings.

It is not possible to decrease the logical size of a VDO volume.

Procedure

473
Red Hat Enterprise Linux 8 System Design Guide

To grow the logical size, use:

# vdo growLogical --name=my-vdo \


--vdoLogicalSize=new-logical-size

When the logical size increases, VDO informs any devices or file systems on top of the volume
of the new size.

27.2.9.4. Increasing the physical size of a VDO volume

This procedure increases the amount of physical storage available to a VDO volume.

It is not possible to shrink a VDO volume in this way.

Prerequisites

The underlying block device has a larger capacity than the current physical size of the VDO
volume.
If it does not, you can attempt to increase the size of the device. The exact procedure depends
on the type of the device. For example, to resize an MBR or GPT partition, see the Resizing a
partition section in the Managing storage devices guide.

Procedure

Add the new physical storage space to the VDO volume:

# vdo growPhysical --name=my-vdo

27.2.10. Removing VDO volumes


You can remove an existing VDO volume on your system.

27.2.10.1. Removing a working VDO volume

This procedure removes a VDO volume and its associated UDS index.

Procedure

1. Unmount the file systems and stop the applications that are using the storage on the VDO
volume.

2. To remove the VDO volume from your system, use:

# vdo remove --name=my-vdo

27.2.10.2. Removing an unsuccessfully created VDO volume

This procedure cleans up a VDO volume in an intermediate state. A volume is left in an intermediate
state if a failure occurs when creating the volume. This might happen when, for example:

The system crashes

Power fails

474
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

The administrator interrupts a running vdo create command

Procedure

To clean up, remove the unsuccessfully created volume with the --force option:

# vdo remove --force --name=my-vdo

The --force option is required because the administrator might have caused a conflict by
changing the system configuration since the volume was unsuccessfully created.

Without the --force option, the vdo remove command fails with the following message:

[...]
A previous operation failed.
Recovery from the failure either failed or was interrupted.
Add '--force' to 'remove' to perform the following cleanup.
Steps to clean up VDO my-vdo:
umount -f /dev/mapper/my-vdo
udevadm settle
dmsetup remove my-vdo
vdo: ERROR - VDO volume my-vdo previous operation (create) is incomplete

27.2.11. Additional resources


You can use the Ansible tool to automate VDO deployment and administration. For details, see:

Ansible documentation: https://docs.ansible.com/

VDO Ansible module documentation:


https://docs.ansible.com/ansible/latest/modules/vdo_module.html

27.3. DISCARDING UNUSED BLOCKS


You can perform or schedule discard operations on block devices that support them. The block discard
operation communicates to the underlying storage which filesystem blocks are no longer in use by the
mounted filesystem. Block discard operations allow SSDs to optimize garbage collection routines, and
they can inform thinly-provisioned storage to repurpose unused physical blocks.

Requirements

The block device underlying the file system must support physical discard operations.
Physical discard operations are supported if the value in the
/sys/block/<device>/queue/discard_max_bytes file is not zero.

27.3.1. Types of block discard operations


You can run discard operations using different methods:

Batch discard
Is triggered explicitly by the user and discards all unused blocks in the selected file systems.
Online discard

Is specified at mount time and triggers in real time without user intervention. Online discard
475
Red Hat Enterprise Linux 8 System Design Guide

Is specified at mount time and triggers in real time without user intervention. Online discard
operations discard only blocks that are transitioning from the used to the free state.
Periodic discard
Are batch operations that are run regularly by a systemd service.

All types are supported by the XFS and ext4 file systems.

Recommendations
Red Hat recommends that you use batch or periodic discard.

Use online discard only if:

the system’s workload is such that batch discard is not feasible, or

online discard operations are necessary to maintain performance.

27.3.2. Performing batch block discard


You can perform a batch block discard operation to discard unused blocks on a mounted file system.

Prerequisites

The file system is mounted.

The block device underlying the file system supports physical discard operations.

Procedure

Use the fstrim utility:

To perform discard only on a selected file system, use:

# fstrim mount-point

To perform discard on all mounted file systems, use:

# fstrim --all

If you execute the fstrim command on:

a device that does not support discard operations, or

a logical device (LVM or MD) composed of multiple devices, where any one of the device does
not support discard operations,

the following message displays:

# fstrim /mnt/non_discard

fstrim: /mnt/non_discard: the discard operation is not supported

Additional resources

fstrim(8) man page on your system

476
CHAPTER 27. DEDUPLICATING AND COMPRESSING STORAGE

27.3.3. Enabling online block discard


You can perform online block discard operations to automatically discard unused blocks on all supported
file systems.

Procedure

Enable online discard at mount time:

When mounting a file system manually, add the -o discard mount option:

# mount -o discard device mount-point

When mounting a file system persistently, add the discard option to the mount entry in the
/etc/fstab file.

Additional resources

mount(8) and fstab(5) man pages on your system

27.3.4. Enabling periodic block discard


You can enable a systemd timer to regularly discard unused blocks on all supported file systems.

Procedure

Enable and start the systemd timer:

# systemctl enable --now fstrim.timer


Created symlink /etc/systemd/system/timers.target.wants/fstrim.timer →
/usr/lib/systemd/system/fstrim.timer.

Verification

Verify the status of the timer:

# systemctl status fstrim.timer


fstrim.timer - Discard unused blocks once a week
Loaded: loaded (/usr/lib/systemd/system/fstrim.timer; enabled; vendor preset: disabled)
Active: active (waiting) since Wed 2023-05-17 13:24:41 CEST; 3min 15s ago
Trigger: Mon 2023-05-22 01:20:46 CEST; 4 days left
Docs: man:fstrim

May 17 13:24:41 localhost.localdomain systemd[1]: Started Discard unused blocks once a


week.

477
Red Hat Enterprise Linux 8 System Design Guide

PART V. DESIGN OF LOG FILE

478
CHAPTER 28. AUDITING THE SYSTEM

CHAPTER 28. AUDITING THE SYSTEM


Audit does not provide additional security to your system; rather, it can be used to discover violations of
security policies used on your system. These violations can further be prevented by additional security
measures such as SELinux.

28.1. LINUX AUDIT


The Linux Audit system provides a way to track security-relevant information about your system. Based
on pre-configured rules, Audit generates log entries to record as much information about the events
that are happening on your system as possible. This information is crucial for mission-critical
environments to determine the violator of the security policy and the actions they performed.

The following list summarizes some of the information that Audit is capable of recording in its log files:

Date and time, type, and outcome of an event

Sensitivity labels of subjects and objects

Association of an event with the identity of the user who triggered the event

All modifications to Audit configuration and attempts to access Audit log files

All uses of authentication mechanisms, such as SSH, Kerberos, and others

Changes to any trusted database, such as /etc/passwd

Attempts to import or export information into or from the system

Include or exclude events based on user identity, subject and object labels, and other attributes

The use of the Audit system is also a requirement for a number of security-related certifications. Audit is
designed to meet or exceed the requirements of the following certifications or compliance guides:

Controlled Access Protection Profile (CAPP)

Labeled Security Protection Profile (LSPP)

Rule Set Base Access Control (RSBAC)

National Industrial Security Program Operating Manual (NISPOM)

Federal Information Security Management Act (FISMA)

Payment Card Industry — Data Security Standard (PCI-DSS)

Security Technical Implementation Guides (STIG)

Audit has also been:

Evaluated by National Information Assurance Partnership (NIAP) and Best Security Industries
(BSI)

Certified to LSPP/CAPP/RSBAC/EAL4+ on Red Hat Enterprise Linux 5

Certified to Operating System Protection Profile / Evaluation Assurance Level 4+


(OSPP/EAL4+) on Red Hat Enterprise Linux 6

479
Red Hat Enterprise Linux 8 System Design Guide

Use Cases

Watching file access


Audit can track whether a file or a directory has been accessed, modified, executed, or the file’s
attributes have been changed. This is useful, for example, to detect access to important files and
have an Audit trail available in case one of these files is corrupted.
Monitoring system calls
Audit can be configured to generate a log entry every time a particular system call is used. This can
be used, for example, to track changes to the system time by monitoring the settimeofday,
clock_adjtime, and other time-related system calls.
Recording commands run by a user
Audit can track whether a file has been executed, so rules can be defined to record every execution
of a particular command. For example, a rule can be defined for every executable in the /bin
directory. The resulting log entries can then be searched by user ID to generate an audit trail of
executed commands per user.
Recording execution of system pathnames
Aside from watching file access which translates a path to an inode at rule invocation, Audit can now
watch the execution of a path even if it does not exist at rule invocation, or if the file is replaced after
rule invocation. This allows rules to continue to work after upgrading a program executable or before
it is even installed.
Recording security events
The pam_faillock authentication module is capable of recording failed login attempts. Audit can be
set up to record failed login attempts as well and provides additional information about the user who
attempted to log in.
Searching for events
Audit provides the ausearch utility, which can be used to filter the log entries and provide a
complete audit trail based on several conditions.
Running summary reports
The aureport utility can be used to generate, among other things, daily reports of recorded events. A
system administrator can then analyze these reports and investigate suspicious activity further.
Monitoring network access
The nftables, iptables, and ebtables utilities can be configured to trigger Audit events, allowing
system administrators to monitor network access.

NOTE

System performance may be affected depending on the amount of information that is


collected by Audit.

28.2. AUDIT SYSTEM ARCHITECTURE


The Audit system consists of two main parts: the user-space applications and utilities, and the kernel-
side system call processing. The kernel component receives system calls from user-space applications
and filters them through one of the following filters: user, task, fstype, or exit.

After a system call passes the exclude filter, it is sent through one of the aforementioned filters, which,
based on the Audit rule configuration, sends it to the Audit daemon for further processing.

The user-space Audit daemon collects the information from the kernel and creates entries in a log file.
480
CHAPTER 28. AUDITING THE SYSTEM

The user-space Audit daemon collects the information from the kernel and creates entries in a log file.
Other Audit user-space utilities interact with the Audit daemon, the kernel Audit component, or the
Audit log files:

The auditctl Audit control utility interacts with the kernel Audit component to manage rules and
to control many settings and parameters of the event generation process.

The remaining Audit utilities take the contents of the Audit log files as input and generate
output based on user’s requirements. For example, the aureport utility generates a report of all
recorded events.

In RHEL 8, the Audit dispatcher daemon (audisp) functionality is integrated in the Audit daemon
(auditd). Configuration files of plugins for the interaction of real-time analytical programs with Audit
events are located in the /etc/audit/plugins.d/ directory by default.

28.3. CONFIGURING AUDITD FOR A SECURE ENVIRONMENT


The default auditd configuration should be suitable for most environments. However, if your
environment must meet strict security policies, you can change the following settings for the Audit
daemon configuration in the /etc/audit/auditd.conf file:

log_file
The directory that holds the Audit log files (usually /var/log/audit/) should reside on a separate
mount point. This prevents other processes from consuming space in this directory and provides
accurate detection of the remaining space for the Audit daemon.
max_log_file
Specifies the maximum size of a single Audit log file, must be set to make full use of the available
space on the partition that holds the Audit log files. The max_log_file` parameter specifies the
maximum file size in megabytes. The value given must be numeric.
max_log_file_action
Decides what action is taken once the limit set in max_log_file is reached, should be set to
keep_logs to prevent Audit log files from being overwritten.
space_left
Specifies the amount of free space left on the disk for which an action that is set in the
space_left_action parameter is triggered. Must be set to a number that gives the administrator
enough time to respond and free up disk space. The space_left value depends on the rate at which
the Audit log files are generated. If the value of space_left is specified as a whole number, it is
interpreted as an absolute size in megabytes (MiB). If the value is specified as a number between 1
and 99 followed by a percentage sign (for example, 5%), the Audit daemon calculates the absolute
size in megabytes based on the size of the file system containing log_file.
space_left_action
It is recommended to set the space_left_action parameter to email or exec with an appropriate
notification method.
admin_space_left
Specifies the absolute minimum amount of free space for which an action that is set in the
admin_space_left_action parameter is triggered, must be set to a value that leaves enough space
to log actions performed by the administrator. The numeric value for this parameter should be lower
than the number for space_left. You can also append a percent sign (for example, 1%) to the number
to have the audit daemon calculate the number based on the disk partition size.
admin_space_left_action

Should be set to single to put the system into single-user mode and allow the administrator to free
481
Red Hat Enterprise Linux 8 System Design Guide

Should be set to single to put the system into single-user mode and allow the administrator to free
up some disk space.
disk_full_action
Specifies an action that is triggered when no free space is available on the partition that holds the
Audit log files, must be set to halt or single. This ensures that the system is either shut down or
operating in single-user mode when Audit can no longer log events.
disk_error_action
Specifies an action that is triggered in case an error is detected on the partition that holds the Audit
log files, must be set to syslog, single, or halt, depending on your local security policies regarding
the handling of hardware malfunctions.
flush
Should be set to incremental_async. It works in combination with the freq parameter, which
determines how many records can be sent to the disk before forcing a hard synchronization with the
hard drive. The freq parameter should be set to 100. These parameters assure that Audit event data
is synchronized with the log files on the disk while keeping good performance for bursts of activity.

The remaining configuration options should be set according to your local security policy.

28.4. STARTING AND CONTROLLING AUDITD


After auditd is configured, start the service to collect Audit information and store it in the log files. Use
the following command as the root user to start auditd:

# service auditd start

To configure auditd to start at boot time:

# systemctl enable auditd

You can temporarily disable auditd with the # auditctl -e 0 command and re-enable it with # auditctl -e
1.

You can perform other actions on auditd by using the service auditd <action> command, where
<action> can be one of the following:

stop
Stops auditd.
restart
Restarts auditd.
reload or force-reload
Reloads the configuration of auditd from the /etc/audit/auditd.conf file.
rotate
Rotates the log files in the /var/log/audit/ directory.
resume
Resumes logging of Audit events after it has been previously suspended, for example, when there is
not enough free space on the disk partition that holds the Audit log files.
condrestart or try-restart
Restarts auditd only if it is already running.
status

482
CHAPTER 28. AUDITING THE SYSTEM

Displays the running status of auditd.

NOTE

The service command is the only way to correctly interact with the auditd daemon. You
need to use the service command so that the auid value is properly recorded. You can
use the systemctl command only for two actions: enable and status.

28.5. UNDERSTANDING AUDIT LOG FILES


By default, the Audit system stores log entries in the /var/log/audit/audit.log file; if log rotation is
enabled, rotated audit.log files are stored in the same directory.

Add the following Audit rule to log every attempt to read or modify the /etc/ssh/sshd_config file:

# auditctl -w /etc/ssh/sshd_config -p warx -k sshd_config

If the auditd daemon is running, for example, using the following command creates a new event in the
Audit log file:

$ cat /etc/ssh/sshd_config

This event in the audit.log file looks as follows:

type=SYSCALL msg=audit(1364481363.243:24287): arch=c000003e syscall=2 success=no exit=-13


a0=7fffd19c5592 a1=0 a2=7fffd19c4b50 a3=a items=1 ppid=2686 pid=3538 auid=1000 uid=1000
gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts0 ses=1
comm="cat" exe="/bin/cat" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
key="sshd_config"
type=CWD msg=audit(1364481363.243:24287): cwd="/home/shadowman"
type=PATH msg=audit(1364481363.243:24287): item=0 name="/etc/ssh/sshd_config" inode=409248
dev=fd:00 mode=0100600 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:etc_t:s0
nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
type=PROCTITLE msg=audit(1364481363.243:24287) :
proctitle=636174002F6574632F7373682F737368645F636F6E666967

The above event consists of four records, which share the same time stamp and serial number. Records
always start with the type= keyword. Each record consists of several name=value pairs separated by a
white space or a comma. A detailed analysis of the above event follows:

First Record

type=SYSCALL
The type field contains the type of the record. In this example, the SYSCALL value specifies that this
record was triggered by a system call to the kernel.

msg=audit(1364481363.243:24287):
The msg field records:

A time stamp and a unique ID of the record in the form audit(time_stamp:ID). Multiple
records can share the same time stamp and ID if they were generated as part of the same
Audit event. The time stamp is using the Unix time format - seconds since 00:00:00 UTC on
1 January 1970.

483
Red Hat Enterprise Linux 8 System Design Guide

Various event-specific name=value pairs provided by the kernel or user-space applications.

arch=c000003e
The arch field contains information about the CPU architecture of the system. The value, c000003e,
is encoded in hexadecimal notation. When searching Audit records with the ausearch command, use
the -i or --interpret option to automatically convert hexadecimal values into their human-readable
equivalents. The c000003e value is interpreted as x86_64.
syscall=2
The syscall field records the type of the system call that was sent to the kernel. The value, 2, can be
matched with its human-readable equivalent in the /usr/include/asm/unistd_64.h file. In this case, 2
is the open system call. Note that the ausyscall utility allows you to convert system call numbers to
their human-readable equivalents. Use the ausyscall --dump command to display a listing of all
system calls along with their numbers. For more information, see the ausyscall(8) man page.
success=no
The success field records whether the system call recorded in that particular event succeeded or
failed. In this case, the call did not succeed.
exit=-13
The exit field contains a value that specifies the exit code returned by the system call. This value
varies for a different system call. You can interpret the value to its human-readable equivalent with
the following command:

# ausearch --interpret --exit -13

Note that the previous example assumes that your Audit log contains an event that failed with exit
code -13.

a0=7fffd19c5592, a1=0, a2=7fffd19c5592, a3=a


The a0 to a3 fields record the first four arguments, encoded in hexadecimal notation, of the system
call in this event. These arguments depend on the system call that is used; they can be interpreted by
the ausearch utility.
items=1
The items field contains the number of PATH auxiliary records that follow the syscall record.
ppid=2686
The ppid field records the Parent Process ID (PPID). In this case, 2686 was the PPID of the parent
process such as bash.
pid=3538
The pid field records the Process ID (PID). In this case, 3538 was the PID of the cat process.
auid=1000
The auid field records the Audit user ID, that is the loginuid. This ID is assigned to a user upon login
and is inherited by every process even when the user’s identity changes, for example, by switching
user accounts with the su - john command.
uid=1000
The uid field records the user ID of the user who started the analyzed process. The user ID can be
interpreted into user names with the following command: ausearch -i --uid UID.
gid=1000
The gid field records the group ID of the user who started the analyzed process.
euid=1000

484
CHAPTER 28. AUDITING THE SYSTEM

The euid field records the effective user ID of the user who started the analyzed process.
suid=1000
The suid field records the set user ID of the user who started the analyzed process.
fsuid=1000
The fsuid field records the file system user ID of the user who started the analyzed process.
egid=1000
The egid field records the effective group ID of the user who started the analyzed process.
sgid=1000
The sgid field records the set group ID of the user who started the analyzed process.
fsgid=1000
The fsgid field records the file system group ID of the user who started the analyzed process.
tty=pts0
The tty field records the terminal from which the analyzed process was invoked.
ses=1
The ses field records the session ID of the session from which the analyzed process was invoked.
comm="cat"
The comm field records the command-line name of the command that was used to invoke the
analyzed process. In this case, the cat command was used to trigger this Audit event.
exe="/bin/cat"
The exe field records the path to the executable that was used to invoke the analyzed process.
subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
The subj field records the SELinux context with which the analyzed process was labeled at the time
of execution.
key="sshd_config"
The key field records the administrator-defined string associated with the rule that generated this
event in the Audit log.

Second Record

type=CWD
In the second record, the type field value is CWD — current working directory. This type is used to
record the working directory from which the process that invoked the system call specified in the
first record was executed.
The purpose of this record is to record the current process’s location in case a relative path winds up
being captured in the associated PATH record. This way the absolute path can be reconstructed.

msg=audit(1364481363.243:24287)
The msg field holds the same time stamp and ID value as the value in the first record. The time
stamp is using the Unix time format - seconds since 00:00:00 UTC on 1 January 1970.
cwd="/home/user_name"
The cwd field contains the path to the directory in which the system call was invoked.

Third Record

type=PATH

In the third record, the type field value is PATH. An Audit event contains a PATH-type record for

485
Red Hat Enterprise Linux 8 System Design Guide

In the third record, the type field value is PATH. An Audit event contains a PATH-type record for
every path that is passed to the system call as an argument. In this Audit event, only one path
(/etc/ssh/sshd_config) was used as an argument.
msg=audit(1364481363.243:24287):
The msg field holds the same time stamp and ID value as the value in the first and second record.
item=0
The item field indicates which item, of the total number of items referenced in the SYSCALL type
record, the current record is. This number is zero-based; a value of 0 means it is the first item.
name="/etc/ssh/sshd_config"
The name field records the path of the file or directory that was passed to the system call as an
argument. In this case, it was the /etc/ssh/sshd_config file.
inode=409248
The inode field contains the inode number associated with the file or directory recorded in this
event. The following command displays the file or directory that is associated with the 409248 inode
number:

# find / -inum 409248 -print


/etc/ssh/sshd_config

dev=fd:00
The dev field specifies the minor and major ID of the device that contains the file or directory
recorded in this event. In this case, the value represents the /dev/fd/0 device.
mode=0100600
The mode field records the file or directory permissions, encoded in numerical notation as returned
by the stat command in the st_mode field. See the stat(2) man page for more information. In this
case, 0100600 can be interpreted as -rw-------, meaning that only the root user has read and write
permissions to the /etc/ssh/sshd_config file.
ouid=0
The ouid field records the object owner’s user ID.
ogid=0
The ogid field records the object owner’s group ID.
rdev=00:00
The rdev field contains a recorded device identifier for special files only. In this case, it is not used as
the recorded file is a regular file.
obj=system_u:object_r:etc_t:s0
The obj field records the SELinux context with which the recorded file or directory was labeled at the
time of execution.
nametype=NORMAL
The nametype field records the intent of each path record’s operation in the context of a given
syscall.
cap_fp=none
The cap_fp field records data related to the setting of a permitted file system-based capability of
the file or directory object.
cap_fi=none
The cap_fi field records data related to the setting of an inherited file system-based capability of
the file or directory object.

486
CHAPTER 28. AUDITING THE SYSTEM

cap_fe=0
The cap_fe field records the setting of the effective bit of the file system-based capability of the
file or directory object.
cap_fver=0
The cap_fver field records the version of the file system-based capability of the file or directory
object.

Fourth Record

type=PROCTITLE
The type field contains the type of the record. In this example, the PROCTITLE value specifies that
this record gives the full command-line that triggered this Audit event, triggered by a system call to
the kernel.
proctitle=636174002F6574632F7373682F737368645F636F6E666967
The proctitle field records the full command-line of the command that was used to invoke the
analyzed process. The field is encoded in hexadecimal notation to not allow the user to influence the
Audit log parser. The text decodes to the command that triggered this Audit event. When searching
Audit records with the ausearch command, use the -i or --interpret option to automatically convert
hexadecimal values into their human-readable equivalents. The
636174002F6574632F7373682F737368645F636F6E666967 value is interpreted as cat
/etc/ssh/sshd_config.

28.6. USING AUDITCTL FOR DEFINING AND EXECUTING AUDIT RULES


The Audit system operates on a set of rules that define what is captured in the log files. Audit rules can
be set either on the command line using the auditctl utility or in the /etc/audit/rules.d/ directory.

The auditctl command enables you to control the basic functionality of the Audit system and to define
rules that decide which Audit events are logged.

File-system rules examples

1. To define a rule that logs all write access to, and every attribute change of, the /etc/passwd file:

# auditctl -w /etc/passwd -p wa -k passwd_changes

2. To define a rule that logs all write access to, and every attribute change of, all the files in the
/etc/selinux/ directory:

# auditctl -w /etc/selinux/ -p wa -k selinux_changes

System-call rules examples

1. To define a rule that creates a log entry every time the adjtimex or settimeofday system calls
are used by a program, and the system uses the 64-bit architecture:

# auditctl -a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time_change

2. To define a rule that creates a log entry every time a file is deleted or renamed by a system user
whose ID is 1000 or larger:

487
Red Hat Enterprise Linux 8 System Design Guide

# auditctl -a always,exit -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F


auid!=4294967295 -k delete

Note that the -F auid!=4294967295 option is used to exclude users whose login UID is not set.

Executable-file rules
To define a rule that logs all execution of the /bin/id program, execute the following command:

# auditctl -a always,exit -F exe=/bin/id -F arch=b64 -S execve -k execution_bin_id

Additional resources

auditctl(8) man page on your system

28.7. DEFINING PERSISTENT AUDIT RULES


To define Audit rules that are persistent across reboots, you must either directly include them in the
/etc/audit/rules.d/audit.rules file or use the augenrules program that reads rules located in the
/etc/audit/rules.d/ directory.

Note that the /etc/audit/audit.rules file is generated whenever the auditd service starts. Files in
/etc/audit/rules.d/ use the same auditctl command-line syntax to specify the rules. Empty lines and text
following a hash sign (#) are ignored.

Furthermore, you can use the auditctl command to read rules from a specified file using the -R option,
for example:

# auditctl -R /usr/share/audit/sample-rules/30-stig.rules

28.8. PRE-CONFIGURED AUDIT RULES FILES FOR COMPLIANCE WITH


STANDARDS
To configure Audit for compliance with a specific certification standard, such as OSPP, PCI DSS, or
STIG, you can use the set of pre-configured rules files installed with the audit package as a starting
point. The sample rules are located in the /usr/share/audit/sample-rules directory.


WARNING

The Audit sample rules in the sample-rules directory are not exhaustive nor up to
date because security standards are dynamic and subject to change. These rules are
provided only to demonstrate how Audit rules can be structured and written. They
do not ensure immediate compliance with the latest security standards. To bring
your system into compliance with the latest security standards according to specific
security guidelines, use the SCAP-based security compliance tools .

30-nispom.rules

Audit rule configuration that meets the requirements specified in the Information System Security

488
CHAPTER 28. AUDITING THE SYSTEM

Audit rule configuration that meets the requirements specified in the Information System Security
chapter of the National Industrial Security Program Operating Manual.
30-ospp-v42*.rules
Audit rule configuration that meets the requirements defined in the OSPP (Protection Profile for
General Purpose Operating Systems) profile version 4.2.
30-pci-dss-v31.rules
Audit rule configuration that meets the requirements set by Payment Card Industry Data Security
Standard (PCI DSS) v3.1.
30-stig.rules
Audit rule configuration that meets the requirements set by Security Technical Implementation
Guides (STIG).

To use these configuration files, copy them to the /etc/audit/rules.d/ directory and use the augenrules
--load command, for example:

# cd /usr/share/audit/sample-rules/
# cp 10-base-config.rules 30-stig.rules 31-privileged.rules 99-finalize.rules /etc/audit/rules.d/
# augenrules --load

You can order Audit rules using a numbering scheme. See the /usr/share/audit/sample-rules/README-
rules file for more information.

Additional resources

audit.rules(7) man page on your system

28.9. USING AUGENRULES TO DEFINE PERSISTENT RULES


The augenrules script reads rules located in the /etc/audit/rules.d/ directory and compiles them into an
audit.rules file. This script processes all files that end with .rules in a specific order based on their
natural sort order. The files in this directory are organized into groups with the following meanings:

10
Kernel and auditctl configuration
20
Rules that could match general rules but you want a different match
30
Main rules
40
Optional rules
50
Server-specific rules
70
System local rules
90
Finalize (immutable)

The rules are not meant to be used all at once. They are pieces of a policy that should be thought out

489
Red Hat Enterprise Linux 8 System Design Guide

The rules are not meant to be used all at once. They are pieces of a policy that should be thought out
and individual files copied to /etc/audit/rules.d/. For example, to set a system up in the STIG
configuration, copy rules 10-base-config, 30-stig, 31-privileged, and 99-finalize.

Once you have the rules in the /etc/audit/rules.d/ directory, load them by running the augenrules script
with the --load directive:

# augenrules --load
/sbin/augenrules: No change
No rules
enabled 1
failure 1
pid 742
rate_limit 0
...

Additional resources

audit.rules(8) and augenrules(8) man pages.

28.10. DISABLING AUGENRULES


Use the following steps to disable the augenrules utility. This switches Audit to use rules defined in the
/etc/audit/audit.rules file.

Procedure

1. Copy the /usr/lib/systemd/system/auditd.service file to the /etc/systemd/system/ directory:

# cp -f /usr/lib/systemd/system/auditd.service /etc/systemd/system/

2. Edit the /etc/systemd/system/auditd.service file in a text editor of your choice, for example:

# vi /etc/systemd/system/auditd.service

3. Comment out the line containing augenrules, and uncomment the line containing the auditctl -
R command:

#ExecStartPost=-/sbin/augenrules --load
ExecStartPost=-/sbin/auditctl -R /etc/audit/audit.rules

4. Reload the systemd daemon to fetch changes in the auditd.service file:

# systemctl daemon-reload

5. Restart the auditd service:

# service auditd restart

Additional resources

augenrules(8) and audit.rules(8) man pages.

490
CHAPTER 28. AUDITING THE SYSTEM

Auditd service restart overrides changes made to /etc/audit/audit.rules (Red Hat


Knowledgebase)

28.11. SETTING UP AUDIT TO MONITOR SOFTWARE UPDATES


In RHEL 8.6 and later versions, you can use the pre-configured rule 44-installers.rules to configure
Audit to monitor the following utilities that install software:

dnf [2]

yum

pip

npm

cpan

gem

luarocks

By default, rpm already provides audit SOFTWARE_UPDATE events when it installs or updates a
package. You can list them by entering ausearch -m SOFTWARE_UPDATE on the command line.

In RHEL 8.5 and earlier versions, you can manually add rules to monitor utilities that install software into
a .rules file within the /etc/audit/rules.d/ directory.

NOTE

Pre-configured rule files cannot be used on systems with the ppc64le and aarch64
architectures.

Prerequisites

auditd is configured in accordance with the settings provided in Configuring auditd for a secure
environment .

Procedure

1. On RHEL 8.6 and later, copy the pre-configured rule file 44-installers.rules from the
/usr/share/audit/sample-rules/ directory to the /etc/audit/rules.d/ directory:

# cp /usr/share/audit/sample-rules/44-installers.rules /etc/audit/rules.d/

On RHEL 8.5 and earlier, create a new file in the /etc/audit/rules.d/ directory named 44-
installers.rules, and insert the following rules:

-a always,exit -F perm=x -F path=/usr/bin/dnf-3 -F key=software-installer


-a always,exit -F perm=x -F path=/usr/bin/yum -F

You can add additional rules for other utilities that install software, for example pip and npm,
using the same syntax.

2. Load the audit rules:

491
Red Hat Enterprise Linux 8 System Design Guide

# augenrules --load

Verification

1. List the loaded rules:

# auditctl -l
-p x-w /usr/bin/dnf-3 -k software-installer
-p x-w /usr/bin/yum -k software-installer
-p x-w /usr/bin/pip -k software-installer
-p x-w /usr/bin/npm -k software-installer
-p x-w /usr/bin/cpan -k software-installer
-p x-w /usr/bin/gem -k software-installer
-p x-w /usr/bin/luarocks -k software-installer

2. Perform an installation, for example:

# yum reinstall -y vim-enhanced

3. Search the Audit log for recent installation events, for example:

# ausearch -ts recent -k software-installer


––––
time->Thu Dec 16 10:33:46 2021
type=PROCTITLE msg=audit(1639668826.074:298):
proctitle=2F7573722F6C6962657865632F706C6174666F726D2D707974686F6E002F75737
22F62696E2F646E66007265696E7374616C6C002D790076696D2D656E68616E636564
type=PATH msg=audit(1639668826.074:298): item=2 name="/lib64/ld-linux-x86-64.so.2"
inode=10092 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:ld_so_t:s0 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0
cap_fver=0 cap_frootid=0
type=PATH msg=audit(1639668826.074:298): item=1 name="/usr/libexec/platform-python"
inode=4618433 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:bin_t:s0 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0
cap_fver=0 cap_frootid=0
type=PATH msg=audit(1639668826.074:298): item=0 name="/usr/bin/dnf" inode=6886099
dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:rpm_exec_t:s0
nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(1639668826.074:298): cwd="/root"
type=EXECVE msg=audit(1639668826.074:298): argc=5 a0="/usr/libexec/platform-python"
a1="/usr/bin/dnf" a2="reinstall" a3="-y" a4="vim-enhanced"
type=SYSCALL msg=audit(1639668826.074:298): arch=c000003e syscall=59 success=yes
exit=0 a0=55c437f22b20 a1=55c437f2c9d0 a2=55c437f2aeb0 a3=8 items=3 ppid=5256
pid=5375 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3
comm="dnf" exe="/usr/libexec/platform-python3.6"
subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="software-installer"

28.12. MONITORING USER LOGIN TIMES WITH AUDIT


To monitor which users logged in at specific times, you do not need to configure Audit in any special
way. You can use the ausearch or aureport tools, which provide different ways of presenting the same
information.

Prerequisites

492
CHAPTER 28. AUDITING THE SYSTEM

Prerequisites

auditd is configured in accordance with the settings provided in Configuring auditd for a secure
environment .

Procedure
To display user log in times, use any one of the following commands:

Search the audit log for the USER_LOGIN message type:

# ausearch -m USER_LOGIN -ts '12/02/2020' '18:00:00' -sv no


time->Mon Nov 22 07:33:22 2021
type=USER_LOGIN msg=audit(1637584402.416:92): pid=1939 uid=0 auid=4294967295
ses=4294967295 subj=system_u:system_r:sshd_t:s0-s0:c0.c1023 msg='op=login acct="
(unknown)" exe="/usr/sbin/sshd" hostname=? addr=10.37.128.108 terminal=ssh res=failed'

You can specify the date and time with the -ts option. If you do not use this option,
ausearch provides results from today, and if you omit time, ausearch provides results from
midnight.

You can use the -sv yes option to filter out successful login attempts and -sv no for
unsuccessful login attempts.

Pipe the raw output of the ausearch command into the aulast utility, which displays the output
in a format similar to the output of the last command. For example:

# ausearch --raw | aulast --stdin


root ssh 10.37.128.108 Mon Nov 22 07:33 - 07:33 (00:00)
root ssh 10.37.128.108 Mon Nov 22 07:33 - 07:33 (00:00)
root ssh 10.22.16.106 Mon Nov 22 07:40 - 07:40 (00:00)
reboot system boot 4.18.0-348.6.el8 Mon Nov 22 07:33

Display the list of login events by using the aureport command with the --login -i options.

# aureport --login -i

Login Report
============================================
# date time auid host term exe success event
============================================
1. 11/16/2021 13:11:30 root 10.40.192.190 ssh /usr/sbin/sshd yes 6920
2. 11/16/2021 13:11:31 root 10.40.192.190 ssh /usr/sbin/sshd yes 6925
3. 11/16/2021 13:11:31 root 10.40.192.190 ssh /usr/sbin/sshd yes 6930
4. 11/16/2021 13:11:31 root 10.40.192.190 ssh /usr/sbin/sshd yes 6935
5. 11/16/2021 13:11:33 root 10.40.192.190 ssh /usr/sbin/sshd yes 6940
6. 11/16/2021 13:11:33 root 10.40.192.190 /dev/pts/0 /usr/sbin/sshd yes 6945

Additional resources

ausearch(8), aulast(8), and aureport(8) man pages on your system

28.13. ADDITIONAL RESOURCES


The RHEL Audit System Reference Knowledgebase article.

493
Red Hat Enterprise Linux 8 System Design Guide

The Auditd execution options in a container Knowledgebase article.

The Linux Audit Documentation Project page .

The audit package provides documentation in the /usr/share/doc/audit/ directory.

auditd(8), auditctl(8), ausearch(8), audit.rules(7), audispd.conf(5), audispd(8),


auditd.conf(5), ausearch-expression(5), aulast(8), aulastlog(8), aureport(8), ausyscall(8),
autrace(8), and auvirt(8) man pages.

[2] Because dnf is a symlink in RHEL, the path in thednf Audit rule must include the target of the symlink. To
receive correct Audit events, modify the 44-installers.rules file by changing the path=/usr/bin/dnf path to
/usr/bin/dnf-3 .

494
PART VI. DESIGN OF KERNEL

PART VI. DESIGN OF KERNEL

495
Red Hat Enterprise Linux 8 System Design Guide

CHAPTER 29. THE LINUX KERNEL


Learn about the Linux kernel and the Linux kernel RPM package provided and maintained by Red Hat
(Red Hat kernel). Keep the Red Hat kernel updated, which ensures the operating system has all the
latest bug fixes, performance enhancements, and patches, and is compatible with new hardware.

29.1. WHAT THE KERNEL IS


The kernel is a core part of a Linux operating system that manages the system resources and provides
interface between hardware and software applications.

The Red Hat kernel is a custom-built kernel based on the upstream Linux mainline kernel that
Red Hat engineers further develop and harden with a focus on stability and compatibility with the latest
technologies and hardware.

Before Red Hat releases a new kernel version, the kernel needs to pass a set of rigorous quality
assurance tests.

The Red Hat kernels are packaged in the RPM format so that they are easily upgraded and verified by
the YUM package manager.


WARNING

Kernels that are not compiled by Red Hat are not supported by Red Hat.

29.2. RPM PACKAGES


An RPM package consists of an archive of files and metadata used to install and erase these files.
Specifically, the RPM package contains the following parts:

GPG signature
The GPG signature is used to verify the integrity of the package.
Header (package metadata)
The RPM package manager uses this metadata to determine package dependencies, where to install
files, and other information.
Payload
The payload is a cpio archive that contains files to install to the system.

There are two types of RPM packages. Both types share the file format and tooling, but have different
contents and serve different purposes:

Source RPM (SRPM)


An SRPM contains source code and a spec file, which describes how to build the source code
into a binary RPM. Optionally, the SRPM can contain patches to source code.

Binary RPM
A binary RPM contains the binaries built from the sources and patches.

496
CHAPTER 29. THE LINUX KERNEL

29.3. THE LINUX KERNEL RPM PACKAGE OVERVIEW


The kernel RPM is a meta package that does not contain any files, but rather ensures that the following
required sub-packages are properly installed:

kernel-core
Provides the binary image of the kernel, all initramfs-related objects to bootstrap the system, and a
minimal number of kernel modules to ensure core functionality. This sub-package alone could be
used in virtualized and cloud environments to provide a Red Hat Enterprise Linux 8 kernel with a
quick boot time and a small disk size footprint.
kernel-modules
Provides the remaining kernel modules that are not present in kernel-core.

The small set of kernel sub-packages above aims to provide a reduced maintenance surface to system
administrators especially in virtualized and cloud environments.

Optional kernel packages are for example:

kernel-modules-extra
Provides kernel modules for rare hardware. Loading of the module is disabled by default.
kernel-debug
Provides a kernel with many debugging options enabled for kernel diagnosis, at the expense of
reduced performance.
kernel-tools
Provides tools for manipulating the Linux kernel and supporting documentation.
kernel-devel
Provides the kernel headers and makefiles that are enough to build modules against the kernel
package.
kernel-abi-stablelists
Provides information pertaining to the RHEL kernel ABI, including a list of kernel symbols required by
external Linux kernel modules and a yum plug-in to aid enforcement.
kernel-headers
Includes the C header files that specify the interface between the Linux kernel and user-space
libraries and programs. The header files define structures and constants required for building most
standard programs.

497

You might also like