Back to Home

Full Setup Guide

From unboxing to your first upload — everything you need, step by step. No experience required.

~30 minutes
Beginner Friendly
9 Steps
1 2 3 4 5 6 7 8 9
1

Assemble the Hardware

~5 minutes

First, let's make sure you have everything. Check off each item as you go:

Once you have everything:

  1. Attach the NVMe SSD to the NVMe HAT/Base board — it clicks into the M.2 slot at an angle, then press down and screw it in.
  2. Connect the HAT to the Pi 5 — plug in the flat ribbon cable to the PCIe connector on the underside of the Pi.
  3. Insert the MicroSD card into the Pi's card slot (we'll flash it in the next step).
  4. Don't power it on yet — we need to flash the OS first.
Tip: If you bought a case, assemble it now. The NVMe drive can get warm during heavy use, so a case with ventilation helps with longevity.
2

Flash the Operating System

~10 minutes

We need to install Raspberry Pi OS on the MicroSD card. This is what powers your Pi.

  1. Download and install Raspberry Pi Imager on your computer (Mac, Windows, or Linux).
  2. Open the Imager and configure these settings:
Device Raspberry Pi 5
Operating System Raspberry Pi OS Lite (64-bit)
Storage Your MicroSD card
Important: Choose Raspberry Pi OS Lite (64-bit) — find it under "Raspberry Pi OS (other)". The Lite version has no desktop environment, which is exactly what we want for a headless server.
  1. Before writing, click the gear icon (⚙️) or "Edit Settings" and configure:
Hostname ughstorage
Enable SSH Yes — Use password authentication
Username pi
Password Choose something strong — you'll need this
WiFi Your home WiFi name & password
  1. Click Write and wait for it to finish (~5 min).
  2. Put the MicroSD card back into the Pi and plug in the power supply.
  3. Wait ~2 minutes for the Pi to boot up for the first time.
Tip: The WiFi you enter here is just for the initial setup. The UghStorage app will properly configure WiFi later via Bluetooth.
3

SSH into the Pi

~2 minutes

SSH (Secure Shell) lets you control the Pi from your computer's terminal. Think of it as a remote control for the command line.

On Mac: Open Terminal (search Spotlight for "Terminal").
On Windows: Open PowerShell (search Start for "PowerShell").

Type this command and press Enter:

Terminal
$ ssh pi@ughstorage.local

Enter the password you set in Step 2 when prompted. You should see a welcome message and a command prompt like pi@ughstorage:~ $

Can't connect? Try these alternatives:
  • ssh pi@raspberrypi.local — if you didn't change the hostname
  • Check your router's admin page for the Pi's IP address, then use ssh pi@<IP_ADDRESS>
  • Make sure the Pi has been powered on for at least 2 minutes
  • Ensure your computer is on the same WiFi network as the Pi
4

Partition & Format the NVMe SSD

~5 minutes

Your NVMe SSD is a blank drive right now. We need to partition it (tell the system to use the whole drive as one big space) and format it (prepare it to store files). This is like formatting a USB drive — but bigger.

Warning: This will erase everything on the SSD. Since it's a brand new drive, this is fine. But if you're reusing a drive, back up any data first.

4a. Verify the Pi sees your SSD

Terminal
$ lsblk
Expected Output
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
mmcblk0     179:0    0  29.7G  0 disk
├─mmcblk0p1 179:1    0   512M  0 part /boot/firmware
└─mmcblk0p2 179:2    0  29.2G  0 part /
nvme0n1     259:0    0 931.5G  0 disk

You should see nvme0n1 in the list — that's your SSD. The size should match what you bought (e.g., ~931GB for a 1TB drive).

4b. Create a partition

Terminal
$ sudo fdisk /dev/nvme0n1

This opens an interactive partition tool. Type these keys one at a time, pressing Enter after each:

nCreate new partition
EnterPrimary partition (default)
EnterPartition number 1 (default)
EnterFirst sector (default)
EnterLast sector — use entire drive (default)
wWrite changes and exit

