Labs follow the guide fixes #3

Merged
jcoffey-dev merged 1 commits from labs/match-guide-fixes into main 2026-10-30 23:42:10 +00:00
28 changed files with 205 additions and 99 deletions

No files matched your search

+1 -1
View File
@@ -20,7 +20,7 @@ were.
run `systemctl list-units --state=running`, then `systemctl reboot`. Not
graded: check yourself that only a handful of units were running. Root
needs a password for rescue mode (`passwd root`); lock it again
afterwards with `passwd -l root`.
afterward with `passwd -l root`.
3. Make a lasting change to the kernel command line, then reboot. RHEL
family: remove `quiet` from every installed kernel with grubby. Ubuntu:
add `loglevel=7` to `GRUB_CMDLINE_LINUX_DEFAULT` and run `update-grub`.
@@ -28,5 +28,8 @@ login startup file is `~/.bash_profile`; on Ubuntu it's `~/.profile`.
`chmod +x`.
- `echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bash_profile` (or
`~/.profile`), then `source` it; `which hi`.
- Both families already put `~/bin` on the PATH: AlmaLinux's default
`~/.bashrc` adds it, and Ubuntu's `~/.profile` adds it at login if it
exists. The `export` line is how you'd add any other directory.
- bash runs only the first of `~/.bash_profile`, `~/.bash_login` and
`~/.profile` that it finds for a login shell.
+9 -2
View File
@@ -9,6 +9,15 @@ The lab removes `/tmp/s.conf` if it's there, and notes the startup files
task 4 may change so that reset can put them back. Ubuntu empties `/tmp` at
boot, so do task 2 without a reboot.
On the RHEL family, install full Vim and nano first. A minimal or cloud
install has only `vi`:
```
dnf install -y vim-enhanced nano
```
Reset removes them again if they weren't installed when the lab started.
## Tasks
1. Run `vimtutor` and work through lessons 1 and 2 (about 15 minutes). Not
@@ -25,8 +34,6 @@ boot, so do task 2 without a reboot.
## Hints
- On the RHEL family `vim` and `vimtutor` are in `vim-enhanced`, and nano
is in `nano`.
- `:set number`, `/Port`, `yy`, `p`, `cw` or `C`, `:%s/yes/YES/g`, `u`,
`:wq`.
- In nano, `Ctrl+x` then `n` quits without saving.
@@ -9,5 +9,8 @@ fi
if [ -f "$LAB_STATE/absent" ]; then
while read -r f; do case $f in *'*'*) ;; *) rm -rf "$f" ;; esac; done <"$LAB_STATE/absent"
fi
if [ -s "$LAB_STATE/missing-pkgs" ]; then
dnf -y -q remove $(cat "$LAB_STATE/missing-pkgs") >/dev/null 2>&1
fi
command -v restorecon >/dev/null && restorecon -R /etc/environment /etc/profile.d /root /home 2>/dev/null
true
@@ -11,3 +11,9 @@ for f in /etc/environment /etc/profile.d /root/.bashrc /root/.bash_profile /root
printf '%s\n' "$f" >>"$LAB_STATE/absent"
fi
done
# The README has the student install full Vim and nano on the RHEL family;
# note which are missing, for reset to remove.
if is_rhel; then
for p in vim-enhanced nano; do pkg_installed $p || printf '%s\n' $p >>"$LAB_STATE/missing-pkgs"; done
fi
true
@@ -8,7 +8,8 @@ compressed log, and cpio.
The lab clears away the files the tasks create in `/tmp`, if they're there.
Ubuntu empties `/tmp` at boot, so do the tasks without a reboot, and run
`le-lab check` before the chapter's clean-up step (`le-lab reset` cleans up
too). Tasks 2 and 3 ask for findings: write them to the files in
too, and removes `bzip2` again if it wasn't installed when the lab
started). Tasks 2 and 3 ask for findings: write them to the files in
`/root/lab-answers/` that they name.
## Tasks
@@ -16,10 +17,11 @@ too). Tasks 2 and 3 ask for findings: write them to the files in
1. Archive `/etc` into `/tmp/etc.tar.gz` with gzip, list it to find
`sshd_config`, and restore just `etc/ssh/sshd_config` from it into
`/tmp/restore`.
2. Archive `/etc` without compression into `/tmp/etc.tar`. Copy it to
`/tmp/t-gzip.tar`, `/tmp/t-bzip2.tar` and `/tmp/t-xz.tar`, and compress
each with the tool it's named after, keeping the copies. Write the name
of the tool that made the smallest file to `/root/lab-answers/2`.
2. Install `bzip2` if it's missing (it often is). Archive `/etc` without
compression into `/tmp/etc.tar`. Copy it to `/tmp/t-gzip.tar`,
`/tmp/t-bzip2.tar` and `/tmp/t-xz.tar`, and compress each with the tool
it's named after, keeping the copies. Write the name of the tool that
made the smallest file to `/root/lab-answers/2`.
3. Save the last 500 lines of the journal, compressed with gzip, as
`/tmp/j.gz`. Without unpacking it, count the lines that mention `error`
in any case, and write the count to `/root/lab-answers/3`.
@@ -29,8 +31,8 @@ too). Tasks 2 and 3 ask for findings: write them to the files in
## Hints
- `tar -czf`, `tar -tzf`, `tar -xzf ARCHIVE -C DIR MEMBER`.
- `gzip -k`, `bzip2 -k`, `xz -k`; `ls -lh /tmp/t-*`. bzip2 may need
installing. The tools skip a file whose name already ends in their own
suffix (`.gz`, `.bz2`, `.xz`).
- `dnf install bzip2` or `apt install bzip2`. `gzip -k`, `bzip2 -k`,
`xz -k`; `ls -lh /tmp/t-*`. The tools skip a file whose name already
ends in their own suffix (`.gz`, `.bz2`, `.xz`).
- `journalctl -n 500 --no-pager | gzip > ...`; `zgrep -c -i`, `zless`.
- `cd /etc && find ssh -type f | cpio -o > ...`; `cpio -idv < ...`.
@@ -1,2 +1,5 @@
rm -rf /tmp/etc.tar /tmp/etc.tar.gz /tmp/t-gzip.tar* /tmp/t-bzip2.tar* /tmp/t-xz.tar* /tmp/j.gz /tmp/ssh.cpio /tmp/restore /tmp/c
if [ -n "$(state_get no-bzip2)" ] && pkg_installed bzip2; then
if is_rhel; then dnf -y -q remove bzip2 >/dev/null 2>&1; else DEBIAN_FRONTEND=noninteractive apt-get -y -qq purge bzip2 >/dev/null 2>&1; fi
fi
true
@@ -1 +1,4 @@
rm -rf /tmp/etc.tar /tmp/etc.tar.gz /tmp/t-gzip.tar* /tmp/t-bzip2.tar* /tmp/t-xz.tar* /tmp/j.gz /tmp/ssh.cpio /tmp/restore /tmp/c
# Task 2 has the student install bzip2 if it's missing; reset removes it.
pkg_installed bzip2 || state_set no-bzip2 1
true
@@ -3,7 +3,7 @@ grep -ls 'lab\.test' /etc/nginx/conf.d/*.conf 2>/dev/null | xargs -r rm -f
grep -ls 'shop\.test' /etc/httpd/conf.d/*.conf 2>/dev/null | xargs -r rm -f
command -v semanage >/dev/null && semanage fcontext -d '/srv/www(/.*)?' 2>/dev/null
rm -rf /srv/www
for p in nginx httpd postfix s-nail mailutils; do
for p in nginx httpd postfix s-nail mailutils policycoreutils-python-utils; do
[ -n "$(state_get had-$p)" ] && continue
pkg_installed $p || continue
systemctl disable --now --quiet $p 2>/dev/null
@@ -1,3 +1,3 @@
[ ! -e /srv/www ] || refuse "/srv/www already exists; move it away first"
for p in nginx httpd postfix s-nail mailutils; do pkg_installed $p && state_set had-$p 1; done
for p in nginx httpd postfix s-nail mailutils policycoreutils-python-utils; do pkg_installed $p && state_set had-$p 1; done
touch "$LAB_STATE/started"
+11 -11
View File
@@ -6,15 +6,16 @@ package.
## Before you start
The lab makes sure `cowsay` and `hello` aren't installed, and sets the
time zone to UTC if it's Europe/Berlin already (reset puts the old one
back). Write answers to the files in `/root/lab-answers/`.
The lab makes sure `mc` and `hello` aren't installed (reset puts `mc`
back if you had it), and sets the time zone to UTC if it's Europe/Berlin
already (reset puts the old one back). Write answers to the files in
`/root/lab-answers/`.
## Tasks
1. Install `cowsay` with `apt-get`, list its files with `dpkg -L`, check
its status with `dpkg -s`, then remove it and purge it, checking
`dpkg -l` after each step.
1. Install `mc` with `apt-get`, list its files with `dpkg -L`, check its
status with `dpkg -s`, then remove it and purge it, checking `dpkg -l`
after each step.
2. Find which package provides `/usr/bin/ls`, then try `/bin/ls` and see
why it fails. Then use `apt-file` to find which package would provide
the `ab` command, which you don't have yet. Write the package that owns
@@ -27,11 +28,10 @@ back). Write answers to the files in `/root/lab-answers/`.
## Hints
- `dpkg -l cowsay` shows `ii` while it's installed. A package with
configuration files shows `rc` after `apt-get remove` and disappears
with `apt-get purge`; `cowsay` has none (`dpkg -s` lists no
`Conffiles:`), so it's gone after `remove` and `purge` has nothing left
to do.
- `dpkg -l mc` shows `ii` while it's installed. `mc` has configuration
files (`dpkg -s` lists them under `Conffiles:`), so it shows `rc` after
`apt-get remove`, and disappears with `apt-get purge`. A package without
any, such as `cowsay`, is gone after `remove`.
- `dpkg -S`; `/bin` is a symlink to `usr/bin`, and the package lists the
file only under `/usr/bin`. `apt-get install apt-file`, `apt-file
update`, `apt-file search bin/ab`.
+6 -5
View File
@@ -4,12 +4,13 @@ dpkg_did() {
cat /var/log/dpkg.log 2>/dev/null | awk -v s="$since" -v a="$1" -v p="$2" \
'($1 " " $2) >= s && $3 == a && ($4 == p || index($4, p ":") == 1) {ok = 1} END {exit !ok}'
}
gone() { ! dpkg-query -W -f '${Status}' "$1" 2>/dev/null | grep -Eq 'installed|config-files'; }
gone() { ! dpkg-query -W -f '${Status}' "$1" 2>/dev/null | grep -Eq ' (installed|config-files)$'; }
task 1 "cowsay installed, then removed (and purged)"
need "dpkg's log shows cowsay installed" 'dpkg_did install cowsay'
need "dpkg's log shows cowsay removed" 'dpkg_did remove cowsay'
need "cowsay is gone, configuration files too (dpkg -l)" 'gone cowsay'
task 1 "mc installed, removed, then purged"
need "dpkg's log shows mc installed" 'dpkg_did install mc'
need "dpkg's log shows mc removed" 'dpkg_did remove mc'
need "dpkg's log shows mc purged" 'dpkg_did purge mc'
need "mc is gone, configuration files too (dpkg -l)" 'gone mc'
task 2 "Owner of /usr/bin/ls and provider of ab found"
need "line 1 of /root/lab-answers/2 is the package that owns /usr/bin/ls" '[ "$(sed -n 1p /root/lab-answers/2 | tr -d "[:space:]" | cut -d: -f1)" = "$(dpkg -S /usr/bin/ls | cut -d: -f1)" ]'
+7 -2
View File
@@ -1,7 +1,12 @@
for p in cowsay hello; do
dpkg-query -W -f '${Status}' "$p" 2>/dev/null | grep -Eq 'installed|config-files' &&
for p in mc hello; do
dpkg-query -W -f '${Status}' "$p" 2>/dev/null | grep -Eq ' (installed|config-files)$' &&
DEBIAN_FRONTEND=noninteractive apt-get -y -qq purge "$p" >/dev/null 2>&1
done
if [ -n "$(state_get had-mc)" ]; then
DEBIAN_FRONTEND=noninteractive apt-get -y -qq install mc >/dev/null 2>&1
elif [ -z "$(state_get had-mc-data)" ] && pkg_installed mc-data; then
DEBIAN_FRONTEND=noninteractive apt-get -y -qq purge mc-data >/dev/null 2>&1
fi
rm -f /root/hello_*.deb
tz=$(state_get tz)
if [ -n "$tz" ] && [ -e "/usr/share/zoneinfo/$tz" ]; then
+5 -2
View File
@@ -1,5 +1,8 @@
for p in cowsay hello; do
pkg_installed "$p" && DEBIAN_FRONTEND=noninteractive apt-get -y -qq purge "$p" >/dev/null
pkg_installed mc && state_set had-mc 1
pkg_installed mc-data && state_set had-mc-data 1
for p in mc hello; do
dpkg-query -W -f '${Status}' "$p" 2>/dev/null | grep -Eq ' (installed|config-files)$' &&
DEBIAN_FRONTEND=noninteractive apt-get -y -qq purge "$p" >/dev/null
done
state_set tz "$(timedatectl show -p Timezone --value)"
[ "$(state_get tz)" = Europe/Berlin ] && timedatectl set-timezone Etc/UTC
+3 -2
View File
@@ -30,5 +30,6 @@ in `/root/lab-answers/`.
checksum, `S` the size, `T` the time), `c` marks a configuration file.
- `dnf download --destdir`, `rpm -qpi`, `rpm -qpl`; `rpm2cpio FILE.rpm |
cpio -idv ./usr/bin/tree`, run inside `/root/rpms`.
- `dnf provides dig` downloads the file lists first, which can take a
minute. `dnf history`, `dnf history info last`.
- On RHEL 10 and its relatives, the first `dnf provides` downloads the
repositories' file lists, which can take several minutes on a slow
mirror. `dnf history`, `dnf history info last`.
@@ -8,8 +8,9 @@ partition, wiping a disk, and Btrfs subvolumes and snapshots.
The lab adds two empty 4 GiB spare disks, `/dev/loop40` and `/dev/loop41`
(the chapter's `/dev/sdb` and `/dev/sdc`). Their partitions show up as
`/dev/loop40p1` and so on. It installs the Btrfs tools if they're missing.
Swap you turn on by hand is off again after a reboot, so check before you
reboot.
Task 5 needs Btrfs, which AlmaLinux 10 and Ubuntu have but RHEL and Rocky
Linux leave out, so the lab won't start there. Swap you turn on by hand
is off again after a reboot, so check before you reboot.
## Tasks
@@ -1,4 +1,7 @@
command -v mkfs.btrfs >/dev/null || pkg_install btrfs-progs
modprobe btrfs 2>/dev/null || refuse "this kernel has no Btrfs support, which task 5 needs."
# Task 5 needs Btrfs. RHEL and Rocky Linux have neither the module nor
# btrfs-progs; AlmaLinux 10, Debian and Ubuntu have both.
command -v mkfs.btrfs >/dev/null || pkg_install btrfs-progs ||
refuse "there's no btrfs-progs package here (RHEL and Rocky Linux leave Btrfs out), and task 5 needs it; use AlmaLinux or Ubuntu."
modprobe btrfs 2>/dev/null || refuse "this kernel has no Btrfs support, which task 5 needs (RHEL and Rocky Linux leave it out; use AlmaLinux or Ubuntu)."
disk_add 0 4G >/dev/null
disk_add 1 4G >/dev/null
+4 -4
View File
@@ -15,8 +15,9 @@ that directory, and write answers to the files in `/root/lab-answers/`.
symlink `soft.txt` to it, and look at all three with `ls -li`. Delete
the original, then `cat` both links.
2. Try to hard-link a file onto another filesystem (`df` shows which
directories are on separate ones), and to hard-link a directory. Write
both error messages to `/root/lab-answers/2`.
directories are on separate ones; `/dev/shm` is a tmpfs everywhere,
while `/tmp` is only on some systems), and to hard-link a directory.
Write both error messages to `/root/lab-answers/2`.
3. Make a directory `parent`, check its link count, add two
subdirectories, and check again. Write the first count on line 1 of
`/root/lab-answers/3` and the second on line 2.
@@ -32,8 +33,7 @@ that directory, and write answers to the files in `/root/lab-answers/`.
- `ln`, `ln -s`, `ls -li`; a symlink stores a name, a hard link is another
name for the same inode.
- `/tmp` is on the root filesystem on many systems; `/dev/shm` and `/run`
are tmpfs. `ln FILE /dev/shm/`; `ln DIR NEWNAME`.
- `ln FILE /dev/shm/`; `ln DIR NEWNAME`.
- `ls -ld parent` (the second column), `stat -c %h parent`.
- Without `-n`, `ln -sf 1.1 current` follows `current` into `1.0` and
makes the link there.
+17 -12
View File
@@ -1,20 +1,26 @@
# LPIC-1 108.4: Printers and printing
CUPS with a PDF printer: printing, holding and cancelling jobs, and debug
CUPS with a PDF printer: printing, holding and canceling jobs, and debug
logging.
## Before you start
The lab creates user `alice` (password `Lab-Pass-1`) and installs
`ipptool`, which the check uses to read CUPS's job history. CUPS itself isn't installed yet: that's task 1. Reset removes CUPS
and the PDF printer again.
`ipptool`, which the check uses to read CUPS's job history. CUPS itself
isn't installed yet: that's task 1. Reset removes CUPS and the PDF printer
again.
## Tasks
1. Install `cups` and a PDF printer (`printer-driver-cups-pdf` on Debian and
Ubuntu; `cups-pdf`, from EPEL, on the RHEL family), and find the printer
with `lpstat -p`. As `alice`, print a text file to it; find the PDF it
makes, and write the PDF's full path to `/root/lab-answers/1`.
1. Install `cups` and a PDF printer, and find it with `lpstat -p`. On
Debian and Ubuntu, install `printer-driver-cups-pdf` and `cups-bsd`; the
first adds a printer named `PDF` by itself. On the RHEL family,
`cups-pdf` comes from EPEL (`dnf install epel-release` first) and adds
no printer, so add one:
`lpadmin -p PDF -E -v cups-pdf:/ -m CUPS-PDF_opt.ppd`. As `alice`, print
a text file to it (a job printed by root makes no PDF on the RHEL
family); find the PDF it makes, and write the PDF's full path to
`/root/lab-answers/1`.
2. Disable the printer with a reason, print two files, list them with `lpq`
and `lpstat -o`, remove one with `lprm` and the other with `cancel`, then
enable it again. Also reject jobs on the printer and try to print; read
@@ -26,10 +32,9 @@ and the PDF printer again.
- `lpstat -p -v`; `lp -d PRINTER file`. The PDF lands in `~/PDF` on Debian
and Ubuntu; on the RHEL family it goes to `~/Desktop`, or the home
directory when there's no Desktop. Root's own jobs may fail there. If
`lpstat -p` shows no printer, add one: `lpinfo -m | grep -i pdf`, then
`lpadmin -p PDF -E -v cups-pdf:/ -m ...`.
directory when there's no Desktop. `lpinfo -m | grep -i pdf` lists the
PDF printer's driver.
- `cupsdisable -r "reason"`, `cupsenable`, `cupsreject -r`, `cupsaccept`;
`lpstat -p -l`. On Ubuntu, `lpq` and `lprm` are in the `cups-bsd`
package.
`lpstat -p -l`. On Debian and Ubuntu, `lpq` and `lprm` are in the
`cups-bsd` package.
- `cupsctl --debug-logging`, `cupsctl`; `/var/log/cups/error_log`.
@@ -1,28 +1,33 @@
# LPIC-1 109.2: Persistent network configuration
NetworkManager's devices, profiles and their files, a static address that
lasts, the host name, and `/etc/hosts`.
NetworkManager's devices, profiles and their files (netplan's on Ubuntu), a
static address that lasts, the host name, and `/etc/hosts`.
## Before you start
The peer, at `10.99.0.2` (name `peer`), stands in for another machine.
On the RHEL family, the lab also adds a second network for task 2, so your
own connection to the VM is never touched: interface `le-lan`, with the
NetworkManager profile `lab-net`, which gets an address by DHCP from a
server at `10.98.0.1` on the far side. Tasks 1 and 2 use NetworkManager and
are graded on the RHEL family only; Ubuntu servers use netplan instead.
The lab also adds a second network for task 2, so your own connection to
the VM is never touched: interface `le-lan`, with a machine at `10.98.0.1`
on the far side. On the RHEL family it has the NetworkManager profile
`lab-net`, which gets an address by DHCP from that machine. Ubuntu Server
uses netplan with networkd and doesn't install NetworkManager, so there
`le-lan` starts with no address, and you do tasks 1 and 2 with netplan.
## Tasks
1. RHEL family: read `nmcli device` and `nmcli connection show`, and find the
file of the main interface's active connection with
`nmcli -f NAME,FILENAME connection show`. Read it with `sudo`, and write
its path to `/root/lab-answers/1`.
2. RHEL family: give profile `lab-net` the static address `10.98.0.10/24`
with `nmcli connection modify`, bring the connection up, check with
`ip addr` and `ip route`, and reboot to show it lasts. (The chapter then
returns it to DHCP: do that after you've run the check.)
1. Find the configuration file of the main interface, and write its path
to `/root/lab-answers/1`. RHEL family: read `nmcli device` and
`nmcli connection show`, find the file of the active connection with
`nmcli -f NAME,FILENAME connection show`, and read it with `sudo`.
Ubuntu: read the files in `/etc/netplan/` and `networkctl status`, and
find the netplan file that sets up the main interface.
2. Give `le-lan` the static address `10.98.0.10/24`, check with `ip addr`
and `ip route`, and reboot to show it lasts. RHEL family: on profile
`lab-net`, with `nmcli connection modify`, then bring the connection up.
(The chapter then returns it to DHCP: do that after you've run the
check.) Ubuntu: in a new netplan file, `/etc/netplan/90-lab.yaml`,
applied with `netplan try`.
3. Change the host name to `lab2.example.net` with `hostnamectl`, and check
`/etc/hostname`, the prompt in a new shell, and `hostname -f`.
4. Add the name `files.lab.example` for the peer's address, `10.99.0.2`, to
@@ -30,8 +35,12 @@ are graded on the RHEL family only; Ubuntu servers use netplan instead.
## Hints
- `nmcli -f NAME,DEVICE,FILENAME connection show --active`.
- `nmcli -f NAME,DEVICE,FILENAME connection show --active`. On Ubuntu,
`ls /etc/netplan`, `networkctl list`, `networkctl status`.
- `nmcli connection modify lab-net ipv4.method manual ipv4.addresses ...`,
then `nmcli connection up lab-net`; `ip -br addr show le-lan`.
- In netplan, an `ethernets:` entry for `le-lan` with
`addresses: [10.98.0.10/24]`; `chmod 600` the file; `netplan try` (press
Enter to keep it).
- `hostnamectl set-hostname`, `hostnamectl status`.
- One line in `/etc/hosts`: the address, then the names; `getent hosts`.
@@ -1,15 +1,32 @@
IF=$(ip -4 route show default | awk '{for (i = 1; i < NF; i++) if ($i == "dev") { print $(i + 1); exit }}')
if is_rhel; then
IF=$(ip -4 route show default | awk '{for (i = 1; i < NF; i++) if ($i == "dev") { print $(i + 1); exit }}')
MAINFILE=$(nmcli -t -f DEVICE,FILENAME connection show --active 2>/dev/null | awk -F: -v d="$IF" '$1 == d {print $2; exit}')
prof() { nmcli -g "$1" connection show lab-net 2>/dev/null | tr -d '\\'; }
fi
# The netplan file in answer 1 sets up the main interface (by name or MAC).
netplan_main_ok() {
local f mac
f=$(head -n1 /root/lab-answers/1 2>/dev/null)
case $f in /etc/netplan/*.yaml | /run/netplan/*.yaml | /lib/netplan/*.yaml | /usr/lib/netplan/*.yaml) ;; *) return 1 ;; esac
[ -f "$f" ] && [ -n "$IF" ] || return 1
mac=$(cat "/sys/class/net/$IF/address" 2>/dev/null)
grep -qwF "$IF" "$f" || { [ -n "$mac" ] && grep -qiF "$mac" "$f"; }
}
task 1 "The main connection's file in /root/lab-answers/1" rhel
need "the answer is the file of $IF's active connection" '[ -n "$MAINFILE" ] && [ "$(head -n1 /root/lab-answers/1)" = "$MAINFILE" ]'
task 1 "The main interface's configuration file in /root/lab-answers/1"
if is_rhel; then
need "the answer is the file of $IF's active connection" '[ -n "$MAINFILE" ] && [ "$(head -n1 /root/lab-answers/1)" = "$MAINFILE" ]'
else
need "the answer is the netplan file that sets up $IF" netplan_main_ok
fi
task 2 "lab-net has the static address 10.98.0.10/24, persistently" rhel
need "lab-net's IPv4 method is manual" '[ "$(prof ipv4.method)" = manual ]'
need "lab-net has 10.98.0.10/24" 'prof ipv4.addresses | tr "," "\n" | tr -d " " | grep -qx 10.98.0.10/24'
task 2 "le-lan has the static address 10.98.0.10/24, persistently"
if is_rhel; then
need "lab-net's IPv4 method is manual" '[ "$(prof ipv4.method)" = manual ]'
need "lab-net has 10.98.0.10/24" 'prof ipv4.addresses | tr "," "\n" | tr -d " " | grep -qx 10.98.0.10/24'
else
need "a file in /etc/netplan/ gives le-lan 10.98.0.10/24" 'grep -qs le-lan /etc/netplan/*.yaml && netplan get ethernets.le-lan.addresses 2>/dev/null | grep -qF 10.98.0.10/24'
fi
need "le-lan has 10.98.0.10/24, not from DHCP" 'ip -o -4 addr show dev le-lan | grep -F " 10.98.0.10/24 " | grep -vq dynamic'
need "the route to 10.98.0.0/24 goes out le-lan" 'ip route get 10.98.0.1 | grep -q "dev le-lan"'
need "10.98.0.1 answers ping" 'ping -c1 -W2 10.98.0.1'
@@ -2,16 +2,25 @@ if is_rhel; then
for c in $(nmcli -g UUID,DEVICE,NAME connection show 2>/dev/null | awk -F: '$2 == "le-lan" || $3 == "lab-net" {print $1}'); do
nmcli connection delete "$c" >/dev/null 2>&1
done
systemctl disable --now --quiet le-lab-dhcp.service le-lab-lan.service 2>/dev/null
rm -f /etc/systemd/system/le-lab-dhcp.service /etc/systemd/system/le-lab-lan.service
systemctl daemon-reload
ip link del le-lan 2>/dev/null
systemctl disable --now --quiet le-lab-dhcp.service 2>/dev/null
rm -f /etc/systemd/system/le-lab-dhcp.service /var/lib/dnsmasq/le-lab.leases
[ -n "$(state_get added-dnsmasq)" ] && dnf -y -q remove dnsmasq >/dev/null 2>&1
elif [ -f "$LAB_STATE/netplan.tar" ]; then
rm -rf /etc/netplan
tar -C /etc -xpf "$LAB_STATE/netplan.tar"
netplan generate 2>/dev/null
networkctl reload 2>/dev/null
fi
systemctl disable --now --quiet le-lab-lan.service 2>/dev/null
rm -f /etc/systemd/system/le-lab-lan.service
systemctl daemon-reload
ip link del le-lan 2>/dev/null
if is_rhel; then
rm -f /etc/NetworkManager/conf.d/92-le-lab-lan.conf
systemctl reload NetworkManager 2>/dev/null
rm -f /usr/local/lib/le-lab/lan-net.sh /var/lib/dnsmasq/le-lab.leases
rmdir /usr/local/lib/le-lab 2>/dev/null
[ -n "$(state_get added-dnsmasq)" ] && dnf -y -q remove dnsmasq >/dev/null 2>&1
fi
rm -f /usr/local/lib/le-lab/lan-net.sh
rmdir /usr/local/lib/le-lab 2>/dev/null
old=$(state_get hostname)
[ -n "$old" ] && [ "$(hostname)" != "$old" ] && hostnamectl set-hostname "$old"
sed -i -E '/^[^#]*[[:space:]]files\.lab\.example([[:space:]]|$)/d' /etc/hosts
@@ -1,15 +1,22 @@
if is_rhel; then
command -v nmcli >/dev/null && systemctl is-active --quiet NetworkManager ||
refuse "NetworkManager isn't running; this lab uses it"
else
command -v netplan >/dev/null && systemctl is-active --quiet systemd-networkd ||
refuse "this lab needs netplan with systemd-networkd"
grep -qs le-lan /etc/netplan/*.yaml && refuse "a file in /etc/netplan already mentions le-lan; remove it first"
fi
ip link show le-lan >/dev/null 2>&1 && refuse "an interface le-lan already exists; remove it first"
state_set hostname "$(hostname)"
[ "$(hostname)" != lab2.example.net ] || hostnamectl set-hostname lab-vm
sed -i -E '/^[^#]*[[:space:]]files\.lab\.example([[:space:]]|$)/d' /etc/hosts
peer_up
if is_rhel; then
command -v nmcli >/dev/null && systemctl is-active --quiet NetworkManager ||
refuse "NetworkManager isn't running; this lab uses it"
pkg_installed dnsmasq || { pkg_install dnsmasq; state_set added-dnsmasq 1; }
# le-lan, linked to the peer, where a DHCP server answers on 10.98.0.1.
mkdir -p /usr/local/lib/le-lab
cat >/usr/local/lib/le-lab/lan-net.sh <<'X'
# le-lan, linked to the peer, where 10.98.0.1 answers (and, on the RHEL
# family, a DHCP server).
mkdir -p /usr/local/lib/le-lab
cat >/usr/local/lib/le-lab/lan-net.sh <<'X'
#!/bin/sh
ip link show le-lan >/dev/null 2>&1 || ip link add le-lan type veth peer name le-lanp netns lepeer
ip -n lepeer addr replace 10.98.0.1/24 dev le-lanp
@@ -18,8 +25,8 @@ ip link set le-lan up
command -v nmcli >/dev/null && nmcli device set le-lan managed yes 2>/dev/null
true
X
chmod 755 /usr/local/lib/le-lab/lan-net.sh
cat >/etc/systemd/system/le-lab-lan.service <<'X'
chmod 755 /usr/local/lib/le-lab/lan-net.sh
cat >/etc/systemd/system/le-lab-lan.service <<'X'
[Unit]
Description=Practice lab: the le-lan network
Requires=le-lab-peer.service
@@ -33,6 +40,9 @@ ExecStart=/usr/local/lib/le-lab/lan-net.sh
[Install]
WantedBy=multi-user.target
X
if is_rhel; then
pkg_installed dnsmasq || { pkg_install dnsmasq; state_set added-dnsmasq 1; }
cat >/etc/systemd/system/le-lab-dhcp.service <<'X'
[Unit]
Description=Practice lab DHCP server at 10.98.0.1, on the peer
@@ -56,5 +66,10 @@ X
nmcli connection add type ethernet ifname le-lan con-name lab-net \
ipv4.method auto ipv6.method disabled >/dev/null
timeout 60 nmcli connection up lab-net >/dev/null 2>&1 || warn "lab-net didn't get an address yet; try: nmcli connection up lab-net"
else
# For reset to put back.
tar -C /etc -cf "$LAB_STATE/netplan.tar" netplan
systemctl daemon-reload
systemctl enable --now --quiet le-lab-lan.service
fi
true
@@ -26,7 +26,7 @@ with `sudo ip netns exec lepeer bash`.
directory, and start `python3 -m http.server` there, bound to
`10.99.0.2`. On this VM, configure that repository as `lab` in
`/etc/yum.repos.d/lab.repo` with signature checking on, and install one
of its packages from it.
of its packages from it with `dnf install --repo lab`.
3. Find and install the package that provides the `semanage` command.
4. Remove a package you installed, then undo the removal from dnf's
history.
@@ -41,5 +41,7 @@ with `sudo ip netns exec lepeer bash`.
The repo file needs `baseurl=http://10.99.0.2:8000/`, `gpgcheck=1` and
a `gpgkey=` from `/etc/pki/rpm-gpg/`. `dnf repoinfo lab`;
`dnf install --repo lab NAME` takes it from that repository only.
- `dnf provides semanage` (or `'*/semanage'`).
- `dnf provides semanage` (or `'*/semanage'`). The first `dnf provides`
downloads the file lists of every repository, which can take several
minutes. It isn't hung.
- `dnf history list`, `dnf history info`, `dnf history undo`.
+4 -1
View File
@@ -29,4 +29,7 @@ It also adds a line to `/etc/fstab` for a UUID that doesn't exist, at
- `mkfs.ext4 -L backups`, or `e2label`; `LABEL=backups /backups ext4
defaults 0 2`.
- `findmnt --verify` marks the bad line with `[E]`; run
`systemctl daemon-reload` after editing `/etc/fstab`.
`systemctl daemon-reload` after editing `/etc/fstab`. Run `findmnt
--verify` as root: as a normal user it can't read the devices and warns
`cannot detect on-disk filesystem type (Permission denied)` for every
line.
+3
View File
@@ -21,4 +21,7 @@ zone and chrony's configuration, and puts them back when you reset it.
- `/etc/chrony.conf`: comment out the `pool` line, add a `server` line
with `iburst`; `systemctl restart chronyd`; `chronyc sources`,
`chronyc tracking`.
- If your DHCP server hands out NTP servers, they show up in
`chronyc sources` too: comment out the `sourcedir /run/chrony-dhcp`
line as well.
- `timedatectl list-timezones`, `timedatectl set-timezone`, `timedatectl`.
+2 -2
View File
@@ -23,8 +23,8 @@ service, `le-lab-watch`, that notes the profiles for `eth1` for the check.
`fd00:50::10/64`, all persistent, in a profile made with `nmcli`.
2. Add a second IPv4 address, `192.168.50.11/24`, to the same profile
without removing the first.
3. Delete that profile with `nmcli connection delete`, and do task 1 again
with `nmtui` on a fresh profile.
3. Delete that profile with `nmcli connection delete`, and do tasks 1 and
2 again with `nmtui` on a fresh profile.
## Hints
+3 -1
View File
@@ -25,7 +25,9 @@ task1_needs
task 2 "A second address, 192.168.50.11/24, on the same profile"
need "a profile for eth1 had both 192.168.50.10/24 and 192.168.50.11/24" 'tr " " "\n" <"$LOG" | grep "192\.168\.50\.10/24" | grep -q "192\.168\.50\.11/24"'
task 3 "The profile deleted and made again with nmtui"
task 3 "The profile deleted and tasks 1 and 2 done again with nmtui"
need "a second, fresh profile for eth1 was made" '[ "$(seen_uuids | wc -l)" -ge 2 ]'
need "the first profile is gone" '! nmcli -g UUID connection show | grep -qx "$(seen_uuids | head -n1)"'
task1_needs
need "the fresh profile has 192.168.50.11/24 too" 'prof ipv4.addresses | grep -q "192\.168\.50\.11/24"'
need "eth1 has 192.168.50.11/24 too" 'live 192.168.50.11/24'