This documents shows all my attempts to develop containers that are supposed to run on a Raspberry Pi in my home network. In the end I decided to simply represent the architecture with Docker Compose and run VS Code Dev Containers:
https://github.com/eulersson/taconez/wiki/4.-Development-Workflow
Lsyncd (Live Syncing Daemon) synchronizes local directories with remote targets.
In my case it would be handy to keep the current project folder in sync with the various
Raspberry Pis without having to run rsync
to all of them or scp
.
It uses rsync and ssh under the hood every time it detects a filesystem event.
I discarded it because the mantainer himself said it is not reliable on macOS:
the osx events interface of Lsyncd is generally very outdated, and as far as I know unmaintained, unless someone finds willing to do that, and best rewrite it all together to use FSEvents insted of that experiment I did back then to directly access the internal buffer, I'd advice against using it, or removing it from Lsyncd altogether.
Source: lsyncd/lsyncd#204 (comment)
Installing a distant service on the Raspberry Pi and connecting to it via Neovim is possible. You would be able to browse through the remote files from Neovim and open them up with your local Neovim resources.
PROS:
- Good for connecting to resources that might be outside of the network.
- The communication is efficient and fast because it goes through custom TCP distant protocol between the distant client and distant server.
- It's encrypted.
CONS:
- I couldn't get the language server features working, it seemed to rely on me installing all the intellisense tooling on the Raspberry Pi, which I prefer not because the compute power of my computer is better than the Pi.
- Code would not reside in my powerful computer.
- I would have to sync from that Raspberry Pi to the rest of them.
I struggled to have it setup properly, but it could be paired with remote development to help with the case of sshfs or NFS, where the files are entirely remote but the container is built locally with the remote files that are synched with sshfs or NFS.
A volume could be bound on the host machine (macOS) and Raspberry Pi could mount it with NFS or SMB. When outside the home LAN then an OpenVPN solution should be set up which is outside of the scope of this guide.
An alternative to the NFS + OpenVPN would be something like sshfs
.
PROS:
- Transparent to navigate the mounted remote volume.
- Intellisense (LSP) would work since it resides on the host.
CONS:
- When outside home LAN you need to use VPN to access home LAN resources.
I also evaluated other workflows such as lsyncd
, distant
and distant.nvim
but each
had caveats. I explain why I discarded them in
Discarded Tools.
When NFS shares we want a specific user remotedevuser with a specific remotedevgroup group to be used when writing on that share from the client. That user only needs to exist on the host server. When you mount the share, the client's user (e.g. myraspberrypiuser) will be mapped to remotedevuser.
# See what user IDs and group IDs exist so you don't pick an existing one:
dscl . -list /Users UniqueID
dscl . -list /Groups PrimaryGroupID
# Create user:
sudo dscl . -create /Users/remotedevuser
sudo dscl . -create /Users/remotedevuser UniqueID 301
# Create group:
sudo dscl . -create /Groups/remotedevgroup
sudo dscl . -create /Groups/remotedevgroup gid 301
sudo dscl . -create /Groups/remotedevgroup PrimaryGroupID 301
sudo dscl . -append /Groups/remotedevgroup GroupMembership eulersson
sudo dscl . -append /Groups/remotedevgroup GroupMembership remotedevuser
# Make the default's remotedevuser primary group be remotedevgroup:
sudo dscl . -create /Users/remotedevuser PrimaryGroupID 301
# Check it's all good:
sudo dscl . -read /Groups/remotedevgroup GroupMembership
GroupMembership: eulersson remotedevuser
Sources:
- Creating a Group Via Users & Groups in Command Line
- Why can't I use my newly created user with chown?
- dscl Manual
Change the owning group of the /Users/eulersson/Devel/taconez
project folder from
eulersson:eulersson
to eulersson:remotedevgroup
so all users from remotedevgroup
can write, edit, read, delete contents on that folder.
# Change the owning group:
sudo chown -R eulersson:remotedevgroup /Users/eulersson/Devel/taconez
# Ensure group users can write as well as read:
sudo chmod -R g+w /Users/eulersson/Devel/taconez
We will now export the project folder as an NFS share.
Open up /etc/exports
on the macOS (which acts as NFS server):
/Users/eulersson/Devel/taconez -network 192.168.1.0 -mask 255.255.255.0 -mapall remotedevuser
[!NOTE]
192.168.1.0/24
with your home LAN network range. If you want to be conservative it could be setup as read-only instead of read-write (by adding the-ro
flag), that way if the Raspberry Pi goes nuts and starts corrupting files it would not affect the host's folder, but I guess it's not critical if the code is versioned with git.
Check the share is being exported correctly:
eulersson@macbook:~ $ sudo nfsd restart
# Should not error. If it's good it does not output.
eulersson@macbook:~ $ sudo nfsd checkexports
More information on the /etc/exports
format on its manual: man exports
.
If you are out of home use a VPN to connect to your home LAN.
Sources:
Then on the Raspberry Pi mount the volume (192.168.1.22
is the IP of the MacBook that
runs the NFS service):
sudo mkdir -p /mnt/nfs/development
sudo mount --types nfs --verbose 192.168.1.22:/Users/eulersson/Devel/taconez /mnt/nfs/development
You can check it mounted correctly with df -h
or by listing the mounted folder
ls /mnt/nfs/taconez
.
When you are done unmount the volume on the client:
taconez@raspberrypi $:~ umount /mnt/nfs/taconez --lazy
And stop exporting it from the server by removing the line we added on /etc/exports
.