Aside

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

What I did

Install Ubuntu Server on Mac Mini (late 2014)

  1. Download Ubuntu Server (Ubuntu 24.04.2 LTS)
  2. Create a bootable USB stick on macOS
  3. Boot from install media
    1. Restart Mac, press Option key immediately after chime
    2. Select EFI Boot

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.
  1. Preferred language
    1. English
    2. Enter
  2. Keyboard layout + variant
    1. English (US)
    2. English (US)
    3. Select Done, Enter
  3. Choose installation
    1. [x] Ubuntu Server
    2. Select Done, Enter
  4. Network configuration
    1. I do not see an IP address, as is typical in guides, and instead see: disabled autoconfiguration failed
    2. 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
  5. Proxy configuration
    1. Left blank
    2. Select Done, Enter
  6. Ubuntu archive mirror configuration
    1. Select Done, Enter
  7. Storage configuration
    1. [x] Use an entire disk
    2. [x] Set up this disk as an LVM group
    3. Select Done, Enter
    4. Select Done, Enter
  8. Confirm destructive action
    1. Select Continue
  9. Profile configuration
    1. Filled the fields for name, server name, username, and password
    2. Select Done, Enter
  10. Upgrade to Ubuntu Pro
    1. [x] Skip Ubuntu Pro setup for now
    2. Select Continue, Enter
  11. SSH configuration
    1. Since I don't have network access nor SSH keys registered with Launchpad or GitHub...
    2. [x] Allow password authentication over SSH
    3. Select Done, Enter
  12. Installation complete!
    1. Select Reboot Now
  13. Prompted to remove the USB stick, so I do, then Enter
  14. It's looking for the network again, so I unplug the Mac Mini, bring it downstairs, and connect it to the router via ethernet
  15. Turn on the Mac Mini and wait
  16. 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?

  1. Try to find IP address
    1. ip a
      • There is no IP address (not a surprise, since the autoconfiguration earlier failed)
    2. ip link
      • I see state DOWN
      • Look for something similar to enp0s25
  2. I find Network interface down - how to turn it on again? and follow its steps
    1. ip link show up
    2. dhclient enp0s25
    3. Add IP addresses manually
      1. sudo ip address add 192.168.x.x/24 dev enp0s25
        1. 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
        2. Replace enp0s25 with what was listed in ip link
      2. sudo ip route add default via 192.168.x.x
        1. This is my local network/router IP
    4. Confirm the updates went through
      1. ip a
      2. ip r
      3. I see the IP addresses I manually added (and understand that this is temporary)
  3. Test connection
    1. ping -c 3 9.9.9.9
      • 3 packets transmitted, 3 packets received, so it works
    2. ping -c 3 archive.ubuntu.com
      • See error: Temporary failure in name resolution
  4. Set up Quad9 for domain name resolution (also temporary)
    1. sudo nano /etc/resolv.conf
    2. Replace current nameserver with:
nameserver 9.9.9.9
nameserver 149.112.112.112
  1. ping -c 3 archive.ubuntu.com
    • 3 packets transmitted, 3 packets received, so it works
  2. Install SSH
    1. sudo apt update
    2. sudo apt install openssh-server
    3. y
    4. sudo systemctl start ssh
    5. sudo systemctl enable ssh
    6. sudo systemctl status ssh

SSH into Mac Mini & update to key-based login

  1. Go to Windows computer, ensure Mullvad VPN has Local network sharing enabled
    • PowerShell window 1: SSH in with password
      • $user@192.168.x.x
  2. Set up key-based login from my Windows computer to the Ubuntu server
    1. Open new PowerShell window 2: Get my computer's public key
      1. type $env:USERPROFILE\.ssh\id_ed25519.pub
      2. Copy the content
    2. PowerShell window 1: Add key to the server & update permissions
      1. mkdir -p ~/.ssh
      2. nano ~/.ssh/authorized_keys
      3. Paste in the copied content and save
      4. cd
      5. chmod 700 ~/.ssh
      6. chmod 600 ~/.ssh/authorized_keys
    3. PowerShell window 2: Log in with SSH key
      1. ssh $user@192.168.x.x
      2. Should not be prompted for a password
    4. Close either window
  3. Disable password login & root login
    1. sudo nano /etc/ssh/sshd_config
    2. Update the following lines and ensure they do not have a # in front:
      1. PermitRootLogin no
      2. PasswordAuthentication no
      3. Save
    3. cd
    4. sudo systemctl restart ssh

