HarbourOS Docs

HarbourOS Documentation

Everything you need to set up and manage your Raspberry Pi 5 Plex Media Server appliance.

What is HarbourOS?

HarbourOS is a custom Raspberry Pi OS image that turns your Raspberry Pi 5 into a dedicated Plex Media Server appliance. It comes with:

  • Plex Media Server pre-installed and auto-updating
  • A web-based admin dashboard accessible at port 8080
  • NAS mount management for NFS and SMB shares
  • System monitoring (CPU, RAM, temperature, disk)
  • Network configuration tools
  • Episode Manager - find missing TV episodes across 185,000+ shows
  • Security hardening applied out of the box (CSRF, non-root service, rate limiting)
  • First-boot setup wizard for easy configuration

Quick Start

  1. Download the HarbourOS image from GitHub Releases
  2. Flash it to a microSD card using Raspberry Pi Imager
  3. Insert the card into your Raspberry Pi 5 and power on
  4. Open http://harbouros.local:8080 in your browser
  5. Complete the setup wizard
Tip

Already running Raspberry Pi OS? You can install HarbourOS remotely over SSH without re-flashing. See Remote Install.

Requirements

What you need to run HarbourOS.

Hardware

ComponentRequirement
BoardRaspberry Pi 5 (4 GB or 8 GB)
StorageMicroSD card, 16 GB+, Class 10 / A2
NetworkEthernet (recommended) or Wi-Fi
PowerOfficial Raspberry Pi 5 USB-C power supply (27W)

Network Storage

HarbourOS manages your media files from a network share. You'll need one of:

  • NFS share - from a NAS (Synology, QNAP, TrueNAS, etc.) or any Linux server
  • SMB/CIFS share - from a NAS, Windows PC, or macOS
Note

You can also use USB-attached storage (external hard drives), but NAS is recommended for reliability and flexibility.

Software

To flash the image, you'll need Raspberry Pi Imager installed on your computer (Windows, macOS, or Linux).

Installation

Install HarbourOS on a Raspberry Pi running Raspberry Pi OS — no re-flashing required.

One-line installer

SSH into your Pi and run:

curl -sL https://harbouros.eu/install.sh | sudo bash

That's it. The script downloads HarbourOS from GitHub and installs everything automatically. No git, make, or SSH keys needed on your computer — just a terminal on the Pi.

The script will:

  1. Install all required packages (Plex, NFS/SMB tools, fail2ban, etc.)
  2. Deploy the admin UI and configuration
  3. Set up systemd services and auto-updates
  4. Apply security hardening
  5. Start HarbourOS
Prerequisites
  • Raspberry Pi running Raspberry Pi OS (Bookworm or Trixie)
  • SSH enabled (set during Raspberry Pi Imager setup)
  • Internet connection on the Pi

Verifying the Installation

Once the script completes, the Pi will be running:

  1. Hostname set to harbouros
  2. Admin UI on port 8080
  3. Plex Media Server

Open http://harbouros.local:8080 in your browser. You should see the login page.

Important

The default password is harbouros. You will be required to change it during the first-boot setup wizard.

For the advanced from-source install method, see Remote Install.

First Boot Setup

The setup wizard guides you through initial configuration.

Step 1: Change Your Password

Log in with the default password harbouros. The setup wizard will require you to set a new, secure password before proceeding. This password protects the admin dashboard.

Step 2: Connect Your NAS

The wizard scans your network for available NFS and SMB shares. Select your NAS device and configure the mount. You can also skip this step and configure it later.

Step 3: Verify Plex

The wizard verifies that Plex Media Server is running. You'll be directed to claim your server at http://harbouros.local:32400/web using your Plex account.

Tip

After completing the wizard, you can access all settings from the dashboard at any time.

Dashboard

Your command center for managing HarbourOS.

Accessing the Dashboard

Open http://harbouros.local:8080 in any browser on your network. Log in with your password.

Overview

The dashboard uses a desktop-style UI with these components:

  • Top bar - shows the current time, logout button
  • App icons - Plex, NAS Storage, Network, System, Plex Settings
  • Widgets - System stats (CPU, RAM, temperature), storage usage, Plex library info, service status
  • Dock - quick access to version info and GitHub

App Windows

