TL;DR

Repurposed an old HP laptop into a home NAS running Ubuntu Server + Docker for ~₹8K. Handles photo backup (Immich), file sharing (Samba),
and remote access (Tailscale).

Specs & Parts

Bought:

# Type Part Cost Qty Net Cost
1 Storage WD Green 480 GB SSD 2899 1 2899
2 Storage WD Green 240 GB SSD 1751.25 1 1751.25
3 Connector WAVLINK USB 3.0 to SATA 2.5" External Hard Drive Enclosure with UASP Protocol 754 1 754
4 Hardware Justec 270pcs M2 Male Female Brass Spacer Standoff Screw Nut Assortment Kit" 499 1 499
5 Connector 22Pin (7+15) Female Jack Connector SATA Serial ATA Data Power Combo Extension Cables Wire Cords 164.5 2 329
6 Connector Optical Bay 2nd Hard Drive Caddy, Caddy 9.5mm for Laptop 189 1 189
7 RAM Hi-tech Hynix 8GB DDR3L Laptop RAM 1600 Mhz PC3L-12800S 1.35 Volt 204 Pin SODIMM 750.775 2 1501.55
8 Storage SanDisk Ultra Fit 3.1 64GB USB Flash Drive 864 1 864

Reused / already had:

# Type Part
1 Motherboard HP 15-r041tx Motherboard
2 CPU 4th Gen Intel Core i3 4005U 1.7 GHz Cores Dual Core, 4 Threads 3 MB Cache
3 GPU 2 GB, Nvidia Geforce 820m (2 Gb Ddr3 Dedicated) Graphics
4 Storage Seagate Mobile SDC001 1TB HDD

Total spent: ₹8786.8

Architecture

POWER ↓ MOTHERBOARD + CPU + RAM + GPU (Integrated) │ ├── SATA CONTROLLER → SATA Port 1 → SSD 250GB (primary) │ ├── CD Bay → CD to SATA Adapter → SSD 480GB (Secondary) │ └── USB CONTROLLER ├── USB 2.0 → SanDisk Ultra Fit 64GB [Ubuntu Server (OS Only)] ├── USB 2.0 (Unused / available) └── USB 3.0 → SATA to USB Adapter → 2.5" HDD 1TB 

Storage Layout

Drive Size Purpose Notes
sda (64 GB USB) OS only Ubuntu Server Plenty of space for OS, updates, logs (if kept on tmpfs or minimal), very safe for writes.
sdb (240 GB SSD) Data + Docker volumes Fast storage for Docker containers, apps, and frequently accessed data SSD ensures fast container performance; avoid putting heavy media here to reduce wear.
sdc (500 GB SSD) Data + Docker volumes Additional fast storage for apps, media caches, or working datasets Same as sdb; great for splitting Docker workloads or high-speed media access.
sdd (1 TB External HDD via USB) Media + backups Bulk storage for movies, photos, and periodic backups Slower, but perfect for large, sequential file storage; reduces wear on SSDs.

Network Layout

[ Internet ] ↓ [ Router / Modem ] (LAN / DHCP) ↓ [ NAS Server (Ubuntu Server) ] │ ├── SSH (22) → Remote Management │ ├── Web Services │ ├─ Immich (2283) │ ├─ Webmin (10000) │ └─ Dockge (5001) │ ├── Security Layer │ ├─ UFW (Firewall) │ └─ Fail2Ban (Intrusion Protection) │ ├── Backup Services │ └─ Restic (Scheduled Backups) │ ├── Local Tools │ ├─ htop (Process Monitor) │ └─ neofetch (System Info) │ ├── Remote Access │ └─ Tailscale (Secure VPN) │ ├── File Services │ └─ Samba (445) │ └── Monitoring └─ Netdata (19999) 

Software Stack (Optimized)

1. Ubuntu Server OS 2. Dockge (Docker control) 3. Immich (Photos) 4. Samba (File sharing) 5. Webmin (Admin UI) 6. Netdata (Monitoring) 7. Restic (Backups) 8. UFW + Fail2Ban (Security) 9. htop (Process monitor) 10. neofetch (Info display) 11. Tailscale (Remote access) 12. Avahi (hostname.local) 

The Build

1. Teardown

Popped the back panel and battery off the laptop and pulled the motherboard free from the chassis to see exactly what it had to offer. Booted a Ubuntu live USB briefly just to confirm what the board could actually see:

lsblk -o NAME,SIZE,TYPE,MOUNTPOINT lscpu | grep "Model name" dmesg | grep -i sata 

What turned up: a single onboard SATA port (already claimed by the original 1TB Seagate HDD), a CD-ROM SATA header that a caddy adapter could repurpose into a second SATA connection, two DDR3L SO-DIMM slots, one USB 3.0 port, and a daughterboard riding in on a ribbon cable with two more USB 2.0 ports. The single SATA port was the real constraint — the caddy adapter got it to two, which meant one drive for the OS and exactly one for actual storage until the USB controller got pulled into the plan too.

2. OS Install

Flashed Ubuntu Server 24.04 LTS onto the 64GB USB drive — this is the drive the whole system now boots from, keeping the SSDs free of OS writes:

# From a separate machine sudo dd if=ubuntu-24.04-live-server-amd64.iso of=/dev/sdX bs=4M status=progress conv=fsync 

