Self-hosting at home with Ubuntu Server + Easypanel on Mac Mini (late 2014)
When I shared my notes on self-hosting Syncthing and File Browser on OpenBSD, mgx wrote that he uses Easypanel to quickly deploy containerized apps. I was curious, so I looked into spinning up a RackNerd KVM server with Ubuntu to try. Along the way, I figured that since I already have a Mac Mini lying around, I could install Ubuntu Server on it to try things out instead.
Setting up an Ubuntu server + Easypanel was surprisingly quick & simple (really, I couldn't believe how easy it was). I realized from this process that starting with a remote OpenBSD server was playing in hard mode. 🙃 (No regrets though. I appreciate OpenBSD's minimalism + proactive security.)
My general plan is to use this for self-hosting services for me & my people, with everything tucked away behind my router, available on local network only. Some things will require remote access, but I'll look into that later.
My devices
Mac Mini (late 2014)
- Processor: 2.6 GHz Dual-Core Intel Core i5
- Memory: 8 GB 1600 MHz DDR3
- Graphics: Intel Iris 1536 MB
- Storage: 1 TB SATA Disk
- OS: macOS Monterey, Version 12.6.5
SanDisk Ultra 64GB USB 3.0 flash drive
What I did
Install Ubuntu Server on Mac Mini (late 2014)
- Download Ubuntu Server (Ubuntu 24.04.2 LTS)
- Create a bootable USB stick on macOS
- Boot from install media
- Restart Mac, press
Option
key immediately after chime - Select
EFI Boot
- Restart Mac, press
One thing I'd do differently: connect my Mac Mini to the router via ethernet before starting the install.
I didn't change any of the defaults, but listed my selections here anyway.
- Preferred language
English
- Enter
- Keyboard layout + variant
English (US)
English (US)
- Select
Done
, Enter
- Choose installation
[x] Ubuntu Server
- Select
Done
, Enter
- Network configuration
- I do not see an IP address, as is typical in guides, and instead see:
disabled autoconfiguration failed
- I realize this is because my Mac Mini is not connected to my router, so I
Continue without network
, since I can circle back to this later
- I do not see an IP address, as is typical in guides, and instead see:
- Proxy configuration
- Left blank
- Select
Done
, Enter
- Ubuntu archive mirror configuration
- Select
Done
, Enter
- Select
- Storage configuration
[x] Use an entire disk
[x] Set up this disk as an LVM group
- Select
Done
, Enter - Select
Done
, Enter
- Confirm destructive action
- Select
Continue
- Select
- Profile configuration
- Filled the fields for name, server name, username, and password
- Select
Done
, Enter
- Upgrade to Ubuntu Pro
[x] Skip Ubuntu Pro setup for now
- Select
Continue
, Enter
- SSH configuration
- Since I don't have network access nor SSH keys registered with Launchpad or GitHub...
[x] Allow password authentication over SSH
- Select
Done
, Enter
- Installation complete!
- Select
Reboot Now
- Select
- Prompted to remove the USB stick, so I do, then Enter
- It's looking for the network again, so I unplug the Mac Mini, bring it downstairs, and connect it to the router via ethernet
- Turn on the Mac Mini and wait
- Everything is set up!
What am I doing
Why can't I see my new server on my router's list of connected devices? What's my Ubuntu server's IP address? How do I SSH in?
- Try to find IP address
ip a
- There is no IP address (not a surprise, since the autoconfiguration earlier failed)
ip link
- I see
state DOWN
- Look for something similar to
enp0s25
- I see
- I find Network interface down - how to turn it on again? and follow its steps
ip link show up
dhclient enp0s25
- See the error:
dhclient: command not found
(apparently dhclient is no longer maintained)
- See the error:
- Add IP addresses manually
sudo ip address add 192.168.x.x/24 dev enp0s25
- This is my local network/router IP, with a unique fourth number — I checked my router's list of connected devices and selected a number that wasn't being used
- Replace
enp0s25
with what was listed inip link
sudo ip route add default via 192.168.x.x
- This is my local network/router IP
- Confirm the updates went through
ip a
ip r
- I see the IP addresses I manually added (and understand that this is temporary)
- Test connection
ping -c 3 9.9.9.9
- 3 packets transmitted, 3 packets received, so it works
ping -c 3 archive.ubuntu.com
- See error:
Temporary failure in name resolution
- See error:
- Set up Quad9 for domain name resolution (also temporary)
sudo nano /etc/resolv.conf
- Replace current
nameserver
with:
nameserver 9.9.9.9
nameserver 149.112.112.112
ping -c 3 archive.ubuntu.com
- 3 packets transmitted, 3 packets received, so it works
- Install SSH
sudo apt update
sudo apt install openssh-server
y
sudo systemctl start ssh
sudo systemctl enable ssh
sudo systemctl status ssh
SSH into Mac Mini & update to key-based login
- Go to Windows computer, ensure Mullvad VPN has Local network sharing enabled
- PowerShell window 1: SSH in with password
$user@192.168.x.x
- PowerShell window 1: SSH in with password
- Set up key-based login from my Windows computer to the Ubuntu server
- Open new PowerShell window 2: Get my computer's public key
type $env:USERPROFILE\.ssh\id_ed25519.pub
- Copy the content
- PowerShell window 1: Add key to the server & update permissions
mkdir -p ~/.ssh
nano ~/.ssh/authorized_keys
- Paste in the copied content and save
cd
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
- PowerShell window 2: Log in with SSH key
ssh $user@192.168.x.x
- Should not be prompted for a password
- Close either window
- Open new PowerShell window 2: Get my computer's public key
- Disable password login & root login
sudo nano /etc/ssh/sshd_config
- Update the following lines and ensure they do not have a
#
in front:PermitRootLogin no
PasswordAuthentication no
- Save
cd
sudo systemctl restart ssh
Set up network configuration
sudo nano /etc/netplan/01-static.yaml
- Add the following, then save:
network:
version: 2
renderer: networkd
ethernets:
enp0s25:
dhcp4: no
addresses:
- 192.168.x.x/24
routes:
- to: default
via: 192.168.x.x
nameservers:
addresses: [9.9.9.9, 149.112.112.112]
sudo netplan apply
- See warnings about the .yaml file's permissions being too open
sudo chmod 600 /etc/netplan/01-static.yaml
ip a
- Should see:
inet 192.168.x.x/24 ... scope global enp0s25
- Confirm things work
ping -c 3 9.9.9.9
ping -c 3 archive.ubuntu.com
- Go to http://192.168.x.x
- Update my router's DHCP list to manually assign the IP address to my server (so that the router doesn't assign it to any other device)
Install security updates
When I SSH in, I'm greeted with:
108 updates can be applied immediately.
56 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable
So I'll update:
sudo apt update
sudo apt upgrade
y
sudo reboot
Set up firewall & other security
$user@192.168.x.x
- Install firewall
sudo apt update
sudo apt install ufw
- Block incoming traffic, but allow outgoing connections & SSH
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow openssh
- Turn on firewall
sudo ufw enable
- Command may disrupt existing ssh connections. Proceed with operation?
y
- Check firewall rules
sudo ufw status verbose
- Disable IPv6
sudo nano /etc/default/ufw
- Update
IPV6=yes
toIPV6=no
, then save sudo ufw disable
sudo ufw enable
- Install Fail2Ban
sudo apt update
sudo apt install fail2ban
y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo systemctl status fail2ban
q
- Follow Configuring Fail2Ban guide
cd /etc/fail2ban
head -20 jail.conf
sudo cp jail.conf jail.local
sudo nano jail.local
- I didn't make any changes, but wanted to take a peek at the rules in there
- Set up automatic updates
cd
sudo apt update
sudo apt install unattended-upgrades
systemctl status unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades
<Yes>
Install Docker
Follow Install Docker Engine on Ubuntu guide, specifically Install using the apt
repository:
- Uninstall conflicting packages
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
- Set up
apt
repository (just here copy-pasting from the guide...)
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
- Install Docker packages
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
y
- Add myself to the docker group, per Manage Docker as a non-root user
sudo usermod -aG docker $USER
newgrp docker
- Verify that I can run
docker
commands withoutsudo
docker run hello-world
- See:
Hello from Docker!
(It works!)
- Remove hello-world container
docker ps -a
- See name:
quirky_euclid
docker rm quirky_euclid
docker rmi hello-world
Install Easypanel
Follow Easypanel's Manual Installation guide:
- Skip the
get.docker.com
line because I already have Docker installed - Copy-paste this command:
docker run --rm -it \
-v /etc/easypanel:/etc/easypanel \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
easypanel/easypanel setup
- See:
Easypanel was installed successfully on your server!
and my server's external IP address- My firewall + router blocks this, so it's not exposed to the internet
docker ps
- See two containers:
easypanel
andtraefik
- Access Easypanel's web GUI at my local IP: http://192.168.x.x:3000
- Log into Easypanel
- Generate a new email address alias
- Generate a new password
- How did you find Easypanel: Indie web blog
- I'm in!
- In the web GUI, create project buckets (free for up to three)
playground
— for experimentshome
— for private home servicesweb
— for public web services
Install Jellyfin with Easypanel
Jellyfin is for streaming & managing media. (I chose this just to test an app install. My hardware does not meet Jellyfin's requirements.)
- Go to Dashboard >
home
project - Select the ➕ to add an app
- Pick a template: Jellyfin
- Select Deploy
- Go to Domains
- If this were publicly available, I'd click Open (↗) and be done
- Since my Mac Mini isn't available on the internet, Easypanel's subdomains won't work for me — to access the app, I need to expose the port and go to the IP address + port directly
- Find Jellyfin's port: 8096
- Go to Dashboard >
jellyfin
> Advanced > Ports- Select Add Port
- Protocol: TCP
- Published: 8096
- Target: 8096
- Select Create
- Select Stop (⏹), Deploy, then Start (▶)
- Go to http://192.168.x.x:8096 (it works!)
To delete Jellyfin, I go to jellyfin
and select Destroy (🗑️).
References
I used ChatGPT to explain errors to me. I also used it to verify if my plans would work.
- Ubuntu server install guides
- Network stuff
- SSH stuff
- Security
- Docker + Easypanel things
Notes
- Pi-hole?
- WireGuard tunneling
- Containerize an application
- Proxmox