Resolving “Permission denied” When Moving Files Into a Sticky‑Bit Directory Using ACLs

Sticky‑Bit Directories and ACLs: Why “Permission denied” Still Happens

When you try to move a file into a directory that has the sticky bit set, the kernel first checks the directory’s owner and the user’s write permission. If the directory is owned by someone else, the sticky bit forces it to also check the file’s owner. ACLs can grant write access to a group or user, but the sticky‑bit logic still requires the file’s owner to match the directory’s owner unless the moving user has the write permission on the file itself. That subtle rule is the source of a lot of “Permission denied” errors that only surface when ACLs are involved.

[Read More]

Web Application and API Protection (WAAP) platforms and Next-Generation WAFs (NGWAF)

Web Application and API Protection on Linux

Why WAAP and NGWAF matter for self‑hosters

When you expose a service over HTTP(S), the attack surface expands beyond the kernel. Modern web apps and APIs get hit with injection, XSS, CSRF, and the newer API‑specific threats like replay or rate‑limit abuse. A WAAP (Web Application and API Protection) or NGWAF (Next‑Generation Web Application Firewall) sits in front of your HTTP stack and can stop most of those before they even reach your code.

[Read More]

How to Use systemd‑resolved to Serve a Local Search Domain on My Home Network

Why a Local Search Domain Matters

In a home network you often want to reach devices by simple names—printer, raspberrypi, nas—instead of remembering IP addresses. A local search domain lets the resolver append a suffix automatically, turning printer into printer.home.local. systemd‑resolved can supply that suffix for the host itself, and, when coupled with a lightweight DNS forwarder, can expose the same domain to all clients.

Prerequisites

ItemWhy it mattersTypical command
systemd‑resolved enabledIt supplies the stub resolver on 127.0.0.53systemctl enable --now systemd-resolved
systemd‑networkd or another network managerNeeded to push the domain to clients via DHCPsystemctl enable --now systemd-networkd
Optional: dnsmasq or bindTo serve the domain to other hostsapt install dnsmasq (Debian/Ubuntu)
Firewall configuredTo restrict DNS trafficufw allow 53 (or firewalld rules)

All examples assume a Debian‑based system; adjust package names for your distro.

[Read More]

Pulling a Single File from a Borg Backup Without Unpacking the Whole Archive

Pulling a single file from a Borg backup without unpacking the whole archive is a common task for sysadmins who need quick recovery of a configuration file, a database dump, or a user document.
The following walkthrough shows how to do it safely, efficiently, and with a minimal security footprint.

Why pull a single file?

  • Speed – Extracting an entire archive can take minutes or hours on large repositories.
  • Disk space – You may not have room to unpack thousands of files.
  • Security – Extracting only what you need reduces the attack surface; you avoid exposing the rest of the backup to the current filesystem.
  • Automation – Scripts that restore a single file can run in CI/CD pipelines or as part of a systemd timer.

Borg basics recap

Borg is a deduplicating backup program that stores data in a repository.
Each backup is an archive that can contain one or more directories.
The repository can be local or remote (SSH, HTTP, or a network filesystem).
Borg supports strong encryption (repokey, passphrase, or keyfile) and can be configured to use a keyfile stored on the backup host.

[Read More]

Stop systemd‑journald from filling your Raspberry Pi’s 8 GB SD card with logs – how to cap its size

Why journald can eat your SD card

Running a Raspberry Pi on an 8 GB SD card is a rite of passage for home labs, IoT experiments, and low‑cost servers.
On Pi OS the default is to keep systemd‑journald persistent, so every log line ends up on that tiny flash drive.
In practice the Pi runs a handful of services—networking, SSH, Docker, custom scripts—that churn out logs faster than the card can keep up.
The result? The SD card fills up, you can’t install updates, and the OS itself starts to feel cramped.

[Read More]

Send a Telegram Alert When Your Home Server’s /home Reaches 90% Usage With a Tiny systemd Service and curl

Monitoring /home Usage with a Systemd Timer

A home server rarely needs a full‑blown monitoring stack.
If you just want a quick alert when /home fills up, a tiny systemd service plus curl will do the trick. The example below keeps the footprint minimal, respects security best practices, and uses the official Telegram Bot API.

