https://pixelfed.de/p/cammelspit/657887422594974310

After using my Steam Deck for over a year, I had an idea regarding network storage when I was installing Emu Deck. Despite the portability of the Steam Deck, I wanted to mount ROMs, Media, and even a Steam Library from a network-attached storage (NAS) device at home.

Recently, due to health reasons, I find myself bed-bound, making the Steam Deck a great companion. However, It’s storage options are rather limited so I attempted to find a solution.

I faced challenges due to SteamOS’s immutable file system. To overcome these I explored using NFS shares for a Steam Library, as Samba shares had limitations and wouldnt work on Linux for a Steam Library. Mounting NFS shares worked as long as i used a specific option to make the files executable.

To automate this process I created a systemd service that loads on boot, triggering a script to mount the shares. However, SteamOS’s immutable file system posed challenges for typical auto-start methods like the KDE autostart tool and especially fstab.

The key was leveraging the service that loads even in in gamemode so you wont have to do anything manually, not even switch to desktop mode at all. The solution involved that service checking network connectivity before mounting the shares. This ensures the script doesn’t run before the wifi comes up, if it has no connectivity it rechecks every 30 seconds for connectivity until it does. Once this happens, the mount script itself is run. On a wired connectionwhile docked the mount is ready before Steam even loads for me so this hasnt been an issue but I felt it was a problem i needed to solve before putting it into production.

I’ve shared the service file and script as well as a handy script that I used to unmount those same shares during testing, noting that hard-coded paths will need to be modified. The script also logs successful and unsuccessful mounts for debugging but i liked the feature so i left it. Although not the final version, it offers a functional solution for now.

If you use Unraid, the script includes paths relevant to its shares. Server IP, share list, and mount points Will need to be modified to fit your needs or it likely won’t work. The script lacks support for authenticated shares, but it persists between reboots and has shown reliability in my testing. I also realize that the script is basically just dumped on my desktop, that’s where I created it and the pads are hard coded and I just don’t care to change it so if you want it somewhere else you’re going to have to do that alteration yourself.

Feel free to modify it or share improved versions and above all, have fun!!

  1. netmount.sh
#!/bin/sh

NFS_SERVER=10.10.10.99
SHARE_PATH="/mnt/user"
SHARES=("Media" "Emulation" "Steam" "Downloads" "DUMPBOX" "isos" "NSFWMedia" "Software" "Tools")

# Set up log file
LOG_FILE="/home/deck/Desktop/netmount.log"

# Loop through the shares and mount each one with -o exec
for SHARE_NAME in "${SHARES[@]}"; do
  MOUNT_POINT="/home/deck/mounts/$SHARE_NAME"
  mkdir -p $MOUNT_POINT  # Create the mount point directory

  TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
  mount -t nfs -o exec $NFS_SERVER:$SHARE_PATH/$SHARE_NAME $MOUNT_POINT

  # Log the results with timestamps
  if [ $? -eq 0 ]; then
    echo "$TIMESTAMP: NFS share '$SHARE_NAME' mounted successfully at $MOUNT_POINT" >> $LOG_FILE
  else
    echo "$TIMESTAMP: Failed to mount NFS share '$SHARE_NAME'" >> $LOG_FILE
  fi
done
  1. unmount.sh
#!/bin/sh

