Certifications · LFCS · Practice Tasks

LFCS Practice Tasks

There is no multiple choice on this exam, so there is no multiple choice on this page either. Below are 20 performance-style tasks — the same shape as the real thing: a short scenario, an end state you must produce, and nothing telling you which commands to use to get there. They're split across the five official domains in the same proportion the Linux Foundation weights them — 5 Operations Deployment, 5 Networking, 4 Storage, 4 Essential Commands, 2 Users and Groups, tracking 25/25/20/20/10% — so time spent here mirrors time spent on exam day. Read LFCS — the exam first if you haven't, since these tasks assume you already know what each domain covers; this page is where that knowledge becomes typing. Every task includes a full worked solution and a verification step, because on a performance-based exam, checking your own work is half the skill being tested. Once this bank stops surprising you, move on to a full timed run: Mock Exam · Set 1, Set 2, or Set 3.

☺ Explain it like I'm 10

Some driving tests just ask you questions about road signs. This one hands you actual keys to an actual car with something actually wrong with it — a flat tyre, a dead headlight, a door that won't lock — and two hours to fix as many as you can, for real, with real tools. Nobody gives you credit for saying "I would check the tyre pressure." They walk around the car afterward and check whether the tyre is actually holding air. This page is twenty of those broken cars, one at a time, each with the fix written out afterward so you can compare what you did to what actually works — and however many of the twenty feel new to you right now is roughly how much more garage time you still need before test day.

🦥🦫Your hosts for this topic: Sol the Sloth & Benny the Beaver — Sol won't let a task count as "done" until it's actually verified, not just attempted; Benny is the one who insists you build it, not just read it, before you move to the next line.

How this bank works — and how to use it

☺ Like you're 10: Cover the solution with your hand, try the whole task for real on a spare machine first, and only then peek — the peeking is where the actual learning happens.

Each task below states an end state — what the machine should look like when you're done — the way the real exam's task sheet does. It deliberately does not say which tool to use, because the real one doesn't either: nft or a firewall front-end, nmcli or a raw config file, they're your choice as long as the graded state at the end is correct. Attempt each task cold, on a throwaway Linux VM you can become root on, before opening the worked solution — a local VM under Multipass, VirtualBox or libvirt/KVM works fine, and since one Operations Deployment competency names SELinux specifically, a Fedora-family distro (Fedora, Rocky, AlmaLinux) is the safer practice target than a Debian/Ubuntu box running AppArmor by default.

One task, three stages — only the last one is graded THE PROMPT an end state, described in words — not a recipe YOUR TERMINAL root shell, any tool, any order, man pages only THE FINAL STATE — this alone is what's graded No partial credit for explaining the fix in words. Only the machine's state after you finish counts.
🦫Operations Deployment
5 tasks · 25%
🐦Networking
5 tasks · 25%
🦥Storage
4 tasks · 20%
🐢Essential Commands
4 tasks · 20%
🦝Users and Groups
2 tasks · 10%
⚠ Original tasks, not official exam content

Every task below was written for this course against the LFCS's published domains and competencies. None of it is drawn from, or claims to reproduce, the real proctored exam, which the Linux Foundation does not release publicly. Solving all twenty tells you the shape of your own gaps; it isn't a guarantee of the real paper's exact difficulty or phrasing. Duration, task count and the 67% pass mark referenced throughout this bank are per the official LFCS page and candidate instructions as of writing — verify all of it officially before you book, since Linux Foundation exams change these numbers over time.

This bank contains no Kubernetes whatsoever, on purpose — LFCS tests the layer underneath it, not the cluster itself. If you want the equivalent performance-based drilling for the cluster layer this course assumes you already hold, that lives on the Kubernetes course's own practice pages, for example the CKA practice tasks.

Operations Deployment — Tasks 1–5 (25% of the exam)

