computing

Using Raspberry PI as home server to extend life of old computers

Harold Smith

Intro

My venerable ThinkPad X200 runs Linux quite happily with its 8 gigs of RAM and 512GB SSD. The same goes for my 2015 MacBook Pro 13” (i7/16GB/512GB) running macOS Sonoma via OpenCore Legacy Patcher. They give me decent mobility (with recently replaced batteries) and the ergonomics is perfect: nothing beats ThinkPad’s keyboard nor MacBook’s display and touchpad.

I use them for development, writing, media consumption and emulation. Given the age of this hardware, it would be very beneficial to enable data sharing and to avoid running servers/services locally whenever possible.

That’s where the Raspberry PI 5 comes to play. It has small size, low power consumption, ability to use fast storage, runs Linux and has more than enough processing power to serve my needs, which are:

·       ssh (for headless operation)

·       NFS (to share code & data)

·       LAMP server (for development of this site, among other things)

·       Redis

·       PostgreSQL

·       ActiveMQ (I’m using v6-classic)

·       Emscripten

 

Note on security

            This will be a development, headless appliance - sitting in a specific LAN segment, with me as a single user who has access to this network. There will be no valuable or confidential data on it and no ports will be forwarded for access from outside of its LAN segment. I want to be able to move it into another (private/closed) network  segment with zero configuration and therefore all services will listen to all interfaces! 

            All of this means that security exists ONLY to protect LAN segment from outside (via router config), but not from the inside (as I’m the only user there) – any attempt to connect this to “outside world” will require pinning of network interfaces, reconfiguration of services to limit access, setting up of secure auth, use of certificates and Kerberos, and/or things like ssh tunnels, AS CONFIGURATION DESCRIBED BELLOW IS NOT SECURE!

 

Hardware setup

            As I already had an EVO 970 Plus, power supply and microSD card lying around, my purchase consisted of Raspberry PI 5 8GB and a GeekPi N04 NVMe shield.

            With Raspberry PI OS imaged to microSD card, I’ve assembled & started the tiny computer. PI booted up without issues, and after initial configuration, I proceeded to grab its MAC address (via ‘sudo ifconfig’). Armed with PI’s MAC, I’ve updated my wireless router configuration to bind it to a fixed IP address (set to 192.168.10.10 for the purpose of this text). This way, I can to emulate static IP and to make it simple for other devices to connect.

            Now its time to enable PCIe access for Raspbery:

sudo nano /boot/firmware/config.txt

and added:

            dtparam=pciex1_gen=3

to enable PCI express and run it v3 mode.

            With that set, I’ve rebooted the PI. When the OS was loaded again, I went to ‘Start -> Accessories -> Raspberry PI Imager’, selected PI5, 64bit OS and my NVMe drive as target, and wrote the image with no OS customization. After imaging, it was time to enable booting from it:

            sudo rpi-eeprom-config –edit

and added the following:

            PCI_PROBE=1

            BOOT_ORDER=0xf416

To boot from PCIEx & put it on top of priority list.

            I did another reboot, and this time PI started from NVMe and prompted me to update its configuration (and install system updates). Everything was ready now, and microSD card is no longer necessary for PI’s operation (although I’ve kept it to be used for backup).

            Here’s the final product:

 PI Server - FINAL

 

Basic utilities

            There is only few things that I needed here at this stage, as Raspberry PI OS comes with usual assortment of Linux utilities:

            sudo apt install mc git dfc

 

SSH

            Raspberry PI OS comes with ssh server intalled, and it only needs to be enabled, which can be done by running:

            sudo raspi-config

and navigating to ‘Interface -> SSH -> Enable’.

 

NFS

            Configuring NFS can be tricky, as it is a service that uses Unix permissions for access by default. In my case, I want it to treat every user as default/local (pi) user, so I can connect from different systems and accounts without having to worry about file ownership. This is what I did:

            sudo apt install nfs-kernel-server

            sudo mkdir /nfsrv

            sudo chown nobody:nogroup /nfsrv

            sudo chmod 777 /nfsrv

            sudo nano /etc/exports

and added:

/nfsrv  192.168.10.0/255.255.255.0(rw,sync,all_squash,anonuid=1000,anongid=1000,no_subtree_check)

(note that 1000 is id of the 'pi' user - you can find it via ‘sudo cat /etc/passwd’). With server config done, its time run the following:

            sudo exportfs -a

            sudo systemctl restart nfs-kernel-server

to enable the file share.

            Mounting NFS on client side is simple on Linux, all it takes is the following command(s):

            mkdir nfsrv

            sudo mount -t nfs 192.168.10.10:/nfsrv nfsrv

and note that mounting on macOS requires additional switch in command:

            mkdir nfsrv

            sudo mount -t nfs -o resvport 192.168.10.10:/nfsrv nfsrv

to make it work.

 

