TL;DR
EX200 is now based on Red Hat Enterprise Linux 10, and the official study list has ten objective groups: essential tools, software (RPM and Flatpak), shell scripts, running systems, local storage, file systems, deploy and maintain, basic networking, users and groups, security. There is no containers group on the current list. Build a RHEL 10 family lab VM, keep SELinux enforcing, and work the list top to bottom until every task survives a reboot.
First thing to run on your lab box, to confirm it matches the exam platform:
$ cat /etc/redhat-release; uname -r; getenforce
AlmaLinux release 10.0 (Purple Lion)
6.12.0-55.el10.x86_64
Enforcing
Why this RHCSA study guide is built around the official list
The objective list is the syllabus. Red Hat publishes it, grades against it, and rewrites it when the exam moves to a new RHEL release. Everything else (courses, video series, that PDF someone sent you) is an interpretation. The old community reference that a generation of us studied from still has its objective walkthroughs online, but they were written for RHEL 6 and RHEL 7. The exam is two major releases past that now.
So this page tracks the live list. I checked it on 17 September 2026 and it says the exam is based on RHEL 10. Two things stand out compared to the RHEL 9 era lists that are still circulating in study groups. First, "Manage software" now names Flatpak explicitly: configure access to Flatpak repositories, install and remove Flatpak packages, next to the RPM bullets. Second, there is no containers group. Many RHEL 9 era study sheets include one (podman, skopeo, Containerfile, running a container as a systemd service) and it is not on the page today. Check the page yourself the week you book, because that list is the only authority, and it changes without a press release.
For what changed in the exam format (environment, tooling, how the RHEL 10 move played out), see the companion piece: RHCSA exam changes 2026, the new EX200 format explained. This page is about the content.
The ten objective groups, and what to actually practice
One section per group. Each one gives the shape of the objective in Red Hat's own terms, then the commands I would drill for it. Where a command has a persistent form and a temporary form, learn the persistent one: the grading environment reboots.
1. Understand and use essential tools
Shell syntax, redirection (>, >>, |, 2>), grep and regular expressions, SSH to remote systems, switching users, tar/gzip/bzip2, creating and editing text files, copying and moving files, hard and soft links, standard ugo/rwx permissions, and finding documentation in man, info and /usr/share/doc.
The trap here is speed, not difficulty. You will lose time you do not have if you hunt for syntax. Two habits pay for themselves:
# man -k "password aging"
chage (1) - change user password expiry information
If man -k returns nothing, the index is missing, not the man page. Run mandb once and it works for the rest of the session.
$ ln -s /etc/hosts /tmp/hosts-link; ls -l /tmp/hosts-link
lrwxrwxrwx. 1 root root 10 Sep 17 10:02 /tmp/hosts-link -> /etc/hosts
Notice the dot after the permission bits. That dot means the file has an SELinux context. You will see it everywhere on RHEL and it is a free reminder that context is part of the file, not an afterthought.
2. Manage software
Configure access to RPM repositories, install and remove RPM packages, and the same for Flatpak repositories and packages.
The graded task is almost never "install this one package". It is "configure access to this repository, then install from it". Write the repo file by hand and verify it resolves:
# cat > /etc/yum.repos.d/lab.repo <<'EOF'
[lab]
name=Lab repo
baseurl=file:///mnt/repo
enabled=1
gpgcheck=0
EOF
# dnf repolist lab
repo id repo name
lab Lab repo
One RHEL 10 detail worth knowing before it bites you: the RPM database moved from /var/lib/rpm to /usr/lib/sysimage/rpm. Your commands do not change, but any script or tutorial that pokes at the old path directly is wrong on RHEL 10. If your lab distro ships the newer package manager generation, the subcommands are the same but some flags and outputs differ, so read what your own system prints rather than what a tutorial promised.
Flatpak is new on this list, so do not skip it. Add a remote, list remotes, install, remove:
# flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
# flatpak remotes
Name Options
flathub system
3. Create simple shell scripts
Conditionals (if, test, [ ]), loops (for), positional parameters ($1, $2), and processing the output of commands inside a script.
Nobody is asking for elegant Bash. They are asking for a script that reads arguments, loops, branches, and exits sanely. Practice writing this one from memory in under two minutes:
#!/bin/bash
for f in "$@"; do
if [ -f "$f" ]; then
echo "$f: $(wc -l < "$f") lines"
else
echo "$f: not a regular file" >&2
fi
done
$ chmod +x count.sh; ./count.sh /etc/hostname /etc
/etc/hostname: 1 lines
/etc: not a regular file
Quote your variables. An unquoted $f with a space in the filename is the single most common way a working script fails on the grader's test data.
4. Operate running systems
Boot, reboot and shut down normally; boot into different targets manually; interrupt the boot process to gain access to a system; find CPU and memory hogs and kill them; adjust process scheduling; manage tuning profiles; read logs and journals; preserve system journals; start, stop and check network services; transfer files securely between systems.
"Interrupt the boot process to gain access" is the polite name for the root password reset, and it is the one procedure I would rehearse until it is muscle memory: interrupt GRUB, append rd.break, remount /sysroot read write, chroot /sysroot, change the password, then touch /.autorelabel before you exit. Skipping the autorelabel is how people lock themselves out a second time, because the new /etc/shadow comes back with the wrong SELinux context.
"Preserve system journals" means persistent storage, not log rotation:
# mkdir -p /var/log/journal
# systemd-tmpfiles --create --prefix /var/log/journal
# systemctl restart systemd-journald
# journalctl -u sshd -p err -n 3 --no-pager
-- No entries --
Tuning profiles are one command and a free point if you have seen it once:
# tuned-adm active
Current active profile: virtual-guest
# tuned-adm profile throughput-performance
And process scheduling means nice and renice:
# renice -n 10 -p 1874
1874 (process ID) old priority 0, new priority 10
5. Configure local storage
List, create and delete partitions on GPT disks; create and remove physical volumes; assign PVs to volume groups; create and delete logical volumes; mount file systems at boot by UUID or label; add partitions, logical volumes and swap non destructively.
The whole LVM stack, start to finish, is four commands:
# parted -s /dev/vdb mklabel gpt mkpart lab 1MiB 2GiB set 1 lvm on
# pvcreate /dev/vdb1
Physical volume "/dev/vdb1" successfully created.
# vgcreate vglab /dev/vdb1
Volume group "vglab" successfully created
# lvcreate -n lvdata -L 1G vglab
Logical volume "lvdata" created.
"Non destructively" is the word that carries the grade. Mount by UUID, never by device name, because device names move:
# mkfs.xfs /dev/vglab/lvdata
meta-data=/dev/vglab/lvdata isize=512 agcount=4, agsize=65536 blks
data = bsize=4096 blocks=262144, imaxpct=25
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=2560, version=2
realtime =none extsz=4096 blocks=0, rtextents=0
# blkid /dev/vglab/lvdata
/dev/vglab/lvdata: UUID="8a5b1f0c-9d2e-4a31-b5c7-6f0d3e1a2b44" TYPE="xfs"
# echo 'UUID=8a5b1f0c-9d2e-4a31-b5c7-6f0d3e1a2b44 /data xfs defaults 0 0' >> /etc/fstab
# mount -a
# findmnt /data
TARGET SOURCE FSTYPE OPTIONS
/data /dev/mapper/vglab-lvdata xfs rw,relatime,attr2,inode64
mount -a after every /etc/fstab edit. Every single time. It costs one second and it is the difference between passing and staring at an emergency shell.
6. Create and configure file systems
Create, mount, unmount and use VFAT, ext4 and XFS; mount and unmount NFS network file systems; configure autofs; extend existing logical volumes; diagnose and correct file permission problems.
Growing a logical volume and its file system is one command when you remember -r:
# lvextend -r -L +1G /dev/vglab/lvdata
Size of logical volume vglab/lvdata changed from 1.00 GiB (256 extents) to 2.00 GiB (512 extents).
Logical volume vglab/lvdata successfully resized.
autofs is the objective people leave for last and then meet on exam day. Two files and one service:
# cat /etc/auto.master.d/lab.autofs
/shares /etc/auto.lab
# cat /etc/auto.lab
data -rw,sync server1:/export/data
# systemctl enable --now autofs
Created symlink '/etc/systemd/system/multi-user.target.wants/autofs.service' -> '/usr/lib/systemd/system/autofs.service'.
# ls /shares/data
report.txt archive.tar.gz
The mount point under /shares does not exist until you reference it. That is the feature, and it is also why people think autofs is broken when ls /shares looks empty.
7. Deploy, configure and maintain systems
Schedule tasks with at, cron and systemd timer units; start and stop services and enable them at boot; boot into a specific target automatically; configure time service clients; install and update packages from the Red Hat CDN, a remote repository or the local file system; modify the system bootloader.
# systemctl set-default multi-user.target
Removed "/etc/systemd/system/default.target".
Created symlink '/etc/systemd/system/default.target' -> '/usr/lib/systemd/system/multi-user.target'.
Time client means chrony, and the check is whether you are actually synchronised, not whether the service is running:
# chronyc sources
MS Name/IP address Stratum Poll Reach LastRx Last sample
^* ntp.example.com 2 6 377 21 +112us[ +130us] +/- 12ms
The asterisk in ^* is the source currently in use. No asterisk anywhere means no sync, and a graded "configure a time client" task with no asterisk is a failed task.
Bootloader changes go through grubby, not by hand editing generated config:
# grubby --update-kernel=ALL --args="console=ttyS0"
# grubby --info=DEFAULT | grep ^args
args="ro crashkernel=1G-4G:192M console=ttyS0"
8. Manage basic networking
Configure IPv4 and IPv6 addresses, configure hostname resolution, start network services automatically at boot, and restrict network access using firewalld and firewall-cmd.
Static addressing on a NetworkManager connection profile, which is the only thing that persists:
# nmcli -t -f NAME,DEVICE connection show
System eth0:eth0
# nmcli connection modify "System eth0" ipv4.method manual \
ipv4.addresses 192.168.122.50/24 ipv4.gateway 192.168.122.1 ipv4.dns 192.168.122.1
# nmcli connection up "System eth0"
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)
Anything you do with ip addr add dies at reboot. It is fine for a quick test and worthless for a grade.
# firewall-cmd --permanent --add-service=http
success
# firewall-cmd --reload
success
# firewall-cmd --list-services
dhcpv6-client ssh http
--permanent writes the config, --reload applies it. Without --reload the rule is in the file and not in the kernel; without --permanent it is in the kernel and gone after reboot. The exam finds both mistakes.
9. Manage users and groups
Create, delete and modify local user accounts; change passwords and adjust password aging; create, delete and modify local groups and memberships; configure privileged access.
# useradd -G wheel -s /bin/bash elton
# chage -M 60 -W 7 elton
# chage -l elton
Last password change : Sep 17, 2026
Password expires : Nov 16, 2026
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 60
Number of days of warning before password expires : 7
"Configure privileged access" is sudo. Use a drop in file in /etc/sudoers.d/ and always validate it, because a broken sudoers file on a system where you have no root shell open is a very bad afternoon:
# echo '%ops ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart httpd' > /etc/sudoers.d/ops
# visudo -cf /etc/sudoers.d/ops
/etc/sudoers.d/ops: parsed OK
10. Manage security
Firewall settings with firewall-cmd and firewalld, default file permissions, key based SSH authentication, SELinux enforcing and permissive modes, listing and identifying SELinux file and process contexts, restoring default contexts, managing SELinux port labels, and using booleans.
Read that list again. Five of its eight bullets are SELinux bullets, and none of them says "turn it off". The exam is graded with SELinux enforcing, and a machine that comes back permissive after a reboot loses points on tasks that otherwise worked. If a service will not start, find out why:
# ausearch -m AVC -ts recent
time->Wed Sep 17 10:41:02 2026
type=AVC msg=audit(1789638062.412:318): avc: denied { read } for pid=2211
comm="httpd" name="index.html" dev="vda2" ino=17104
scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0
That tcontext of default_t is the answer: the file has the wrong label. Fix the label rule and relabel, so the fix survives a relabel and a reboot:
# semanage fcontext -a -t httpd_sys_content_t '/srv/web(/.*)?'
# restorecon -Rv /srv/web
Relabeled /srv/web from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Non standard port, boolean, and reading the current boolean state, the three other shapes the SELinux task takes:
# semanage port -a -t http_port_t -p tcp 8088
# getsebool httpd_can_network_connect
httpd_can_network_connect --> off
# setsebool -P httpd_can_network_connect on
The -P is the exam. Without it the boolean is set until the next boot and the grader sees nothing. The longer version of this workflow, including when audit2allow is the right answer and when it is a trap, is in SELinux troubleshooting: fix AVC denials without disabling SELinux. RHEL 10 ships SELinux userspace 3.8, which added a CIL output mode to audit2allow, so the module workflow you may have seen in older guides still works and has an extra output format.
Default file permissions means umask, set per shell in /etc/profile.d/ or system wide in /etc/login.defs, and key based SSH is ssh-keygen plus ssh-copy-id. Both are quick points. Do not lose them by improvising on the day.
How to drill this list without burning a month
Read once, then stop reading. The loop that works: pick one objective group, do every bullet in it on a fresh VM, reboot, and verify that everything you configured is still there. If it is not, you learned something more valuable than the task itself. Then break it deliberately (bad fstab line, wrong SELinux label, firewalld rule that was never reloaded) and fix it against the clock.
Two VMs beat one, because half the objectives (SSH, NFS, autofs, secure file transfer, time client) need a second machine to be real. A local hypervisor is free and enough. A pair of small cloud instances works too if your laptop cannot spare the RAM, and the second machine is where networking finally clicks.
Timebox it. Three hours of hands on work per objective group, ten groups, and you have covered the syllabus in about thirty hours of real practice. That is the honest number, and it is far less than the number people spend rewatching videos.
If this fails
The VM will not boot after an fstab edit. You get an emergency shell asking for the root password, then:
Give root password for maintenance (or press Control-D to continue):
# mount -o remount,rw /
# vi /etc/fstab
# systemctl daemon-reload
# reboot
Add nofail to lab entries while you practise, and run mount -a before every reboot. This is the most common self inflicted RHCSA study wound.
semanage: command not found. The tool is not installed by default. The answer is dnf install policycoreutils-python-utils, never setenforce 0. If you catch yourself reaching for permissive mode to "make it work", you have just practised the one habit that fails you on the exam and gets a production change rejected.
Everything worked, then the reboot ate it. Nine times out of ten it is one of three things: a firewalld rule added without --permanent, an SELinux boolean set without -P, or an IP address added with ip addr add instead of an nmcli connection profile. Check all three at once after every reboot:
# firewall-cmd --list-services; getsebool httpd_can_network_connect; ip -4 addr show eth0
dhcpv6-client ssh
httpd_can_network_connect --> off
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
The service missing from the firewall list, the boolean back to off, and no static address on eth0 are the three exact symptoms of the three exact mistakes above. Make "reboot and re verify" the last step of every practice task and you will never lose those points.
Keep this page honest with me
The objective list moves. When Red Hat edits it, this page gets edited, and the change gets noted. If you are still deciding whether the exam is worth the fee and the month of evenings, I ran the numbers against real job postings in Is RHCSA worth it in 2026. If you already decided, close this tab and go build the VM. The list above is not knowledge until your hands have done it.
Primary source: Red Hat, Red Hat Certified System Administrator (RHCSA) exam, EX200, objective list read on 17 September 2026. RHEL 10 platform details (RPM database path, SELinux userspace 3.8) from the Red Hat Enterprise Linux 10.0 release notes.