For years, my home storage setup was functional — but architecturally messy. You can check this out here -> iamJohnnySam | Media Box
Each hard drive was mounted independently, and each disk had its own Samba share. It worked, but it wasn’t scalable, resilient, or clean from a systems perspective. As someone working in systems engineering and automation, that bothered me. The system functioned, but it wasn’t designed.
This post walks through how I migrated from independent HDD shares to a structured LVM-based storage pool on Ubuntu Server, integrated Samba, Transmission, and a custom C# automation layer — all running on repurposed hardware that most people would have retired.
Phase 1 — The Original Setup (The “It Works” Stage)
Initially, I had:
- Multiple 1TB HDDs
- Ubuntu Server
- Individual mount points
- Separate Samba shares per drive
Each had its own Samba block in smb.conf.
Problems With This Architecture
- No unified storage abstraction
- Manual allocation of data per disk
- Uneven disk utilization
- Difficult future expansion
- No clean way to re-balance data
It was storage at the filesystem level, not at the volume-management level. Every time a disk filled up, I had to manually decide where new data should go. There was no logical aggregation layer between physical disks and network access.
Phase 2 — The Goal: A Single Logical Pool
What I wanted:
- One logical storage pool
- Single mount point
- Clean folder hierarchy
- Proper permission model
- Easy future expansion
- Ability to automate file orchestration
Naturally, I evaluated ZFS and TrueNAS.
Why Not TrueNAS?
I attempted installing TrueNAS (CORE and SCALE), but the older hardware presented compatibility and installation issues.
I am running a very old HP Compaq 8100 Elite PC with an early-generation Intel Core i5 processor. This machine has served reliably for years, but it was never designed for modern storage-heavy operating systems.

Instead of fighting the hardware, I stepped back and reconsidered:
Do I actually need full ZFS-level enterprise features for a home NAS?
For my use case — media storage, automation workflows, and torrent orchestration — the honest answer was no.
Why I Settled on LVM
While reinstalling Ubuntu Server, I revisited Logical Volume Manager (LVM). LVM provides a clean abstraction layer between physical disks and filesystems without imposing heavy system requirements.
LVM gave me:
- A unified volume group
- Logical abstraction over physical disks
- Expandability (add disks later)
- Snapshot capability
- Simplicity
- Native Linux integration
And most importantly — it worked immediately on my hardware with zero compatibility friction.
Current Storage Architecture
Physical disks → Volume Group → Logical Volume → Single mount
/dev/sdarn/dev/sdbrn/dev/sdcrn/dev/sddrn/dev/sde rn↓ rnVolume Group: molecule rn↓ rnLogical Volume: media rn↓ rnMounted at: /molecule
This transformed five independent disks into one logical storage pool.
Samba Configuration
I structured Samba into two logical shares to reflect system architecture rather than just folders.
Public Media Share (Open Access)
[Media]rn path = /molecule/Mediarn writeable = Yesrn create mask = 0777rn directory mask = 0777rn public = Yes
Purpose:
- Accessible by all LAN devices
- Centralized media repository
- No authentication friction for TVs, tablets, and laptops
Private SSD Application Share
[atom] rn path = /home/atomrn browseable = yesrn read only = norn valid users = userrn create mask = 0775rn directory mask = 0775
Purpose:
- Lives on SSD for performance
- Hosts my custom C# automation service
- Restricted access
- Cleaner permission control
This separation enforces architectural intent:
- HDD pool = Storage layer
- SSD = Compute and orchestration layer
The system is now layered instead of improvised.
Transmission Integration
Transmission is configured with:
'download-dir': '/molecule/Media/Downloads', rn'incomplete-dir': '/molecule/Media/IncompleteDownloads'
Key detail:
Transmission runs as debian-transmission, not my primary user account. That means Linux permissions must be intentionally structured.
I created a shared group and applied proper ownership:
groupadd media rnusermod -aG media debian-transmission rnusermod -aG media user rnchown -R root:media /molecule/Media rnchmod -R 2775 /molecule/Media
This ensures:
- Transmission can write
- Samba users can write
- New files inherit correct group
- No permission deadlocks
This is critical in multi-service Linux storage systems where daemons and users interact on the same filesystem.
Custom C# Automation Layer (Atom → MediaBox)
This is where the system becomes more than just a NAS.
On the SSD share (/home/atom), I deployed a background C# service that:
- Monitors Transmission via RPC
- Organizes downloaded content
- Moves files into structured directories
- Deletes torrents post-processing
- Interfaces with me via Telegram
- Maintains folder taxonomy rules
This module started life under the broader Atom project as the MediaBox engine, and has since become a dedicated .NET 10 service. I cover the full journey and the system that hosts it here -> iamJohnnySam | MediaBox 2026.
This effectively acts as a lightweight orchestration engine for home media lifecycle management. It separates raw ingestion (torrent downloads) from structured storage, keeping the media library clean and deterministic.
Why Not ZFS?
ZFS is powerful and feature-rich:
- End-to-end checksumming
- Self-healing data
- RAID-Z configurations
- Snapshots
- Compression
But for this hardware and workload:
- LVM is lighter
- Easier to recover on standard Linux installs
- No significant RAM overhead
- No kernel compatibility concerns
If I upgrade to newer hardware with ECC memory and higher RAM capacity, I may migrate to ZFS. For now, LVM provides the correct abstraction-to-complexity ratio.

