Linux from Zero – Online Appendix

This is the online appendix to *Linux from Zero*. It holds everything that would go stale too quickly in print: install lines, versions, model names, provider lists. Address: **https://linuxfromzero.com/appendix**.

Every section starts with the date it was checked and its sources. The rule is the same as in the book: if this page and the official documentation disagree, the documentation wins. Copy commands only from here or from the official source, never from a random blog.

The book’s examples use the desktop user john, the server user admin, the server address 203.0.113.10, and the domain john-site.com. Always substitute your own values.

Contents


Versions table

Checked 2026-09-24. Sources: https://linuxmint.com/download_all.php · https://documentation.ubuntu.com/release-notes/26.04/ · https://www.debian.org/releases/ · https://docs.docker.com/engine/release-notes/29/ · https://git-scm.com/ · https://packages.ubuntu.com/resolute/git · https://packages.ubuntu.com/noble-updates/git · https://nginx.org/en/download.html · https://launchpad.net/ubuntu/+source/nginx
Component In the book (tested) Now (2026-09-24)
Desktop system Linux Mint 22.3 “Zena” Linux Mint 22.3 “Zena” is the latest, recommended release; based on Ubuntu 24.04, supported until April 2029. Linux Mint 23 has not been released yet.
Server system Ubuntu Server 26.04 LTS Ubuntu 26.04 LTS “Resolute Raccoon”, released 2026-04-23; point release 26.04.1 is out. Standard support until May 2031 (Ubuntu release cycle).
Debian Debian 13 “trixie” Debian 13 “trixie” is stable; latest point release 13.7 (2026-09-12).
Docker Engine 29.x 29.8.1 (2026-09-15)
Git 2.43 (Mint 22.3), 2.53 (Ubuntu 26.04); latest 2.55 Mint 22.3 repositories: 2.43.0; Ubuntu 26.04 repositories: 2.53.0; latest Git release: 2.55.0 (2026-06-29).
nginx 1.30.x nginx.org: stable branch 1.30.5, mainline 1.31.6. Ubuntu 26.04 repositories: 1.28.3 (package 1.28.3-2ubuntu1.11).

To check your own versions:

cat /etc/os-release
docker --version
git --version
nginx -v

A note on nginx. If you installed nginx from the Ubuntu 26.04 repositories (sudo apt install nginx, as in the book), nginx -v shows 1.28.3, not 1.30.x. The directives the book uses (server, listen, server_name, location, proxy_pass, client_max_body_size) are core directives and work the same way in both branches.


Installing Docker on an Ubuntu 26.04 server

Checked 2026-09-24. Sources: https://docs.docker.com/engine/install/ubuntu/ · https://docs.docker.com/engine/install/linux-postinstall/ · https://docs.docker.com/engine/network/packet-filtering-firewalls/

These are the lines Chapter 22 deliberately leaves out. They mirror the official page “Install Docker Engine on Ubuntu.” Ubuntu 26.04 LTS (Resolute) is on the officially supported list, along with 24.04 and 22.04. You are working on the server, logged in over SSH as admin.

0. (Optional on a fresh server) Remove conflicting packages. If anything was already installed from the Ubuntu repositories (docker.io, podman-docker, and so on), the official guide says to remove it first:

sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc | cut -f1)

If none of these packages is installed, apt simply reports that there is nothing to remove.

1. The repository key.

sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

Here curl only downloads the key file to /etc/apt/keyrings/docker.asc. It runs nothing.

2. The repository definition (deb822 format, file docker.sources).

sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

Copy the whole block, up to and including the final EOF line. Check it with cat /etc/apt/sources.list.d/docker.sources: the Suites: line should say resolute, and the Architectures: line amd64 (or arm64).

3. Install the packages.

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

4. Check.

docker --version
systemctl status docker
sudo docker run hello-world

docker --version shows a number starting with 29; systemctl status docker shows active (running) (press q to leave); the hello-world container prints a greeting that starts with Hello from Docker!.

5. Working without sudo. As in the book:

sudo usermod -aG docker admin

Then log out (exit) and connect over SSH again. Check: docker ps without sudo answers with an empty table.

Important. The official Docker documentation says it plainly: the docker group grants root-level privileges. Add only a user you would also give sudo.

Important. Ports that Docker publishes bypass ufw rules; this is officially documented. That is why the book writes ports with 127.0.0.1: in front, for example "127.0.0.1:3000:8080".


Installing Ollama

Checked 2026-09-24. Sources: https://docs.ollama.com/linux · https://docs.ollama.com/faq

Option A: the official install script (as in the book)

curl -fsSL https://ollama.com/install.sh | sh

Important. This line downloads someone else’s script and runs it immediately. The book’s rule: only from a source you trust (here, the official Ollama website), and preferably after reading it. Want to see what it would do first? Download it without running it, read it, and only then run it:

curl -fsSL https://ollama.com/install.sh -o /tmp/ollama-install.sh
less /tmp/ollama-install.sh
sh /tmp/ollama-install.sh

Check: systemctl status ollama shows active (running). To update Ollama later, run the same script again.

Option B: manual install with systemd (no script)

If you would rather not run the script, the official documentation describes a manual path. The example is for a regular amd64 server (on an ARM server, replace amd64 with arm64 in the address).

1. Download the program and unpack it into /usr:

curl -fsSL https://ollama.com/download/ollama-linux-amd64.tar.zst | sudo tar x -C /usr

Here curl hands the archive to tar, not to a shell: nothing is executed, only unpacked. The archive is compressed with zstd; if tar complains that it cannot unpack it, install sudo apt install zstd first and repeat. Check: ollama -v.

2. Create the ollama system user:

sudo useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama
sudo usermod -a -G ollama $(whoami)

3. Create the service file with sudo nano /etc/systemd/system/ollama.service:

[Unit]
Description=Ollama Service
After=network-online.target

[Service]
ExecStart=/usr/bin/ollama serve
User=ollama
Group=ollama
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

(The official example also has the line Environment="PATH=$PATH"; the install script fills in your PATH at install time. In a hand-written file you can leave it out, because ExecStart gives the full path /usr/bin/ollama.)

4. Enable and start it:

sudo systemctl daemon-reload
sudo systemctl enable ollama
sudo systemctl start ollama

Check: systemctl status ollama shows active (running).

OLLAMA_HOST: where Ollama listens

By default, Ollama listens only on 127.0.0.1, port 11434, so it cannot be reached from the network. That is exactly what the book’s project needs: nothing to change.

If you ever need to change the address or another setting, it goes into an override, not into the service file itself:

sudo systemctl edit ollama.service

In the editor that opens, under [Service], add for example:

[Service]
Environment="OLLAMA_HOST=127.0.0.1:11434"

Then:

sudo systemctl daemon-reload
sudo systemctl restart ollama

Dangerous command. OLLAMA_HOST=0.0.0.0:11434 opens Ollama to the whole network, with no password. Do not do this on a VPS. If Ollama has to be reachable from outside, put it behind nginx with HTTPS and access control.

On Linux, models are stored in /usr/share/ollama/.ollama/models. The OLLAMA_MODELS variable points to a different directory (set it the same systemctl edit way); the ollama user needs read and write access to it.


A small model to start with

Checked 2026-09-24. Sources: https://ollama.com/library/llama3.2/tags · https://ollama.com/library/qwen3/tags · https://ollama.com/library/gemma3/tags

The book writes <model> in place of a model name. To start, we suggest:

llama3.2:1b

ollama run llama3.2:1b

Inside the container (the Chapter 24 compose file):

docker compose exec ollama ollama pull llama3.2:1b

Other small models from the Ollama library, if you want to compare:

Model Download size (Ollama library, 2026-09-24)
gemma3:270m 292 MB
qwen3:0.6b 523 MB
gemma3:1b 815 MB
llama3.2:1b 1.3 GB
qwen3:1.7b 1.4 GB
llama3.2:3b 2.0 GB
qwen3:4b 2.5 GB
gemma3:4b 3.3 GB

How much RAM do you need? The Ollama library does not state exact RAM requirements, so we do not print any here. A cautious rule: a model needs at least as much free RAM as its file size, plus some room to work. Check on your own server:

free -h
ollama ps

The available column of free -h shows how much memory is free; ollama ps (while a model is loaded) shows in its SIZE column how much the model actually takes. If available is smaller than the model, pick a smaller model or take path B.

Updated. Sizes and tags in the Ollama library change. Before you download, look at the model’s page at https://ollama.com/library/<name>/tags. The smallest models answer quickly but simply; that is normal at this size.


Open WebUI behind nginx

Checked 2026-09-24. Sources: https://docs.openwebui.com/getting-started/quick-start/ · https://docs.openwebui.com/reference/https/nginx/ · https://docs.openwebui.com/reference/env-configuration/

The book’s interface is still Open WebUI; we do not currently recommend a replacement. The official image is unchanged: ghcr.io/open-webui/open-webui:main, data in /app/backend/data, and the interface listens on 8080 inside the container.

Two additions to the book’s nginx block, recommended by the official Open WebUI documentation:

  1. proxy_buffering off; and proxy_cache off;. Without them, nginx can re-chunk the live-streamed answer, and you will see broken formatting in the chat (visible ## and **, missing words).
  2. The CORS_ALLOW_ORIGIN variable in the interface container. Behind a reverse proxy, the WebSocket connection can fail without it.

The full block for /etc/nginx/sites-available/ai:

server {
    listen 80;
    listen [::]:80;
    server_name ai.john-site.com;

    client_max_body_size 50M;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_buffering off;
        proxy_cache off;
    }
}