1. Create a Bot and Grab Credentials

  1. Talk to BotFather on Telegram and create a bot.
  2. Note the bot token (e.g. 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11).
  3. Find your chat ID by sending a message to the bot and querying https://api.telegram.org/bot<token>/getUpdates.
  4. Store both values in a read‑only file:
sudo mkdir -p /etc/telegram-alert
sudo tee /etc/telegram-alert/credentials <<EOF
TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
CHAT_ID=987654321
EOF
sudo chmod 600 /etc/telegram-alert/credentials

2. Service Unit – home-usage-alert.service

# /etc/systemd/system/home-usage-alert.service
[Unit]
Description=Send Telegram alert when /home exceeds 90%% usage
After=network.target

[Service]
Type=oneshot
EnvironmentFile=/etc/telegram-alert/credentials
ExecStart=/usr/bin/bash -c '
  USAGE=$(df --output=pcent /home | tail -1 | tr -d "%")
  if [ "$USAGE" -ge 90 ]; then
    curl -s -X POST https://api.telegram.org/bot$TOKEN/sendMessage \
      -d chat_id=$CHAT_ID \
      -d text="⚠️ /home is at ${USAGE}%% capacity. Free space needed." \
      -H "Content-Type: application/x-www-form-urlencoded"
  fi
'
PrivateTmp=yes
ProtectSystem=full
RestrictAddressFamilies=AF_INET AF_INET6
Restart=no

[Install]
WantedBy=multi-user.target

Security notes

[Read More]

Stop the “REMOTE HOST IDENTIFICATION HAS CHANGED!” error by cleaning ~/.ssh/known_hosts.

Why the “REMOTE HOST IDENTIFICATION HAS CHANGED!” error appears

The message “REMOTE HOST IDENTIFICATION HAS CHANGED!” shows up every time you try to SSH into a host that reports a different key than the one you stored in ~/.ssh/known_hosts.
It’s a sanity check that protects you from man‑in‑the‑middle attacks, but it can also be a pain when you’re just redeploying a server or spinning up a VM that got a new IP.

[Read More]

Easily Remove Stale Entries from ~/.ssh/known_hosts When a Host Rebuilds with ssh-keygen ‑R

When a host rebuilds, its SSH key changes

A fresh install or a system rebuild swaps the host’s RSA/ED25519 key pair.
If you still have the old key in ~/.ssh/known_hosts, the next SSH connection will trigger a “WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!” message.
That warning is a safety feature, but it also blocks automation and forces users to manually edit the file.

The quickest, safest way to clean up stale entries is to let OpenSSH do the work with ssh-keygen -R. The command removes every key that matches the supplied hostname or IP, regardless of whether the entry is hashed or plain.

[Read More]

Fix a Boot Stuck at “Loading initramfs” After Adding an NVMe to Ubuntu 24.04

When a new NVMe sticks, the boot can stall at “Loading initramfs”

Adding a second NVMe drive to an existing Ubuntu 24.04 installation is a quick way to get more storage or carve out a dedicated data partition.
Most of the time the kernel pulls the NVMe driver on its own, but a handful of mis‑configurations can make the system hang in the initramfs shell.
Typical symptoms:

  • The screen shows “Loading initramfs …” and then stops.
  • The prompt switches to a root shell (root@hostname:/#).
  • Nothing else happens until you manually exit or reboot.

Below is a hands‑on walk‑through of the most common culprits and how to fix them. I’ll assume you have a working Ubuntu 24.04 install and a spare NVMe device that you just plugged in.

[Read More]

Launch a temporary root process with `systemd‑run` instead of `sudo`

Run a single command as root with systemd‑run

When you just need to fire up one command as root and then drop back, sudo is the go‑to.
But if your distro already runs systemd, systemd‑run can be a leaner, more isolated way to do it—especially for short‑lived tasks.

What systemd‑run actually does

systemd‑run spawns a transient unit (either a scope or a service) that inherits the caller’s privileges and then elevates them to root when you add --user or --scope with --user.
Unlike sudo, the unit vanishes as soon as the command finishes, and you can sprinkle a handful of systemd properties on it to tighten the environment.

[Read More]