This NAS is not enterprise-grade. It is not redundant RAID with hot spares and ECC memory. But it is structured, expandable, automated, and intentionally engineered.
And that makes all the difference.
sudo apt updaternsudo apt upgradernsudo apt updaternrn# Sudo permissionsrnsudo usermod -aG sudo atomrnrn# Wipe Drivesrnsudo wipefs -a /dev/sdbrnsudo wipefs -a /dev/sdcrnsudo wipefs -a /dev/sddrnsudo wipefs -a /dev/sdernrn# Create physical volumernsudo pvcreate /dev/sdbrnsudo pvcreate /dev/sdcrnsudo pvcreate /dev/sddrnsudo pvcreate /dev/sdernrn# Create logical volumernsudo vgcreate molecule /dev/sdb /dev/sdc /dev/sdd /dev/sdernsudo lvcreate -l 100%FREE -n media moleculernrn# Formatrnsudo mkfs.ext4 /dev/molecule/mediarnrn# Create mount point and mountrnsudo mkdir /moleculernsudo mount /dev/molecule/media /moleculernrn# Make the mounting permanentrnsudo blkidrnsudo nano /etc/fstabrn→ UUID=6b3b1323-87fb-4842-8e67-7e75737a8c2b /molecule ext4 defaults,noatime 0 2rnrnsudo tune2fs -m 0 /dev/molecule/mediarnrn# Set Static IPrnls /etc/netplan/rnsudo nano /etc/netplan/01-netcfg.yamlrnrn→ # This is the network config written by 'subiquity'rnnetwork:rn version: 2rn ethernets:rn enp0s25:rn dhcp4: norn addresses:rn - 192.168.1.30/24rn routes:rn - to: defaultrn via: 192.168.1.1rn nameservers:rn addresses: [1.1.1.1]rnrn# Samba Set uprnsudo apt install sambarnsudo systemctl status smbdrnrnsudo adduser userrnsudo usermod -aG molecule userrnrnsudo nano /etc/samba/smb.confrnrn→ [Media]rn path = /molecule/Mediarn writeable=Yesrn create mask=0777rn directory mask=0777rn public=Yesrn rn→ [atom]rn path = /home/atomrn browseable = yesrn read only = norn valid users = userrn create mask = 0775rn directory mask = 0775rn rnsudo smbpasswd -a userrnrn→ .NETrnsudo curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel STSrnrnsudo apt-get update && rn sudo apt-get install -y dotnet-sdk-9.0rnrnsudo apt-get update && rn sudo apt-get install -y aspnetcore-runtime-10.0rnrnsudo apt updaternsudo apt install dotnet-runtime-8.0rnrnecho 'export DOTNET_ROOT=$HOME/.dotnet' >> ~/.bashrcrnecho 'export PATH=$PATH:$HOME/.dotnet' >> ~/.bashrcrnsource ~/.bashrcrnrndotnet --versionrnrn→ Transmissionrnsudo chmod -R 775 /molecule/Mediarnsudo apt install transmission-daemonrnrnsudo systemctl stop transmission-daemonrnrnsudo chown -R debian-transmission:debian-transmission /molecule/Media/Downloadsrnsudo chown -R debian-transmission:debian-transmission /molecule/Media/IncompleteDownloadsrnrn/etc/transmission-daemon/settings.jsonrnrn→ {rn 'alt-speed-down': 0,rn 'alt-speed-enabled': false,rn 'alt-speed-time-begin': 465,rn 'alt-speed-time-day': 127,rn 'alt-speed-time-enabled': true,rn 'alt-speed-time-end': 15,rn 'alt-speed-up': 0,rn 'bind-address-ipv4': '0.0.0.0',rn 'bind-address-ipv6': '::',rn 'blocklist-enabled': false,rn 'blocklist-url': 'http://www.example.com/blocklist',rn 'cache-size-mb': 4,rn 'dht-enabled': true,rn 'download-dir': '/molecule/Media/Downloads',rn 'download-limit': 100,rn 'download-limit-enabled': 0,rn 'download-queue-enabled': true,rn 'download-queue-size': 5,rn 'encryption': 1,rn 'idle-seeding-limit': 30,rn 'idle-seeding-limit-enabled': false,rn 'incomplete-dir': '/molecule/Media/IncompleteDownloads',rn 'incomplete-dir-enabled': true,rn 'lpd-enabled': false,rn 'max-peers-global': 200,rn 'message-level': 1,rn 'peer-congestion-algorithm': '',rn 'peer-id-ttl-hours': 6,rn 'peer-limit-global': 200,rn 'peer-limit-per-torrent': 50,rn 'peer-port': 51413,rn 'peer-port-random-high': 65535,rn 'peer-port-random-low': 49152,rn 'peer-port-random-on-start': false,rn 'peer-socket-tos': 'default',rn 'pex-enabled': true,rn 'port-forwarding-enabled': false,rn 'preallocation': 1,rn 'prefetch-enabled': true,rn 'queue-stalled-enabled': true,rn 'queue-stalled-minutes': 30,rn 'ratio-limit': 0,rn 'ratio-limit-enabled': true,rn 'rename-partial-files': true,rn 'rpc-authentication-required': false,rn 'rpc-bind-address': '0.0.0.0',rn 'rpc-enabled': true,rn 'rpc-host-whitelist': '192.168.1.*',rn 'rpc-host-whitelist-enabled': true,rn 'rpc-password': '{828b6db2a9fc2115177ab572cce421d5d89d5e74UtkMgp.E',rn 'rpc-port': 9091,rn 'rpc-url': '/transmission/',rn 'rpc-username': 'transmission',rn 'rpc-whitelist': '127.0.0.1, 192.168.1.*',rn 'rpc-whitelist-enabled': true,rn 'scrape-paused-torrents-enabled': true,rn 'script-torrent-done-enabled': false,rn 'script-torrent-done-filename': '',rn 'seed-queue-enabled': false,rn 'seed-queue-size': 10,rn 'speed-limit-down': 100,rn 'speed-limit-down-enabled': false,rn 'speed-limit-up': 100,rn 'speed-limit-up-enabled': false,rn 'start-added-torrents': true,rn 'trash-original-torrent-files': false,rn 'umask': 2,rn 'upload-limit': 100,rn 'upload-limit-enabled': 0,rn 'upload-slots-per-torrent': 14,rn 'utp-enabled': truern}rn
Setting up YouTube downloads
sudo apt updaternsudo apt install -y python3 python3-pip ffmpegrnrnpip install -U yt-dlprnpip install ytdl-subrnrnmkdir -p /molecule/Media/YouTubernrnconfiguration:rn working_directory: /home/atom/.cache/ytdl-subrnrnyt-dlp rn --download-archive /home/atom/.config/ytdl-archive.txt rn --no-overwrites rn -o '/molecule/Media/YouTube/%(uploader)s/%(upload_date)s - %(title)s.%(ext)s' rn -f 'best[height<=720]' rn https://www.youtube.com/@BlokandDino