Click any app icon to open its management window. Each window provides focused tools for that function - Plex controls, NAS management, network settings, or system configuration.

Plex Management

Control your Plex Media Server from the dashboard.

Service Controls

From the Plex app window, you can:

  • Start / Stop / Restart the Plex Media Server service
  • View real-time service status
  • Access Plex server logs for troubleshooting

Auto Updates

HarbourOS checks for Plex updates automatically and installs them. You can also trigger a manual update check from the System app.

Plex Settings

Click the "Plex Settings" icon to open the native Plex Web UI at port 32400. From there you can manage libraries, users, transcoding settings, and all other Plex configuration.

Libraries

The dashboard widget shows your Plex libraries with item counts. To add or modify libraries, use the Plex Web UI.

NAS Storage

Connect network shares for your media files.

Adding a NAS Mount

  1. Open the NAS Storage app from the dashboard
  2. Click "Add Mount"
  3. Select a discovered device from the network scan, or enter details manually
  4. Choose NFS or SMB protocol
  5. For SMB: enter username and password if required
  6. Click "Mount" to connect

Mount Points

All NAS mounts are created under /media/nas/. Systemd mount and automount units are generated automatically for persistent mounts that survive reboots.

Troubleshooting

  • Mount fails - check that the NAS IP is reachable and the share path is correct
  • Permission denied - for SMB, verify credentials. For NFS, check the NAS export permissions
  • NAS not discovered - ensure both devices are on the same subnet and the NAS advertises via mDNS/Avahi

Network Configuration

Configure hostname and IP settings.

Hostname

Change the system hostname from the Network app. The default is harbouros. After changing, the Pi will be reachable at <hostname>.local via mDNS.

IP Configuration

Choose between DHCP (automatic) or a static IP address. For a media server, a static IP is recommended so Plex clients always find it at the same address.

Warning

Changing the IP address will disconnect your current browser session. Reconnect using the new IP.

System & Updates

Monitor system health and manage updates.

System Monitoring

The dashboard shows real-time metrics:

  • CPU usage - current load percentage
  • Memory - used / total RAM
  • Temperature - CPU temperature in °C
  • Disk usage - space used on the SD card and mounted shares
  • Service status - Plex, fail2ban, and other monitored services

Updates

HarbourOS has two independent auto-update systems, both visible in the System → Updates tab.

Plex auto-update

A systemd timer checks plex.tv for a new ARM64 release once a day. When a newer version is available it downloads the .deb, installs it with dpkg, and restarts Plex. The update appears in the Updates tab.

HarbourOS self-update

A systemd timer runs every 6 hours (with a random 15-minute jitter). It:

  1. Fetches the latest commit from github.com/tnik71/HarbourOS (main branch)
  2. If a new version is available, stages the files and runs the deploy script
  3. Installs any new Python dependencies if requirements.txt changed
  4. Reloads systemd units and restarts the HarbourOS service
  5. Writes a changelog (last 20 commits) to the update status file
Automatic rollback

If the update fails at any point, HarbourOS automatically resets to the previous version and restarts. The error is recorded in the update log.

Changelog & history

After each successful update, the System → Updates tab shows the new version, the previous version, and a list of commits that were included in the update.

Manual trigger

Click Check for Updates in the System tab to run an immediate check, or click Install Update if one is already available. You can also run it from SSH:

sudo /usr/local/bin/harbouros-self-update.sh

Logs

View system and service logs directly from the dashboard. Select the service (Plex, HarbourOS, fail2ban, etc.) from the dropdown.

Episode Manager

Find missing TV episodes in your Plex library.

Overview

The Episode Manager compares your Plex TV show library against a central database of 185,000+ shows and 5.7 million episodes. It shows you exactly which episodes you have, which are missing, and which haven't aired yet.

Getting Started

  1. Open the Episode Manager from the dashboard
  2. Click Update Database to download the latest episode database from harbouros.eu (about 23 MB)
  3. Click Scan Plex Library (or wait for auto-scan) to match your Plex shows against the database
Tip

After the first scan, results are saved to disk and persist across server restarts. The Episode Manager will show your last scan results immediately when you open it.

Show Grid

Shows are displayed in a Sonarr-inspired grid with color-coded cards:

  • Green border - 100% complete (all aired episodes collected)
  • Blue border - 75-99% complete
  • Orange border - 50-74% complete
  • Red border - Below 50% complete
  • Gray border - Show not found in the database (unmatched)

