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
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!
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:
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
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’.
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.
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
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 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
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 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).
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.
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.
And as this year’s Black Friday looms just around the corner, I can save money by buying – nothing