In the compose file, under the interface’s environment:, add a line with your address:

    environment:
      - OLLAMA_BASE_URL=http://ollama:11434
      - CORS_ALLOW_ORIGIN=https://ai.john-site.com

The rest is as in the book: docker compose up -d, sudo nginx -t, sudo systemctl reload nginx, sudo certbot --nginx -d ai.john-site.com.

If very long answers get cut off, the official documentation suggests raising the timeouts in the same location block: proxy_read_timeout and proxy_send_timeout (its example uses 1800 seconds for long tasks). A small model usually does not need this.

Important. The ports line stays "127.0.0.1:3000:8080". Without 127.0.0.1, the interface would open to the whole internet, bypassing ufw.


Path B: provider API settings, models, and prices

Checked 2026-09-24. Sources: https://docs.openwebui.com/reference/env-configuration/ · https://developers.openai.com/api/docs/models · https://developers.openai.com/api/docs/pricing · https://platform.claude.com/docs/en/about-claude/models/overview · https://platform.claude.com/docs/en/about-claude/pricing · https://platform.claude.com/docs/en/api/openai-sdk

Model name and prices (Chapter 23)

Open WebUI with a provider API (Chapter 24, path B)

Open WebUI connects to any OpenAI-compatible API through two variables: OPENAI_API_BASE_URL (the API address) and OPENAI_API_KEY (the key).

1. The file ~/ai-service/.env (permissions chmod 600, as in the book), with one line:

OPENAI_API_KEY=sk-...

Replace sk-... with your real key from the provider’s keys page. Never put this file in Git or send it to anyone.

2. ~/ai-service/compose.yaml for path B, without the ollama container and without depends_on:

services:
  ui:
    image: ghcr.io/open-webui/open-webui:main
    restart: unless-stopped
    environment:
      - ENABLE_OLLAMA_API=false
      - OPENAI_API_BASE_URL=https://api.openai.com/v1
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - CORS_ALLOW_ORIGIN=https://ai.john-site.com
    volumes:
      - ui-data:/app/backend/data
    ports:
      - "127.0.0.1:3000:8080"

volumes:
  ui-data:

${OPENAI_API_KEY} is only the variable’s name: docker compose takes the value from the .env file in the same directory by itself. The key itself never appears in the compose file.

3. docker compose up -d, then check: docker compose ps shows Up.

Important. Open WebUI reads OPENAI_API_BASE_URL and OPENAI_API_KEY only on its first start and then stores them in its data volume. If you later change the key in .env, the interface will not notice. Enter a new key or address in the interface’s admin settings instead: Settings → Admin → Connections.

Another provider. Any provider that offers an OpenAI-compatible API connects the same way: change only OPENAI_API_BASE_URL to the address given in its documentation, and the key in .env.

Anthropic (Claude). Anthropic offers an OpenAI SDK compatibility layer at https://api.anthropic.com/v1/, used with a Claude API key. However, Anthropic’s own documentation says the layer is meant for testing and comparing models, not as a long-term or production-ready solution, and some parameters are ignored. We have not checked whether every Open WebUI feature works through it: unknown. For the full feature set, Anthropic recommends its native Claude API.


Choosing a VPS provider

Checked 2026-09-24. Sources: https://docs.hetzner.cloud/changelog · https://docs.hetzner.com/cloud/servers/backups-snapshots/overview/ · https://docs.hetzner.com/cloud/servers/getting-started/vnc-console/ · https://docs.digitalocean.com/release-notes/ · https://docs.digitalocean.com/platform/regional-availability/ · https://docs.digitalocean.com/products/backups/ · https://docs.digitalocean.com/products/droplets/how-to/connect-with-console/

Criteria (the same five as in Chapter 16): a data center near you; price; backups; a web console (required!); an Ubuntu 26.04 LTS image.

Prices. We deliberately print no prices: providers set them, they change, and they depend on the plan, region, and taxes. Compare providers’ pricing pages on the same day for the same plan (1–2 GB RAM, 1 core), and always check what backups cost.

Comparison. Only what we could verify in the provider’s official documentation. “Not verified” means: check it yourself on the provider’s site.

Provider Ubuntu 26.04 LTS Data centers Backups Web console
Hetzner Cloud Yes (since 2026-05-18, image ubuntu-26.04) Falkenstein and Nuremberg (Germany), Helsinki (Finland), Ashburn and Hillsboro (USA), Singapore Automatic daily, 7 slots; price on the provider’s site Yes (console in the Cloud Console)
DigitalOcean Yes (since 2026-07-01, ubuntu-26-04-x64) In Europe: Amsterdam, Frankfurt, London; more regions worldwide Paid add-on; frequency from every 4 hours to weekly Yes (Droplet Console and Recovery Console)
OVHcloud Not verified Not verified Not verified Not verified
Scaleway Not verified Not verified Not verified Not verified

