Raspberry Pi: Private Network, Media Server and Home Automation (Hotel-friendly)

Set up a private local network from public Wi‑Fi using a travel router and a Raspberry Pi – includes Jellyfin media server, Samba shares, Home Assistant, and monitoring.
Raspberry Pi
Networking
DIY
Published

February 8, 2026

Because of reasons I am living in a residence that provides internet through an external provider. I tend to be particularly wary of any kind of service that provides internet services, so I decided to set up a local network that would let me access the internet, while keeping some privacy.

I also used this as an excuse to put my Raspberry Pi to work: a media center and centralized storage for my data. In this post I’ll go over the local network setup and the configuration steps I used to get the Pi working.

The result? Now I can back up my laptop to the HDDs attached to the Pi, and stream the videos stored on those same drives to any device on the local network.

If you’re interested in how I put everything together, read on!

WarningDisclaimer on AI usage

I used various coding agents to write most of the configuration in this post, but I also had to do a lot of debugging of those same configurations myself.

If I trusted everything that the agents did, most of what is reported below would not work.

This post is the results of combining the output of the agents, with a healthy amount of human debugging.

Requirements

While I’ll describe my own setup, you may need less depending on your goals. At the very least you should have:

  • A travel router.
  • A Raspberry Pi.
  • Another computer to connect to the Pi.
  • One (or more) external hard drive.
  • All the relevant cables and chargers.

My setup

  • A GL-SFT1200 travel router (chosen because it was cheap)
  • A Raspberry Pi 5
  • A MacBook Air as my laptop
  • Two 3.5” external HDDs (one has two partitions)
  • An official 5V/5A charger for the Raspberry Pi – phone chargers often can’t provide enough power
  • An ethernet cable to connect the Pi to the router
  • Additional devices (phones, etc.) will connect to Wi‑Fi once it’s set up

Building a local network from inside a hotel network

Note that this section can be skipped if you’re already on a private network.

The idea here is to use a travel router’s repeater feature to connect to the public Wi‑Fi, create a private Wi‑Fi network, and let other devices connect “from behind a screen.”

I followed the manufacturer’s instructions for the router. I ran into a few snags due to quirks from my provider, but eventually got full internet access on the router.

Once that was done, I was able to connect to the new private network from my various devices.

An advantage is that I bypass the limit on the number of devices on my account. The public network sees only the router, while my multiple devices get full access behind it.

I can’t go into detail because the exact steps depend on the hotel’s setup, but it wasn’t complicated – you should manage fine.

Change your passwords!

The router had a default admin password – change it. Also change the Wi‑Fi password; don’t give someone access because you didn’t bother updating defaults.

Setting up the Raspberry Pi

This part was the trickiest and involved a lot of querying LLMs for configuration snippets. I used outputs from ChatGPT and Mistral’s LeChat, but I still had to tinker and debug things myself.

Step 0: Preparing the Pi

Before doing anything else, I installed Raspberry Pi OS from the official image. I wanted a general purpose Pi, so I avoided specialized images.

The usual recommendation is to set up the Pi with a monitor, keyboard, and mouse. I did that – years ago I had to sniff a network to find a Pi’s IP so I could SSH in, and it wasn’t fun.

Besides the OS setup, I enabled the SSH server (it’s disabled by default). See the official docs: https://www.raspberrypi.com/documentation/computers/remote-access.html#ssh

Since I’ll mostly access the Pi from my Mac, I added the Pi’s IP to /etc/hosts, for example:

raspberrypi 1.1.1.1

where 1.1.1.1 is the Pi’s address. This lets me just ssh raspberrypi instead of the full IP – very convenient.


Step 1: Installing Docker compose

Following some AI-provided advice, I used Docker containers for the services, so I installed Docker Compose to manage them.

I followed the official instructions and added my user to the docker group:

sudo usermod -aG docker $USER

Finally, I logged out and back in to apply the changes.

I also created a folder for my containers:

mkdir ~/containers
cd ~/containers

Step 2: Preparing the HDDs

Normally an external drive gets a device like /dev/sda, /dev/sdb, etc. I wanted stable mount points so services (Samba, Jellyfin) always find the data.

One disk had an exFAT partition and an NTFS partition, so I created separate mount points for each partition.

Why two partitions? I have both a Mac and a Windows laptop. macOS can’t write to NTFS without extra software, so I made an exFAT partition for files I want to share easily between machines.

In any case, I created three mounting points:

sudo mkdir -p /mnt/storage   # NTFS partition
sudo mkdir -p /mnt/storage2  # exFAT partition
sudo mkdir -p /mnt/storage3  # second disk

