Skip to content

Instantly share code, notes, and snippets.

@eulersson
Last active April 29, 2024 05:15
Show Gist options
  • Save eulersson/2682fdcc1773b39d882f859a7ca8edb2 to your computer and use it in GitHub Desktop.
Save eulersson/2682fdcc1773b39d882f859a7ca8edb2 to your computer and use it in GitHub Desktop.

Revisions

  1. eulersson revised this gist Apr 29, 2024. 1 changed file with 5 additions and 3 deletions.
    8 changes: 5 additions & 3 deletions nvim-remote-dev.md
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,11 @@
    # Discarded Tools for Remote Development

    In the end I used VS Code Dev Containers:
    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

    # Discarded Tools for Remote Development

    ## Discarded Alternative 1: lsyncd

    Lsyncd (Live Syncing Daemon) synchronizes local directories with remote targets.
  2. eulersson revised this gist Apr 29, 2024. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions nvim-remote-dev.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,9 @@
    # Discarded Tools for Remote Development

    In the end I used VS Code Dev Containers:

    https://github.com/eulersson/taconez/wiki/4.-Development-Workflow

    ## Discarded Alternative 1: lsyncd

    Lsyncd (Live Syncing Daemon) synchronizes local directories with remote targets.
  3. eulersson revised this gist Apr 29, 2024. 1 changed file with 52 additions and 49 deletions.
    101 changes: 52 additions & 49 deletions nvim-remote-dev.md
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,56 @@
    # Discarded Tools for Remote Development

    ## Discarded Alternative 1: lsyncd

    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: https://github.com/lsyncd/lsyncd/issues/204#issuecomment-1794164518
    ## Discarded Alternative 2: Distant + distant.nvim

    - https://distant.dev/
    - https://distant.dev/editors/neovim/installation/

    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.


    # Container Development Overview

    - [nvim-remote-containers: Develop inside docker containers, just like VSCode](https://github.com/jamestthompson3/nvim-remote-containers)

    I struggled to have it setup properly.
    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.

    # Network Volume Approach Overview

    @@ -27,7 +75,7 @@ had caveats. I explain why I discarded them in

    ## Create a Sharing User & Group on the macOS Host

    When mounting NFS shares we want a specific user **remotedevuser** with a specific
    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_.
    @@ -109,7 +157,7 @@ Sources:

    - [exports Manual](https://ss64.com/osx/export.html)

    # Mounting the NFS Share from the Raspberry Pi
    ## Mounting the NFS Share from the Raspberry Pi

    Then on the Raspberry Pi mount the volume (`192.168.1.22` is the IP of the MacBook that
    runs the NFS service):
    @@ -128,49 +176,4 @@ 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`.

    # Discarded Tools for Remote Development

    ## Discarded Alternative 1: lsyncd

    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: https://github.com/lsyncd/lsyncd/issues/204#issuecomment-1794164518
    ## Discarded Alternative 2: Distant + distant.nvim

    - https://distant.dev/
    - https://distant.dev/editors/neovim/installation/

    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.
    And stop exporting it from the server by removing the line we added on `/etc/exports`.
  4. eulersson revised this gist Apr 29, 2024. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions nvim-remote-dev.md
    Original file line number Diff line number Diff line change
    @@ -25,7 +25,7 @@ I also evaluated other workflows such as `lsyncd`, `distant` and `distant.nvim`
    had caveats. I explain why I discarded them in
    [Discarded Tools](4-development-workflow#discarded-tools-for-remote-development).

    # Create a Sharing User & Group on the macOS Host
    ## Create a Sharing User & Group on the macOS Host

    When mounting 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
    @@ -62,7 +62,7 @@ Sources:
    - [Why can't I use my newly created user with chown?](https://superuser.com/a/923843)
    - [dscl Manual](https://www.unix.com/man-page/osx/1/dscl/)

    # Change Project Folder Permissions on the macOS Host
    ## Change Project Folder Permissions on the macOS Host

    Change the owning group of the `/Users/eulersson/Devel/taconez` project folder from
    `eulersson:eulersson` to `eulersson:remotedevgroup` so all users from **remotedevgroup**
    @@ -76,7 +76,7 @@ sudo chown -R eulersson:remotedevgroup /Users/eulersson/Devel/taconez
    sudo chmod -R g+w /Users/eulersson/Devel/taconez
    ```

    # Set NFS Share on the macOS Host
    ## Set NFS Share on the macOS Host

    We will now export the project folder as an NFS share.

  5. eulersson renamed this gist Apr 29, 2024. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  6. eulersson created this gist Apr 29, 2024.
    176 changes: 176 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,176 @@
    # Container Development Overview

    - [nvim-remote-containers: Develop inside docker containers, just like VSCode](https://github.com/jamestthompson3/nvim-remote-containers)

    I struggled to have it setup properly.

    # Network Volume Approach Overview

    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](4-development-workflow#discarded-tools-for-remote-development).

    # Create a Sharing User & Group on the macOS Host

    When mounting 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](https://apple.stackexchange.com/a/307186)
    - [Why can't I use my newly created user with chown?](https://superuser.com/a/923843)
    - [dscl Manual](https://www.unix.com/man-page/osx/1/dscl/)

    # Change Project Folder Permissions on the macOS Host

    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
    ```

    # Set NFS Share on the macOS Host

    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:

    - [exports Manual](https://ss64.com/osx/export.html)

    # Mounting the NFS Share from the Raspberry Pi

    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`.

    # Discarded Tools for Remote Development

    ## Discarded Alternative 1: lsyncd

    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: https://github.com/lsyncd/lsyncd/issues/204#issuecomment-1794164518

    ## Discarded Alternative 2: Distant + distant.nvim

    - https://distant.dev/
    - https://distant.dev/editors/neovim/installation/

    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.