The list is short, incomplete, and not an endorsement: nobody pays for these links. The first two are listed first only because we could verify their details in official documentation. For a local or regional provider, apply the same five criteria and ask directly: “Do you offer an Ubuntu 26.04 LTS image and a web console?”


Domains and registrars

Checked 2026-09-24. Sources: https://www.icann.org/en/accredited-registrars · https://www.iana.org/domains/root/db · https://developers.cloudflare.com/registrar/

Generic endings (.com, .net, .org, and so on) are sold by registrars accredited by ICANN. The official list: https://www.icann.org/en/accredited-registrars

Country-code endings (.us, .uk, .de, .lt, and so on) are run by each country’s registry under its own rules. The IANA root zone database shows who manages each ending: https://www.iana.org/domains/root/db

Why prices differ. The registry for each ending sets the wholesale price and the rules. For generic endings, the registries operate under contracts with ICANN, which also adds its own fee to generic-domain registrations; country-code endings follow their national registry’s policy. The registrar adds its margin on top. So the same ending costs different amounts at different registrars, and different endings cost different amounts even at the same registrar. We print no prices here, because they change.

How to choose a registrar:

  1. Compare the renewal price, not just the first year; the first year is often cheaper.
  2. The control panel must let you manage DNS records yourself (A, AAAA, CNAME); you need that in Chapter 17.
  3. Check that transferring the domain to another registrar is straightforward.
  4. Turn on two-factor sign-in for the account: losing a domain hurts more than losing a server.

One example of how registrars differ in their model: Cloudflare Registrar’s documentation says it charges only the registry and ICANN fees, with no markup. Which endings it supports is listed in its documentation.


Let's Encrypt and certbot

Checked 2026-09-24. Sources: https://letsencrypt.org/2025/12/02/from-90-to-45 · https://letsencrypt.org/2025/06/26/expiration-notification-service-has-ended · https://certbot.eff.org/instructions?ws=nginx&os=snap · https://packages.ubuntu.com/resolute/certbot

Certificate lifetimes are changing:

Date Default (classic) profile
Now 90 days
From 2027-02-10 64 days
From 2028-02-16 45 days

Since 2026-05-13 you can opt in to the tlsserver profile with 45-day certificates; there is also a shortlived profile with 6-day certificates. Readers of this book do not need to choose anything: the default profile is fine.

What this means for you: nothing manual. certbot renews the certificate by itself when about a third of its lifetime is left. What matters is that automatic renewal works; check it with the book’s command:

sudo certbot renew --dry-run
systemctl list-timers | grep certbot

No emails. Let’s Encrypt stopped sending expiration warning emails on 2025-06-04. That makes a monthly renew --dry-run a good habit.

apt or snap? The book installs certbot from the Ubuntu repositories: sudo apt install certbot python3-certbot-nginx (Ubuntu 26.04 ships certbot 4.0.0). That works. The certbot developers’ (EFF) page recommends installing it through snap; if you choose that route, remove the apt version first and follow the official instructions. Do not mix both methods on one server.


The "elsewhere" backup: cloud and encryption

Checked 2026-09-24. Sources: https://restic.readthedocs.io/en/stable/020_installation.html · https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html · https://restic.readthedocs.io/en/stable/050_restore.html · https://www.borgbackup.org/

Where the “elsewhere” copy can go

  • Your home computer: the Chapter 18 route (rsync over SSH). Free, but it depends on your own disk.
  • A second server, or storage reachable over SFTP: the same SSH principle, but the copy lives in another provider’s data center.
  • S3-compatible object storage: many cloud providers offer it; you pay for the gigabytes stored and sometimes for downloads.

We do not compare prices with numbers, because they change. Compare: the price per GB per month, the fee for downloading data (you need it to restore!), the country of the data center, and any minimum storage period.

A tool: restic (always encrypts)

