Deploy & Maintain: dnf Repositories, Packages, Time Sync, Boot Target
- Define a custom dnf repository as a .repo file and explain why gpgcheck protects you
- Install, update, remove, search, and query packages with dnf — including a local .rpm file
- Set the system timezone and clock with timedatectl and keep it synced with chrony
- Choose the default boot target and rebuild the GRUB2 configuration safely
Why a machine needs repositories
Understand what a dnf repository is and why software comes from one trusted place.
A Red Hat-family system installs software from repositories — network locations holding thousands of prebuilt
.rpmpackages plus an index that lists every package, its version, and what it depends on. The package manager dnf reads that index, works out the full dependency chain for whatever you asked for, downloads it, and installs it.Think of a repository as an app store with a printed catalogue. The catalogue (the repo metadata) tells dnf exactly what is on the shelves and what each item needs to function, so dnf never has to guess. Without a configured repo,
dnf install httpdhas nowhere to look — it's a phone with no app store account.You tell dnf where the shelves are by dropping a small text file into `/etc/yum.repos.d/`. Any file there ending in
.repois read at the start of every dnf run.Define a .repo file by hand
Write a working repository definition and understand each required line.
A repo definition is plain INI-style text. The exam task is almost always "a repo is available at
http://<host>/..., configure the system to use it." Here is the minimum that does the job, written to/etc/yum.repos.d/internal.repo:Example — not runnable on your lab box
cat /etc/yum.repos.d/internal.repo[internal] name=Internal Tools Repo baseurl=http://mirror.example.test/repo/internal/ enabled=1 gpgcheck=1 gpgkey=http://mirror.example.test/repo/RPM-GPG-KEY-internal
Six lines, each load-bearing. `[internal]` is the repo id (the bracketed label, must be unique on the box). `name=` is a human-readable description. `baseurl=` is where the packages and metadata live. `enabled=1` means dnf actually uses it. `gpgcheck=1` demands a valid signature on every package, and `gpgkey=` says which public key verifies that signature. Example — not runnable on your lab box
dnf repolistrepo id repo name baseos Rocky Linux 9 - BaseOS appstream Rocky Linux 9 - AppStream internal Internal Tools Repo
- repolist
- List enabled repositories. Add --all to include disabled ones too.
repolistshows every enabled repo dnf currently sees. Your newinternalid appearing here is the proof the file was parsed and is live. If it's missing, dnf never read your definition — check the filename ends in.repoandenabled=1.Check yourself
Your repo file has gpgcheck=1 but no gpgkey line, and installs fail with a GPG error. What is the correct fix?
Manage packages with dnf
Install, update, remove, search, and query packages — including a local rpm.
Once a repo is wired up, the day-to-day verbs are few and predictable. Each one resolves dependencies for you, so you rarely chase a missing library by hand.
Example — not runnable on your lab box
sudo dnf install httpdDependencies resolved. ================================================================ Package Arch Version Repository Size ================================================================ Installing: httpd x86_64 2.4.57-5.el9 appstream 46 k Installing dependencies: httpd-core x86_64 2.4.57-5.el9 appstream 1.5 M ... Is this ok [y/N]:
- install <pkg>
- Install a package and its dependencies from enabled repos.
- -y
- Assume yes — skip the prompt. Useful in scripts, dangerous interactively.
installpulls the named package plus every dependency, shows the plan, and waits for confirmation. TheRepositorycolumn tells you which repo each piece comes from — handy for confirming your custom repo is actually being used.Example — not runnable on your lab box
sudo dnf install ./monitoring-agent-2.1-1.el9.x86_64.rpmDependencies resolved. Installing: monitoring-agent x86_64 2.1-1.el9 @commandline 220 k Is this ok [y/N]:
- install ./file.rpm
- Install a local rpm file; dnf still pulls its dependencies from repos.
When you have an rpm file sitting on disk, give dnf the path (the ./or a full path is what marks it as a local file, not a repo name). dnf still resolves the file's dependencies from your enabled repos — a big advantage over the oldrpm -i, which would just error out on a missing library.The rest of the verbs round out the lifecycle.
update(aliasupgrade) brings packages to their newest version; with no name it updates everything.remove(aliaserase) uninstalls and removes now-unneeded dependencies.listandprovidesanswer questions before you change anything.Example — not runnable on your lab box
dnf provides /usr/sbin/httpdhttpd-core-2.4.57-5.el9.x86_64 : Apache HTTP Server (core) Repo : appstream Matched from: Filename : /usr/sbin/httpd
- provides <path|cmd>
- Find which package provides a given file or capability.
- list <pattern>
- List available/installed packages matching a name pattern.
providesanswers the reverse question: which package owns this file or command? Indispensable when an exam task says "thefoocommand must be available" but doesn't tell you the package name. Here it reveals that/usr/sbin/httpdis shipped byhttpd-core.Check yourself
A task says the
semanagecommand must be present, but doesn't name the package. Which dnf subcommand finds the owning package?Set the time, then keep it synced
Use timedatectl for timezone/clock and chrony to keep the clock accurate.
Correct time is not cosmetic. TLS certificates, Kerberos tickets, log correlation, and scheduled jobs all break when a clock drifts. There are two separate jobs here, and mixing them up is the trap:
- `timedatectl` sets the timezone and can set the clock — the one-time configuration.
- `chrony` (its daemon is
chronyd) continuously corrects the clock against network time servers — the ongoing maintenance.
Think of it like setting a wall clock:
timedatectlis you turning the hands to the right time once;chronyis a tiny technician living inside who nudges the hands a fraction every minute so it never drifts.timedatectlLocal time: Mon 2026-06-23 14:05:11 UTC Universal time: Mon 2026-06-23 14:05:11 UTC RTC time: Mon 2026-06-23 14:05:11 Time zone: Etc/UTC (UTC, +0000) System clock synchronized: yes NTP service: activeRun with no arguments it's a status report. The two lines that matter for exam grading: `Time zone:` (is it the one the task asked for?) and `NTP service: active` plus `System clock synchronized: yes` (is chrony running and has it locked on?). sudo timedatectl set-timezone America/Chicago- set-timezone <zone>
- Set the system timezone (updates /etc/localtime).
- set-time '<YYYY-MM-DD HH:MM:SS>'
- Manually set the clock — refused while NTP sync is on (see mistake below).
- list-timezones
- Print every valid timezone name.
Silent success, the systemd convention. This updates the /etc/localtimesymlink for you — far safer than editing that link by hand. Usetimedatectl list-timezones | grep -i chicagowhen you can't recall the exact spelling.chrony is configured in
/etc/chrony.conf(aserverorpoolline names the upstream time sources). Oncechronydis running and enabled, you confirm it's actually talking to those servers withchronyc sources.Example — not runnable on your lab box
chronyc sourcesMS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^* ntp1.example.test 2 6 377 21 +14us[ +20us] +/- 9ms ^- 192.0.2.123 3 6 377 23 -2117us[-2089us] +/- 41ms
- sources
- Show the time servers chrony knows and which one it's synced to.
- tracking
- Show how far off and how fast the local clock is being corrected.
Each line is one time source. The leading marks tell the story: *`^ ** is the source chrony has **selected and synced to**,^-is an acceptable but unused candidate. A healthy **Reach** of377(octal — all 8 recent polls answered) means the link is solid. If every source showed?orReach 0`, chrony can't reach its servers and the clock won't stay correct.Check yourself
In
chronyc sourcesoutput, which leading symbol marks the server the system is currently synchronized to?Choose the boot target and rebuild GRUB
Set the default systemd target and regenerate the bootloader config correctly.
Two different things decide how the machine comes up, and the exam tests both:
- The default target — does it boot to a full graphical desktop (
graphical.target) or to a text-only multi-user system (multi-user.target)? This is systemd's job, set withsystemctl set-default. - The GRUB2 configuration — the menu and kernel options the bootloader uses before systemd even starts. After changing kernel options (in
/etc/default/grub) you must regenerate the compiled config file.
sudo systemctl set-default multi-user.targetRemoved /etc/systemd/system/default.target. Created symlink /etc/systemd/system/default.target → /usr/lib/systemd/system/multi-user.target.
- set-default <target>
- Set the target the system boots into (multi-user vs graphical).
- get-default
- Print the current default boot target.
set-defaultjust repoints thedefault.targetsymlink. Booting tomulti-user.target(text, no GUI) is the standard server choice and what most RHCSA tasks ask for. Check the current setting any time withsystemctl get-default.Changing the boot target above takes effect on the next boot with no further steps. But editing kernel parameters is different: those live in
/etc/default/grub, and that file is only a source. GRUB actually reads a compiled file you must regenerate.Example — not runnable on your lab box
sudo grub2-mkconfig -o /boot/grub2/grub.cfgGenerating grub configuration file ... Found linux image: /boot/vmlinuz-5.14.0-362.el9.x86_64 Found initrd image: /boot/initramfs-5.14.0-362.el9.x86_64.img done
- -o <file>
- Output path for the generated config — must be the real grub.cfg GRUB loads.
grub2-mkconfigreads/etc/default/gruband the scripts in/etc/grub.d/, then writes the result to the file named by-o. On a BIOS system that's `/boot/grub2/grub.cfg`; on UEFI it's/boot/efi/EFI/<distro>/grub.cfg. Until you run this, your/etc/default/grubedits are inert.Check yourself
You added a kernel parameter in /etc/default/grub, rebooted, and the parameter isn't active. What step did you skip?
- The default target — does it boot to a full graphical desktop (
Try it in your live terminal
Run safe, read-only checks on the real sandbox to your right.
You have a real root shell. These commands are read-only — they inspect state without installing, removing, or rebooting anything. Run them in order and read each result against what you learned above. This is exactly the 'verify before and after' habit a graded deploy-and-maintain task rewards.
Example — not runnable on your lab box
dnf repolistList the enabled repositories. Confirm the box knows where to get software — and that any repo you'd expect (like a custom one) is present and enabled. timedatectlCheck the timezone, whether NTP is active, and whether the clock is synchronized. These are the exact fields a time-config task grades. chronyc sources 2>/dev/null || trueShow chrony's time sources and which one it's locked onto (look for ^*). The|| truekeeps the step clean if chrony isn't installed on this particular sandbox.systemctl get-defaultPrint the current default boot target — multi-user.target(text) orgraphical.target(GUI). No change is made; you're just confirming the system's boot intent.
- A repo is configured as a
.repofile in/etc/yum.repos.d/with an[id],baseurl=,enabled=1, and signature settings —dnf repolistproves it loaded. - Keep
gpgcheck=1and supply the matchinggpgkey=; the fix for a GPG failure is the right key, never disabling the check. - dnf resolves dependencies for install/update/remove and for a local
./file.rpm;providesmaps a file or command back to its package. - Two separate time jobs:
timedatectlsets timezone/clock once;chrony/chronydkeeps it synced — don't set the clock by hand while sync is on. systemctl set-defaultpicks the boot target; kernel-option changes needgrub2-mkconfig -o <real grub.cfg>or they never take effect.
| Command | Effect | Watch for |
|---|---|---|
/etc/yum.repos.d/x.repo | Defines a repo (id, baseurl, enabled, gpg) | File must end in .repo; enabled=1 |
dnf install <pkg> / ./x.rpm | Install package or local rpm + deps | Local file needs a path (./) |
dnf provides <path> | Find the package owning a file/command | Use when the task hides the package name |
timedatectl set-timezone <z> | Set the system timezone | Spelling — use list-timezones |
chronyc sources | Show time sources + synced one | ^* = synced; Reach 377 = healthy |
systemctl set-default <t> | Set the default boot target | multi-user (text) vs graphical |
grub2-mkconfig -o <grub.cfg> | Rebuild compiled GRUB config | BIOS vs UEFI output path |