Then, I needed to find the UUID of each partition:

sudo blkid

I then modified /etc/fstab with entries like:

UUID="xxxxxxxxx"  /mnt/storage  ntfs  defaults,auto,users,rw,uid=1000,gid=1000,nofail 0 0
UUID="xxxxxxxxx"  /mnt/storage2 exfat defaults,auto,users,rw,uid=1000,gid=1000,nofail 0 0
UUID="xxxxxxxxx"  /mnt/storage3 ntfs  defaults,auto,users,rw,uid=1000,gid=1000,nofail 0 0

Explanation of the options:

- `defaults`: Uses default mount options (rw, suid, dev, exec, auto, nouser, async).
- `auto`: Allows the partition to be mounted automatically at boot.
- `users`: Allows any user (not just root) to mount/unmount the partition.
- `rw`: Mounts the filesystem as read-write.
- `uid=1000,gid=1000`: Sets the owner and group of all files to the user/group with ID 1000 (my user account).
- `nofail`: Prevents boot failures if the partition is unavailable (e.g., external drive not connected).

0 0: Disables filesystem checks (fsck) and backup by dump.

Tip

The partitions are exFAT and NTFS. Make sure you have support for them – on modern Debian/Raspbian you can use exfat-fuse or exfatprogs for exFAT and ntfs-3g for NTFS.

For example:

sudo apt install exfat-fuse ntfs-3g

Step 3: Setting up Jellyfin

I use Jellyfin as a media server. It’s open source and lets you stream media from the local network – perfect for this setup.

The set up was quite simple. First, I created the directory for the container:

cd ~/containers
mkdir jellyfin
cd jellyfin

Then, I wrote this docker-compose.yml file:

services:
  jellyfin:
    image: jellyfin/jellyfin:latest
    container_name: jellyfin
    ports:
      - "8096:8096"
    volumes:
      - /mnt/storage/media:/media
      - /mnt/storage2/media:/media2
      - ./config:/config
      - ./cache:/cache
    restart: unless-stopped

I added both storage and storage2 for the sake of the example: the point here is to provide Jellyfin with the locations of the media folders by binding the mount positions to locations inside the container. Adapt the paths to the locations and partition names that you are working with.

Then, I started the Jellyfin container in detached mode (-d):

docker compose up -d

Jellyfin is now available at raspberrypi:8096 (where raspberrypi is the Pi’s hostname or IP as set in /etc/hosts).

Tip

In order to access the Raspberry Pi from both Firefox and Vivaldi (the two web browsers I use) on my Mac I had to change the privacy settings for both so that they’d be allowed to find devices on the local network. This is in System Settings -> Privacy & Security -> Local Network.

A big advantage of using Jellyfin is that now I can access my media files from any device that is connected to the local network, either by using the browser or by using one of the mobile apps for Jellyfin.


Step 4: Setting up Samba

Setting up Samba was a bigger headache. I could access the Pi’s data from my Android phone and my Mac, but not from my Windows laptop – annoying, and I need to revisit it later.

I also had trouble with authentication and permissions; part of the issue was using exFAT, which doesn’t support symlinks (that broke some of my plans).

Below is the docker-compose.yml I settled on after the permission shenanigans.

services:
  samba:
    image: dperson/samba
    container_name: samba
    restart: unless-stopped
    ports:
      - "139:139"
      - "445:445"
    volumes:
      - /mnt/storage:/shared
      - /mnt/storage2:/shared-2
      - /mnt/storage3:/shared-3
    environment:
      - USERID=1000
      - GROUPID=1000
      - USERNAME=${SAMBA_USERNAME}  
      - PASSWORD=${SAMBA_PASSWORD}
      - PERMISSIONS=0755 
    command: >
      -u "${SAMBA_USERNAME};${SAMBA_PASSWORD}"
      -s "shared;/shared;yes;yes;no;all;none;${SAMBA_USERNAME};0775;0664"
      -s "shared-2;/shared-2;yes;yes;no;all;none;${SAMBA_USERNAME};0775;0664"
      -s "shared-3;/shared-3;yes;yes;no;all;none;${SAMBA_USERNAME};0775;0664"

In the end, I decided to block any access to the drives behind authentication, with the SAMBA_USERNAME and SAMBA_PASSWORD variables containing the username and password I’d need to use in order to connect from my other devices.

Note: SAMBA_USERNAME and SAMBA_PASSWORD can be provided via a .env file next to the docker-compose.yml:

SAMBA_PASSWORD=mypassword
SAMBA_USERNAME=myusername

Explanation of the docker-compose command