The book deliberately named no tool. We suggest restic: it always encrypts its backups, copies only what changed, and works with SFTP, S3-compatible storage, and more. An alternative is BorgBackup (https://www.borgbackup.org/).

Example on the server: the ~/backups directory travels to another server over SFTP (backup@198.51.100.20: replace with your own address and user; the SSH key must be set up as in Chapter 15).

sudo apt install restic
restic -r sftp:backup@198.51.100.20:/srv/restic-repo init
restic -r sftp:backup@198.51.100.20:/srv/restic-repo backup ~/backups
restic -r sftp:backup@198.51.100.20:/srv/restic-repo snapshots
restic -r sftp:backup@198.51.100.20:/srv/restic-repo restore latest --target /tmp/restore
  • init creates the repository once and asks for a password.
  • backup makes a copy; snapshots lists the copies.
  • restore latest --target /tmp/restore is a restore test into a temporary directory, as in the book; then compare with diff -r.

Important. The restic documentation says it plainly: losing your password means your data is irrecoverably lost. Write the password on paper and keep it somewhere other than the server. As the book says: an encrypted backup without its key is not a backup.


Disk space: logs and Docker

Checked 2026-09-24. Sources: https://manpages.ubuntu.com/manpages/resolute/man1/journalctl.1.html · https://docs.docker.com/reference/cli/docker/system/df/ · https://docs.docker.com/reference/cli/docker/system/prune/ · https://docs.docker.com/engine/logging/configure/

Appendices C and D mention two commands the chapters did not cover. Here is more.

The system journal

journalctl --disk-usage

Shows how much space all journal files take (read-only, safe). If it is too much, you can remove the oldest archived journal files:

sudo journalctl --vacuum-size=500M

or by age:

sudo journalctl --vacuum-time=4weeks

Only the archived part is cleaned, so after vacuuming --disk-usage may show a little more than the size you gave. Deleted journal entries cannot be recovered; if you are investigating a fault, read what you need first.

Docker

docker system df

SIZE shows how much space images, containers, volumes, and build cache take; RECLAIMABLE shows how much you could get back.

To clean up:

docker system prune

This removes all stopped containers, unused networks, dangling (untagged) images, and unused build cache. It asks for confirmation first ([y/N]).

Dangerous command. docker system prune -a also deletes all unused images (you will have to download them again), and --volumes deletes unused anonymous volumes, which means data. The volumes in the book’s compose files have names, but still: before using --volumes, check docker volume ls and make sure you have a backup.

Docker’s container logs also grow by default. The official documentation suggests enabling log rotation or using the local logging driver; see https://docs.docker.com/engine/logging/configure/


App formats: .deb, .AppImage, Flatpak

Checked 2026-09-24. Sources: https://docs.appimage.org/introduction/quickstart.html · https://flathub.org/ · https://linuxmint-user-guide.readthedocs.io/

Chapter 3 promised more on file formats. The safest route is still the Software Manager.

  • Flatpak. Mint’s Software Manager also offers some applications as Flatpak packages from Flathub (https://flathub.org/). They are ordinary Linux packages that run separately from the system libraries. Installing them through the Software Manager needs no extra steps.

  • .deb. The Debian/Ubuntu/Mint package format. You can install a downloaded file by double-clicking it, or in the terminal, from the directory it is in:

    sudo apt install ./app.deb

    The ./ is required: it tells apt this is a file, not a package name. Important: a .deb file installs with root privileges, so take it only from the application’s official website. Such a package often adds its own repository too (like Docker in Chapter 22).

  • .AppImage. A single executable file that installs nothing into the system. Run it like this:

    chmod +x App.AppImage
    ./App.AppImage

    Again, only from the application’s official website. If an AppImage will not start and complains about FUSE, look for the fix in the application developer’s documentation.

  • .exe, .msi: Windows programs; Mint does not run them.


Checked 2026-09-24 (every link opened).

Every link printed in Appendix E worked on 2026-09-24:

If any address changes, the new one will appear here.

Color figures

Checked 2026-09-24.

All of the book’s diagrams (FIG-xx-yy) are published here in color. The figure numbers match the numbers in the book: find the one you need and open the color version. The printed figures are designed to be clear in grayscale, so the color version is a convenience, not a necessity.

  • The road through this book: from meeting Linux to the final project

    Figure 0.1 The road through this book: from meeting Linux to the final project

  • Three layers: programs, the kernel and the hardware

    Figure 1.1 Three layers: programs, the kernel and the hardware

  • An operating system is like a building manager sharing resources among programs

    Figure 1.2 An operating system is like a building manager sharing resources among programs

  • A Linux timeline: from Unix (1969) to today

    Figure 1.3 A Linux timeline: from Unix (1969) to today

  • What a distribution is made of

    Figure 2.1 What a distribution is made of

  • The VirtualBox main window

    Figure 2.2 The VirtualBox main window

  • A snapshot is a point you can always return to

    Figure 2.3 A snapshot is a point you can always return to

  • The Linux Mint (Cinnamon) desktop

    Figure 3.1 The Linux Mint (Cinnamon) desktop

  • The Software Manager

    Figure 3.2 The Software Manager

  • Familiar Windows tools and their Linux Mint counterparts

    Figure 3.3 Familiar Windows tools and their Linux Mint counterparts

  • The store window and the storekeeper: the graphical interface and the terminal

    Figure 4.1 The store window and the storekeeper: the graphical interface and the terminal

  • The parts of the prompt

    Figure 4.2 The parts of the prompt

  • The parts of a command line: command, options, arguments

    Figure 4.3 The parts of a command line: command, options, arguments

  • The terminal after an error: the system tells you what went wrong

    Figure 4.4 The terminal after an error: the system tells you what went wrong

  • The file system tree and the main directories

    Figure 5.1 The file system tree and the main directories

  • An absolute and a relative path to the same directory

    Figure 5.2 An absolute and a relative path to the same directory

  • The mv command: renaming and moving

    Figure 6.1 The mv command: renaming and moving

  • The Trash and rm: what comes back and what doesn't

    Figure 6.2 The Trash and rm: what comes back and what doesn't

  • The nano text editor

    Figure 7.1 The nano text editor

  • A pipe: cat passes text to wc

    Figure 7.2 A pipe: cat passes text to wc

  • Key rings: users, groups and root

    Figure 8.1 Key rings: users, groups and root

  • sudo – a temporary key with a timer

    Figure 8.2 sudo – a temporary key with a timer

  • Taking apart a line of ls -l output

    Figure 9.1 Taking apart a line of ls -l output

  • Three permissions for three circles of people

    Figure 9.2 Three permissions for three circles of people

  • From the repository through apt into the system

    Figure 10.1 From the repository through apt into the system

  • apt update and apt upgrade are not the same thing

    Figure 10.2 apt update and apt upgrade are not the same thing

  • One program, several processes

    Figure 11.1 One program, several processes

  • Processes as kitchen staff

    Figure 11.2 Processes as kitchen staff

  • How to read the output of free -h

    Figure 11.3 How to read the output of free -h

  • systemd – the system's building manager

    Figure 12.1 systemd – the system's building manager

  • start, stop, enable and disable: when the service runs

    Figure 12.2 start, stop, enable and disable: when the service runs

  • Anatomy of a log entry

    Figure 12.3 Anatomy of a log entry

  • A mount point is a gateway to a drive

    Figure 13.1 A mount point is a gateway to a drive

  • tar options at a glance

    Figure 13.2 tar options at a glance

  • The DNS path from a name to a page

    Figure 14.1 The DNS path from a name to a page

  • Ports are like flats in an apartment block

    Figure 14.2 Ports are like flats in an apartment block

  • DNS – the internet's address book

    Figure 14.3 DNS – the internet's address book

  • SSH – an encrypted tunnel between computers

    Figure 15.1 SSH – an encrypted tunnel between computers

  • An SSH key pair: a key and a lock

    Figure 15.2 An SSH key pair: a key and a lock

  • The fingerprint question on the first connection

    Figure 15.3 The fingerprint question on the first connection

  • Server setup checklist

    Figure 16.1 Server setup checklist

  • The firewall: what is open and what is closed

    Figure 16.2 The firewall: what is open and what is closed

  • Why the SSH rule always comes first

    Figure 16.3 Why the SSH rule always comes first

  • A visitor's path to your website's files

    Figure 17.1 A visitor's path to your website's files

  • Redirecting from HTTP to HTTPS

    Figure 17.2 Redirecting from HTTP to HTTPS

  • Server blocks: one nginx, several websites

    Figure 17.3 Server blocks: one nginx, several websites

  • The 3-2-1 backup rule

    Figure 18.1 The 3-2-1 backup rule

  • A backup is only worth something once a restore has been tested

    Figure 18.2 A backup is only worth something once a restore has been tested

  • The restore test, step by step

    Figure 18.3 The restore test, step by step

  • A script is like a recipe

    Figure 19.1 A script is like a recipe

  • A variable is a labelled box

    Figure 19.2 A variable is a labelled box

  • The if statement: two possible branches

    Figure 19.3 The if statement: two possible branches

  • The crontab time format: five fields

    Figure 20.1 The crontab time format: five fields

  • Where secret keys must never go

    Figure 20.2 Where secret keys must never go

  • How cron works: time, command, log

    Figure 20.3 How cron works: time, command, log

  • The three Git areas

    Figure 21.1 The three Git areas

  • Git history as a time machine

    Figure 21.2 Git history as a time machine

  • A container is a packed-up workplace

    Figure 22.1 A container is a packed-up workplace

  • A virtual machine and a container

    Figure 22.2 A virtual machine and a container

  • Image, containers and a volume

    Figure 22.3 Image, containers and a volume

  • From a program through the API to the model and back

    Figure 23.1 From a program through the API to the model and back

  • Tokens – the pieces of text you pay for

    Figure 23.2 Tokens – the pieces of text you pay for

  • Privacy compared: a public website, a paid API, a local model

    Figure 23.3 Privacy compared: a public website, a paid API, a local model

  • RAM and VRAM – two workbenches for a model

    Figure 24.1 RAM and VRAM – two workbenches for a model

  • Quantization: the same picture at different resolutions

    Figure 24.2 Quantization: the same picture at different resolutions

  • An agent is an assistant with a list of tools

    Figure 24.3 An agent is an assistant with a list of tools

  • The AI service architecture: browser, interface, model

    Figure 24.4 The AI service architecture: browser, interface, model

  • The whole system you have built

    Figure 25.1 The whole system you have built

  • The final project: 15 steps in 5 stages

    Figure 25.2 The final project: 15 steps in 5 stages

  • The troubleshooting tree

    Figure 26.1 The troubleshooting tree

  • A symptom is not a cause

    Figure 26.2 A symptom is not a cause

  • QR code for the online appendix

    Figure 28.1 QR code for the online appendix

Copy the commands

Checked 2026-09-24.

Every numbered command in the book (for example, “Command 22.1”) in one place, grouped by chapter, so you do not have to retype long lines from paper. This page is generated from the file komandos-en.json.

Before you paste a command into the terminal, read it and replace the example values (john, admin, 203.0.113.10, john-site.com, <model>) with your own.

2. Distributions and a Safe Practice Environment

Command 2.1 – a Windows PowerShell command, run on your main Windows computer, not in Linux

                          certutil -hashfile "C:\Users\YourName\Downloads\linuxmint-22.3-cinnamon-64bit.iso" SHA256
                        

4. The Terminal: Your First Conversation with the System

Command 4.1

                          pwd
                        

Command 4.2

                          ls
                        

Command 4.3

                          ls -l
                        

Command 4.4

                          ls --help
                        

Command 4.5

                          history
                        

5. The File System Tree and Paths

Command 5.1

                          pwd
                        

Command 5.2

                          ls /
                        

Command 5.3

                          cd /home
pwd
ls
cd john
pwd
cd ..
pwd
cd ~
pwd
                        

Command 5.4

                          ls -R tree
                        

7. Text Files: Reading, Editing, Searching

Command 7.1

                          cd ~/practice
echo "first line" > notes.txt
echo "second line from the café" >> notes.txt
                        

Command 7.2

                          nano greeting.txt
                        

Command 7.3

                          cat notes.txt | wc -l
                        

Command 7.4

                          grep "second" notes.txt
                        

Command 7.5

                          wc notes.txt
                        

8. Users, Groups, root, and sudo

Command 8.1

                          whoami
                        

Command 8.2

                          id
                        

Command 8.3

                          sudo ls /root
                        

Command 8.4

                          sudo adduser tester
                        

Command 8.5

                          su - tester
                        

Command 8.6

                          sudo deluser tester
                        

9. Permissions and File Owners

Command 9.1

                          chmod u+x script.sh
                        

Command 9.2

                          chmod 644 script.sh
                        

Command 9.3

                          stat -c '%A %U %n' script.sh
                        

Command 9.4

                          sudo chown john:john project
                        

10. Installing Programs in the Terminal: Packages and Repositories

Command 10.1

                          sudo apt update
                        

Command 10.2

                          sudo apt install tree htop
                        

Command 10.3

                          apt show bash
                        

Command 10.4

                          sudo apt remove tree
                        

Command 10.5

                          sudo apt upgrade
                        

11. Processes and System Resources: What Is Going On Inside

Command 11.1

                          ps aux
                        

Command 11.2

                          htop
                        

Command 11.3

                          free -h
                        

Command 11.4

                          df -h
                        

Command 11.5

                          uptime
                        

Command 11.6

                          kill 2451
                        

12. Services, systemd, and System Logs

Command 12.1

                          systemctl status cups
                        

Command 12.2

                          sudo systemctl stop cups
sudo systemctl start cups
sudo systemctl restart cups
                        

Command 12.3

                          sudo systemctl disable cups
sudo systemctl enable cups
                        

Command 12.4

                          ls /var/log
                        

Command 12.5

                          journalctl -u cups
journalctl -u cups -e
journalctl -u cups --since "1 hour ago"
                        

Command 12.6

                          journalctl -f
                        

13. Disks, Drives, and Archives

Command 13.1

                          lsblk
                        

Command 13.2

                          df -h
                        

Command 13.3

                          tar -czf archive.tar.gz docs notes.txt
                        

Command 13.4

                          tar -tzf archive.tar.gz
                        

Command 13.5

                          tar -xzf archive.tar.gz -C extracted/
                        

14. Networking: IP Addresses, DNS, and Ports

Command 14.1

                          ip addr
                        

Command 14.2

                          host example.com
                        

Command 14.3

                          ss -tlnp
                        

Command 14.4

                          ping -c 4 127.0.0.1
ping -c 4 192.168.1.1
                        

15. SSH: Controlling a Computer from Far Away

Command 15.1

                          ssh john@192.168.56.101
                        

Command 15.2

                          ssh-keygen -t ed25519
                        

Command 15.3

                          ssh-copy-id john@192.168.56.101
                        

Command 15.4

                          scp ~/practice/hello.txt john@192.168.56.101:~
                        

16. Your Own Server: Setting Up a VPS Safely

Command 16.1

                          sudo adduser admin
sudo usermod -aG sudo admin
                        

Command 16.2

                          sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status verbose
                        

Command 16.3

                          sudo sshd -t
sudo systemctl reload ssh
                        

Command 16.4

                          sudo apt install unattended-upgrades
                        

17. A Website: nginx, a Domain, and HTTPS

Command 17.1

                          sudo apt install nginx
sudo ufw allow 'Nginx Full'
sudo ufw status
                        

Command 17.2

                          sudo nginx -t
sudo systemctl reload nginx
                        

Command 17.3

                          sudo apt install certbot python3-certbot-nginx
                        

Command 17.4

                          sudo certbot --nginx -d john-site.com
                        

Command 17.5

                          sudo certbot renew --dry-run
                        

18. Backups and Server Maintenance

Command 18.1

                          mkdir -p ~/backups
sudo tar -czf ~/backups/etc-nginx-$(date +%F).tar.gz /etc/nginx
                        

Command 18.2

                          rsync -av --dry-run ~/practice/ ~/practice-copy/
rsync -av ~/practice/ ~/practice-copy/
                        

Command 18.3

                          mkdir -p /tmp/restore
sudo tar -xzf ~/backups/etc-nginx-$(date +%F).tar.gz -C /tmp/restore
sudo diff -r /tmp/restore/etc/nginx /etc/nginx
                        

Command 18.4

                          mkdir -p ~/server-backups
rsync -av -e ssh admin@203.0.113.10:backups/ ~/server-backups/
                        

19. Your First Script: Bash Basics

Command 19.1

                          cd ~/practice
nano first.sh
                        

Command 19.2

                          NAME="John"
echo "$NAME"
echo "Hello, $NAME!"
                        

Command 19.3

                          nano guest.sh
                        

Command 19.4

                          nano checker.sh
                        

Command 19.5

                          cd ~/practice
nano backup.sh
                        

Command 19.6

                          bash -n backup.sh
chmod u+x backup.sh
./backup.sh
                        

20. Automation: Scheduled Tasks and Environment Variables

Command 20.1

                          crontab -e
                        

Command 20.2

                          crontab -l
                        

Command 20.3

                          printenv
export PRACTICE=hello
echo $PRACTICE
                        

Command 20.4

                          nano ~/.env
chmod 600 ~/.env
                        

21. Git: A Time Machine for Your Files

Command 21.1

                          mkdir ~/server-docs
cd ~/server-docs
git init
                        

Command 21.2

                          git status
                        

Command 21.3

                          git add README.md
git status
                        

Command 21.4

                          git commit -m "Create the server documentation repository"
                        

Command 21.5

                          git log --oneline
                        

Command 21.6

                          git status
git diff
                        

22. Docker: A Whole Program in a Box

Command 22.1

                          docker run -d --name my-page -p 8080:80 nginx
docker ps
                        

Command 22.2

                          docker logs my-page
                        

Command 22.3

                          docker exec my-page sh -c 'echo "<h1>Changed inside the container</h1>" > /usr/share/nginx/html/index.html'
docker stop my-page
docker rm my-page
docker run -d --name my-page -p 8080:80 nginx
                        

Command 22.4

                          docker volume create page-data
docker run -d --name my-page -p 8080:80 -v page-data:/usr/share/nginx/html nginx
                        

Command 22.5

                          docker compose up -d
docker compose ps
                        

24. Your Own AI Service: A Local Model or an API

Command 24.1

                          ollama run <model>
                        

Command 24.2

                          curl http://localhost:11434/api/generate -d '{
  "model": "<model>",
  "prompt": "Write one sentence about Linux.",
  "stream": false
}'
                        

Command 24.3

                          mkdir -p ~/ai-service && cd ~/ai-service
nano compose.yaml
docker compose up -d
                        

Command 24.4

                          sudo reboot
                        

26. When Something Doesn't Work: Methodical Troubleshooting

Command 26.1

                          curl -I http://203.0.113.10
systemctl status nginx
sudo systemctl start nginx
curl -I http://203.0.113.10
                        

Command 26.2

                          curl -I --max-time 10 https://john-site.com
systemctl status nginx
ss -tlnp
ping -c 3 203.0.113.10
sudo ufw status
sudo ufw allow 'Nginx Full'
curl -I https://john-site.com
                        

Command 26.3

                          df -h
sudo du -sh /*
sudo du -sh /home/*
ls -lh /home/admin
rm ~/block1.img ~/block2.img
df -h
                        

Errata

Checked 2026-09-24.

No corrections yet.

Found a mistake: a command that does not work, an inaccurate fact, or a typo? Write to hello@ovanap.no. Please include:

  1. the page or chapter and the command number;
  2. the exact command and the exact error message;
  3. your system version (cat /etc/os-release).

Every confirmed correction will be listed here with its date.

About the book