This post is primarily aimed as a primer for the installation and post-install config tasks for a RHEL-based Linux install. It’s by no means designed to cover everything that needs to be, or should be, actioned for a Linux device, but will hopefully touch on the main items that can be looked at to get you on your way with your new device.
This article isn’t designed to be a how-to-install RHEL. The assumption is that the OS is already installed. Given time, this process may evolve to implement automation to perform the config tasks. As with most things though, that takes time, knowledge and resources; We’ll keep that on the to-do list for now.
Some of the steps in this article assume that a basic installation of the operating system has been performed – That is, a bare-bones installation. Not all of the steps below may apply to all instances.
Enabling EPEL for RHEL 9
Extended Packages for Enterprise Linux (EPEL) is a repository maintained by Fedora packagers for use with CentOS Stream and RHEL and contains numerous packages that add value to a RHEL deployment.
subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
Install basic packages
Install packages that may not be included in the base build of the system.
dnf install -y vim bash-completion net-tools tcpdump wget bash-color-prompt rhc-worker-playbook
Basic app config
VIM defaults
Create a .vimrc
file in the root of the home directory:
vim ~/.vimrc
Populate it with the following contents:
set nowrap
set ic
set paste
These settings:
- Disable wrapping to the terminal width;
- Ignores case for functions such as search;
- Paste mode disables features such as auto indent. It may not be a good idea to enable this long term.
Disable SELinux
As described by Redhat, Security-Enhanced Linux (SELinux) is a security architecture for Linux systems that allows administrators to have more control over who can access the system. It defines access controls for the applications, processes, and files on a system. It uses security policies, which are a set of rules that tell SELinux what can or can’t be accessed, to enforce the access allowed by a policy.
In short, SELinux enforces process and file security based on defined policies. This can be extremely beneficial in maintaining system integrity and security, but it also brings with it a level of complexity and restrictions that can result in significant time lost in troubleshooting non-functioning applications.
For the purposes of this article we’ll be disabling SELinux. Be advised that doing so will lower the security posture of your system.
Edit /etc/selinux/config
. Set the mode to disabled
:
...
#
SELINUX=disabled
# SELINUXTYPE= can take one of these three values:
...
Prevent SELinux kernel loading at boot:
grubby --update-kernel ALL --args selinux=0
System crypto-policy
With the release of RHEL 9 (and it’s upstream equivalents, including Fedora and CentOS), it was decided to disable a number of weaker cryptographic algorithms and digests. For example:
- Algorithms:
- RSAMD5;
- RSASHA1;
- NSEC3RSASHA1;
- DSA;
- NSEC3DSA;
- ECCGOST;
- Digests:
- SHA-1;
- GOST;
This can cause some problems with systems and services that still implement and operate with these mechanisms. An example of this is the use of DNSSEC for validation. A lot of providers still operate using SHA-1, however with this mechanism disabled, a local BIND server is unable to validate authenticity.
One option to work around this is to change the system-wide crypto policy. Doing this, however, lowers the security posture of the system.
update-crypto-policies --show
DEFAULT
update-crypto-policies --set LEGACY
Setting system policy to LEGACY
Note: System-wide crypto policies are applied on application start-up.
It is recommended to restart the system for the change of policies
to fully take place.
Graphical boot
Enable graphical boot
A basic OS install doesn’t include a graphical boot and sometimes the fast scrolling text of the boot process is a little busy and frantic. Install and configure plymouth to tidy up the boot process.
dnf install -y plymouth-theme-spinner
plymouth-set-default-theme
plymouth-set-default-theme --list
grubby --update-kernel ALL --args "rhgb quiet"
Disable graphical boot
Sometimes you don’t want a graphical boot loader or hidden boot process:
grubby --remove-args="rhgb quiet" --update-kernel ALL
Create SSH keys
SSH keys can provide a more secure method of authenticating to a system. Create a new key for root and add the public key to the authorized_keys
file.
ssh-keygen -t ed25519 -f ~/.ssh/$HOSTNAME-$USER.id_ed25519
cat ~/.ssh/$HOSTNAME-$USER.id_ed25519.pub >> ~/.ssh/authorized_keys
Managing the GUI (GDM)
Switching to a GUI
There’s a couple of ways that you can switch to a UI.
- Set the default boot target to
graphical.target
- Change the target for the current runtime:
systemctl isolate graphical.target
. This impacts the whole system and modifies service state based on the run-level. - Simply call
startx
.
Setting the boot target
Switching the boot target to a text-based console reduces system resource usage:
systemctl get-default
multi-user.target
systemctl set-default multi-user.target
Enabling a graphical target is just as simple:
systemctl get-default
multi-user.target
systemctl set-default graphical.target
The various targets can be viewed:
systemctl list-units --type target
UNIT LOAD ACTIVE SUB DESCRIPTION
basic.target loaded active active Basic System
cryptsetup.target loaded active active Local Encrypted Volumes
getty.target loaded active active Login Prompts
integritysetup.target loaded active active Local Integrity Protected Volumes
local-fs-pre.target loaded active active Preparation for Local File Systems
local-fs.target loaded active active Local File Systems
multi-user.target loaded active active Multi-User System
network-online.target loaded active active Network is Online
network-pre.target loaded active active Preparation for Network
network.target loaded active active Network
nss-user-lookup.target loaded active active User and Group Name Lookups
paths.target loaded active active Path Units
remote-fs-pre.target loaded active active Preparation for Remote File Systems
remote-fs.target loaded active active Remote File Systems
slices.target loaded active active Slice Units
sockets.target loaded active active Socket Units
sshd-keygen.target loaded active active sshd-keygen.target
swap.target loaded active active Swaps
sysinit.target loaded active active System Initialization
timers.target loaded active active Timer Units
veritysetup.target loaded active active Local Verity Protected Volumes
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
21 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
systemctl list-units --type target --all
...
Installing a graphical user interface
If you installed the system as a standard Server instance, that is no GUI, you can install the required packages post-installation:
dnf grouplist
Available Environment Groups:
Server with GUI
Minimal Install
Workstation
Custom Operating System
Virtualization Host
Installed Environment Groups:
Server
Installed Groups:
Headless Management
Container Management
Available Groups:
Legacy UNIX Compatibility
Scientific Support
Network Servers
Development Tools
Console Internet Tools
System Tools
Security Tools
Graphical Administration Tools
Smart Card Support
.NET Development
RPM Development Tools
dnf group install GNOME base-x Fonts "Internet Browser"
...
Installing Groups:
GNOME
base-x
Fonts
Transaction Summary
========================================================
Install 446 Packages
Upgrade 8 Packages
Total download size: 536 M
Is this ok [y/N]:y
...
Complete!
Disabling the user list on the login screen
You don’t always want to advertise which users have accounts on the system. Disable the login screen user list by following this procedure.
- Edit the file
/etc/dconf/db/gdm.d/00-login-screen
:
[org/gnome/login-screen]
# Do not show the user list
disable-user-list=true
- Update the
dconf
database and verify the setting:
dconf update
sudo -u gdm DCONF_PROFILE=gdm dconf read /org/gnome/login-screen/disable-user-list
true
- Restart the GDM service:
systemctl restart gdm.service
Firewall lock-down
The out-of-the-box configuration for firewalld is to associate the active interface (e.g. ens34) with the public
zone and permit system management and critical network protocol flows – ssh, cockpit, DHCPv6. Due to the association with the network interface, this configuration makes public
the fall-back zone.
To increase the security of the system, it’s recommended to lock-down the public zone and leverage additional zones with specific source and destination configuration, offering greater flexibility and control.
Change the default zone
For simplicity, you can change the default zone to allow for brevity in fireawalld configuration.
firewall-cmd --set-default-zone=trusted
success
firewall-cmd --get-default-zone
trusted
firewall-cmd --remove-interface=ens34 --zone=trusted
success
firewall-cmd --add-interface=ens34 --zone=public
success
firewall-cmd --runtime-to-permanent
success
Default drop
The firewalld service drops all TCP/UDP packets unless allowed by the policy. The target out-of-the box for the active zones is default
. The default target permits ICMP but drops TCP/UDP if not explicitly permitted by policy. There are situations were you may want to drop any packet that is not explicitly permitted by your policy. To do this, change the default target for the firewall firewall zone to drop
.
firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: ens34
sources:
services: cockpit dhcpv6-client ssh
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
firewall-cmd --set-target=DROP --zone=public --permanent
success
firewall-cmd --set-target=DROP --zone=trusted --permanent
success
firewall-cmd --reload
success
firewall-cmd --list-all
trusted (active)
target: DROP
icmp-block-inversion: yes
interfaces:
sources: 192.168.0.0/24
services: cockpit ssh
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks: echo-request
rich rules:
Configure the default zone
Configure the default zone (trusted
) with source and service configuration of permitted flows.
firewall-cmd --add-source=192.168.0.0/24
success
firewall-cmd --add-service=ssh --add-service=cockpit
success
firewall-cmd --runtime-to-permanent
success
Clean-up the public zone
Remove unnecessary services from the public
zone.
firewall-cmd --remove-service=ssh --remove-service=cockpit --remove-service=dhcpv6-client --zone=public
success
firewall-cmd --runtime-to-permanent
success
Allowing ICMP
With the target set to drop
, we can manage which ICMP messages are permitted. Being a little counter-intuitive, as firewalld is now dropping all non-permitted flows, we have to enable ICMP inversion and add allowed ICMP messages with the add-icmp-block
directive.
firewall-cmd --add-icmp-block-inversion --permanent
success
firewall-cmd --add-icmp-block=echo-request --permanent
success
firewall-cmd --reload
success
firewall-cmd --list-all
trusted (active)
target: DROP
icmp-block-inversion: yes
interfaces:
sources: 192.168.0.0/24
services: cockpit ssh
ports:
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks: echo-request
rich rules: