Labs follow the guide fixes #3
No files matched your search
@@ -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,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"
|
||||
@@ -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`.
|
||||
|
||||
@@ -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)" ]'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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`.
|
||||
@@ -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.
|
||||
@@ -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`.
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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'
|
||||
Reference in new issue
Block a user