command: >
  -u "${SAMBA_USERNAME};${SAMBA_PASSWORD}"
  -s "shared;/shared;yes;yes;no;all;none;${SAMBA_USERNAME};0775;0664"
  -s "shared-2;/shared-2;yes;yes;no;all;none;${SAMBA_USERNAME};0775;0664"
  -s "shared-3;/shared-3;yes;yes;no;all;none;${SAMBA_USERNAME};0775;0664"

-u flag (User definition)

-u "${SAMBA_USERNAME};${SAMBA_PASSWORD}"

Creates a Samba user with the specified username and password.

-s flag (Share definition) Each -s parameter defines a network share. The syntax is:

-s "name;path;browseable;readonly;guest;users;admins;writelist;create_mask;directory_mask"

In this example:

-s "shared;/shared;yes;yes;no;all;none;${SAMBA_USERNAME};0775;0664"

Where:

  1. shared - Share name
    • What users see on the network (e.g., \\raspberry-pi\shared)
  2. /shared - Path inside the container
    • The actual directory being shared (maps to /mnt/storage here)
  3. yes - Browseable
    • yes = Share appears in network browser listings
    • no = Share is hidden (but still accessible if you know the name)
  4. yes - Read-only
    • Set the drive to be read-only. The authenticated user can still write.
  5. no - Guest access
    • no = Requires authentication (username/password)
    • yes = Anyone can access without credentials
  6. all - Valid users
    • all = All authenticated users can access
    • Or specify usernames: user1,user2
  7. none - Admin users
    • none = No admin privileges
    • Or specify usernames who get full control
  8. ${SAMBA_USERNAME} - Write list
    • Users allowed to write (important when read-only=yes is overridden)
    • In this case, my Samba user gets write permissions
  9. 0775 - Directory mask (create mask for directories)
    • 0775 = Owner: rwx, Group: rwx, Others: r-x
    • New directories created with these permissions
  10. 0664 - File mask (create mask for files)
    • 0664 = Owner: rw-, Group: rw-, Others: r–
    • New files created with these permissions

These masks ensure that:

  • I (owner) can read/write/delete
  • My group members can read/write
  • Others can only read
  • Directories are executable (required to enter them)

Step 5: Setting up Home Assistant

Home Assistant is an open-source platform for home automation. It lets you connect IoT devices and monitor metrics via sensors.

I’ve been looking into ways to track the temperature and humidity of my house for a long time, and in one earlier attempt I tried to set up Home Assistant with a standalone sensor. It was very complicated, did not work well, and I gave up after a while.

For this set up I decided to make my life a bit easier by purchasing a connected temperature/humidity sensor and a Zigbee antenna to connect it with.

Still, I first had to boot the Home Assistant software, and as before I used a Docker container with this docker-compose.yml file:

services:
  homeassistant:
    container_name: homeassistant
    image: ghcr.io/home-assistant/home-assistant:stable
    volumes:
      - ./config:/config
    environment:
      - TZ=Europe/Paris
    network_mode: host
    restart: unless-stopped
    devices:
      - "/dev/ttyUSB0:/dev/ttyUSB0"

Everything is pretty much default, except for the device passthrough below:

devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"

These lines are needed to let the Home Assistant container communicate with the antenna, which is /dev/ttyUSB0. Depending on the device, the serial code may be different: you should be able to find it with the command

ls /dev/tty*

At this point, all I did was following the instructions shown by Home Assistant.

The only thing I need to mention is that I had some issues connecting the sensor to the antenna, and the solution for that particular problem was turning it off and back on by taking out the battery. Once it rebooted, I was able to connect it just fine.

Finally, I was able to access the Home Assistant dashboard by connecting to http://raspberrypi:8123.


Step 6: Monitoring with Cockpit

The final step (for this post, at any rate) consisted in finding a way to monitor the Raspberry from the Mac, to check that it was not melting itself down, and in general keep an eye on the setup.

To do so, I installed cockpit, a monitoring software that monitors the resource usage of the board, as well as its temperature. For this, no container: apt was sufficient.

sudo apt install cockpit
sudo systemctl enable --now cockpit.socket

After this, cockpit became accessible at the address http://raspberrypi:9090.

Wrapping up

In this very long post I covered how I set up a full private network, a local file sharing service with samba, a media center with Jellyfin, a IoT dashboard with Home Assistant and a monitoring service with cockpit.

That was a long process! And I’m not done with it yet either. There are a few more additions I’d like to make, like Photoprism and pi.hole, but I’m not sure yet when I’ll get around doing that.

I hope this very long write up was useful. See you in the next posts!