In my dealings with MagicMirror and the work I have been doing there, I have seen a few people mention the word NAS and “pulling” their photos from their NAS into their MM setup for display. This triggered some research and the more I read about self-hosting it made sense to me. No reliance on any Cloud storage that you have to pay for and as for privacy, that was front of mind. This meant I had to setup my own NAS to bring my media back under my own control.
The Journey
I only had a RPi 3B+ at hand and as I wanted to check this out, I decided to use that.
And thus, the initial setup was as follows.
🔧 What You’ll Need:
- Raspberry Pi 3B+
- microSD card (8GB minimum, 16GB+ recommended)
- USB external hard drive or SSD (or large USB flash drive)
- Raspberry Pi power supply
- Ethernet cable or Wi-Fi (Ethernet preferred for stability/speed)
- Raspberry Pi OS installed (Lite version is fine if you’re using SSH)
🪛 Step-by-Step Setup
- Set Up Raspberry Pi OS
- Download Raspberry Pi OS from https://www.raspberrypi.com/software
- Use Raspberry Pi Imager to flash it to your SD card.
- Boot the Pi and configure basics (
sudo raspi-config), including hostname, timezone, SSH, etc.
- Update Your Pi
sudo apt update && sudo apt upgrade -y
- Connect Your Storage Drive
- Plug in your external USB drive
- Find the drive:
lsblk
- Mount it (e.g., to
/mnt/nasdrive:
sudo mkdir /mnt/nasdrive
sudo mount /dev/sda1 /mnt/nasdrive
- Make it mount on boot:
sudo blkid # Get UUID of the drive
- Add to
/etc/fstab:
sudo nano /etc/fstab
- Add a line like:
UUID=your-drive-uuid /mnt/nasdrive ext4 defaults,nofail 0 0
- Install Samba (for Windows/macOS access)
sudo apt install samba samba-common-bin -y
- Configure Samba Share
Edit config:
sudo nano /etc/samba/smb.conf
- Add at the bottom:
[NAS]
path = /mnt/nasdrive
browseable = yes
writeable = yes
only guest = no
create mask = 0777
directory mask = 0777
public = no
- Create Samba User
sudo adduser yourusername
sudo smbpasswd -a yourusername
- Restart Samba
sudo systemctl restart smbd
Accessing the NAS
- On Windows: open File Explorer and go to
\\raspberrypi.local\NASor use the IP - On macOS: in Finder > Go > Connect to Server:
smb//raspberrypi.local/NAS
Now, this works just fine if you want a simple setup and manually transferring you media to your NAS. This was not my ideal setup and I did a little more digging.
This lead me to OMV, OpenMediaVault. OMV, as it is known for short, is a full-featured NAS web interface. However, this is much too heavy to run on a Pi 3. I then decided to take the plunge and ordered an RPi5 8Gb. Had to wait a few days for this to arive.
I initially looked at Synology. Now, some of you would ask what is Synology? Well,
Synology is a Taiwanese corporation that specializes in Network Attached Storage (NAS) devices. The Synology DiskStation Manager (DSM) cannot run on a RasberryPi because:
- DSM is closed-source and designed only to run on Synology’s own custom x86 and ARM-based hardware.
- It requires specific hardware drives and bootloaders that the Pi does not support
- Synology doesn’t officially support DIY installations or non-Synology hardware.
For the above reasons I decided to go with OMV.
OpenMediaVault (OMV) is a free network-attached storage (NAS) solution based on Debian Linux. It’s designed for home and small office environments which made it perfect for my scenario.
NOTE
I installed OMV on my Pi 3B and tried setting up my 1TB SSD but this seemed to keep failing and giving me endless issues. Reason being that the Pi 3B does not play well with that big storage.
- ⚡ Power Issues
- Pi 3B+ has limited power, especially for 2.5" HDDs or SSD’s which causes it to continously disconnect.
The above was one of the main motivators for me getting my Pi 5 as it has dedicated USB 3 ports which works well with the SSD.
What I saw on the Pi3B was:
The driver for the USB controller dwc_otg_hcd does not support scatter-gather which is required by the UAS driver.
This confirmed two important things:
- The USB-to-SATA adaptor supports UAS (USB Attached SCI) – a faster, more efficient USB protocol used by many SSDs and modern enclosures.
- The Raspberry Pi 3B+’s USB controller (
dwc_otg_hcd) does not fully support UAS, and can’t handle “scatter-gather” operations
What follows is the setup of OMV on my RPi 5.
🖥️ Raspberry Pi 5 NAS Setup with OpenMediaVault and External SSD
This guide walks through installing OpenMediaVault (OMV) on a Raspberry Pi 5, adding an SSD for media storage, and preparing it for Docker-based media and sync services.
🧰 Prerequisites
- Raspberry Pi 5 (8GB recommended for media tasks)
- microSD card (32GB or larger) for boot
- USB 3.0 SSD or NVMe via USB adapter (for media storage)
- Stable 5V 5A USB-C power supply
- Ethernet connection (recommended for NAS)
- Another PC for flashing the OS
1️⃣ Install Raspberry Pi OS (Lite Recommended)
-
Download Raspberry Pi Imager:
https://www.raspberrypi.com/software/ -
Select:
- Raspberry Pi 5 → Raspberry Pi OS Lite (64-bit)
(Lite is preferred for servers; no desktop environment needed)
- Before writing, press the gear icon:
- Enable SSH
- Set username and password
- Configure Wi-Fi (if not using Ethernet)
- Set hostname (e.g.,
rpi-nas)
2️⃣ Initial Configuration
SSH into the Pi:
ssh pi@<raspberrypi-ip>
Update the OS:
sudo apt update && sudo apt upgrade -y
sudo reboot
3️⃣ Install OpenMediaVault
- Download and run the official OMV install script:
wget -O - https://github.com/OpenMediaVault-Plugin-Developers/installScript/raw/master/install | sudo bash
- After the script finishes:
- Access OMV web UI:
http://<raspberrypi-ip>/
- Default credentials:
- User:
admin - Password:
openmediavault
- User:
- Immediately change the password in the Web UI.
4️⃣ Connect and Mount Your SSD
- Plug in the SSD (USB 3.0 recommended)
- In OMV web UI:
- Go to Storage → Disks
- Verify your SSD is listed
- Wipe the SSD (if new or safe to erase):
- Storage → Disks → Wipe → Quick
- Create a Filesystem:
- Storage → File Systems → Create → EXT4
- Mount the filesystem (OMV will mount it under
/srv/dev-disk-by-uuid-xxxx)
5️⃣ Create Shared Folders
For media and sync services:
- Access Rights Management → Shared Folders → Add
- Example folders:
musicvideosphotosappdata(for Docker persistent configs)
- Set Permissions:
- Set Owner:
root - Group:
users - Permissions:
775with setgid if you want all new files to inherit theusersgroup.
6️⃣ Enable SMB/NFS for Network Access (Optional)
- Services → SMB/CIFS → Enable
- Add shared folders as SMB shares for easy access from Windows/Mac.
- (Optional) Enable NFS for Linux clients.
7️⃣ Install OMV-Extras and Docker
- OMV-Extras (gives Docker and Portainer support):
wget -O - https://github.com/OpenMediaVault-Plugin-Developers/packages/raw/master/install | sudo bash
- In the OMV web UI:
- Go to System → OMV-Extras
- Install Docker
- Install Portainer for container management. Services → Compose → Files and Click the plus button
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: always
ports:
- "9000:9000"
- "8000:8000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:
8️⃣ Map Docker Volumes to SSD
When creating containers (Syncthing, Jellyfin, etc.) in Portainer:
- Map host folders from your mounted SSD, for example:
Service Host Path Container Path
Syncthing /srv/dev-disk-by-uuid-xxxx/music /sync/music
Jellyfin /srv/dev-disk-by-uuid-xxxx/music and /srv/dev-disk-by-uuid-xxxx/videos /media/music & /media/videos
App Configs /srv/dev-disk-by-uuid-xxxx/appdata/<service> /config
9️⃣ Setup Syncthing for Phone → NAS Sync
- Deploy Syncthing via Docker:
- Map
/musicand/photosto container paths - Use PUID=1000 and PGID=1000 for permission consistency
- Map
- Pair devices using Syncthing-Fork on Android
- Set Send-Only (Phone) → Receive-Only (NAS) for one-way sync
services:
syncthing:
image: syncthing/syncthing:latest
container_name: syncthing
restart: always
ports:
- "8384:8384" # Web UI
- "22000:22000" # Sync traffic
- "21027:21027/udp" # Discovery
volumes:
- /srv/path-to-your-disk/syncthing/config:/var/syncthing
- /srv/path-to-your-disk/syncthing/data:/mnt/sync
🔟 Setup Jellyfin for Media Playback
See my media-management blog post for a complete setup guide.
- Deploy Jellyfin via Docker
- Map
/musicand/videosfolders to/media/musicand/media/videos - Add libraries in the Jellyfin dashboard
1️⃣1️⃣ Enable Secure Remote Access with Tailscale (Optional)
- Install Tailscale:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
- Sign in and access OMV/Jellyfin securely from anywhere using:
http://<device-name>.tailnet.ts.net
✅ Final Notes
- Always use EXT4 for SSDs to avoid Linux permission issues
- Set proper permissions (
775with groupusers) for all media folders - Keep your Pi cool if transcoding with Jellyfin
- Regularly backup
/srv/dev-disk-by-uuid-xxxx/appdatafor Docker configs