My SD card is 32GB. I chose to partition it with
- 256 MiB (FAT32) for the operating system,
- 2 GiB (ext4) for the local backup utility and package cache, and
- the remainder (ext4) for
/var/lib/docker.
Find the device name with
$ diskutil listIn my case, the SD card was /dev/disk4.
Partition the SD card with
$ diskutil partitionDisk /dev/disk4 \
MBR \
FAT32 PI-HOLE 256MiB \
FREE %noformat% RDownload and extract Alpine Linux to the SD card with
$ gpg --receive-keys 293ACD0907D9495A
gpg: key 293ACD0907D9495A: public key "Natanael Copa <ncopa@alpinelinux.org>" imported
$ gpg --lsign-key 293ACD0907D9495A
$ curl --remote-name-all https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/aarch64/alpine-rpi-3.20.0-aarch64.tar.gz{.asc,}
$ gpg --verify alpine-rpi-3.20.0-aarch64.tar.gz{.asc,}
gpg: Signature made Wed 22 May 11:33:03 2024 BST
gpg: using RSA key 0482D84022F52DF1C4E7CD43293ACD0907D9495A
gpg: Good signature from "Natanael Copa <ncopa@alpinelinux.org>" [full]
$ tar \
--extract \
--file alpine-rpi-3.20.0-aarch64.tar.gz \
--directory /Volumes/PI-HOLEEject the SD card with
$ diskutil eject /Volumes/PI-HOLEGenerate an SSH key in 1password with
$ op item create --category ssh --title piholeUpload the public key as a gist with
$ op read "op://personal/pihole/public key" |
gh gist create --filename pihole.pub -
https://gist.githubusercontent.com/...Take a note of the URL for later.
Insert the SD card and start the Raspberry Pi.
Login as root with no password.
Set up Alpine in diskless mode with
# setup-alpine| Setting | Value | Notes |
|---|---|---|
| Keyboard layout | gb |
|
| Keyboard layout variant | gb |
|
| System hostname | pihole |
|
| Network interface | eth0 |
|
| IP address | 192.168.0.2 |
This depends on the router's LAN settings |
| Netmask | 255.255.255.0 |
|
| Gateway | 192.168.0.1 |
|
| Manual network configuration | n |
|
| DNS domain name | (empty) | |
| DNS nameservers | 1.1.1.1 1.0.0.1 |
|
| Timezone | UTC |
|
| HTTP/FTP proxy URL | none |
|
| NTP client | chrony |
|
| Mirror | uk.alpinelinux.org |
|
| Setup a user? | pihole |
|
| SSH server | openssh |
|
Unmount /media/mmcblk0p1? |
n |
|
| Where to store configs | none |
|
apk cache directory |
/var/cache/apk |
Install certificate authority certificates with
# apk add ca-certificatesEnable the community repository and configure the mirror with HTTPS by running
# cat >/etc/apk/repositories <<EOF
/media/mmcblk0p1/apks
https://uk.alpinelinux.org/alpine/v3.20/main
https://uk.alpinelinux.org/alpine/v3.20/community
EOF
Upgrade any outdated packages with
# apk update
# apk upgradeFinish partitioning the SD card with
# apk add e2fsprogs parted
# parted /dev/mmcblk0 mkpart primary ext4 257MiB 2305MiB
# mkfs.ext4 /dev/mmcblk0p2
# parted /dev/mmcblk0 mkpart primary ext4 2305MiB 100%
# mkfs.ext4 /dev/mmcblk0p3
# apk del e2fsprogs partedCreate mount points for the writable partitions with
# mkdir /media/mmcblk0p2 /var/lib/dockerAdd the writable partitions with
# cat >>/etc/fstab <<EOF
/dev/mmcblk0p2 /media/mmcblk0p2 ext4 defaults 0 0
/dev/mmcblk0p3 /var/lib/docker ext4 defaults 0 0
EOF
Mount the writable partitions with
# mount -aSet up the local backup utility with
# setup-lbu mmcblk0p2Set up the apk cache with
# setup-apkcache /media/mmcblk0p2/cacheAuthorize the SSH key with
# su - pihole
$ mkdir ~/.ssh
$ chmod a=,u=rwx ~/.ssh
$ wget --output-document ~/.ssh/authorized_keys https://gist.githubusercontent.com/...
$ chmod a=,u=rw ~/.ssh/authorized_keys
$ exitAllow chronyd to step the system clock with
# echo "makestep 1 -1" >>/etc/chrony/chrony.conf
Install Docker with
# apk add docker
# rc-update add dockerEnable user namespace remapping with
# echo "pihole:65536:65536" >/etc/subgid
# echo "pihole:65536:65536" >/etc/subuid
# mkdir /etc/docker
# echo '{"userns-remap":"pihole"}' >/etc/docker/daemon.jsonStart Docker with
# service docker startCreate a file setting the Pi-hole environment variables to
DNSMASQ_LISTENING=all
PIHOLE_DNS_=1.1.1.1;1.0.0.1
WEBPASSWORD=...
with
# vi /etc/pihole
# chmod u=rw,g=r,o= /etc/piholeAdd a script to start Pi-hole with
# cat >/usr/local/bin/pihole <<EOF
docker run \
--detach \
--dns 127.0.0.1 \
--dns 1.1.1.1 \
--dns 1.0.0.1 \
--env-file /etc/pihole \
--mount type=volume,source=dnsmasq,target=/etc/dnsmasq.d \
--mount type=volume,source=pihole,target=/etc/pihole \
--name pihole \
--publish 53:53/tcp \
--publish 53:53/udp \
--publish 80:80 \
--pull always \
--restart always \
pihole/pihole:latest
EOF
# chmod +x /usr/local/bin/pihole
# lbu include /usr/local/bin/piholeStart Pi-hole with
# piholeClear the message of the day with
# : >/etc/motdCommit configuration with
# lbu commit