Each card shows the show name, status badge (Returning/Ended/Canceled), a progress bar, episode counts, and completion percentage.

Search and Filter

Use the search bar to find shows by name. Filter by category (All, Incomplete, Complete, Unmatched) and sort by completion, name, or most missing episodes.

Episode Detail View

Click any show card to see a detailed per-season breakdown. Each season shows:

  • How many episodes you have vs. total aired
  • A list of specific missing episodes with names and air dates
  • Seasons that haven't aired yet are marked separately

Summary Line

A summary bar above the grid shows totals: number of shows scanned, matched, unmatched, complete, and incomplete.

Auto-Scan

When you open the Episode Manager with a downloaded database but no existing scan results, a scan starts automatically. During scanning, a spinner is displayed and the scan button is disabled to prevent double-clicks.

Remote Install

Install HarbourOS on a running Raspberry Pi - no SD card re-flashing required.

One-line install (recommended)

SSH into your Pi and run:

curl -sL https://harbouros.eu/install.sh | sudo bash

That's it. The script downloads HarbourOS from GitHub and installs everything automatically. No git, make, or SSH keys needed on your computer - just a terminal window on the Pi.

The script will:

  1. Install all required packages (Plex, NFS tools, etc.)
  2. Deploy the admin UI and configuration
  3. Set up systemd services and auto-updates
  4. Apply security hardening
  5. Start HarbourOS

Prerequisites

  • Raspberry Pi running Raspberry Pi OS (Bookworm or Trixie)
  • SSH enabled (set during Raspberry Pi Imager setup)
  • Internet connection on the Pi

From source (advanced)

If you have the repo cloned on your computer, you can also install remotely over SSH:

git clone https://github.com/tnik71/HarbourOS.git
cd HarbourOS

# Install to a Pi at a specific IP
make install-remote PI=192.168.1.50

# Or use mDNS hostname
make install-remote PI=raspberrypi.local
Note

The from-source method supports both SSH key and password authentication. If SSH keys are not set up, it will prompt for the Pi's password.

Docker Plex Migration

Migrate from Docker Plex to native Plex while preserving all your data.

What Gets Migrated

  • All Plex libraries and media paths
  • Watch history and progress
  • Server metadata and configuration
  • User accounts and sharing settings

How to Migrate

# From your computer (not the Pi)
make migrate-plex PI=192.168.1.50

The migration tool will:

  1. Auto-detect your Docker Plex container
  2. Back up the Plex data directory
  3. Install native Plex Media Server (if not already installed)
  4. Restore all data to the native installation
  5. Verify the migration
Important

Run make migrate-plex PI=... -- --dry-run first to preview the migration without making changes.

Security

HarbourOS comes security-hardened out of the box.

What's Hardened

FeatureDetails
Password enforcementDefault password must be changed during first-boot setup
fail2banSSH brute-force protection: 5 attempts → 1 hour ban
SSH hardeningRoot login disabled, X11 forwarding disabled
Sysctl tuningNetwork stack hardened against common attacks
Plex log rotationPrevents disk fill from runaway Plex logs
Session authAdmin UI uses bcrypt-hashed passwords with secure sessions
CSRF protectionOrigin/Referer header validation on all state-changing requests
Non-root serviceAdmin UI runs as dedicated harbouros user with targeted sudoers
Rate limitingLogin attempts limited to 5 per minute per IP
Security headersX-Content-Type-Options, X-Frame-Options, Content-Security-Policy

Changing the Admin Password

From the dashboard, open System → change your password from the settings panel. Passwords are hashed with bcrypt and never stored in plain text.

SSH Access

SSH remains accessible for advanced users. Root login is disabled by default - use your regular user account and sudo.

Security Tab

The System modal in the dashboard includes a Security tab that shows your live security posture:

  • Password changed - whether the default password has been replaced
  • fail2ban status - active/inactive, plus current banned IP count
  • Root SSH login - whether PermitRootLogin no is set in sshd_config
  • Failed login attempts - count from the current server session

Security Update Policy

HarbourOS self-updates every 6 hours from GitHub. Security fixes are included in normal releases and applied automatically. The changelog is visible in the System → Updates tab after each update.