Set up network configuration

  1. sudo nano /etc/netplan/01-static.yaml
  2. 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]
  1. sudo netplan apply
  2. See warnings about the .yaml file's permissions being too open
  3. sudo chmod 600 /etc/netplan/01-static.yaml
  4. ip a
    • Should see:
inet 192.168.x.x/24 ... scope global enp0s25
  1. Confirm things work
    1. ping -c 3 9.9.9.9
    2. ping -c 3 archive.ubuntu.com
  2. 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:

  1. sudo apt update
  2. sudo apt upgrade
  3. y
  4. sudo reboot

Set up firewall & other security

  1. $user@192.168.x.x
  2. Install firewall
    1. sudo apt update
    2. sudo apt install ufw
  3. Block incoming traffic, but allow outgoing connections & SSH
    1. sudo ufw default deny incoming
    2. sudo ufw default allow outgoing
    3. sudo ufw allow openssh
  4. Turn on firewall
    1. sudo ufw enable
    2. Command may disrupt existing ssh connections. Proceed with operation?
    3. y
  5. Check firewall rules
    1. sudo ufw status verbose
  6. Disable IPv6
    1. sudo nano /etc/default/ufw
    2. Update IPV6=yes to IPV6=no, then save
    3. sudo ufw disable
    4. sudo ufw enable
  7. Install Fail2Ban
    1. sudo apt update
    2. sudo apt install fail2ban
    3. y
    4. sudo systemctl enable fail2ban
    5. sudo systemctl start fail2ban
    6. sudo systemctl status fail2ban
    7. q
  8. Follow Configuring Fail2Ban guide
    1. cd /etc/fail2ban
    2. head -20 jail.conf
    3. sudo cp jail.conf jail.local
    4. sudo nano jail.local
    5. I didn't make any changes, but wanted to take a peek at the rules in there
  9. Set up automatic updates
    1. cd
    2. sudo apt update
    3. sudo apt install unattended-upgrades
    4. systemctl status unattended-upgrades
    5. sudo dpkg-reconfigure unattended-upgrades
    6. <Yes>

Install Docker

Follow Install Docker Engine on Ubuntu guide, specifically Install using the apt repository:

  1. Uninstall conflicting packages
    1. for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
  2. 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
  1. Install Docker packages
    1. sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    2. y
  2. Add myself to the docker group, per Manage Docker as a non-root user
    1. sudo usermod -aG docker $USER
    2. newgrp docker
  3. Verify that I can run docker commands without sudo
    1. docker run hello-world
    2. See: Hello from Docker! (It works!)
  4. Remove hello-world container
    1. docker ps -a
    2. See name: quirky_euclid
    3. docker rm quirky_euclid
    4. docker rmi hello-world

Install Easypanel

Follow Easypanel's Manual Installation guide:

  1. Skip the get.docker.com line because I already have Docker installed
  2. 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
  1. See: Easypanel was installed successfully on your server! and my server's external IP address
    1. My firewall + router blocks this, so it's not exposed to the internet
  2. docker ps
  3. See two containers: easypanel and traefik
  4. Access Easypanel's web GUI at my local IP: http://192.168.x.x:3000
  5. Log into Easypanel
    1. Generate a new email address alias
    2. Generate a new password
    3. How did you find Easypanel: Indie web blog
    4. I'm in!
  6. In the web GUI, create project buckets (free for up to three)
    1. playground — for experiments
    2. home — for private home services
    3. web — 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.)

  1. Go to Dashboard > home project
  2. Select the ➕ to add an app
  3. Pick a template: Jellyfin
  4. Select Deploy
  5. Go to Domains
    1. If this were publicly available, I'd click Open (↗) and be done
    2. 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
    3. Find Jellyfin's port: 8096
  6. Go to Dashboard > jellyfin > Advanced > Ports
    1. Select Add Port
    2. Protocol: TCP
    3. Published: 8096
    4. Target: 8096
    5. Select Create
  7. Select Stop (⏹), Deploy, then Start (▶)
  8. 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.

Notes