4c. Format the partition

Terminal
$ sudo mkfs.ext4 /dev/nvme0n1p1

This formats the partition with the ext4 filesystem — the standard Linux format. It's reliable, fast, and handles large files perfectly. This may take 10–30 seconds depending on drive size.

What's the difference? nvme0n1 is the whole drive. nvme0n1p1 is the partition we just created on it (partition 1). From now on, we'll always use nvme0n1p1.
5

Mount the SSD

~2 minutes

Mounting means connecting the SSD to a folder so the system can read and write files to it. Think of it like plugging in an external hard drive — except we tell Linux exactly where to "plug it in."

5a. Create the mount point and mount

Terminal
$ sudo mkdir -p /mnt/nvme
$ sudo mount /dev/nvme0n1p1 /mnt/nvme
$ sudo chown pi:pi /mnt/nvme

Here's what each line does:

  • mkdir -p /mnt/nvme — Creates the folder /mnt/nvme where the SSD will be accessible
  • mount — Connects the formatted partition to that folder
  • chown pi:pi — Gives your user account permission to read/write files on the SSD

5b. Make it permanent (auto-mount on boot)

Without this step, the SSD would disconnect every time the Pi restarts. This command adds it to the system's startup list:

Terminal
$ echo '/dev/nvme0n1p1 /mnt/nvme ext4 defaults,noatime 0 2' | sudo tee -a /etc/fstab

5c. Verify everything worked

Terminal
$ df -h /mnt/nvme
Expected Output
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p1  916G   28K  870G   1% /mnt/nvme

You should see your drive's full capacity. The "Avail" column is your usable storage space.

6

Install UghStorage

~5 minutes

Now for the good part — installing the UghStorage server software. This is a single script that handles everything automatically.

Terminal
$ cd /home/pi
$ git clone https://github.com/hneogy/ughstorage.git
$ cd ughstorage/server
$ chmod +x setup.sh ble_setup_service.sh
$ ./setup.sh

The setup script runs 6 steps automatically. Here's what it's doing behind the scenes:

[1/6]
System dependencies

Installs Python 3, pip, and FFmpeg (for generating video thumbnails)

[2/6]
Cloudflared

Downloads the Cloudflare Tunnel binary — this is what makes your Pi accessible from anywhere without opening ports

[3/6]
Python environment

Creates an isolated Python environment and installs all server dependencies

[4/6]
Storage directories

Creates /mnt/nvme/storage and /mnt/nvme/thumbnails on your SSD

[5/6]
Environment config

Generates the .env file with pre-configured cloud connection settings

[6/6]
Systemd service

Creates a background service so the server starts automatically whenever the Pi boots

Expected Output (summary)
============================================
  UghStorage Setup (v2 - Multi-Tenant)
============================================

[1/6] Installing system dependencies...
[2/6] Installing cloudflared...
  cloudflared installed: 2025.x.x
[3/6] Creating Python virtual environment...
  Installed Python packages.
[4/6] Creating storage directories...
  /mnt/nvme/storage
  /mnt/nvme/thumbnails
[5/6] Configuring environment...
  Environment saved to /home/pi/ughstorage/server/.env
[6/6] Creating systemd service...
  Service installed: ughstorage

============================================
  Setup complete!
============================================
7

Install Bluetooth Service

~2 minutes

This script sets up Bluetooth Low Energy (BLE) so the UghStorage iPhone app can find your Pi wirelessly and configure it — no cables or keyboard needed.

Terminal
$ sudo bash ble_setup_service.sh

Here's what this script configures:

BLE
Bluetooth packages

Installs BlueZ (the Linux Bluetooth stack), Pi-specific Bluetooth drivers, and the dbus-next Python library

WiFi
NetworkManager

Switches WiFi management from the basic dhcpcd to NetworkManager, which allows the app to scan and connect to WiFi networks remotely

SVC
Background service

