add initial 3 lessons
This commit is contained in:
+159
@@ -0,0 +1,159 @@
|
|||||||
|
# Basic Linux Commands (Bash)
|
||||||
|
|
||||||
|
Almost every software engineer, sysadmin, and DevOps person uses the terminal daily.
|
||||||
|
This lesson takes you from never having used Linux to being comfortable navigating
|
||||||
|
and managing files on a machine. You can practice on a Raspberry Pi, a cloud VM,
|
||||||
|
or any Linux distro — the commands are the same.
|
||||||
|
|
||||||
|
## 1. What is a terminal?
|
||||||
|
|
||||||
|
A terminal is a text window where you type a command and press Enter. The program
|
||||||
|
that reads your commands is called a **shell**. On most Linux systems (including
|
||||||
|
Raspberry Pi OS) it's **Bash**.
|
||||||
|
|
||||||
|
To open one on the Pi, press `Ctrl+Alt+T` or find "Terminal" in the menu.
|
||||||
|
|
||||||
|
Commands in this lesson go in code boxes. Type exactly what's in the box and press
|
||||||
|
Enter. Anything in a box by itself is a command; anything after `#` is a comment
|
||||||
|
explaining it — don't type that part.
|
||||||
|
|
||||||
|
## 2. Your first commands
|
||||||
|
|
||||||
|
Run these one by one and read the output:
|
||||||
|
|
||||||
|
```
|
||||||
|
whoami # prints your username
|
||||||
|
pwd # prints your current folder (your "address")
|
||||||
|
ls # lists the files in your current folder
|
||||||
|
date # prints the date and time
|
||||||
|
```
|
||||||
|
|
||||||
|
Linux organizes everything as files and folders in one big tree. The very top
|
||||||
|
folder is `/` (the root), and your personal folder (like `/home/pi`) is your home.
|
||||||
|
|
||||||
|
## 3. Moving around
|
||||||
|
|
||||||
|
```
|
||||||
|
ls # what's in this folder
|
||||||
|
ls -la # everything, including hidden files, with details
|
||||||
|
cd downloads # go into a folder (no space between cd and the name)
|
||||||
|
cd .. # go up one level
|
||||||
|
cd ~ # go to your home folder (cd with no argument does the same)
|
||||||
|
```
|
||||||
|
|
||||||
|
Tip: type the first few letters of a folder name and press **Tab** — Linux
|
||||||
|
autocompletes it for you. Use Tab constantly.
|
||||||
|
|
||||||
|
## 4. Files and folders
|
||||||
|
|
||||||
|
```
|
||||||
|
touch notes.txt # create an empty file
|
||||||
|
mkdir projects # create a folder
|
||||||
|
mkdir -p projects/web/app # create nested folders in one go
|
||||||
|
cp notes.txt backup.txt # copy a file
|
||||||
|
mv notes.txt projects/ # move a file (or rename it)
|
||||||
|
rm backup.txt # delete a file
|
||||||
|
rm -r projects # delete a folder and everything inside it
|
||||||
|
```
|
||||||
|
|
||||||
|
Warning: `rm` does not ask "are you sure?" and there is no trash bin. Deleted is
|
||||||
|
deleted. Read your command carefully before pressing Enter — especially `rm -rf`,
|
||||||
|
which deletes recursively without mercy.
|
||||||
|
|
||||||
|
## 5. Looking at files
|
||||||
|
|
||||||
|
```
|
||||||
|
cat notes.txt # print the whole file
|
||||||
|
head notes.txt # first 10 lines
|
||||||
|
tail notes.txt # last 10 lines
|
||||||
|
less notes.txt # scroll through a big file (press q to quit)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Writing to files
|
||||||
|
|
||||||
|
```
|
||||||
|
echo "hello" > notes.txt # write (overwrites the file if it exists)
|
||||||
|
echo "second line" >> notes.txt # append (>> adds to the end)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. Editing files: nano
|
||||||
|
|
||||||
|
`nano` is the standard beginner editor. Open a file with:
|
||||||
|
|
||||||
|
```
|
||||||
|
nano notes.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can edit. The keys you need are shown at the bottom of the screen:
|
||||||
|
|
||||||
|
- `Ctrl+O` then `Enter` — save (it calls saving "Write Out")
|
||||||
|
- `Ctrl+X` — quit
|
||||||
|
|
||||||
|
If it asks "Save modified buffer?" when you quit, press `y`, then `Enter`.
|
||||||
|
|
||||||
|
## 8. Searching and pipes
|
||||||
|
|
||||||
|
```
|
||||||
|
grep "hello" notes.txt # print only the lines containing "hello"
|
||||||
|
ls | grep notes # list only files whose name contains "notes"
|
||||||
|
```
|
||||||
|
|
||||||
|
That `|` is called a **pipe**. It takes the output of the command on the left and
|
||||||
|
feeds it as input to the command on the right. Piping small tools together is one
|
||||||
|
of the core ideas of Linux — small commands that each do one thing, chained up.
|
||||||
|
|
||||||
|
## 9. Getting help
|
||||||
|
|
||||||
|
```
|
||||||
|
ls --help # short summary of how to use a command
|
||||||
|
man ls # full manual page (press q to quit)
|
||||||
|
```
|
||||||
|
|
||||||
|
When you don't know a command, `man` is the first place to look. It's on the
|
||||||
|
machine itself, so it works even without internet.
|
||||||
|
|
||||||
|
## 10. Installing software: apt
|
||||||
|
|
||||||
|
On Raspberry Pi OS (and Ubuntu/Debian), software comes in packages managed by
|
||||||
|
`apt`. `sudo` means "run this as the administrator" and it will ask for your
|
||||||
|
password:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt update # refresh the list of available packages
|
||||||
|
sudo apt install -y curl # install a package (the -y means "yes to prompts")
|
||||||
|
sudo apt remove curl # remove a package
|
||||||
|
```
|
||||||
|
|
||||||
|
## 11. About your system
|
||||||
|
|
||||||
|
```
|
||||||
|
uname -a # what machine and kernel this is
|
||||||
|
df -h # how much disk space is left
|
||||||
|
free -h # how much memory is in use
|
||||||
|
history # everything you've typed so far
|
||||||
|
clear # clear the screen
|
||||||
|
```
|
||||||
|
|
||||||
|
## 12. Shortcuts that feel like magic
|
||||||
|
|
||||||
|
- **Tab** — autocomplete a command or filename
|
||||||
|
- **Up/Down arrows** — cycle through your previous commands
|
||||||
|
- **Ctrl+C** — stop whatever is currently running
|
||||||
|
- **Ctrl+L** — clear the screen (same as `clear`)
|
||||||
|
- **Ctrl+R** — search your command history: start typing the old command, keep
|
||||||
|
pressing Ctrl+R to cycle through matches, Enter to run it
|
||||||
|
|
||||||
|
## Practice
|
||||||
|
|
||||||
|
Try these from memory (scroll up only when you're stuck):
|
||||||
|
|
||||||
|
1. Create a folder called `lesson1` and go into it.
|
||||||
|
2. Create a file `hello.txt` containing the line `hello world`.
|
||||||
|
3. Append a second line: `second line`.
|
||||||
|
4. Print only the lines containing `hello`.
|
||||||
|
5. Copy `hello.txt` to `hello-backup.txt`, then delete the original.
|
||||||
|
6. Print the first line of `hello-backup.txt`.
|
||||||
|
|
||||||
|
If you can do all six without looking, you know the essentials: `pwd`, `ls`, `cd`,
|
||||||
|
`touch`, `nano`, `cat`, `rm`, `cp`, `mv`, `grep`, and pipes. That's the toolkit
|
||||||
|
you'll reach for on any Linux machine.
|
||||||
+285
@@ -0,0 +1,285 @@
|
|||||||
|
# Raspberry Pi VPN (Networking)
|
||||||
|
|
||||||
|
In this lesson you'll build a personal VPN server on your Raspberry Pi using
|
||||||
|
**WireGuard** — the modern standard for VPNs. It gives you a private road into
|
||||||
|
your home network: when you're at school, at a friend's house, or on vacation,
|
||||||
|
you can reach devices on your home Wi-Fi — the Pi, a NAS, a media server, a smart
|
||||||
|
home dashboard — as if your phone were plugged into the house.
|
||||||
|
|
||||||
|
As a side effect, the road is encrypted, so nobody in between can read what
|
||||||
|
you're accessing.
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
A quick networking refresher so the steps make sense:
|
||||||
|
|
||||||
|
- Devices on your home network get **local** IP addresses like
|
||||||
|
`192.168.1.42`. To the internet, your whole house appears as **one** public IP
|
||||||
|
address (the router's).
|
||||||
|
- By default the internet can only knock on the front door — the router. To reach
|
||||||
|
devices *inside* the house, we set up one exception: the Pi runs a VPN server,
|
||||||
|
and the router forwards that one port to it.
|
||||||
|
- A VPN creates an **encrypted tunnel** between your phone and the Pi. Inside the
|
||||||
|
tunnel we use our own private addresses: the Pi is `10.100.0.1`, your phone is
|
||||||
|
`10.100.0.2`.
|
||||||
|
- When you connect, your phone has two identities at once: it's on your carrier's
|
||||||
|
network *and* on your home network. Anything in your home range
|
||||||
|
(`192.168.1.x`) travels through the tunnel into the house.
|
||||||
|
|
||||||
|
```
|
||||||
|
phone --encrypted tunnel--> Pi --home network--> NAS, Pi, media server, ...
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check your own network first:** find your Pi's local IP on the Pi with
|
||||||
|
`hostname -I`. This lesson assumes it looks like `192.168.1.42`, so the home
|
||||||
|
range is `192.168.1.0/24`. If your router uses a different range (some use
|
||||||
|
`192.168.0.x` or `10.0.0.x`), substitute yours everywhere.
|
||||||
|
|
||||||
|
## What you need
|
||||||
|
|
||||||
|
- A Raspberry Pi running Raspberry Pi OS, connected to your home network (wired
|
||||||
|
ethernet is best and easiest)
|
||||||
|
- Your phone, with the official **WireGuard** app (iOS or Android)
|
||||||
|
- Access to your router's admin page (usually `192.168.1.1` in a browser)
|
||||||
|
|
||||||
|
## Step 1 — Install WireGuard on the Pi
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y wireguard wireguard-tools nftables qrencode
|
||||||
|
```
|
||||||
|
|
||||||
|
(`qrencode` prints a scannable QR code; `nftables` handles the forwarding rules
|
||||||
|
later.)
|
||||||
|
|
||||||
|
## Step 2 — Create the server's keys
|
||||||
|
|
||||||
|
Every WireGuard device has a **private key** (a secret) and a **public key**
|
||||||
|
(safe to share). Think of them like a password and a public address. The Pi gets
|
||||||
|
its pair now:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo -i
|
||||||
|
cd /etc/wireguard
|
||||||
|
umask 077
|
||||||
|
wg genkey | tee server.key | wg pubkey > server.pub
|
||||||
|
cat server.key
|
||||||
|
```
|
||||||
|
|
||||||
|
- `sudo -i` logs you in as the administrator account (root). Type `exit` at the
|
||||||
|
end of each root session to go back to your normal user.
|
||||||
|
- `umask 077` makes sure new files are only readable by you.
|
||||||
|
- Copy the long string from `cat server.key` — you'll paste it into the config in
|
||||||
|
the next step. **Never share your private key.** The public key (`server.pub`)
|
||||||
|
is fine to share.
|
||||||
|
|
||||||
|
## Step 3 — Write the server config
|
||||||
|
|
||||||
|
Still as root, open the config file:
|
||||||
|
|
||||||
|
```
|
||||||
|
nano /etc/wireguard/wg0.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Type this, replacing the last line with your server's private key:
|
||||||
|
|
||||||
|
```
|
||||||
|
[Interface]
|
||||||
|
Address = 10.100.0.1/24, fd08:4711::1/64
|
||||||
|
ListenPort = 47111
|
||||||
|
PrivateKey = PASTE_YOUR_SERVER_PRIVATE_KEY_HERE
|
||||||
|
```
|
||||||
|
|
||||||
|
Save (`Ctrl+O`, `Enter`) and quit (`Ctrl+X`). What the lines mean:
|
||||||
|
|
||||||
|
- `Address` — the Pi's address inside the tunnel (`10.100.0.1`).
|
||||||
|
- `ListenPort` — the port clients connect to. `47111`, UDP.
|
||||||
|
|
||||||
|
## Step 4 — Let the Pi forward traffic
|
||||||
|
|
||||||
|
To send your phone's traffic on to other devices in the house, the Pi has to be
|
||||||
|
willing to pass packets through. Two things enable that: **IP forwarding**
|
||||||
|
(allow packets through) and **NAT** (let tunnel devices share the Pi's internet
|
||||||
|
connection — you'll want it if you ever tunnel more than just home access).
|
||||||
|
|
||||||
|
First, edit `/etc/sysctl.d/99-sysctl.conf` (`nano /etc/sysctl.d/99-sysctl.conf`).
|
||||||
|
Make sure these two lines exist **without** a `#` in front of them (remove the `#`
|
||||||
|
if there is one):
|
||||||
|
|
||||||
|
```
|
||||||
|
net.ipv4.ip_forward = 1
|
||||||
|
net.ipv6.conf.all.forwarding = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Save and quit, then apply:
|
||||||
|
|
||||||
|
```
|
||||||
|
sysctl --system
|
||||||
|
```
|
||||||
|
|
||||||
|
Second, open the server config again (`nano /etc/wireguard/wg0.conf`) and add
|
||||||
|
these two lines inside the `[Interface]` section (paste them exactly as one line
|
||||||
|
each):
|
||||||
|
|
||||||
|
```
|
||||||
|
PostUp = nft add table ip wireguard; nft add chain ip wireguard wireguard_chain {type nat hook postrouting priority srcnat\; policy accept\;}; nft add rule ip wireguard wireguard_chain counter packets 0 bytes 0 masquerade; nft add table ip6 wireguard; nft add chain ip6 wireguard wireguard_chain {type nat hook postrouting priority srcnat\; policy accept\;}; nft add rule ip6 wireguard wireguard_chain counter packets 0 bytes 0 masquerade
|
||||||
|
PostDown = nft delete table ip wireguard; nft delete table ip6 wireguard
|
||||||
|
```
|
||||||
|
|
||||||
|
`PostUp`/`PostDown` are commands that run automatically when the tunnel starts and
|
||||||
|
stops — here they add and remove the NAT rule. Ugly-looking, but it's copy-paste
|
||||||
|
and it's what the official docs recommend.
|
||||||
|
|
||||||
|
When you're done, type `exit` to leave root.
|
||||||
|
|
||||||
|
## Step 5 — Start the VPN
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo systemctl enable wg-quick@wg0
|
||||||
|
sudo systemctl start wg-quick@wg0
|
||||||
|
sudo wg
|
||||||
|
```
|
||||||
|
|
||||||
|
If `sudo wg` prints an interface called `wg0` with a public key and a listening
|
||||||
|
port, the server is up. `enable` makes it start automatically after every reboot,
|
||||||
|
so you only ever run the `start` command after changing the config.
|
||||||
|
|
||||||
|
## Step 6 — Open a door in the router
|
||||||
|
|
||||||
|
Your phone needs to reach the Pi through the internet. Two things in your router's
|
||||||
|
admin page:
|
||||||
|
|
||||||
|
1. **Give the Pi a fixed local IP.** Find the current one on the Pi with
|
||||||
|
`hostname -I`, then add a **DHCP reservation** in the router (binds that IP to
|
||||||
|
the Pi's MAC address). If the Pi's IP ever changes, the port forward breaks.
|
||||||
|
2. **Add a port forward: UDP port `47111` → the Pi's local IP.**
|
||||||
|
|
||||||
|
Also find your home's **public IP** — it's often shown on the router's front page
|
||||||
|
("WAN IP"), or open `https://ifconfig.co` on any device at home. You'll paste it
|
||||||
|
into the client config next.
|
||||||
|
|
||||||
|
## Step 7 — Add your phone as a client
|
||||||
|
|
||||||
|
WireGuard calls every connected device a **peer**. Back on the Pi:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo -i
|
||||||
|
cd /etc/wireguard
|
||||||
|
umask 077
|
||||||
|
name=phone
|
||||||
|
wg genkey | tee ${name}.key | wg pubkey > ${name}.pub
|
||||||
|
wg genpsk > ${name}.psk
|
||||||
|
```
|
||||||
|
|
||||||
|
That created the phone's key pair plus a **preshared key** (an extra per-device
|
||||||
|
layer of encryption).
|
||||||
|
|
||||||
|
Register the phone in the server config — this appends a `[Peer]` section to
|
||||||
|
`wg0.conf`:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo "[Peer]" >> wg0.conf
|
||||||
|
echo "PublicKey = $(cat ${name}.pub)" >> wg0.conf
|
||||||
|
echo "PresharedKey = $(cat ${name}.psk)" >> wg0.conf
|
||||||
|
echo "AllowedIPs = 10.100.0.2/32, fd08:4711::2/128" >> wg0.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Then tell the running server about the change (this reloads the config without
|
||||||
|
kicking off connected clients):
|
||||||
|
|
||||||
|
```
|
||||||
|
wg syncconf wg0 <(wg-quick strip wg0)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now build the config file the phone will use:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo "[Interface]" > ${name}.conf
|
||||||
|
echo "Address = 10.100.0.2/32, fd08:4711::2/128" >> ${name}.conf
|
||||||
|
echo "PrivateKey = $(cat ${name}.key)" >> ${name}.conf
|
||||||
|
echo "" >> ${name}.conf
|
||||||
|
echo "[Peer]" >> ${name}.conf
|
||||||
|
echo "PublicKey = $(cat server.pub)" >> ${name}.conf
|
||||||
|
echo "PresharedKey = $(cat ${name}.psk)" >> ${name}.conf
|
||||||
|
echo "Endpoint = 203.0.113.10:47111" >> ${name}.conf
|
||||||
|
echo "AllowedIPs = 10.100.0.0/24, fd08:4711::/64, 192.168.1.0/24" >> ${name}.conf
|
||||||
|
echo "PersistentKeepalive = 25" >> ${name}.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `203.0.113.10` with **your home's public IP**, and `192.168.1.0/24` with
|
||||||
|
**your home range** if it's different. What the important lines do:
|
||||||
|
|
||||||
|
- `AllowedIPs` decides what travels through the tunnel. Here it's the tunnel
|
||||||
|
itself plus your whole home range — so home devices are reachable. Everything
|
||||||
|
else (normal web browsing, apps) goes over your carrier's network directly,
|
||||||
|
exactly as usual.
|
||||||
|
(If you ever want *everything* tunneled — e.g. to route it through a future
|
||||||
|
Pi-hole — you'd replace that line with `AllowedIPs = 0.0.0.0/0, ::/0`.)
|
||||||
|
- `PersistentKeepalive = 25` — phones sit behind carriers' NAT, so this sends a
|
||||||
|
small packet every 25 seconds to keep the tunnel's door open.
|
||||||
|
|
||||||
|
## Step 8 — Connect your phone
|
||||||
|
|
||||||
|
Still as root, print the config as a QR code:
|
||||||
|
|
||||||
|
```
|
||||||
|
qrencode -t ansiutf8 < ${name}.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
On your phone: open the WireGuard app → tap the blue **+** → scan the QR code →
|
||||||
|
toggle the tunnel **on**. (If you're using the Pi over SSH from a laptop, the QR
|
||||||
|
code appears in your terminal window — just scan it with the phone.) Then `exit`
|
||||||
|
root.
|
||||||
|
|
||||||
|
## Step 9 — Check it works
|
||||||
|
|
||||||
|
The interesting test is from **outside** the house: turn your phone's Wi-Fi off
|
||||||
|
and use cellular data.
|
||||||
|
|
||||||
|
1. On the Pi, run `sudo wg`. Your phone should appear with
|
||||||
|
`latest handshake: X seconds ago` and a transfer count.
|
||||||
|
2. Open your Pi's local address in your phone's browser —
|
||||||
|
`http://192.168.1.42` or `http://192.168.1.42/admin` (use your Pi's own local
|
||||||
|
IP). If the page loads from a school Wi-Fi network, your phone is effectively
|
||||||
|
sitting in your house.
|
||||||
|
3. Try SSH: `ssh YOUR_USER@192.168.1.42` from Termux (Android) or any SSH client
|
||||||
|
on iPhone. If you get a shell, remote access is fully working.
|
||||||
|
|
||||||
|
## What you can do now
|
||||||
|
|
||||||
|
Rule of thumb: anywhere you would have typed a `192.168.1.x` address while at
|
||||||
|
home, that same address now works from anywhere in the world.
|
||||||
|
|
||||||
|
- Web interfaces: Pi-hole admin, your NAS, Home Assistant — open them in the
|
||||||
|
browser.
|
||||||
|
- SSH into any device in the house.
|
||||||
|
- Stream from a media server or download files from a NAS.
|
||||||
|
|
||||||
|
One caveat: device **names** like `raspberrypi.local` only resolve *inside* the
|
||||||
|
house, so over the tunnel, use IP addresses.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
- **Phone never shows a handshake:** check the port forward is UDP (not TCP) on
|
||||||
|
port `47111` pointing at the Pi's current local IP; check the `Endpoint` line
|
||||||
|
has your *current* public IP (it can change — call your ISP for a static one if
|
||||||
|
it's changing often); check keys were copied without extra spaces.
|
||||||
|
- **Can't connect from home Wi-Fi, but cellular works:** common and often
|
||||||
|
unfixable — many routers can't loop a forwarded port back to devices already
|
||||||
|
inside the network (no "NAT loopback"). Test with cellular data.
|
||||||
|
- **Connected, but home devices are unreachable:** the `AllowedIPs` line in the
|
||||||
|
client config has the wrong home range — it must match your router's subnet,
|
||||||
|
the same range your Pi's IP lives in. Also make sure Step 4 (IP forwarding) is
|
||||||
|
done.
|
||||||
|
- **A device works at home but not over the tunnel:** use its IP address instead
|
||||||
|
of its name (see the caveat above), and double-check the device is actually on
|
||||||
|
your home network.
|
||||||
|
|
||||||
|
## Security notes
|
||||||
|
|
||||||
|
- Anyone with your phone's config file can walk into your home network. Treat it
|
||||||
|
like a password — don't screenshot it into a shared chat.
|
||||||
|
- Your Pi is now reachable from the internet. Keeping a firewall enabled (for
|
||||||
|
example with `ufw`) is a good next step.
|
||||||
|
- Lost a device? Delete its `[Peer]` section from `wg0.conf` and run
|
||||||
|
`wg syncconf wg0 <(wg-quick strip wg0)` again — its keys stop working.
|
||||||
+157
@@ -0,0 +1,157 @@
|
|||||||
|
# Raspberry Pi Pihole (DNS)
|
||||||
|
|
||||||
|
In this lesson you'll turn your Raspberry Pi into a **Pi-hole**, a network-wide
|
||||||
|
ad and tracker blocker. Once it's running, every device on your Wi-Fi gets ads
|
||||||
|
blocked automatically — including devices you can't install anything on.
|
||||||
|
|
||||||
|
## What is DNS?
|
||||||
|
|
||||||
|
When you type `example.com` into a browser, your computer first asks a **DNS
|
||||||
|
server**: "what's the IP address of example.com?" DNS is the internet's phone
|
||||||
|
book. Computers only speak IP addresses.
|
||||||
|
|
||||||
|
By default, the phone book is run by your internet provider (or whoever your
|
||||||
|
network uses). That means they can see every website you visit. Ad companies lean
|
||||||
|
on this: your devices look up ad servers *before* the ad loads, and those lookups
|
||||||
|
are how tracking works.
|
||||||
|
|
||||||
|
Pi-hole is a DNS server you run on your own network. It checks every name lookup
|
||||||
|
against blocklists of ads and trackers. Bad lookups get a "nope" answer, so the
|
||||||
|
ad never loads. Everything else is forwarded to a real DNS server upstream.
|
||||||
|
|
||||||
|
```
|
||||||
|
phone / laptop / tablet
|
||||||
|
| "who is doubleclick.net?"
|
||||||
|
v
|
||||||
|
Pi (Pi-hole) --- "blocked"
|
||||||
|
Pi (Pi-hole) --- forwards good lookups to upstream DNS (e.g. 1.1.1.1)
|
||||||
|
```
|
||||||
|
|
||||||
|
## What you need
|
||||||
|
|
||||||
|
- A Raspberry Pi running Raspberry Pi OS, connected to your network (wired
|
||||||
|
ethernet is best)
|
||||||
|
- Access to your router's admin page
|
||||||
|
|
||||||
|
## Step 0 — Give the Pi a fixed IP
|
||||||
|
|
||||||
|
Pi-hole needs an IP address that never changes, because every device on the
|
||||||
|
network will be pointed at it.
|
||||||
|
|
||||||
|
1. On the Pi, find its current IP:
|
||||||
|
|
||||||
|
```
|
||||||
|
hostname -I
|
||||||
|
```
|
||||||
|
|
||||||
|
2. In your router's admin page, add a **DHCP reservation** for the Pi (this binds
|
||||||
|
that IP to the Pi's MAC address so the router always hands out the same one).
|
||||||
|
This is the simplest way to make the IP permanent.
|
||||||
|
|
||||||
|
## Step 1 — Install Pi-hole
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt update
|
||||||
|
curl -sSL https://install.pi-hole.net | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
That downloads and runs Pi-hole's official installer. It walks you through a
|
||||||
|
few questions in the terminal:
|
||||||
|
|
||||||
|
- Accept the defaults for everything (press Enter).
|
||||||
|
- If asked about the upstream/private DNS provider, keep the default unless you
|
||||||
|
have a specific one you want to use.
|
||||||
|
|
||||||
|
When it finishes, it prints your **admin page URL** (it looks like
|
||||||
|
`http://192.168.1.42/admin`) and a **password**. Write both down.
|
||||||
|
|
||||||
|
## Step 2 — Point your network at the Pi
|
||||||
|
|
||||||
|
This is the step that makes it network-wide. In your router's admin page, set the
|
||||||
|
**DNS server for DHCP** to the Pi's IP address (the one from Step 0).
|
||||||
|
|
||||||
|
From now on, every device that gets an address from your router automatically
|
||||||
|
asks the Pi for DNS. Phones, laptops, tablets, smart TVs — all covered, no setup
|
||||||
|
on each device.
|
||||||
|
|
||||||
|
If your router doesn't let you change its DHCP DNS, Pi-hole has a built-in DHCP
|
||||||
|
server you can run instead (you'd turn the router's DHCP off first). As a last
|
||||||
|
resort, you can set the DNS address manually on individual devices — but the
|
||||||
|
router method is the one to use when you can.
|
||||||
|
|
||||||
|
## Step 3 — Let the Pi use itself too
|
||||||
|
|
||||||
|
By default, the Pi doesn't use Pi-hole for its own lookups. Two things to set up:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo usermod -aG pihole $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
That adds your account to the `pihole` group so the command-line tools work
|
||||||
|
without asking for a password every time. Log out of the terminal and back in
|
||||||
|
(so the change takes effect).
|
||||||
|
|
||||||
|
Optionally, make the Pi itself resolve through Pi-hole by adding this line to
|
||||||
|
`/etc/dhcpcd.conf`:
|
||||||
|
|
||||||
|
```
|
||||||
|
static domain_name_servers=127.0.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Be aware of the trade-off: if Pi-hole ever breaks, the Pi itself won't be able to
|
||||||
|
resolve names until you fix it — which can make fixing it annoying.
|
||||||
|
|
||||||
|
## Step 4 — The admin dashboard
|
||||||
|
|
||||||
|
Open `http://YOUR_PI_IP/admin` in a browser and log in with the password the
|
||||||
|
installer gave you. The pages that matter:
|
||||||
|
|
||||||
|
- **Dashboard** — live stats. Watch the query counter climb and the red
|
||||||
|
"Blocked" numbers appear within a minute of your network using it.
|
||||||
|
- **Query Log** — every single name lookup your network made, and what Pi-hole
|
||||||
|
answered. Search it to see what a device looked up.
|
||||||
|
- **Domain Lists** — block or allow specific domains for the whole network. Type
|
||||||
|
a domain, add it, choose "Always deny", and that site is dead on every device.
|
||||||
|
- **Settings** — choose the upstream DNS provider Pi-hole forwards to, the
|
||||||
|
privacy level, and the blocking mode. "Allow only local requests" is a sensible
|
||||||
|
secure default.
|
||||||
|
|
||||||
|
## Step 5 — Check it's actually blocking
|
||||||
|
|
||||||
|
1. On your phone or laptop, visit a website you know is full of ads. The ads
|
||||||
|
should be gone or greatly reduced.
|
||||||
|
2. In the dashboard's Query Log, you should see blocked lookups marked in red.
|
||||||
|
3. On the Pi, confirm the service is healthy:
|
||||||
|
|
||||||
|
```
|
||||||
|
pihole status
|
||||||
|
```
|
||||||
|
|
||||||
|
It should say the DNS server is up and running.
|
||||||
|
|
||||||
|
## Useful commands
|
||||||
|
|
||||||
|
```
|
||||||
|
pihole status # is everything running?
|
||||||
|
pihole -h # list all available commands
|
||||||
|
pihole update # update Pi-hole and its blocklists (run this now and then)
|
||||||
|
```
|
||||||
|
|
||||||
|
Blocklists grow stale, so run `pihole update` once in a while to keep blocking
|
||||||
|
current.
|
||||||
|
|
||||||
|
## Where this goes next
|
||||||
|
|
||||||
|
If you followed the VPN lesson, you can already reach the Pi from anywhere — so
|
||||||
|
once this is done, you can manage your whole house's ad-blocking from your phone
|
||||||
|
at school or on vacation, at `http://YOUR_PI_IP/admin` through the tunnel.
|
||||||
|
|
||||||
|
If you want, the tunnel can also ask Pi-hole for names: add this line to the
|
||||||
|
`[Interface]` section of your client config, then regenerate and rescan the QR
|
||||||
|
code:
|
||||||
|
|
||||||
|
```
|
||||||
|
DNS = 10.100.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Now any name lookups the phone makes go through Pi-hole first.
|
||||||
Reference in New Issue
Block a user