# Unmount all NFS shares
for MOUNT_POINT in /home/deck/mounts/*; do
  umount $MOUNT_POINT
done

echo "All NFS shares unmounted."

  1. netmount.service
[Unit]
Description=Netmount Script at Boot
After=graphical.target

[Service]
Type=simple
ExecStart=/bin/sh -c 'for i in {1..20}; do ping -c 1 google.com && /home/deck/Desktop/netmount.sh && break || sleep 30; done'

[Install]
WantedBy=default.target

You can use these clean versions for your scripts and service file. Adjust paths and configurations as needed.

  • CapillaryUpgrade@lemmy.sdf.org
    link
    fedilink
    arrow-up
    10
    ·
    11 months ago

    This is really cool!

    Where did you put the service file?

    I don’t mean this as critique, but as possible next project, since your solution works perfectly fine. Systemd has some cool features that could make this project have a bit fewer moving parts:

    • a .mount file could replace the mount and unmount script, and handle logging too! (I am pretty sure you would need separate files per mount, though, so “fewer moving parts” might be a bit of a lie, depending on your interpretation)
    • that “After=” setting you used, can also be used to check for network connectivity. IIRC it’s “networking.target” on Fedora, at least. You might want to double check the systemd docs if After is the right one for this, as I have a hard remembering the systemd dependency intricacies.

    That way you would end up with a .mount file per mounted directory, with logging using journald, and no external scripts.

    I really like systemd as it can be a great tool, when you start to break down the complexity of it.

    I hope you get well soon and get the best you can from this time.

    • cammelspit@lemm.eeOP
      link
      fedilink
      arrow-up
      7
      ·
      edit-2
      11 months ago

      Frankly, you are probably right. I am pretty new to all thisandwhat I have here is basically just cobbled together from nonsense examples I scrounged up off the internet. What’s funny is, a good 20% of this I have no idea how it works! Lol

      Originally i was juat going to make the script simply a list of all my mount commands and not even post anything about it at all. I spent a good two days playing around with about a dozen different ideas on how to accomplish my goal until this one, the first that worked at all. But yeah, I have been doinh a lot of fun stuff since I officially dropped Windows entirely a few weeks ago and a lot of the inner workings of how Linux works in general is just starting to make sense to me.

      Pretty much the Arch wiki and the Gentoo wiki alongwith copious amounts of google fu have become an all encompasing hobby of mine as of late. I’ll get there eventually. 😁

      • CapillaryUpgrade@lemmy.sdf.org
        link
        fedilink
        arrow-up
        3
        ·
        11 months ago

        Don’t put yourself down! Using systemd wouldn’t make it work “better”, it’s just more “proper” (and a great tool to know in general!)

        Great job and keep going!

        • cammelspit@lemm.eeOP
          link
          fedilink
          arrow-up
          1
          ·
          11 months ago

          Thanks! Yeah, I have noticed a lot of places where the location of things is not necessarily a requirement but it is considered “proper”. It’s a whole different paradigm compared to the rather severely rigid requirements of Windows. I went through a lot of documentation about services and the real eureka moment was when I realized it was more or less just a command being run with extra fluff around it like environment variables and such. I have the service placed in the /etc/systemd/system directory, where all the other ones valve made are. I have seen how powerful systemd can be when leveraged well but for the moment I’m pleased with the results. Thanks for the encouragement!

          • CapillaryUpgrade@lemmy.sdf.org
            link
            fedilink
            arrow-up
            2
            ·
            11 months ago

            No problem!

            I hacked this together instead of going to sleep, so it might make your deck explode, but maybe it’s a starting point for you or someone else:

            # home-deck-mounts.mount
            #
            # Mount units must be named after the destination path, this / replaced by -, like above
            #
            # This is a template unit.
            # That's explained here: https://fedoramagazine.org/systemd-template-unit-files/
            # TL;DR: run it like this `netmount@linuxisos.mount` if you want to mount the subdirectory "linuxisos" from SHARE_PATH
            [Unit]
            Description=NetMount %I
            After=graphical.target
            # This is commented out, because it is implicit for network mounts https://www.freedesktop.org/software/systemd/man/latest/systemd.mount.html#Default%20Dependencies
            # I keep it here as an example
            #After=network-online.target
            #Requires=network-online.target
            
            [Mount]
            # %i expands to what ever you put after the @ when starting/activating the service
            What=10.10.10.99:/mnt/user/%i
            Where=/home/deck/mounts/%i
            Type=nfs
            Options=exec
            
            [Install]
            WantedBy=default.target
            

            I couldn’t confirm if mount units are allowed to be template units, but if not, just duplicate the service for each path and replace %i.

            Say the word if you run into issues!

    • Lupec@lemm.ee
      link
      fedilink
      arrow-up
      4
      ·
      11 months ago

      It sounds to me the target you’d want here is network-online.target, going by the info here

      • cammelspit@lemm.eeOP
        link
        fedilink
        arrow-up
        5
        ·
        11 months ago

        I actually did try that but I messed it up somehow and didn’t get it working. I then sawanexample similar to what I did here and since it seemed to work for them, I copied it. Would also be able to ping the NAS itself instead so you can not only confirm the network is up but also confirm the NAS is listening and replying properly. 100% sure there are better ways to do almost everything here but it was my first big win and I had to share. 😂

        • Lupec@lemm.ee
          link
          fedilink
          arrow-up
          4
          ·
          edit-2
          11 months ago

          That’s totally valid, just wanted to share my two cents from having messed with systemd a fair bit. At any rate, congrats, that’s a win for sure! :)

  • Fubarberry@sopuli.xyzM
    link
    fedilink
    English
    arrow-up
    2
    ·
    11 months ago

    This is very cool. I originally thought this post was just going to be asking if it was possible or how to do it, so it was a pleasant surprise to find you already have it working and are sharing how.