Creates the ughstorage-ble systemd service that runs on boot and advertises the Pi as "UghStorage-Setup" over Bluetooth

Expected Output
[INFO]  ==========================================
[INFO]   UghStorage BLE Setup Installer
[INFO]  ==========================================
[INFO]  Updating package lists...
[INFO]  Installing Bluetooth and NetworkManager packages...
[INFO]  Installing Python dependencies...
[INFO]  Dependencies installed.
[INFO]  Configuring NetworkManager...
[INFO]  NetworkManager is active.
[INFO]  Configuring Bluetooth...
[INFO]  Bluetooth configured.
[INFO]  Config directory ready at /etc/ughstorage
[INFO]  Creating systemd service: ughstorage-ble...
[INFO]  Service created and started.
[INFO]  ==========================================
[INFO]   Installation complete!
[INFO]  ==========================================
Note: After this script runs, your SSH connection may momentarily drop because NetworkManager restarts the network. Just reconnect with ssh pi@ughstorage.local.
8

Start & Verify

~2 minutes

Let's start the server and make sure everything is running properly.

8a. Start the server

Terminal
$ sudo systemctl start ughstorage

8b. Check the status

Terminal
$ sudo systemctl status ughstorage
Expected Output
● ughstorage.service - UghStorage personal cloud storage
     Loaded: loaded (/etc/systemd/system/ughstorage.service; enabled)
     Active: active (running) since ...
   Main PID: 1234 (python3)
      Tasks: 3 (limit: 4915)
        CPU: 1.234s
     CGroup: /system.slice/ughstorage.service
             └─1234 /home/pi/ughstorage/server/venv/bin/python3 -m uvicorn main:app ...

Look for "active (running)" — that means the server is up and healthy.

8c. Quick health check

Terminal
$ curl http://localhost:8000/health
Expected Output
{"status": "ok", "version": "1.0.0", ...}
Server is running! Your UghStorage server is now live on the Pi. Both the storage server and BLE service will automatically start whenever the Pi boots — even after a power outage.
9

Download the App & Connect

~3 minutes

The hard part is done! Now grab your iPhone and let the app do the rest.

  1. Download UghStorage from the App Store Coming Soon
  2. Create an account in the app
  3. Tap "Add Device" to start the setup wizard

The app will walk you through three automatic steps:

Find Your Pi

The app scans for Bluetooth devices and discovers your Pi as "UghStorage-Setup". Tap to connect.

Connect to WiFi

Select your home WiFi network and enter the password. The Pi connects automatically.

Register & Go Live

The app registers your Pi, provisions a secure Cloudflare Tunnel, and you're live at *.ughstorage.com.

You're done! Your personal cloud is live. Start uploading photos, videos, and documents — they go straight to your Pi's NVMe drive, accessible from anywhere in the world. No subscriptions, no data mining, just your files on your hardware.
?

Troubleshooting

Common issues & fixes

Make sure you're within ~10 feet of the Pi and Bluetooth is enabled on your iPhone (Settings → Bluetooth). On the Pi, check the BLE service status:

Terminal
$ sudo systemctl status ughstorage-ble
$ sudo systemctl restart ughstorage-ble

The NVMe HAT ribbon cable may not be fully seated. Power off the Pi, disconnect the cable, and reconnect it firmly on both ends. Also ensure the SSD is clicked into the M.2 slot and screwed down. Some NVMe HATs require a specific orientation — check the HAT's documentation.

Check both the tunnel and the server:

Terminal
$ sudo systemctl status cloudflared
$ sudo systemctl status ughstorage
$ curl http://localhost:8000/health
$ journalctl -u ughstorage -n 20

Double-check the WiFi password. Make sure the Pi is within range of your router. You can also check what networks the Pi can see:

Terminal
$ nmcli device wifi list

Yes! Your files are stored on the NVMe SSD and won't be lost during a power outage. When power returns, all three services (ughstorage, ughstorage-ble, and cloudflared) start automatically within ~60 seconds. No manual intervention needed.