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