☺ Like you're 10: This pile is "keep the machine's programs running, on schedule, and inside a budget" — the engine room.

  1. Task 1. A monitoring binary already exists at /usr/local/bin/telemetry-agent and reads its config from /etc/telemetry/agent.yaml. Create and enable a systemd service unit named telemetry-agent.service that: runs the agent as the unprivileged user telemetry; restarts automatically 5 seconds after any failure; is capped at 256M of memory and 50% of one CPU; and is both running right now and still running after every future reboot.

    Show worked solution
    # /etc/systemd/system/telemetry-agent.service
    [Unit]
    Description=Telemetry agent
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=simple
    User=telemetry
    ExecStart=/usr/local/bin/telemetry-agent --config /etc/telemetry/agent.yaml
    Restart=on-failure
    RestartSec=5s
    MemoryMax=256M
    CPUQuota=50%
    
    [Install]
    WantedBy=multi-user.target
    sudo systemctl daemon-reload
    sudo systemctl enable --now telemetry-agent.service   # starts it AND marks it for boot, in one command
    systemctl is-enabled telemetry-agent.service           # confirm it survives a reboot
    systemctl status telemetry-agent.service                # confirm it's actually running now

    enable --now is the one command that satisfies "running right now" and "running after reboot" at once — running systemctl start alone would leave the unit disabled, passing half the task and failing the other half.

  2. Task 2. The existing service billing-sync.service was working yesterday and is now failing to start after a colleague's change. Diagnose why, and fix it using the officially supported override mechanism — do not directly edit the vendor unit file at /etc/systemd/system/billing-sync.service, since a future package update would silently overwrite hand-edits made there.

    Show worked solution
    systemctl status billing-sync.service                          # failed, exit code, last lines
    journalctl -u billing-sync.service -p err --since "10 min ago" --no-pager
    # → "config file /etc/billing-sync.yaml: no such file or directory"
    ls /etc/billing-sync/                                           # the file actually lives here now: config.yaml
    
    sudo systemctl edit billing-sync.service   # opens a drop-in editor at
                                                # /etc/systemd/system/billing-sync.service.d/override.conf
    # written inside the drop-in editor
    [Service]
    ExecStart=
    ExecStart=/usr/local/bin/billing-sync --config /etc/billing-sync/config.yaml
    sudo systemctl daemon-reload
    sudo systemctl restart billing-sync.service
    systemctl status billing-sync.service
    systemctl cat billing-sync.service     # shows the EFFECTIVE unit: vendor file + your drop-in, merged

    The empty ExecStart= line on its own is not decorative — ExecStart= can be set multiple times and normally accumulates, so without first clearing it your drop-in would add a second command rather than replace the vendor's. This is the single most common mistake when overriding a unit this way.

  3. Task 3. This host will act as a router between two internal networks. Enable IPv4 forwarding so it survives a reboot — not just for the current running kernel.

    Show worked solution
    sudo sysctl -w net.ipv4.ip_forward=1                              # live, right now — lost on reboot alone
    echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ip-forward.conf
    sudo sysctl --system                                              # reload every file under sysctl.d
    sysctl net.ipv4.ip_forward                                        # confirm = 1
    cat /proc/sys/net/ipv4/ip_forward                                 # same value, read straight from the kernel

    Keep Task 3's parameter in mind for Task 8 below — a NAT rule with forwarding still disabled at the kernel level drops every packet silently, and looks exactly like a broken firewall rule until you check this file.

  4. Task 4. The shell script /usr/local/bin/nightly-report.sh needs to run every day at 02:15, using a systemd timer rather than a crontab entry. If the machine happens to be powered off at exactly 02:15 on a given night, the job should still run once, as soon as the machine boots back up, rather than being silently skipped for that day.

    Show worked solution
    # /etc/systemd/system/nightly-report.service
    [Unit]
    Description=Nightly report generator
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/bin/nightly-report.sh
    
    # /etc/systemd/system/nightly-report.timer
    [Unit]
    Description=Run nightly-report.service daily at 02:15
    
    [Timer]
    OnCalendar=*-*-* 02:15:00
    Persistent=true
    
    [Install]
    WantedBy=timers.target
    sudo systemctl daemon-reload
    sudo systemctl enable --now nightly-report.timer
    systemctl list-timers --all | grep nightly-report      # confirm NEXT and LEFT columns look right

    Persistent=true is the whole answer to the "machine was off" half of the task: it makes systemd record whether a run was missed and fire it once at the next boot, instead of just waiting silently for the following day's 02:15. Note the timer unit is what gets enabled — the paired .service stays disabled and is only ever triggered by its timer.

  5. Task 5. Run the image registry.internal/web:2.4 as a rootless Podman container named web, publishing container port 8080 to host port 8080, and make sure the container comes back automatically after a host reboot — using systemd, not Podman's own --restart flag alone, since only a systemd-managed unit is visible to this host's existing monitoring.

    Show worked solution
    podman run -d --name web -p 8080:8080 registry.internal/web:2.4
    podman ps
    
    mkdir -p ~/.config/systemd/user
    cd ~/.config/systemd/user
    podman generate systemd --new --name web --files --restart-policy=on-failure
    # writes container-web.service into the current directory
    
    systemctl --user daemon-reload
    systemctl --user enable --now container-web.service
    loginctl enable-linger "$(whoami)"      # lets the --user unit run without an active login session
    
    systemctl --user status container-web.service

    loginctl enable-linger is the step people forget: without it, a systemctl --user unit only runs while that user has an active session, and dies the moment they log out — which defeats "comes back after a reboot" entirely. (Newer Podman releases also offer Quadlet, a native .container unit format that skips the generate step; the underlying idea — a real systemd unit managing the container, not Podman's own restart flag — is the same either way.)

Networking — Tasks 6–10 (25% of the exam)

☺ Like you're 10: This pile is "make machines talk to each other, safely, and know what time it is" — wires, addresses, and locks on the door.

  1. Task 6. Interface eth0 currently gets its address via DHCP. Reconfigure it with a static IPv4 address of 10.0.20.15/24, gateway 10.0.20.1, and DNS server 10.0.20.53 — the change must survive a reboot, and must not be a hand-edit of a config file.

    Show worked solution
    nmcli con show                              # find the profile name bound to eth0, e.g. "Wired connection 1"
    nmcli con mod "Wired connection 1" ipv4.method manual
    nmcli con mod "Wired connection 1" ipv4.addresses 10.0.20.15/24
    nmcli con mod "Wired connection 1" ipv4.gateway 10.0.20.1
    nmcli con mod "Wired connection 1" ipv4.dns 10.0.20.53
    nmcli con up "Wired connection 1"
    
    ip -br addr show eth0
    ip route
    resolvectl status eth0

    nmcli writes to NetworkManager's own connection profile (typically under /etc/NetworkManager/system-connections/) rather than a file you touch directly, and the profile is reapplied automatically on every boot — which is exactly what "must not be a hand-edit" and "must survive a reboot" are both testing.

  2. Task 7. This host already reaches 10.0.20.0/24 directly. Add a persistent static route so it can also reach 192.168.77.0/24, via a gateway at 10.0.20.254 on that same interface.

    Show worked solution
    sudo ip route add 192.168.77.0/24 via 10.0.20.254    # live now — does NOT survive a reboot on its own
    nmcli con mod "Wired connection 1" +ipv4.routes "192.168.77.0/24 10.0.20.254"
    nmcli con up "Wired connection 1"
    
    ip route show | grep 192.168.77

    The plain ip route add is worth running first anyway — it proves the route actually works before you commit to a persistent form. The +ipv4.routes syntax adds to the profile's route list rather than replacing it, which matters if other static routes are already configured on the same connection.

  3. Task 8. This host has two interfaces: eth0 facing the internet, eth1 facing an internal 10.0.30.0/24 network. Configure it to (a) allow inbound SSH on eth0, (b) drop every other unsolicited inbound connection on eth0 by default, and (c) let internal hosts on eth1 reach the internet through this box via NAT.

    Show worked solution
    # filtering
    sudo nft add table inet filter
    sudo nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
    sudo nft add rule inet filter input iif lo accept
    sudo nft add rule inet filter input ct state established,related accept
    sudo nft add rule inet filter input iif eth0 tcp dport 22 accept
    
    # NAT
    sudo nft add table ip nat
    sudo nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
    sudo nft add rule ip nat postrouting oif eth0 masquerade
    
    sudo nft list ruleset
    
    # make it survive a reboot (naming varies by distro packaging)
    sudo sh -c 'nft list ruleset > /etc/nftables.conf'
    sudo systemctl enable --now nftables

    Two easy ways to fail this task even with a correct ruleset: forgetting ct state established,related accept, which silently breaks every outbound connection this host itself makes (including your own SSH session's return traffic); and forgetting Task 3's net.ipv4.ip_forward=1 — without it, the kernel drops routed packets before the NAT rule ever sees them, and the ruleset looks completely correct while nothing forwards at all.

  4. Task 9. Convert SSH access to this host from password-based to key-only for the existing user dot, and make sure root can no longer log in over SSH at all.

    Show worked solution
    # on the CLIENT
    ssh-keygen -t ed25519 -f ~/.ssh/mission_ed25519
    ssh-copy-id -i ~/.ssh/mission_ed25519.pub dot@10.0.20.15
    # on the SERVER — /etc/ssh/sshd_config
    PermitRootLogin no
    PasswordAuthentication no
    PubkeyAuthentication yes
    sudo sshd -t                          # validate syntax BEFORE restarting — do not skip this
    sudo systemctl restart sshd
    
    # verify from a SECOND, still-open session — never close your only one first
    ssh -i ~/.ssh/mission_ed25519 dot@10.0.20.15                                    # should succeed
    ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no dot@10.0.20.15  # should be refused

    sshd -t is the step that separates a five-minute task from a locked-out grading host: a typo in sshd_config that passes on save but fails on restart leaves the daemon down entirely, with no way back in over the network it was just supervising.

  5. Task 10. Confirm this host is actually synchronizing its clock against a real time source — not just claiming to — and if it isn't, point it at time servers 10.0.0.1 and 10.0.0.2 and get it synced.

    Show worked solution
    chronyc tracking          # check "Leap status" (should read Normal) and the offset
    chronyc sources -v        # which servers is it actually reaching, and how good is each reading
    # /etc/chrony.conf (RHEL family) or /etc/chrony/chrony.conf (Debian family) —
    # replace any existing pool/server lines with:
    server 10.0.0.1 iburst
    server 10.0.0.2 iburst
    sudo systemctl restart chronyd     # 'chrony' on Debian-family systems
    chronyc tracking                   # re-check — Leap status: Normal
    timedatectl status                 # "NTP service: active" / "System clock synchronized: yes"

    Clock skew is the failure this competency exists for: a few minutes of drift silently breaks TLS certificate validation and any Kerberos-style time-sensitive auth, and the symptom at that point looks nothing like "the clock is wrong" — it looks like a broken certificate or a rejected login.

Storage — Tasks 11–14 (20% of the exam)

☺ Like you're 10: This pile is "where things are actually kept, how much room is left, and what happens when a server disappears."

  1. Task 11. Two raw, unused disks are attached as /dev/sdb and /dev/sdc. Combine them into one volume group named data_vg, carve out a 20G logical volume named app_lv, format it XFS, and mount it at /srv/app — persistently, without you running mount by hand after a reboot.

    Show worked solution
    sudo pvcreate /dev/sdb /dev/sdc
    sudo vgcreate data_vg /dev/sdb /dev/sdc
    sudo lvcreate -n app_lv -L 20G data_vg
    sudo mkfs.xfs /dev/data_vg/app_lv
    sudo mkdir -p /srv/app
    
    blkid /dev/data_vg/app_lv          # grab the UUID — safer in fstab than a /dev/mapper path
    echo "UUID= /srv/app xfs defaults 0 2" | sudo tee -a /etc/fstab
    sudo mount -a                      # tests the fstab line NOW, instead of finding out at next reboot
    
    df -hT /srv/app

    Testing the fstab entry with mount -a before you're graded matters: a typo'd UUID or a missing mount point directory won't show up as an error at all until the box actually reboots, which on a timed exam you may not get to do.

  2. Task 12. The app_lv volume from Task 11 is now at 95% capacity, and data_vg still has 15G of free extents. Grow the logical volume by 10G and grow the XFS filesystem on top of it in the same step, without unmounting /srv/app.

    Show worked solution
    vgs data_vg                          # confirm free PE covers the request
    sudo lvextend -r -L +10G /dev/data_vg/app_lv
    df -hT /srv/app                      # confirm the new size, live, no unmount required

    The -r flag is what makes this one command instead of two — it calls the right filesystem-resize tool (xfs_growfs here; resize2fs for ext4) automatically after the volume resize. Worth knowing for exam day: XFS can only ever grow online — there is no supported way to shrink an XFS filesystem in place, unlike ext4.

  3. Task 13. Add 4G of swap to this host, backed by a new logical volume named swap_lv inside data_vg (which still has room), active immediately and after every future boot.

    Show worked solution
    sudo lvcreate -n swap_lv -L 4G data_vg
    sudo mkswap /dev/data_vg/swap_lv
    sudo swapon /dev/data_vg/swap_lv
    
    echo "/dev/data_vg/swap_lv none swap sw 0 0" | sudo tee -a /etc/fstab
    
    swapon --show
    free -h

    Two separate steps are both required and easy to forget one of: swapon activates it for the running system right now, and the /etc/fstab line is what makes it come back after the next reboot. Skip the fstab line and the task looks complete until the machine restarts.

  4. Task 14. Instead of a hard fstab mount at boot — which would hang this host's startup if the NFS server is ever unreachable — configure the export 10.0.0.20:/export/data to mount on demand under /mnt/auto/data whenever it's accessed, and unmount itself automatically once idle.

    Show worked solution
    sudo dnf install -y autofs          # 'apt install autofs' on Debian-family systems
    # /etc/auto.master
    /mnt/auto  /etc/auto.data
    
    # /etc/auto.data
    data  -fstype=nfs,rw  10.0.0.20:/export/data
    sudo systemctl enable --now autofs
    
    ls /mnt/auto/data           # the access itself triggers the mount
    mount | grep auto.data      # confirm it's there
    
    # after the default 5-minute idle timeout:
    mount | grep auto.data      # → nothing. it unmounted itself.

    This is precisely the "remote filesystems" and "filesystem automounters" competencies working together: a plain fstab NFS entry blocks the whole boot sequence waiting for a server that might be down, while autofs only ever mounts on access and cleans up after itself — the safer default for any share that isn't guaranteed to always be reachable.

Essential Commands — Tasks 15–18 (20% of the exam)

☺ Like you're 10: This pile is a grab-bag every real sysadmin reaches for daily — version control, finding missing disk space, and proving a certificate is what it claims to be.

  1. Task 15. A bare Git repository already exists at git@git.internal:platform/configs.git. Clone it, create a new branch named add-nginx-upstream, add a file nginx/upstream.conf containing a one-line proxy_pass directive to http://127.0.0.1:8080, commit it, and push the branch upstream.

    Show worked solution
    git clone git@git.internal:platform/configs.git
    cd configs
    git checkout -b add-nginx-upstream
    
    mkdir -p nginx
    printf 'location / { proxy_pass http://127.0.0.1:8080; }\n' > nginx/upstream.conf
    
    git add nginx/upstream.conf
    git commit -m "add nginx upstream config"
    git push -u origin add-nginx-upstream
    
    git status                # clean tree, branch tracking origin/add-nginx-upstream
    git log --oneline -3

    -u on the push isn't cosmetic — it sets the upstream tracking branch, which is what lets git status report "up to date with origin/…" instead of leaving the branch's relationship to the remote unset.

  2. Task 16. /var reports 98% full according to df, but manually adding up everything under /var with du only accounts for about 60% of that. Find where the missing space actually is, and reclaim it.

    Show worked solution
    df -hT /var
    du -xhd1 /var | sort -h | tail          # doesn't add up to what df reports
    
    lsof +L1                                # files with a link count of 0 — deleted, but still open
    # → rsyslog     812  root   5w  REG  253,0  6.2G  /var/log/syslog (deleted)
    sudo systemctl restart rsyslog          # reopens its log file cleanly; releases the deleted one's space
    # an alternative that avoids a full restart, if the daemon supports it:
    sudo kill -HUP 812
    
    df -hT /var                             # space is back

    This is the classic "df and du disagree" trap: a process still holds an open file descriptor to a file that was deleted (often by a log rotation gone wrong) — the directory entry is gone, so du can't see it, but the kernel won't reclaim the blocks until every process holding it open closes or is restarted. lsof +L1 is built for exactly this.

  3. Task 17. Generate a self-signed TLS certificate and private key for the hostname api.internal.example, valid for 365 days, and confirm both its expiry date and its Common Name / Subject Alternative Name are correct — without opening the file in a text editor.

    Show worked solution
    openssl req -x509 -newkey rsa:2048 -keyout api.key -out api.crt -days 365 -nodes \
      -subj "/CN=api.internal.example" \
      -addext "subjectAltName=DNS:api.internal.example"
    
    chmod 600 api.key                                  # a private key has no business being world-readable
    
    openssl x509 -in api.crt -noout -dates -subject -ext subjectAltName
    # notBefore / notAfter (365 days apart), subject=CN=api.internal.example,
    # X509v3 Subject Alternative Name: DNS:api.internal.example

    If this certificate is later bound to a live service, the same inspection works over the wire without ever touching the file on disk: openssl s_client -connect api.internal.example:443 -servername api.internal.example </dev/null 2>/dev/null | openssl x509 -noout -dates -subject — worth knowing, because that's how you'd actually verify someone else's certificate deployment, not just your own.

  4. Task 18. Users report this host feels sluggish. Identify which single process is responsible for the load — without guessing — and determine whether the real bottleneck is CPU or something else, such as disk I/O wait.

    Show worked solution
    uptime                                  # load average — compare against nproc
    nproc
    
    ps -eo pid,ppid,cmd,%cpu,%mem --sort=-%cpu | head -6    # or: top -o %CPU
    
    vmstat 1 5                              # watch the 'us'/'sy' columns vs the 'wa' column
    iostat -xz 1 5                          # if 'wa' is high, which device is actually busy

    The distinction between columns is the actual point of this task, not just running the commands: high us/sy means a process is genuinely burning CPU cycles, and the fix is to renice, limit, or kill it; high wa (I/O wait) means the CPU is mostly idle, sitting around waiting on a slow disk or a saturated volume, and the fix is entirely different — chasing the wrong one wastes the two hours you don't have to spare.

Users and Groups — Tasks 19–20 (10% of the exam)

☺ Like you're 10: The smallest pile at 10%, but still worth two full tasks — who's allowed to do what, and exactly how much of the machine they're allowed to use.

  1. Task 19. Create a new local user named dot, with an auto-created home directory, secondary membership in both developers and platform-admins, and /bin/bash as the shell. This user's processes must never be able to open more than 4096 file descriptors at once, even under load, and that limit must survive dot logging out and back in.

    Show worked solution
    sudo groupadd developers 2>/dev/null       # ignore "already exists" if a group is already present
    sudo groupadd platform-admins 2>/dev/null
    
    sudo useradd -m -G developers,platform-admins -s /bin/bash dot
    sudo passwd dot
    
    id dot
    groups dot
    # /etc/security/limits.conf
    dot   soft   nofile   4096
    dot   hard   nofile   4096
    # the limit is applied by PAM at LOGIN time — it will NOT retroactively affect an already-open session
    su - dot -c "ulimit -Sn; ulimit -Hn"       # log in fresh as dot and confirm both read 4096

    Setting both soft and hard to the same value is what actually enforces a hard ceiling — a soft-only entry just changes the default, which dot's own processes could still raise back up to the (unset, effectively unlimited) hard limit. And this is a PAM-enforced limit, not a live kernel toggle: it only takes effect for a session that logs in after the file is edited.

  2. Task 20. The directory /srv/reports is owned root:root, mode 750. Without changing the owner, the group, or the base permission bits, grant the single user dot read+execute access, and make sure any new file created inside /srv/reports by anyone else automatically grants dot the same access too.

    Show worked solution
    getfacl /srv/reports                        # baseline — no extended ACL yet
    
    sudo setfacl -m u:dot:rx /srv/reports        # access ACL: dot can enter and list THIS directory
    sudo setfacl -d -m u:dot:rx /srv/reports     # default ACL: new children inherit the same entry
    
    getfacl /srv/reports
    ls -ld /srv/reports                          # note the trailing '+' — confirms an ACL is attached
    
    sudo touch /srv/reports/test.txt
    getfacl /srv/reports/test.txt                # dot:r-x should appear, inherited from the default ACL

    One genuine gotcha worth knowing before it costs you marks: a default ACL entry is copied onto new files verbatim, but the resulting effective permission is still trimmed by that file's own ACL mask — getfacl will print an explicit #effective: annotation whenever the entry you set and the entry that actually applies differ. Never assume the default ACL you configured is the permission a new file ends up with; always confirm with getfacl on the actual file, not just on the parent directory.

Turning a failed task into a fact

☺ Like you're 10: The score isn't the point. What matters is why a task went wrong — because "I didn't know that tool existed" and "I typed the right idea in the wrong order" need completely different fixes.

When a task doesn't come out right, be honest about which of two things happened. If you genuinely didn't know the mechanism — you'd never heard of a systemd drop-in, or didn't know ACLs existed as a concept — that's a content gap, and the fix is rereading the matching section of LFCS — the exam until you can explain it in your own words, not just recognise the commands here. If you knew the concept but the final state still came out wrong, that's almost always a missed verification step — you ran the command but never checked getfacl, df, or systemctl status afterward to confirm it actually did what you intended. On a graded machine, an unverified fix and no fix at all score identically.

🦆 Dot's-eye view

"Task 8's NAT rule — I built the exact ruleset above, checked it three times with nft list ruleset, and traffic still didn't route. Twenty minutes gone before I thought to check net.ipv4.ip_forward, which was still 0 from a fresh VM image. The firewall rule was never the problem. The kernel was refusing to forward the packet to the NAT table in the first place, and no amount of staring at nft syntax was ever going to show me that, because the ruleset itself was completely correct the whole time."

(Composite, illustrative account — not a specific person's story.)

🦫 Benny's workshop · 45 min

Pick your three lowest-confidence tasks from the bank above and re-run them from a freshly reset VM snapshot, cold, with a timer running — six minutes each, matching roughly the two-hour, 17-to-20-task pace of the real exam. Don't open the worked solution until the timer ends or you're stuck for real. Then diff what you actually typed against the solution above, not just whether the end state matched — a task you solved a slower or clumsier way still counts as solved on exam day, but noticing the faster path now is free speed you keep forever.

🎬 At Mission Control
🦊

Foxy: Twenty tasks and not one of them gives you four options to pick from? That feels so much harder than a normal exam.

🦥

Sol: It's harder to fake, Foxy. Not harder to pass, if you've actually built each thing once before.

🦫

Benny: And you can't half-do a task and hope for partial credit either. Either getfacl shows the entry you meant to set, or it doesn't.

👺

Gizmo: Pfft, skip the verification step, who's got time. If the command didn't print an error, it worked. 😈

🐢

Timmy: Task 20 says otherwise, Gizmo — setfacl ran without a single error and still didn't give you the permission you thought it did. Silence isn't proof. Checking is.

🦥

Sol: Which is why every task above ends the same way — not "and then I'm done," but "and then I confirmed it."

🐰

Remy: Say it back: 20 tasks, weighted 5/5/4/4/2 across the five domains, no partial credit for describing a fix, only for a state you actually verified.

Read the full domain breakdown and exam logistics on LFCS — the exam, follow the day-by-day calendar on the LFCS study plan, or go deeper on any one mechanism at systemd & journald and LVM & Linux Storage Tools. Once every task above feels routine, sit a full timed run: Mock Exam · Set 1, Set 2, Set 3.

🐢 Timmy's checkpoint

1. This bank has 20 tasks split 5/5/4/4/2 across the five domains — which two domains get the most tasks, and why those two specifically? 2. In Task 2, why is an empty ExecStart= line required on its own line before setting the real override? 3. In Task 9, what's the one command you must run before restarting sshd after editing its config, and what happens if you skip it? 4. In Task 14, why is autofs a better fit than a plain fstab entry for a remote NFS share? 5. In Task 20, why might getfacl show a default ACL entry you set, but an "effective" permission that's actually lower? 6. What's the practical difference between the 'us'/'sy' columns and the 'wa' column in vmstat output, and why does that difference change how you'd fix a slow host? 7. True or false: on this exam, correctly describing in words how you would fix a broken unit earns partial credit even if you run out of time to actually type the commands.

Check your answers
  1. Operations Deployment and Networking, 5 tasks each — because they're the two domains the Linux Foundation weights at 25% apiece, together half the real exam, so this bank spends half its tasks there too.
  2. Because ExecStart= can be declared multiple times and normally accumulates rather than replaces — without first clearing it with a bare ExecStart=, your drop-in adds a second command alongside the vendor's instead of overriding it.
  3. sshd -t, which validates the config file's syntax before you touch the running daemon. Skip it and a typo that saves fine can still fail to load on restart, potentially locking out remote access to the very host you were fixing.
  4. A hard fstab mount blocks the boot sequence until the remote server responds, hanging startup entirely if it's ever unreachable; autofs only mounts on access and unmounts itself when idle, so an unreachable server never holds up the boot.
  5. A default ACL entry is copied onto new files verbatim, but the file's own ACL mask can still trim what's actually granted — getfacl prints an explicit #effective: line whenever the set entry and the applied permission differ, so always verify on the actual file rather than assuming the default entry is the final word.
  6. us/sy mean a process is genuinely consuming CPU cycles (fix: renice, limit, or kill it); wa means the CPU is mostly idle, waiting on slow storage (fix: find and address the disk bottleneck instead). Treating one as the other wastes time chasing the wrong fix.
  7. False. This is a performance-based exam graded on the final state of the machine — a correct explanation with no working result scores exactly the same as no attempt at all.