Architecture Overview

How HarbourOS is structured under the hood.

System Stack

HarbourOS is a thin layer on top of Raspberry Pi OS (Bookworm). It installs and manages the following components:

┌─────────────────────────────────────────────────────────┐
│                    Raspberry Pi 5                        │
│                                                         │
│  ┌──────────────────────────────────────────────────┐   │
│  │  HarbourOS Admin UI  (Flask + Gunicorn, port 8080)│   │
│  │  • Dashboard  • Plex tab  • NAS tab  • Network   │   │
│  │  • System tab  • Episode Manager  • Security tab  │   │
│  └────────────────┬─────────────────────────────────┘   │
│                   │ systemd + subprocess                 │
│  ┌────────────────┴────────────────────────────────┐    │
│  │  System Services                                │    │
│  │  • plexmediaserver  (port 32400)                │    │
│  │  • fail2ban                                     │    │
│  │  • avahi-daemon  (mDNS / .local discovery)      │    │
│  │  • systemd-networkd  (IP / hostname)            │    │
│  │  • harbouros-self-update.timer  (every 6h)      │    │
│  └────────────────┬────────────────────────────────┘    │
│                   │ NFS / SMB mounts                     │
│  ┌────────────────┴────────────────────────────────┐    │
│  │  Network Storage                                │    │
│  │  /media/nas/<name>  →  NAS / Synology / QNAP   │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘
                        │
              Plex clients (TV, phone, browser, Apple TV)

Admin UI

The admin UI is a Python Flask application served by Gunicorn. It runs as a dedicated harbouros system user (non-root) with targeted sudoers rules for the specific system calls it needs. Source is at /opt/harbouros/admin-ui/.

Self-Update

A systemd timer runs harbouros-self-update.sh every 6 hours. The script pulls from github.com/tnik71/HarbourOS, applies changes, and writes a status JSON file that the dashboard reads. The changelog from each update is captured and shown in the Updates tab.

Episode Database

Episode data is stored in MySQL on harbouros.eu. The Pi queries a REST API (https://harbouros.eu/db/api.php) to fetch only the shows present in your Plex library - rather than downloading the full 167 MB dataset. Results are cached locally.

Security Model

The admin UI uses Flask sessions with bcrypt password hashing, CSRF validation via Origin/Referer headers, rate limiting on login (5 attempts/minute/IP), and security headers. fail2ban protects SSH independently. See the Security section for full details.

Backup & Restore

Export your HarbourOS configuration and restore it on a fresh install.

What's included in a backup

  • Admin password hash
  • All NAS mount configurations (host, share, type, credentials)
  • Network settings (hostname, IP mode)
  • HarbourOS version at time of backup
Note

Backups do not include your Plex library data or media files - those live on your NAS and are not affected by a reinstall.

Creating a Backup

  1. Open the dashboard and click the System app
  2. Go to the Backup tab
  3. Click Export Backup - a .json file downloads to your browser

Restoring a Backup

  1. Complete the initial setup wizard on a fresh HarbourOS install
  2. Open System → Backup tab
  3. Click Restore Backup and select your saved .json file
  4. Review the configuration and confirm
  5. HarbourOS will apply all settings and remount NAS shares
Tip

Export a backup after you finish initial setup. Keep it somewhere safe - it means a full reinstall takes under 5 minutes to restore to your previous state.

Troubleshooting

Common issues and solutions.

Can't access the dashboard

  • Ensure your Pi is powered on and connected to the network
  • Try accessing by IP: http://<pi-ip>:8080
  • If harbouros.local doesn't resolve, your router may not support mDNS. Use the IP address instead

Plex not starting

  • Check the Plex logs from the dashboard
  • Via SSH: sudo systemctl status plexmediaserver
  • Check disk space: df -h

NAS mount failures

  • NFS: ensure nfs-common is installed and the NAS export allows access from the Pi's IP
  • SMB: ensure cifs-utils is installed and credentials are correct
  • Check connectivity: ping <nas-ip>

Self-update not working

  • Check internet connectivity: ping github.com
  • Check the self-update timer: sudo systemctl status harbouros-self-update.timer
  • Run manually: sudo /usr/local/bin/harbouros-self-update.sh

Getting Help

If you're stuck, open an issue on GitHub Issues.