[
  {
    "slug": "curl-resolve-site-check",
    "title": "Your server is not down. DNS is lying.",
    "caption": "One command separates DNS failure from server failure.",
    "duration_target_seconds": 35,
    "voiceover": "Before you blame Nginx, force one request straight to the VPS. If that works, the server is alive and DNS is the suspect.",
    "youtube_playlist": "Web Server Rescue",
    "site_url": "https://linuxoneliners.com/lessons/curl-resolve-site-check/"
  },
  {
    "slug": "find-large-files",
    "title": "Find the files eating your disk.",
    "caption": "Find large files before deleting anything.",
    "duration_target_seconds": 30,
    "voiceover": "Do not start deleting random folders. First list the largest files, then decide what is actually safe to remove.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/find-large-files/"
  },
  {
    "slug": "rsync-dry-run",
    "title": "Preview rsync before it bites.",
    "caption": "Dry-run destructive syncs first.",
    "duration_target_seconds": 40,
    "voiceover": "The `-n` flag is the pause button. It shows what rsync would do before you let it touch the files.",
    "youtube_playlist": "Dangerous Commands",
    "site_url": "https://linuxoneliners.com/lessons/rsync-dry-run/"
  },
  {
    "slug": "tail-live-logs",
    "title": "Watch the failure happen live.",
    "caption": "Use `tail -f` while reproducing the bug.",
    "duration_target_seconds": 30,
    "voiceover": "Do not open the whole log file. Tail the last useful lines, reproduce the issue, and watch the error arrive.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/tail-live-logs/"
  },
  {
    "slug": "grep-errors-in-logs",
    "title": "Find the failure words first.",
    "caption": "Filter noisy logs before deep reading.",
    "duration_target_seconds": 30,
    "voiceover": "Before reading every line, filter for the words that usually matter: error, failed, denied, and timeout.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/grep-errors-in-logs/"
  },
  {
    "slug": "check-listening-ports",
    "title": "Running is not the same as listening.",
    "caption": "Confirm the port before blaming the app.",
    "duration_target_seconds": 35,
    "voiceover": "A service can look alive and still not answer on the port you expect. Check the socket before chasing the wrong layer.",
    "youtube_playlist": "Web Server Rescue",
    "site_url": "https://linuxoneliners.com/lessons/check-listening-ports/"
  },
  {
    "slug": "inspect-permissions",
    "title": "Inspect before you chmod.",
    "caption": "Find the permission problem before changing permissions.",
    "duration_target_seconds": 35,
    "voiceover": "Recursive chmod is tempting because it is fast. Inspect the path first so you fix the layer that is actually blocking access.",
    "youtube_playlist": "Dangerous Commands",
    "site_url": "https://linuxoneliners.com/lessons/inspect-permissions/"
  },
  {
    "slug": "grep-line-numbers",
    "title": "Find the exact log line first.",
    "caption": "Use `grep -n` before reading the whole log.",
    "duration_target_seconds": 30,
    "voiceover": "Line numbers make log debugging faster. First find the failure, then inspect the few lines around it instead of scrolling forever.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/grep-line-numbers/"
  },
  {
    "slug": "disk-usage-by-folder",
    "title": "Find the folder filling your disk.",
    "caption": "Folder-level disk triage first.",
    "duration_target_seconds": 30,
    "voiceover": "Start broad. Find the folder that is growing before you chase individual files.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/disk-usage-by-folder/"
  },
  {
    "slug": "recent-log-errors",
    "title": "Show the newest errors only.",
    "caption": "Recent errors beat endless scrolling.",
    "duration_target_seconds": 30,
    "voiceover": "Old log lines can waste your time. Filter the likely errors and keep the newest matches first.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/recent-log-errors/"
  },
  {
    "slug": "rsync-show-deletes",
    "title": "Preview rsync deletes first.",
    "caption": "Never trust `--delete` without `-n` first.",
    "duration_target_seconds": 35,
    "voiceover": "Before you let rsync delete files, dry-run it and isolate the delete lines.",
    "youtube_playlist": "Dangerous Commands",
    "site_url": "https://linuxoneliners.com/lessons/rsync-show-deletes/"
  },
  {
    "slug": "file-owner-and-mode",
    "title": "Check owner and mode first.",
    "caption": "Inspect permissions before editing them.",
    "duration_target_seconds": 30,
    "voiceover": "Before changing permissions, print the owner, group, and mode in one compact line.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/file-owner-and-mode/"
  },
  {
    "slug": "list-processes-by-memory",
    "title": "Find memory-heavy processes.",
    "caption": "Check memory pressure before guessing.",
    "duration_target_seconds": 30,
    "voiceover": "Before resizing a server or killing random processes, sort the process list by memory.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/list-processes-by-memory/"
  },
  {
    "slug": "show-top-files-human",
    "title": "Show big files in MB.",
    "caption": "Human-readable file triage.",
    "duration_target_seconds": 40,
    "voiceover": "Finding large files is useful. Making the sizes readable makes the next decision faster.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/show-top-files-human/"
  },
  {
    "slug": "mac-find-what-is-using-port",
    "title": "Port 3000 busy?",
    "caption": "Find the process using your dev port.",
    "duration_target_seconds": 24,
    "voiceover": "When your Mac says a dev port is already in use, do not guess. lsof shows the process and PID that owns it.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-find-what-is-using-port/"
  },
  {
    "slug": "mac-stop-process-on-port",
    "title": "Free a stuck port.",
    "caption": "Free a stale local dev server port.",
    "duration_target_seconds": 28,
    "voiceover": "lsof can output just the PID, and xargs can send a normal kill signal. Only do this when you know what owns the port.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-stop-process-on-port/"
  },
  {
    "slug": "mac-show-path-lines",
    "title": "Read PATH clearly.",
    "caption": "Debug command resolution on macOS.",
    "duration_target_seconds": 22,
    "voiceover": "PATH bugs are often order bugs. Split the variable on colons, number the lines, and see where your Mac looks first.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-show-path-lines/"
  },
  {
    "slug": "mac-which-command-will-run",
    "title": "Which Node is running?",
    "caption": "Check the real CLI binary.",
    "duration_target_seconds": 21,
    "voiceover": "When a command acts strange, ask the shell what it will run. command -v gives the resolved path.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-which-command-will-run/"
  },
  {
    "slug": "mac-find-large-project-files",
    "title": "Find huge project files.",
    "caption": "Spot large files before they spread.",
    "duration_target_seconds": 20,
    "voiceover": "When a repo feels heavy, ask find for files over a size threshold. It is read-only and perfect before a commit.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-find-large-project-files/"
  },
  {
    "slug": "mac-sort-folder-size",
    "title": "What ate my disk?",
    "caption": "Sort folders by disk usage.",
    "duration_target_seconds": 23,
    "voiceover": "Use du for human-readable sizes, then sort numerically by size. Start in the folder you suspect.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-sort-folder-size/"
  },
  {
    "slug": "mac-flush-dns-cache",
    "title": "Flush Mac DNS.",
    "caption": "Clear stale DNS on macOS.",
    "duration_target_seconds": 27,
    "voiceover": "If DNS changed but your Mac keeps using the old answer, flush the local cache and signal mDNSResponder.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-flush-dns-cache/"
  },
  {
    "slug": "mac-watch-file-changes",
    "title": "Follow a log live.",
    "caption": "Watch logs update live.",
    "duration_target_seconds": 19,
    "voiceover": "tail dash f keeps watching a text file and prints new lines as they arrive. Stop it with Control C.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-watch-file-changes/"
  },
  {
    "slug": "mac-search-logs-for-errors",
    "title": "Find errors faster.",
    "caption": "Search logs with context.",
    "duration_target_seconds": 23,
    "voiceover": "grep can show line numbers and context. Dash C two gives you the match plus two lines before and after.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-search-logs-for-errors/"
  },
  {
    "slug": "mac-test-url-headers",
    "title": "Check headers fast.",
    "caption": "Inspect URL headers from Terminal.",
    "duration_target_seconds": 24,
    "voiceover": "curl dash I asks for headers only. It quickly shows status codes, redirects, content type, and cache behavior.",
    "youtube_playlist": "Apple Terminal",
    "site_url": "https://linuxoneliners.com/lessons/mac-test-url-headers/"
  },
  {
    "slug": "backup-list-newest-source-files",
    "title": "See newest source files.",
    "caption": "Start backup checks with file age.",
    "duration_target_seconds": 25,
    "voiceover": "Before checking a backup, print source file timestamps so recent changes stand out.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-list-newest-source-files/"
  },
  {
    "slug": "backup-create-checksum-manifest",
    "title": "Checksum important files.",
    "caption": "Checksums verify bytes, not just names.",
    "duration_target_seconds": 27,
    "voiceover": "When bytes matter, create SHA256 hashes for the files you plan to back up or move.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-create-checksum-manifest/"
  },
  {
    "slug": "backup-verify-checksum-manifest",
    "title": "Verify checksum manifests.",
    "caption": "Do the verification step.",
    "duration_target_seconds": 24,
    "voiceover": "After a restore or copy, run sha256sum -c so every listed file proves it still matches.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-verify-checksum-manifest/"
  },
  {
    "slug": "backup-compare-source-and-backup-file-lists",
    "title": "Compare backup file lists.",
    "caption": "File presence check before byte checks.",
    "duration_target_seconds": 32,
    "voiceover": "Strip the source and backup prefixes, sort both lists, then use comm to see what exists on only one side.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-compare-source-and-backup-file-lists/"
  },
  {
    "slug": "backup-rsync-dry-run-itemize",
    "title": "Preview rsync backup drift.",
    "caption": "Dry-run rsync before changing backups.",
    "duration_target_seconds": 31,
    "voiceover": "Use rsync dry-run with itemized output before syncing backups, especially when delete is involved.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-rsync-dry-run-itemize/"
  },
  {
    "slug": "backup-find-empty-files",
    "title": "Find zero-byte backup files.",
    "caption": "Empty files deserve a second look.",
    "duration_target_seconds": 25,
    "voiceover": "Search backups for zero-byte files after exports or uploads, then decide whether each one is expected.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-find-empty-files/"
  },
  {
    "slug": "backup-list-largest-files",
    "title": "Rank backup files by size.",
    "caption": "Find the biggest backup files first.",
    "duration_target_seconds": 24,
    "voiceover": "When backups grow unexpectedly, sort files by bytes before guessing what changed.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-list-largest-files/"
  },
  {
    "slug": "backup-list-tar-contents",
    "title": "Inspect tar before restore.",
    "caption": "List archive contents safely.",
    "duration_target_seconds": 23,
    "voiceover": "Use tar -tf to list archive contents before extracting or restoring anything.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-list-tar-contents/"
  },
  {
    "slug": "backup-count-source-file-types",
    "title": "Count file types fast.",
    "caption": "Simple inventory by extension.",
    "duration_target_seconds": 26,
    "voiceover": "Count source file extensions to catch missing content classes before or after a backup.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-count-source-file-types/"
  },
  {
    "slug": "backup-find-files-newer-than-snapshot",
    "title": "What changed after backup?",
    "caption": "Timestamp checks show likely backup gaps.",
    "duration_target_seconds": 30,
    "voiceover": "Compare source file times against a snapshot marker to find files newer than the last backup.",
    "youtube_playlist": "Backup Integrity Triage",
    "site_url": "https://linuxoneliners.com/lessons/backup-find-files-newer-than-snapshot/"
  },
  {
    "slug": "postgres-check-server-readiness",
    "title": "Check Postgres readiness first.",
    "caption": "Readiness is the first split.",
    "duration_target_seconds": 25,
    "voiceover": "Before changing configs, ask PostgreSQL whether it is accepting connections on the expected host and port.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/postgres-check-server-readiness/"
  },
  {
    "slug": "postgres-show-active-connections",
    "title": "List Postgres sessions fast.",
    "caption": "pg_stat_activity shows the crowd.",
    "duration_target_seconds": 35,
    "voiceover": "When PostgreSQL feels unavailable, check whether it is out of connection room before restarting anything.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/postgres-show-active-connections/"
  },
  {
    "slug": "postgres-find-long-running-queries",
    "title": "Find the slow query first.",
    "caption": "Start with the oldest query.",
    "duration_target_seconds": 40,
    "voiceover": "Before blaming the whole database, sort active queries by age and see what has been running the longest.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/postgres-find-long-running-queries/"
  },
  {
    "slug": "postgres-check-lock-waits",
    "title": "Check for lock waits.",
    "caption": "Wait events explain the stall.",
    "duration_target_seconds": 35,
    "voiceover": "A stuck database may be waiting behind one lock. Query wait events before you restart PostgreSQL.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/postgres-check-lock-waits/"
  },
  {
    "slug": "postgres-show-database-sizes",
    "title": "Find the biggest Postgres DB.",
    "caption": "Size the database first.",
    "duration_target_seconds": 30,
    "voiceover": "When disk alerts fire, start with database sizes before hunting individual tables.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/postgres-show-database-sizes/"
  },
  {
    "slug": "mysql-check-server-ping",
    "title": "Ping MySQL before guessing.",
    "caption": "mysqladmin ping is the split.",
    "duration_target_seconds": 25,
    "voiceover": "An open port is not the same as a working database. Ask MySQL whether it is alive.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/mysql-check-server-ping/"
  },
  {
    "slug": "mysql-show-processlist",
    "title": "List MySQL sessions.",
    "caption": "Processlist before restart.",
    "duration_target_seconds": 35,
    "voiceover": "Before restarting MySQL, inspect the process list and see who is connected and what they are doing.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/mysql-show-processlist/"
  },
  {
    "slug": "mysql-find-long-running-queries",
    "title": "Find old MySQL queries.",
    "caption": "Oldest active query first.",
    "duration_target_seconds": 40,
    "voiceover": "When MySQL slows down, sort active sessions by runtime before you blame the entire server.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/mysql-find-long-running-queries/"
  },
  {
    "slug": "mysql-check-database-sizes",
    "title": "Find the biggest MySQL schema.",
    "caption": "Schema sizes first.",
    "duration_target_seconds": 30,
    "voiceover": "When MySQL storage grows, get the schema-level view before drilling into individual tables.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/mysql-check-database-sizes/"
  },
  {
    "slug": "database-check-public-listeners",
    "title": "Check database exposure.",
    "caption": "Bind address tells the story.",
    "duration_target_seconds": 35,
    "voiceover": "Before touching credentials, check whether Postgres or MySQL is listening on a public interface.",
    "youtube_playlist": "Database First Response",
    "site_url": "https://linuxoneliners.com/lessons/database-check-public-listeners/"
  },
  {
    "slug": "tail-failing-ci-log-lines",
    "title": "Find CI failures fast.",
    "caption": "grep CI logs for failure lines first.",
    "duration_target_seconds": 25,
    "voiceover": "When CI dumps a huge log, do not start at line one. Grep for failure language and keep the last fifty hits.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/tail-failing-ci-log-lines/"
  },
  {
    "slug": "list-newest-build-artifacts",
    "title": "What did CI build?",
    "caption": "Verify build artifacts before deploy.",
    "duration_target_seconds": 22,
    "voiceover": "Before deploying, list the newest artifact files with timestamps and sizes. It is a fast sanity check.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/list-newest-build-artifacts/"
  },
  {
    "slug": "check-current-release-symlink",
    "title": "Which release is live?",
    "caption": "Verify the live release symlink.",
    "duration_target_seconds": 20,
    "voiceover": "If deploys use a current symlink, readlink shows the real active release path immediately.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/check-current-release-symlink/"
  },
  {
    "slug": "find-largest-ci-logs",
    "title": "Find noisy CI logs.",
    "caption": "Largest logs first.",
    "duration_target_seconds": 21,
    "voiceover": "Sort logs by size first. The biggest file is often where the pipeline is wasting your attention.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-largest-ci-logs/"
  },
  {
    "slug": "show-release-directory-ages",
    "title": "Newest releases first.",
    "caption": "List recent release directories.",
    "duration_target_seconds": 24,
    "voiceover": "When releases are directories, sort them by modification time to see the newest deploy candidates.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/show-release-directory-ages/"
  },
  {
    "slug": "extract-env-names-from-configs",
    "title": "Env names, not secrets.",
    "caption": "Audit env names safely.",
    "duration_target_seconds": 26,
    "voiceover": "For a quick audit, print only environment variable names. Do not dump values into chat or screenshots.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/extract-env-names-from-configs/"
  },
  {
    "slug": "smoke-check-http-status",
    "title": "Deploy smoke check.",
    "caption": "Status code plus timing.",
    "duration_target_seconds": 20,
    "voiceover": "Use curl to print just the HTTP status and timing. It is the fastest post-deploy heartbeat.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/smoke-check-http-status/"
  },
  {
    "slug": "compare-artifact-checksums",
    "title": "Do these artifacts match?",
    "caption": "Compare deployed artifact hashes.",
    "duration_target_seconds": 23,
    "voiceover": "When a deploy looks wrong, hash the built artifact and the deployed artifact. Same hash, same bytes.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/compare-artifact-checksums/"
  },
  {
    "slug": "count-failures-by-test-file",
    "title": "Rank failing tests.",
    "caption": "Count repeated failing test files.",
    "duration_target_seconds": 27,
    "voiceover": "Extract test filenames from the log, count them, and sort. Now the noisy failure has a shape.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/count-failures-by-test-file/"
  },
  {
    "slug": "inspect-release-disk-usage",
    "title": "Find heavy releases.",
    "caption": "Inspect release disk usage safely.",
    "duration_target_seconds": 24,
    "voiceover": "When deploys hit disk pressure, check release directory sizes before deleting anything.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/inspect-release-disk-usage/"
  },
  {
    "slug": "check-container-image-tag-in-manifest",
    "title": "Which image will deploy?",
    "caption": "Check image tags in deploy files.",
    "duration_target_seconds": 25,
    "voiceover": "Grep deployment manifests for image lines to confirm the tag before rollout or rollback.",
    "youtube_playlist": "Linux Deployment Triage",
    "site_url": "https://linuxoneliners.com/lessons/check-container-image-tag-in-manifest/"
  },
  {
    "slug": "docker-ps-human-table",
    "title": "Readable docker ps.",
    "caption": "Make docker ps readable during triage.",
    "duration_target_seconds": 35,
    "voiceover": "When Docker output wraps into a mess, format it. Names, status, image, and ports are the first fields you need.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-ps-human-table/"
  },
  {
    "slug": "docker-restarting-containers",
    "title": "Find Docker restart loops.",
    "caption": "Filter Docker directly for restart loops.",
    "duration_target_seconds": 30,
    "voiceover": "If a host feels broken, look for restart loops first. This filter shows only containers in restarting state.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-restarting-containers/"
  },
  {
    "slug": "docker-container-health-status",
    "title": "Running is not healthy.",
    "caption": "Check Docker health without the full inspect dump.",
    "duration_target_seconds": 40,
    "voiceover": "Running only means the process exists. If the image has a health check, print both Docker status and health status.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-container-health-status/"
  },
  {
    "slug": "docker-tail-recent-logs",
    "title": "Docker logs without the flood.",
    "caption": "Read the failure window, not the whole log history.",
    "duration_target_seconds": 35,
    "voiceover": "For triage, do not start with every log line ever written. Use since and tail together.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-tail-recent-logs/"
  },
  {
    "slug": "docker-stats-once",
    "title": "Docker stats once.",
    "caption": "Use --no-stream for a triage snapshot.",
    "duration_target_seconds": 30,
    "voiceover": "Docker stats defaults to a live stream. Add no-stream for a clean one-time snapshot.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-stats-once/"
  },
  {
    "slug": "docker-port-map",
    "title": "Find Docker port mappings.",
    "caption": "Check the actual Docker port map.",
    "duration_target_seconds": 28,
    "voiceover": "If the app is unreachable, first confirm Docker published the port. docker port shows the mapping directly.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-port-map/"
  },
  {
    "slug": "docker-system-df-verbose",
    "title": "Docker disk usage safely.",
    "caption": "Inspect Docker disk usage before deleting anything.",
    "duration_target_seconds": 36,
    "voiceover": "When Docker fills a disk, do not start with prune. Start with docker system df -v.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-system-df-verbose/"
  },
  {
    "slug": "docker-container-env-redacted",
    "title": "Check env vars without leaking values.",
    "caption": "Inspect config keys without dumping secrets.",
    "duration_target_seconds": 42,
    "voiceover": "Docker inspect can print secrets if you are careless. This version lists environment variable names and redacts values.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-container-env-redacted/"
  },
  {
    "slug": "docker-network-container-map",
    "title": "Check Docker networks.",
    "caption": "Healthy container, wrong network? Check this.",
    "duration_target_seconds": 34,
    "voiceover": "If containers cannot talk, check network membership before changing config.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-network-container-map/"
  },
  {
    "slug": "docker-events-recent",
    "title": "Docker's recent activity trail.",
    "caption": "Use Docker events for a quick change timeline.",
    "duration_target_seconds": 38,
    "voiceover": "When something changed and nobody knows what, check recent Docker events for starts, stops, pulls, and restarts.",
    "youtube_playlist": "Docker Triage One-Liners",
    "site_url": "https://linuxoneliners.com/lessons/docker-events-recent/"
  },
  {
    "slug": "firewall-ufw-status-verbose",
    "title": "Read the firewall defaults.",
    "caption": "Default policy explains the rules.",
    "duration_target_seconds": 29,
    "voiceover": "A firewall rule list is not enough. UFW verbose output shows whether incoming traffic is denied by default.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/firewall-ufw-status-verbose/"
  },
  {
    "slug": "firewall-ufw-numbered-rules",
    "title": "Number firewall rules first.",
    "caption": "Review by number, edit later.",
    "duration_target_seconds": 27,
    "voiceover": "Before changing UFW, print numbered rules. It gives everyone the same ordered list to review.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/firewall-ufw-numbered-rules/"
  },
  {
    "slug": "firewall-nft-input-policy",
    "title": "Check the nftables input chain.",
    "caption": "Look below the friendly wrapper.",
    "duration_target_seconds": 32,
    "voiceover": "When firewall behavior is confusing, inspect the nftables input chain and its default policy.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/firewall-nft-input-policy/"
  },
  {
    "slug": "firewall-iptables-input-rules",
    "title": "Read iptables INPUT rules.",
    "caption": "INPUT policy first.",
    "duration_target_seconds": 29,
    "voiceover": "On older or mixed systems, iptables output can explain why traffic is allowed or dropped.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/firewall-iptables-input-rules/"
  },
  {
    "slug": "exposure-list-listening-sockets",
    "title": "List what is listening.",
    "caption": "Listeners first, firewall second.",
    "duration_target_seconds": 28,
    "voiceover": "Before firewall changes, list listening sockets. Bind address and process name tell you what could be exposed.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/exposure-list-listening-sockets/"
  },
  {
    "slug": "exposure-public-listeners-only",
    "title": "Filter public listeners.",
    "caption": "Public bind addresses deserve review.",
    "duration_target_seconds": 30,
    "voiceover": "A localhost database is not the same as a public service. Filter sockets by bind address first.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/exposure-public-listeners-only/"
  },
  {
    "slug": "firewall-allowed-ports-without-listeners",
    "title": "Find stale allow rules.",
    "caption": "Allowed does not mean used.",
    "duration_target_seconds": 35,
    "voiceover": "Compare UFW allow rules with listening sockets. If a port is allowed but nothing listens, it may be stale exposure.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/firewall-allowed-ports-without-listeners/"
  },
  {
    "slug": "exposure-public-listeners-not-in-ufw",
    "title": "Find unlisted public listeners.",
    "caption": "Public process, missing rule.",
    "duration_target_seconds": 36,
    "voiceover": "Compare public listeners with allowed firewall ports. A wildcard-bound service outside policy deserves review.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/exposure-public-listeners-not-in-ufw/"
  },
  {
    "slug": "ssh-public-exposure-check",
    "title": "Is SSH publicly bound?",
    "caption": "Bind address and source rule both matter.",
    "duration_target_seconds": 31,
    "voiceover": "Check whether SSH binds to a public address, then compare that with the firewall source rule.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/ssh-public-exposure-check/"
  },
  {
    "slug": "db-local-only-listeners",
    "title": "Confirm local-only databases.",
    "caption": "Local bind is part of exposure control.",
    "duration_target_seconds": 30,
    "voiceover": "A database can listen safely when it is bound to localhost. Filter common database ports by local bind address.",
    "youtube_playlist": "Firewall Exposure Triage",
    "site_url": "https://linuxoneliners.com/lessons/db-local-only-listeners/"
  },
  {
    "slug": "nginx-test-config",
    "title": "Test Nginx before reload.",
    "caption": "Run `nginx -t` before reload.",
    "duration_target_seconds": 25,
    "voiceover": "Before reloading Nginx, run the syntax check. It is faster than breaking a live site.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/nginx-test-config/"
  },
  {
    "slug": "nginx-show-enabled-sites",
    "title": "Is the Nginx site enabled?",
    "caption": "Enabled sites are what Nginx reads.",
    "duration_target_seconds": 25,
    "voiceover": "Editing a config is not enough. Check whether Nginx actually has that site enabled.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/nginx-show-enabled-sites/"
  },
  {
    "slug": "nginx-find-server-name",
    "title": "Find the Nginx config for a domain.",
    "caption": "Find the server block before changing it.",
    "duration_target_seconds": 30,
    "voiceover": "When the wrong site answers, search the enabled server names before editing random files.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/nginx-find-server-name/"
  },
  {
    "slug": "check-http-redirect",
    "title": "Check the HTTP redirect.",
    "caption": "HTTP should point to HTTPS.",
    "duration_target_seconds": 25,
    "voiceover": "A valid cert is not the whole setup. Check the plain HTTP path too.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/check-http-redirect/"
  },
  {
    "slug": "inspect-response-headers",
    "title": "Inspect headers before guessing.",
    "caption": "Headers are fast operational clues.",
    "duration_target_seconds": 30,
    "voiceover": "A page can load while headers reveal redirect, cache, or security problems.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/inspect-response-headers/"
  },
  {
    "slug": "dig-a-record",
    "title": "Check where the domain points.",
    "caption": "DNS first, then server.",
    "duration_target_seconds": 25,
    "voiceover": "Before blaming the server, check the A record. The domain may be pointing somewhere else.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/dig-a-record/"
  },
  {
    "slug": "certbot-list-certs",
    "title": "List the certs before changing SSL.",
    "caption": "Inventory certificates first.",
    "duration_target_seconds": 30,
    "voiceover": "Before editing SSL config, check what Certbot already knows about the domain.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/certbot-list-certs/"
  },
  {
    "slug": "check-nginx-symlink-target",
    "title": "Which release is live?",
    "caption": "Check the live release target.",
    "duration_target_seconds": 25,
    "voiceover": "If deploys use a current symlink, resolve it before debugging the wrong release.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/check-nginx-symlink-target/"
  },
  {
    "slug": "nginx-find-404s",
    "title": "Find the URLs throwing 404s.",
    "caption": "Rank your 404s from the access log.",
    "duration_target_seconds": 35,
    "voiceover": "One missing asset can show up again and again. Count 404 paths before guessing.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/nginx-find-404s/"
  },
  {
    "slug": "watch-access-by-referrer",
    "title": "Check referrers from access logs.",
    "caption": "Server-side referrer sanity check.",
    "duration_target_seconds": 30,
    "voiceover": "Platform analytics can be partial. Your server logs can still show referrer clues.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/watch-access-by-referrer/"
  },
  {
    "slug": "find-top-cpu-processes-with-ps",
    "title": "Find CPU burners fast.",
    "caption": "Sort ps by CPU before reacting.",
    "duration_target_seconds": 28,
    "voiceover": "Before restarting services, sort the process table by CPU and identify the actual noisy process.",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-top-cpu-processes-with-ps/"
  },
  {
    "slug": "find-top-memory-processes-with-ps",
    "title": "Find memory-heavy processes.",
    "caption": "Sort ps by memory before guessing.",
    "duration_target_seconds": 28,
    "voiceover": "Low memory needs evidence. Sort ps by memory and include RSS so the largest resident processes stand out.",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-top-memory-processes-with-ps/"
  },
  {
    "slug": "check-memory-pressure-with-free",
    "title": "Read Linux memory correctly.",
    "caption": "Look at available memory first.",
    "duration_target_seconds": 24,
    "voiceover": "In free, start with available, not panic. Cache is normal; low available plus swap use is the warning.",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/check-memory-pressure-with-free/"
  },
  {
    "slug": "read-load-average-with-uptime",
    "title": "Read server pressure fast.",
    "caption": "Load average is a clue.",
    "duration_target_seconds": 25,
    "voiceover": "uptime gives the one, five, and fifteen minute load averages so you can see whether pressure is new or sustained.",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/read-load-average-with-uptime/"
  },
  {
    "slug": "check-disk-space-with-df",
    "title": "Which filesystem is full?",
    "caption": "Start disk triage with df -h.",
    "duration_target_seconds": 23,
    "voiceover": "df answers the first disk question: which mounted filesystem is out of room?",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/check-disk-space-with-df/"
  },
  {
    "slug": "check-inode-pressure-with-df-i",
    "title": "No space, but free GB?",
    "caption": "Disk space is bytes and inodes.",
    "duration_target_seconds": 26,
    "voiceover": "If bytes are available but files still cannot be created, check inode usage with df -ih.",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/check-inode-pressure-with-df-i/"
  },
  {
    "slug": "find-large-directories-with-du",
    "title": "df says full. du says where.",
    "caption": "Keep du scoped and sorted.",
    "duration_target_seconds": 25,
    "voiceover": "After df identifies the full filesystem, use a targeted du scan to find the large directory.",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-large-directories-with-du/"
  },
  {
    "slug": "find-listening-ports-with-ss",
    "title": "What is actually listening?",
    "caption": "Reachability starts with listening sockets.",
    "duration_target_seconds": 27,
    "voiceover": "ss shows local listening sockets, bind addresses, ports, and processes before you chase firewall rules.",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-listening-ports-with-ss/"
  },
  {
    "slug": "find-open-deleted-files-with-lsof",
    "title": "Deleted logs still using disk?",
    "caption": "Find open deleted files.",
    "duration_target_seconds": 30,
    "voiceover": "If space did not return after deleting a huge file, a process may still hold it open. lsof +L1 shows it.",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-open-deleted-files-with-lsof/"
  },
  {
    "slug": "inspect-established-connections-with-ss",
    "title": "See active TCP conversations.",
    "caption": "Established sockets are a snapshot.",
    "duration_target_seconds": 27,
    "voiceover": "Filter ss to established sockets when you need to see who the server is actively talking to.",
    "youtube_playlist": "Linux Resource Triage",
    "site_url": "https://linuxoneliners.com/lessons/inspect-established-connections-with-ss/"
  },
  {
    "slug": "sqlite-list-tables",
    "title": "List SQLite tables fast.",
    "caption": "Start SQLite triage with .tables.",
    "duration_target_seconds": 22,
    "voiceover": "When you get an app.db file, start with dot tables so you know what data exists before querying.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-list-tables/"
  },
  {
    "slug": "sqlite-show-users-schema",
    "title": "Check one table schema.",
    "caption": "Use .schema before ad hoc SQL.",
    "duration_target_seconds": 26,
    "voiceover": "Before guessing column names, ask SQLite for the table schema and indexes directly.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-show-users-schema/"
  },
  {
    "slug": "sqlite-check-integrity",
    "title": "Check SQLite integrity.",
    "caption": "Integrity check first.",
    "duration_target_seconds": 25,
    "voiceover": "If a SQLite app gets weird after a crash, run PRAGMA integrity_check before chasing application code.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-check-integrity/"
  },
  {
    "slug": "sqlite-list-user-tables",
    "title": "Script-friendly table list.",
    "caption": "sqlite_master gives scriptable metadata.",
    "duration_target_seconds": 29,
    "voiceover": "Query sqlite_master when you want table names one per line instead of compact dot tables output.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-list-user-tables/"
  },
  {
    "slug": "sqlite-count-key-tables",
    "title": "Count key tables fast.",
    "caption": "Fast sanity check: table row counts.",
    "duration_target_seconds": 31,
    "voiceover": "Union a few count queries when you need quick data sanity checks across important SQLite tables.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-count-key-tables/"
  },
  {
    "slug": "sqlite-show-order-indexes",
    "title": "List SQLite table indexes.",
    "caption": "Inspect indexes before changing queries.",
    "duration_target_seconds": 28,
    "voiceover": "Use PRAGMA index_list when you need to see which indexes a table actually has.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-show-order-indexes/"
  },
  {
    "slug": "sqlite-show-recent-events",
    "title": "Read recent SQLite events.",
    "caption": "SQLite can hold the incident timeline.",
    "duration_target_seconds": 27,
    "voiceover": "When a tiny app stores events in SQLite, order by timestamp and limit the output for a quick timeline.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-show-recent-events/"
  },
  {
    "slug": "sqlite-count-events-by-type",
    "title": "Group SQLite events.",
    "caption": "Count events by type.",
    "duration_target_seconds": 29,
    "voiceover": "Group events by type to see whether one action or failure is dominating the database.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-count-events-by-type/"
  },
  {
    "slug": "sqlite-find-duplicate-emails",
    "title": "Find duplicate emails.",
    "caption": "Find duplicates before fixing data.",
    "duration_target_seconds": 31,
    "voiceover": "Group by email and use HAVING to print only values that appear more than once.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-find-duplicate-emails/"
  },
  {
    "slug": "sqlite-backup-database-file",
    "title": "Back up SQLite safely.",
    "caption": "Use .backup instead of a blind copy.",
    "duration_target_seconds": 30,
    "voiceover": "Use SQLite's backup command before manual data work, then verify the backup file exists.",
    "youtube_playlist": "SQLite Triage",
    "site_url": "https://linuxoneliners.com/lessons/sqlite-backup-database-file/"
  },
  {
    "slug": "find-duplicate-page-titles",
    "title": "Find duplicate page titles.",
    "caption": "Count titles in the built site.",
    "duration_target_seconds": 27,
    "voiceover": "When every page inherits the same title, search snippets get muddy. Count titles from the built HTML before shipping.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-duplicate-page-titles/"
  },
  {
    "slug": "find-pages-missing-canonical",
    "title": "Find missing canonicals.",
    "caption": "Canonical presence check.",
    "duration_target_seconds": 30,
    "voiceover": "Scan generated pages, not assumptions. This loop prints every HTML file that missed the canonical tag.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-pages-missing-canonical/"
  },
  {
    "slug": "find-noindex-pages",
    "title": "Catch leftover noindex.",
    "caption": "Search generated HTML for noindex.",
    "duration_target_seconds": 24,
    "voiceover": "Before launch, search the built HTML for noindex so draft metadata does not hide a real page.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-noindex-pages/"
  },
  {
    "slug": "find-pages-missing-meta-description",
    "title": "Find pages without descriptions.",
    "caption": "Presence check first, quality pass later.",
    "duration_target_seconds": 28,
    "voiceover": "A simple loop over generated HTML shows which pages skipped the meta description tag.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-pages-missing-meta-description/"
  },
  {
    "slug": "list-sitemap-urls",
    "title": "Print sitemap URLs.",
    "caption": "Turn sitemap XML into a URL list.",
    "duration_target_seconds": 22,
    "voiceover": "For a quick sitemap sanity check, extract loc values and read the URLs line by line.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/list-sitemap-urls/"
  },
  {
    "slug": "check-robots-sitemap-line",
    "title": "Does robots advertise sitemap?",
    "caption": "robots.txt should point at sitemap.xml.",
    "duration_target_seconds": 23,
    "voiceover": "Check robots.txt for the Sitemap line so crawlers can discover the sitemap directly.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/check-robots-sitemap-line/"
  },
  {
    "slug": "find-html-pages-missing-from-sitemap",
    "title": "Which pages missed the sitemap?",
    "caption": "Compare built pages to sitemap URLs.",
    "duration_target_seconds": 35,
    "voiceover": "Map generated HTML paths to public URLs, then print any URL missing from sitemap.xml.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-html-pages-missing-from-sitemap/"
  },
  {
    "slug": "find-broken-internal-links",
    "title": "Find broken internal links.",
    "caption": "Catch broken links before deploy.",
    "duration_target_seconds": 36,
    "voiceover": "Extract root-relative hrefs from generated HTML and test whether each target exists in the build.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-broken-internal-links/"
  },
  {
    "slug": "find-pages-missing-og-title",
    "title": "Find missing social titles.",
    "caption": "Check Open Graph metadata in output.",
    "duration_target_seconds": 29,
    "voiceover": "Scan built HTML for og:title so shared links do not fall back to weak defaults.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-pages-missing-og-title/"
  },
  {
    "slug": "find-feed-links-missing-from-sitemap",
    "title": "Compare feed to sitemap.",
    "caption": "Feed links should line up with sitemap rules.",
    "duration_target_seconds": 33,
    "voiceover": "Extract feed URLs and print the ones missing from sitemap.xml. It catches stale or filtered content fast.",
    "youtube_playlist": "Static Site SEO Triage",
    "site_url": "https://linuxoneliners.com/lessons/find-feed-links-missing-from-sitemap/"
  },
  {
    "slug": "systemd-failed-units",
    "title": "Find failed systemd services fast.",
    "caption": "First server-health check: systemctl --failed.",
    "duration_target_seconds": 35,
    "voiceover": "When a VPS looks sick, do not start by guessing service names. Ask systemd what it already marked failed.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/systemd-failed-units/"
  },
  {
    "slug": "service-status-no-pager",
    "title": "systemctl status without getting stuck.",
    "caption": "Use --no-pager and --lines.",
    "duration_target_seconds": 40,
    "voiceover": "For one service, disable the pager and cap log lines. You get useful state without flooding the terminal.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/service-status-no-pager/"
  },
  {
    "slug": "journalctl-unit-since-boot",
    "title": "Read only this boot's service logs.",
    "caption": "Current boot only: journalctl -b.",
    "duration_target_seconds": 38,
    "voiceover": "When a server has rebooted, stale logs can waste your time. Add -b to journalctl and cap the output.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/journalctl-unit-since-boot/"
  },
  {
    "slug": "journal-disk-usage",
    "title": "Is journald eating your disk?",
    "caption": "Measure before cleanup.",
    "duration_target_seconds": 30,
    "voiceover": "Do not delete random log files during a disk alert. First check how much space the systemd journal actually uses.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/journal-disk-usage/"
  },
  {
    "slug": "slow-boot-services",
    "title": "What slowed down boot?",
    "caption": "Boot triage: systemd-analyze blame.",
    "duration_target_seconds": 42,
    "voiceover": "When a VPS takes too long to come back, systemd can rank startup units by duration. Treat it as a lead list.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/slow-boot-services/"
  },
  {
    "slug": "service-enabled-at-boot",
    "title": "Will this service start after reboot?",
    "caption": "Pair is-active with is-enabled.",
    "duration_target_seconds": 32,
    "voiceover": "A service can be running right now and still not start on the next reboot. Check enablement separately.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/service-enabled-at-boot/"
  },
  {
    "slug": "service-active-check",
    "title": "Quick service state check.",
    "caption": "Fast state check: systemctl is-active.",
    "duration_target_seconds": 28,
    "voiceover": "When you only need the current systemd state, skip the full status page. is-active gives a compact answer.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/service-active-check/"
  },
  {
    "slug": "recent-reboots",
    "title": "When did this VPS reboot?",
    "caption": "Reboot evidence: last -x reboot.",
    "duration_target_seconds": 36,
    "voiceover": "If a server was down or restarted, confirm the reboot timeline directly before digging through every service log.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/recent-reboots/"
  },
  {
    "slug": "memory-pressure-summary",
    "title": "Is your VPS out of memory?",
    "caption": "Memory snapshot: free -h.",
    "duration_target_seconds": 34,
    "voiceover": "Before restarting services or resizing the server, check memory pressure. On Linux, focus on available memory.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/memory-pressure-summary/"
  },
  {
    "slug": "systemd-timers-due",
    "title": "Find scheduled systemd jobs.",
    "caption": "Scheduled work: systemctl list-timers.",
    "duration_target_seconds": 39,
    "voiceover": "Modern Linux servers often use systemd timers for backups, renewals, and cleanup. If you only check cron, you can miss half the schedule.",
    "youtube_playlist": "Linux Survival Basics",
    "site_url": "https://linuxoneliners.com/lessons/systemd-timers-due/"
  },
  {
    "slug": "security-count-failed-ssh-users",
    "title": "Count failed SSH users.",
    "caption": "Group SSH failures by username.",
    "duration_target_seconds": 30,
    "voiceover": "Instead of reading every auth line, extract the failed usernames and count which accounts are being targeted.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-count-failed-ssh-users/"
  },
  {
    "slug": "security-count-failed-ssh-ips",
    "title": "Rank failed SSH IPs.",
    "caption": "Find the loudest SSH source.",
    "duration_target_seconds": 28,
    "voiceover": "Extract source IPs from failed SSH lines and count them to find the loudest source.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-count-failed-ssh-ips/"
  },
  {
    "slug": "security-show-accepted-ssh-logins",
    "title": "Find successful SSH logins.",
    "caption": "Successful logins are timeline anchors.",
    "duration_target_seconds": 27,
    "voiceover": "In first response, filter accepted SSH logins so real access stands apart from failed noise.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-show-accepted-ssh-logins/"
  },
  {
    "slug": "security-show-recent-sudo-commands",
    "title": "Review recent sudo use.",
    "caption": "Privilege use is a first-response clue.",
    "duration_target_seconds": 28,
    "voiceover": "Filter sudo lines from auth logs to see recent privileged commands and who ran them.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-show-recent-sudo-commands/"
  },
  {
    "slug": "security-list-listening-ports",
    "title": "List VPS listening ports.",
    "caption": "Listeners first, firewall second.",
    "duration_target_seconds": 29,
    "voiceover": "Use ss to snapshot listening ports, bind addresses, and processes before changing firewall rules.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-list-listening-ports/"
  },
  {
    "slug": "security-list-login-shell-users",
    "title": "Which users can log in?",
    "caption": "Login shells deserve review.",
    "duration_target_seconds": 27,
    "voiceover": "Read passwd records and print accounts with shell-like login programs during server inventory.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-list-login-shell-users/"
  },
  {
    "slug": "security-check-sshd-auth-settings",
    "title": "Read SSH auth policy.",
    "caption": "Inspect SSH policy first.",
    "duration_target_seconds": 29,
    "voiceover": "Pull the key sshd_config authentication lines before changing access rules or restarting SSH.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-check-sshd-auth-settings/"
  },
  {
    "slug": "security-find-world-writable-web-dirs",
    "title": "Find writable web dirs.",
    "caption": "World-writable web paths need review.",
    "duration_target_seconds": 28,
    "voiceover": "Search the web root for world-writable directories, then review whether each one is truly required.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-find-world-writable-web-dirs/"
  },
  {
    "slug": "security-find-loose-private-key-modes",
    "title": "Find loose SSH keys.",
    "caption": "Private keys should be tightly permissioned.",
    "duration_target_seconds": 30,
    "voiceover": "List id underscore files and flag modes broader than 600 so risky private key permissions stand out.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-find-loose-private-key-modes/"
  },
  {
    "slug": "security-list-authorized-keys-files",
    "title": "Inventory authorized_keys.",
    "caption": "authorized_keys is practical access inventory.",
    "duration_target_seconds": 26,
    "voiceover": "Find authorized keys files and modes so you know where SSH access is configured.",
    "youtube_playlist": "VPS Security First Response",
    "site_url": "https://linuxoneliners.com/lessons/security-list-authorized-keys-files/"
  },
  {
    "slug": "web-config-list-nginx-listen-directives",
    "title": "Check what Nginx listens on.",
    "caption": "Ports first. App later.",
    "duration_target_seconds": 30,
    "voiceover": "Before blaming the app, list the listen directives. A missing 443 or duplicate default server can explain the outage.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-list-nginx-listen-directives/"
  },
  {
    "slug": "web-config-find-nginx-default-server",
    "title": "Find the fallback server.",
    "caption": "Find the fallback before guessing.",
    "duration_target_seconds": 28,
    "voiceover": "If Nginx serves the wrong site, look for default_server. That line decides where unmatched requests go.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-find-nginx-default-server/"
  },
  {
    "slug": "web-config-show-nginx-include-chain",
    "title": "Is that config included?",
    "caption": "Included config is active config.",
    "duration_target_seconds": 30,
    "voiceover": "Editing a file does not matter if Nginx never includes it. Search the include chain before changing more config.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-show-nginx-include-chain/"
  },
  {
    "slug": "web-config-map-nginx-roots-aliases",
    "title": "Find where Nginx serves files.",
    "caption": "Map URL paths to disk paths.",
    "duration_target_seconds": 32,
    "voiceover": "A 404 can be a path problem, not an app problem. List root and alias directives before moving files.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-map-nginx-roots-aliases/"
  },
  {
    "slug": "web-config-map-nginx-proxy-targets",
    "title": "Where is Nginx proxying?",
    "caption": "Find proxy_pass before restarting.",
    "duration_target_seconds": 30,
    "voiceover": "For 502s, check the proxy target before restarting services. Nginx may be forwarding to the wrong port.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-map-nginx-proxy-targets/"
  },
  {
    "slug": "web-config-show-enabled-apache-sites",
    "title": "Is the Apache site enabled?",
    "caption": "Available is not enabled.",
    "duration_target_seconds": 30,
    "voiceover": "Apache can have a perfect virtual host file that is not enabled. List the symlinks before editing more.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-show-enabled-apache-sites/"
  },
  {
    "slug": "web-config-map-apache-virtualhosts",
    "title": "Find Apache virtual hosts.",
    "caption": "Map names to virtual hosts.",
    "duration_target_seconds": 30,
    "voiceover": "When Apache serves the wrong site, map VirtualHost, ServerName, and ServerAlias before changing redirects.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-map-apache-virtualhosts/"
  },
  {
    "slug": "web-config-find-apache-document-roots",
    "title": "Where is Apache serving from?",
    "caption": "Check DocumentRoot first.",
    "duration_target_seconds": 28,
    "voiceover": "Before moving files or changing permissions, list Apache DocumentRoot lines. The web server may be looking elsewhere.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-find-apache-document-roots/"
  },
  {
    "slug": "web-config-map-apache-proxy-rules",
    "title": "Where is Apache proxying?",
    "caption": "ProxyPass tells the route.",
    "duration_target_seconds": 31,
    "voiceover": "A proxy error can be a target problem. List ProxyPass rules before restarting Apache or the app.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-map-apache-proxy-rules/"
  },
  {
    "slug": "web-config-find-redirect-rules",
    "title": "Find redirect rules fast.",
    "caption": "Find redirects before changing them.",
    "duration_target_seconds": 30,
    "voiceover": "Redirect loops often come from one small rule. Search Nginx and Apache config before poking at DNS or certificates.",
    "youtube_playlist": "Web Config Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-config-find-redirect-rules/"
  },
  {
    "slug": "status-code-summary",
    "title": "Start with status codes.",
    "caption": "Summarize first. Drill down next.",
    "duration_target_seconds": 35,
    "voiceover": "A status-code summary gives you the shape of the log before you dive into details. It is the fast way to see whether the problem is mostly 4xx, 5xx, or something else.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/status-code-summary/"
  },
  {
    "slug": "web-4xx-by-ip",
    "title": "Find the loudest 4xx source.",
    "caption": "Count client errors before guessing.",
    "duration_target_seconds": 35,
    "voiceover": "When the access log gets noisy, count 4xx responses by IP first. It shows which clients are generating the most failed requests without changing anything on the server.",
    "youtube_playlist": "Cybersecurity Triage",
    "site_url": "https://linuxoneliners.com/lessons/web-4xx-by-ip/"
  },
  {
    "slug": "web-5xx-by-path",
    "title": "Find which route is throwing 5xx.",
    "caption": "Group 5xx errors by path.",
    "duration_target_seconds": 35,
    "voiceover": "A server error spike is vague until you group it by path. This one-liner shows whether one route is failing or the whole site is in trouble.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/web-5xx-by-path/"
  },
  {
    "slug": "suspicious-web-methods",
    "title": "Look for weird HTTP methods.",
    "caption": "Unusual methods deserve review.",
    "duration_target_seconds": 35,
    "voiceover": "Most access logs are GET, POST, HEAD, and OPTIONS. When something else appears, pull it into a short list and review it defensively.",
    "youtube_playlist": "Cybersecurity Triage",
    "site_url": "https://linuxoneliners.com/lessons/suspicious-web-methods/"
  },
  {
    "slug": "top-web-user-agents",
    "title": "Count user agents fast.",
    "caption": "User agents are clues, not proof.",
    "duration_target_seconds": 35,
    "voiceover": "When traffic changes, user agents are a useful clue. They are not proof of identity, but they quickly show what kind of clients dominate the log.",
    "youtube_playlist": "Cybersecurity Triage",
    "site_url": "https://linuxoneliners.com/lessons/top-web-user-agents/"
  },
  {
    "slug": "admin-probe-paths",
    "title": "Find admin-looking probes.",
    "caption": "Requested path is not compromise.",
    "duration_target_seconds": 35,
    "voiceover": "Public web servers receive requests for software they do not run. This one-liner pulls out admin-looking paths so you can review the noise without changing anything.",
    "youtube_playlist": "Cybersecurity Triage",
    "site_url": "https://linuxoneliners.com/lessons/admin-probe-paths/"
  },
  {
    "slug": "repeated-404-paths",
    "title": "Repeated 404s are a clue.",
    "caption": "Ignore one-offs. Count repeats.",
    "duration_target_seconds": 35,
    "voiceover": "A single 404 is boring. Repeated 404s on the same path are worth grouping so you can tell broken links from noisy probing.",
    "youtube_playlist": "Cybersecurity Triage",
    "site_url": "https://linuxoneliners.com/lessons/repeated-404-paths/"
  },
  {
    "slug": "request-bursts-by-minute",
    "title": "Bucket requests by minute.",
    "caption": "Time buckets make spikes visible.",
    "duration_target_seconds": 35,
    "voiceover": "Before reading hundreds of log lines, group requests by minute. A burst stands out immediately, and you still have the raw log for deeper review.",
    "youtube_playlist": "Cybersecurity Triage",
    "site_url": "https://linuxoneliners.com/lessons/request-bursts-by-minute/"
  },
  {
    "slug": "large-web-responses",
    "title": "Find huge responses fast.",
    "caption": "Large responses explain bandwidth spikes.",
    "duration_target_seconds": 35,
    "voiceover": "When bandwidth jumps, sort by response size. This does not prove anything by itself, but it shows which paths deserve review.",
    "youtube_playlist": "Hosting Operations",
    "site_url": "https://linuxoneliners.com/lessons/large-web-responses/"
  },
  {
    "slug": "ip-path-repeaters",
    "title": "Find IP-path repeaters.",
    "caption": "Pair IP and path to see loops.",
    "duration_target_seconds": 35,
    "voiceover": "Counting requests by IP is useful, but pairing IP with path shows a tighter pattern: one client repeating one URL again and again.",
    "youtube_playlist": "Cybersecurity Triage",
    "site_url": "https://linuxoneliners.com/lessons/ip-path-repeaters/"
  }
]