calico
Radxa Rock Pi S, a teeny little ARM computer with PoE and 100Mb ethernet
Running Armbian this time, I've got Armbian_23.8.1_Rockpi-s_bookworm_current_6.1.50.img.xz
Linux calico 6.1.50-current-rockchip64 #3 SMP PREEMPT Wed Aug 30 14:11:13 UTC 2023 aarch64 GNU/Linux
Much newer than the 4.4 kernel that Radxa distributes themselves- Located at home
Contents
Build notes
I previously wrote general notes for Rock Pi S hardware based on using the Radxa distro, this time I'm trying something different.
Image and setup SSH keys
- Image the SD card with Etcher and let it boot, it'll get on the network with DHCP
- The MAC address will be something random, as these boards don't have a real burnt-in MAC address, so you'll need to find it.
- Login with root // 1234
- Let it run the firstrun thing to set the root password to something secure, and record it safely. Select bash or zsh, your choice.
- Skip user account creation, I won't be using that
Copy your SSH key to the box, using the freshly-set root password
ssh-copy-id root@IP
Login again, now it'll use your SSH key
ssh root@IP
Regenerate SSH host keys to ensure they're clean
rm /etc/ssh/ssh_host_* dpkg-reconfigure openssh-server
We only want to use ed25519 as well
echo "HostKey /etc/ssh/ssh_host_ed25519_key" >> /etc/ssh/sshd_config.d/10-ed25519-hostkey-only.conf
- Logout completely
- Delete the entries from your local known_hosts file
- SSH again as root@IP, accepting the new keys. It'll use your SSH key instead of asking for password now.
Go ahead and reboot to make sure everything is clean.
Run armbian-config to configure the host
- System
- CPU: choose the min/max speeds, use ondemand governor
- Avahi: Let's announce, I guess
- Hardware
Check bs@1.3ghz (I think this is fine for v1.3 RockPiS board
- Firmware: Apply all updates, don't reboot
- Network
- IP
- end0
- Static: 192.168.1.26 // 24 // 192.168.1.1 // 8.8.8.8
- end0
- IP
- Personal
- Timezone: Australia/Sydney
- Locales
Enable en_AU.UTF-8
Leave en_US.UTF-8 enabled too
Select en_AU.UTF-8 as default for system
- Locales
- Hostname: calico
- Welcome
- 10 Armbian header
- 30 Armbian sysinfo
- 40 Armbian updates
- 41 Armbian config
- 98 Armbian autoreboot warn
- !! /etc/update-motd.d/ seems to be missing
- Exit and run armbian-config again, seems fine now
- Timezone: Australia/Sydney
Some notes on the key setup from the Armbian forums: https://forum.armbian.com/topic/23465-apt-get-update-fails-with-public-key-errors/page/2/#comment-178626
I got this error on 2024-04-25 and re/adding the key fixed the issue.
# This is deprecated, but I think it still works wget -qO - http://fi.mirror.armbian.de/apt/armbian.key | sudo apt-key add - # This isn't really necessary but can't hurt cd /etc/apt/trusted.gpg.d/ wget http://fi.mirror.armbian.de/apt/armbian.key mv armbian.key armbian.asc # The linked guide actually suggests doing this: wget https://apt.armbian.com/armbian.key -O key gpg --dearmor < key | sudo tee /usr/share/keyrings/armbian.gpg > /dev/null chmod go+r /usr/share/keyrings/armbian.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/armbian.gpg] http://apt.armbian.com $(lsb_release -cs) main $(lsb_release -cs)-utils $(lsb_release -cs)-desktop" | tee /etc/apt/sources.list.d/armbian.list apt update
Basic environment stuff
Armbian doesn't seem to load root's bashrc so we trigger it ourselves
echo -e "if [ -f ~/.bashrc ] ; then\n . ~/.bashrc\nfi" > /root/.profile
Enable shell timestamping for root, as our usual bashrd.d won't be imported here
echo -e "\n# Timestamped shell FTW\nexport HISTTIMEFORMAT='%Y-%m-%d %H:%M:%S '" >> /root/.bashrc
Set hostname:
hostnamectl set-hostname calico.thighhighs.top
Set timezone
timedatectl set-timezone Australia/Sydney
Set editor
echo "export EDITOR=vim" > /etc/profile.d/editor-vim.sh
Disable HashKnownHosts
echo -e "Host *\n HashKnownHosts no" > /etc/ssh/ssh_config.d/99-global.conf
Configure screen
curl -o ~/.screenrc https://gist.githubusercontent.com/barneydesmond/d16c5201ed9d2280251dfca7c620bb86/raw/.screenrc
Configure top by entering this cheatcode
z x c s 1.5 <Enter> e <zero> 1 W q
Disable wifi, we don't need it and it slows down boot
systemctl disable wpa_supplicant.service --now systemctl disable rpcbind.socket --now systemctl stop rpcbind.service echo -e "# Don't load the WLAN+BT module, we don't need it\nblacklist 8723ds" > /etc/modprobe.d/blacklist-radios.conf update-initramfs -u
Install useful packages
apt update apt install -y ack bind9-dnsutils elinks net-tools netcat-openbsd nmap python-is-python3 screen strace tcpdump vim wget whiptail whois
Do a full upgrade then reboot
apt full-upgrade reboot
Configure networking
We've already got the static IPv4 address, but let's make sure we've got this complete.
What we want:
- Static IPv4 addressing
- Autoconfig dynamic IPv6 addressing
- Global stable IPv6 addresses (I guess)
- Add a locally-defined static IPv6 address, that other hosts can refer to via DNS etc
This is a nifty site for testing: http://ip.bieringer.net/ - Look at EUI64_SCOPE and see if it's random/privacy/global. Global is probably what we want for servers.
- DNS resolvers will be manually defined
The connection is managed by Network Manager, so let's try sticking with that for now.
nmtui to edit the connection
Rename it to Ethernet or something easier
- IPv4
- Set DNS servers to 8.8.8.8 and 8.8.4.4
Add search domain thighhighs.top
- IPv6
- Add v6 address 2404:e80:42e3:0:201:26:314:159
Note that this respects the EUI-64 derivation, changing :1:26 to :201:26
Add search domain thighhighs.top
- Add v6 address 2404:e80:42e3:0:201:26:314:159
Reboot and cross your fingers
Save a known-good image for convenience
On another system with an SD card reader, take an image of the system after shrinking the filesystem
e2fsck -f /dev/mmcblk0p2 resize2fs -M /dev/mmcblk0p2 # Use cfdisk or parted to shrink the partition to a bit larger than the FS, has just been reported. # In this case it's just over 1GiB, so I'll shrink the partition to 1.1GiB. # Now take the image, capture a bit more than the size of the partitions. # boot+root partitions are ~1.22GiB (1254MiB) here, so I'll capture 1300MiB just to be sure. dd bs=1M count=1300 if=/dev/mmcblk0 | pv -br | gzip --fast > 2021-12-13_calico_img_clean_os.img.gz
If you ever need to restore this image, make sure to run resize-assistant afterwards. As well as growing the FS, it needs to locate the backup GPT table at the end of the disk. At the very least you need to run sgdisk -e /dev/mmcblk0 and then partprobe to clean that up.
If you want to expand the filesystem manually:
- Boot the image you just restored to the SD card
sgdisk -e /dev/mmcblk0
partprobe
- Use parted or cfdisk to expand the 2nd partition to the desired size (or the whole disk)
resize2fs /dev/mmcblk0p2
Pihole
Straightforward basic install, no conflict with other installed services.
curl -sSL https://install.pi-hole.net | bash
- Google upstream
- Use suggested blocklist
- Web interface enabled, full query logging and display
[i] Web Interface password: iMm9OBVz [i] This can be changed using 'pihole -a -p' [i] View the web interface at http://pi.hole/admin or http://192.168.1.26/admin [i] You may now configure your devices to use the Pi-hole as their DNS server [i] Pi-hole DNS (IPv4): 192.168.1.26 [i] Pi-hole DNS (IPv6): 2404:e80:42e3:0:39d1:1547:50dd:bce7 [i] If you have not done so already, the above IP should be set to static. [i] The install log is located at: /etc/pihole/install.log
Admin UI at https://calico.thighhighs.top/admin/
Update our network config to use localhost resolvers only. This gives us the sum of what pihole/dnsmasq knows from local static configs, plus whatever is forwarded to Cloudflare.
- Ether1
IPv4 DNS: 127.0.0.1
IPv6 DNS: ::1
- Ignore automatically obtained DNS parameters
In Pihole, enable IPv6 upstreams, and Respond only on interface end0, in http://calico.thighhighs.top/admin/settings.php?tab=dns
This is important as the default setting won't answer queries from other LAN subnets (eg. VPN, IOT segments).
Enable conditional forwarding.
TLS support
Can add TLS \o/ https://discourse.pi-hole.net/t/enabling-https-for-your-pi-hole-web-interface/5771/17
Copy the cert to /etc/ssl/STAR_thighhighs_top.combined.pem, which is a concatenation of the key, the cert, the intermediate CA chain, and apparently the root CA's cert in my case. I dunno why I did that.
Install the mod_openssl for lighttpd:
apt install lighttpd-mod-openssl
Create /etc/lighttpd/conf-enabled/pihole-tls.conf with the following contents
server.modules += ( "mod_openssl" ) $HTTP["host"] =~ "^[a-zA-Z0-9-_]+\.thighhighs\.top$" { # Ensure the Pi-hole Block Page knows that this is not a blocked domain setenv.add-environment = ("fqdn" => "true") # TLS cert for Pihole admin interface $SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/etc/ssl/STAR_thighhighs_top.combined.pem" ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.3", "Options" => "-ServerPreference") } $SERVER["socket"] == "[::]:443" { ssl.engine = "enable" ssl.pemfile = "/etc/ssl/STAR_thighhighs_top.combined.pem" ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.3", "Options" => "-ServerPreference") } # Redirect HTTP to HTTPS $HTTP["scheme"] == "http" { $HTTP["host"] =~ ".*" { url.redirect = (".*" => "https://%0$0") } } }
- Then restart lighttpd and it should just work.
Firewall
As per https://docs.pi-hole.net/main/prerequisites/ I've installed ufw and locked things down.
Limit and fail2ban would be good to do as well: https://www.raspberrypi.org/documentation/configuration/security.md
apt install -y ufw ufw allow from 192.168.1.0/24 to any app OpenSSH ufw allow from 2404:e80:42e3:0::/64 to any app OpenSSH ufw enable # Pihole stuff - https://docs.pi-hole.net/main/prerequisites/#ufw ufw allow http ufw allow https ufw allow domain ufw allow 67/udp ufw allow 67/tcp ufw allow 546:547/udp