Booted the laptop off the USB drive, set the BIOS boot order accordingly, and ran the install headless — no GUI, OpenSSH enabled during the setup wizard so it never needed a monitor again after this point.

First-boot config: a static IP over netplan so the server doesn't wander to a new address after every reboot.

sudo nano /etc/netplan/00-installer-config.yaml 
network: version: 2 ethernets: eth0: dhcp4: no addresses: [192.168.1.50/24] gateway4: 192.168.1.1 nameservers: addresses: [1.1.1.1, 8.8.8.8] 
sudo netplan apply 

Then formatted and mounted the 240GB SSD, 480GB SSD, and the 1TB HDD (via its USB enclosure) into their assigned roles:

sudo mkfs.ext4 /dev/sda # 240GB SSD — Docker / fast storage sudo mkfs.ext4 /dev/sdb # 480GB SSD — app storage sudo mkfs.ext4 /dev/sdc # 1TB HDD — media / backups sudo mkdir -p /mnt/ssd240 /mnt/ssd480 /mnt/hdd1tb sudo mount /dev/sda /mnt/ssd240 sudo mount /dev/sdb /mnt/ssd480 sudo mount /dev/sdc /mnt/hdd1tb 

Added all three to /etc/fstab so the mounts survive a reboot.

3. Service Setup

Installed Docker and Compose first, since almost everything else runs as a container:

curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER sudo apt install docker-compose-plugin -y 

Dockge, for managing everything else through a web UI instead of raw CLI:

services: dockge: image: louislam/dockge:1 restart: unless-stopped ports: - 5001:5001 volumes: - /var/run/docker.sock:/var/run/docker.sock - ./data:/app/data - /mnt/ssd240/stacks:/opt/stacks 

Immich, pointed at the HDD for actual photo storage:

services: immich-server: image: ghcr.io/immich-app/immich-server:release volumes: - /mnt/hdd1tb/immich:/usr/src/app/upload ports: - 2283:2283 restart: unless-stopped 

Samba, for file sharing across the network:

sudo apt install samba -y sudo nano /etc/samba/smb.conf 
[nas-share] path = /mnt/hdd1tb/shared  browseable = yes  writable = yes  guest ok = no 
sudo smbpasswd -a yourusername sudo systemctl restart smbd 

Webmin, Netdata, htop, neofetch — the admin panel and the day-to-day visibility tools:

wget -qO- https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh | sh sudo apt install webmin -y wget -qO- https://get.netdata.cloud/kickstart.sh | sh sudo apt install htop neofetch -y 

UFW, Fail2Ban, Tailscale — locked the server down, then opened exactly one secure door back in:

sudo apt install ufw fail2ban -y sudo ufw allow OpenSSH sudo ufw allow 2283/tcp # Immich sudo ufw allow 5001/tcp # Dockge sudo ufw enable curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up 

Challenges & Fixes

Only one SATA port

Used an "Optical Bay 2nd Hard Drive Caddy, Caddy 9.5mm for Laptop" to increase one more SATA connection

Immediate case/cabinet for the NAS - minimal

For a Case or enclosure for the whole self made NAS I am using a plasic box which costed me INR 200 in local market to be used here. I removed the seperators withn the plastic box with hand tools like hacksaw and a file to finish it of.

Ubuntu wasn't booting at first

Checked the boot menu to keep the pendrive at top of the boot menu and remove secure boot due to a few driver conflicts. Also using the grub 2 boot menu and the UEFI option rathe than legacy boot.

Immich container stuck after a bad SSH script

A careless SSH script deleted Immich's installation folders mid-experiment.
The container still showed up in OMV's UI afterward and wouldn't remove
through the interface. Rather than patch around it, switched to a clean
headless Ubuntu Server install instead of continuing on OMV.

Results & Lessons Learned

Final cost: ~₹8,200 (₹8,000 in drives/adapters + ₹200 for the case) — against ₹20,000-25,000 for even an entry-level commercial NAS. Reusing the laptop's motherboard, CPU, and RAM instead of buying new is what made that gap possible.

What actually held up:

  • Separating storage by purpose (OS on USB, fast storage on SSD, bulk media on HDD) kept the system predictable — no single drive doing double duty and choking under load.
  • Running everything in Docker meant mistakes were cheap. When the Immich install got wiped by a bad SSH script, the fix was "redeploy the container," not "reinstall the OS."
  • Netdata turned troubleshooting from guessing into just... looking. The Immich indexing CPU spike is a good example — you can watch it happen instead of assuming it's happening.

What I'd do differently:

  • Test a backup before you need one. Losing the first Immich instance mid-experiment was low-stakes because there wasn't real data on it yet — it wouldn't have been if there was.
  • One SATA port on a repurposed motherboard is a hard ceiling, not a minor inconvenience. If I were doing this again, I'd check port count before falling in love with a specific piece of donor hardware.

What's Next

  1. Adding a 3D printed case.
  2. Extending the number of SATA ports for data storage to 6 from 2
  3. Ensuring proper cooling by adding external fans
  4. Using full potential for n8n and other tools test as well
  5. adding another server for other services from another laptop motherboard lying around
  6. Adding both to a 10" server rack system

Links

  • 📖 Full story (the "why" behind this build): Medium
  • 💼 More projects like this: Portfolio