Apache/php

            I prefer to run php in FPM mode (with site root for my projects placed on NFS share for easy access), and these are packages needed for my setup (more or less standard set of php components):

            sudo apt install apache2 php-fpm php-common php-mysql php-xml php-xmlrpc php-curl php-gd php-imagick php-cli php-dev php-mbstring php-zip php-bcmath php-ctype php-json php-tokenizer

            Now it’s time to do some tweaking to make sure FPM is setup correctly (version of php installed is 8.2 at the time of this writing):

            sudo /usr/sbin/a2enmod proxy_fcgi 

            sudo /usr/sbin/a2dismod mpm_prefork 

            sudo /usr/sbin/a2enmod mpm_event 

            sudo /usr/sbin/a2enconf php8.2-fpm

            sudo /sbin/service/apache2 restart

 

MariaDB

            For ‘M’ component in LAMP package, I’ll be using MariaDB with example password of ‘prettySecret’:

            sudo apt install mariadb-server

            sudo mysql_secure_installation

and set the root password, disabled Unix socket auth & removed test database. Now to login and enable non-system root to use mysql root:

            sudo su

            mysql -u root

            GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'prettySecret';

            FLUSH PRIVILEGES;

for simple auth (from anywhere). Now I edited:

            sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf

to comment out ‘bind-address 127.0.0.1’ line. This will listen to ALL network interfaces. With config done, I’ve restarted mariadb service:

            sudo /sbin/service mariadb restart

 

Redis

            Redis is a speedy key/value store, ideal for all kinds of caching. To install it, I’ve simply did: 

sudo apt install redis-server

            sudo su

            nano /etc/redis/redis.conf

then changed 'bind 127.0.0.1 -::1' to 'bind * -::*' and 'protected-mode yes' to 'protected-mode no'. Again, please note that this enables access to ANYONE from ANYWHERE and should not be used if your server is accessible from any unwanted location! With config done, restart is in order:

            sudo /sbin/service redis restart

 

PostgreSQL

            Additional database server is (like MariaDB) installed with ‘prettySecret’ password via the following:

            sudo apt install postgresql postgresql-contrib

            sudo su postgres

            psql

            ALTER USER postgres PASSWORD ' prettySecret ';

            sudo passwd postgres

and set it to 'prettySecret '. Now, I’ve enabled auth from all clients:

            sudo nano /etc/postgresql/15/main/pg_hba.conf

by adding this on top of the file:

            host    all             all             0.0.0.0/0            scram-sha-256

Then, I also updated server to listen to all interfaces:

            sudo nano /etc/postgresql/15/main/postgresql.conf

by searching for and updating the following:

listen_addresses = '*'

and restarted the service:     

            sudo /sbin/service postgresql restart

 

ActiveMQ

            ActiveMQ that comes bundled with Raspberry PI OS is missing some components (like GUI/admin console), and therefore I’ve downloaded v6 binary release & extracted it into ‘/nfsrv/activemq’ directory, after which JDK was required and some configuration:

            sudo apt install default-jdk

cd /nfsrv/activemq

            sudo nano conf/jetty.xml

and updated host in jettyPort to use "0.0.0.0" address (listen on all interfaces). At this point I can start/stop activemq manually via:

            /nfsrv/activemq/bin/activemq start

            /nfsrv/activemq/bin/activemq stop

but I’ve decided to create system scripts for automatic startup/shutdown:

            sudo nano /etc/systemd/system/activemq.service

and added the following content:

[Unit]

Description=ActiveMQ Service

After=multi-user.target

 

[Service]

Type=idle

User=pi

ExecStart=/nfsrv/activemq/bin/activemq console

WorkingDirectory=/nfsrv/activemq

StandardOutput=inherit

StandardError=inherit

Restart=always

 

[Install]

WantedBy=multi-user.target

Which enables me to use system for start/stop:

            sudo systemctl start activemq.service

            sudo systemctl stop activemq.service

or to enable automatic service control:

            sudo systemctl enable activemq.service

(when started, GUI console should be available via web browser: 192.168.10.10: 8161).

 

Emscripten install

            Although not a service EMSDK is something I use and want it installed on NFS share. That way I can ssh to PI and build/serve Emscripten apps:

            cd /nfsrv

            git clone https://github.com/emscripten-core/emsdk.git

            cd /nfsrv/emsdk

            ./emsdk install latest

            ./emsdk activate latest

now to use emsdk, I can just do:

            source "/nfsrv/emsdk/emsdk_env.sh"

and it will be added to path.

 

Boot to command line

            While in OS GUI, I’ve switched Raspberry boot mode to use text console by default (as it will run in headless mode) by navigating to:

            Menu > Preferences > Raspberry Pi Configuration

and changing the Boot setting to 'To CLI' and clicking OK.

 

Conclusion    

And as this year’s Black Friday looms just around the corner, I can save money by buying – nothing