3 minute read

g3!

Image credit: GMKtec

I acquired a new server: the tiny, affordable GMKtec NucBox G3. It replaces the Raspberry Pi 3B I’ve had for what feels like an eternity. I installed Ubuntu 25.04 on it, and so here’s a recording of how I set it up.

This post is a part of my Homelab Series. See the index here.

System Stuff

Static IP

Instructions are stolen from this article.

Check if cloud-init is installed:

apt-cache pkgnames | grep cloud-init

If you get an output, you have ‘cloud-init’ installed.

Now, to disable could-init, create a new file inside /etc/cloud/cloud.cfg.d directory:

sudoedit /etc/cloud/cloud.cfg.d/99-disable-cloud-init.cfg

Add the following line to it:

network: {config: disabled}

Reboot the system: sudo reboot now and afterwards, create a new config file:

sudoedit /etc/netplan/00-installer-config.yaml

With the following content:

network:
  ethernets:
    enp3s0:
      dhcp4: no
      addresses:
        - 192.168.1.199/24
      gateway4: 192.168.1.1
      nameservers:
        addresses: [1.1.1.1, 8.8.8.8]
  version: 2

sudo netplan apply

Check if it worked: hostname -I

Disable WiFi

sudo nmcli radio wifi off

SSH without Password

Same as on Pi

Mount External Drives

Same as on Pi

Samba Sharing

Same as on Pi

Apps

Same as on Pi

For several pieces, I was able to follow the same procedures as in my previous Raspberry Pi setup:

And then, we have new goodies!!

Watchtower

This keeps containers updated automatically. First, install Shoutrrr to make sending Watchtower notifications easy:

sudo snap install shoutrrr

And then pop this into Portainer:

version: "3.3"
services:
  watchtower:
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment: WATCHTOWER_NOTIFICATION_URL=ntfy://NTFY.USERNAME:[email protected]:8787/watchtower?Scheme=http
    image: beatkind/watchtower

MusicBrainz Picard

I tried hard to like Lidarr but realized I didn’t need all the complexity and maintenance it required. I’m not a hoarder, I’m rather intentional as far as music is concerned, so I don’t need to any automation for music downloads. And what is quite important to me: Picard gives me full control over the tagging process, whereas in Lidarr it was automated and rather opaque to me.

version: "3.3"
services:
  picard:
    ports:
      - 5800:5800
    volumes:
      - /home/pe8er/docker/picard:/config:rw
      - /home/pe8er/Downloads:/downloads:rw
      - /mnt/ssd-sandisk/Music:/music:rw
    image: mikenye/picard:latest

And my file rename script (or grab the gist):

%albumartist%/\($if(%originalyear%,%originalyear%,$if(%date%,$left(%date%,4),0000))\) %album%/$if($gt(%totaldiscs%,1),%discnumber%-)$num(%tracknumber%,2) $if2(%albumartist%,%artist%) - %title%

Radarr

Radarr manages movie grabbing and management. I prefer this way to grab new movies instead of manual search because it’s much faster and less cognitively intensive for me.

---
services:
  radarr:
    image: lscr.io/linuxserver/radarr:latest
    container_name: radarr
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Warsaw
    volumes:
      - /home/pe8er/docker/radarr:/config
      - /home/pe8er:/data
    ports:
      - 7878:7878
    restart: unless-stopped

Prowlarr

I need this to easily add indexers to *arr apps. It replaces Jackett.

---
services:
  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    container_name: prowlarr
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Warsaw
    volumes:
      - /home/pe8er/docker/prowlarr:/config
      - /home/pe8er/:/data
    ports:
      - 9696:9696
    restart: unless-stopped

Immich

A self-hosted photo library / backup app with pretty solid UX. Solid Docker instructions on Immich website.

Homepage

A simple web app dashboard which I use as a visual bookmark for all my server apps. Website.

services:
  homepage:
    image: ghcr.io/gethomepage/homepage:latest
    container_name: homepage
    ports:
      - 3000:3000
    volumes:
      - /home/pe8er/docker/homepage:/app/config
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev,*

JDownloader2

A handy download manager.

version: '3'
services:
  jdownloader-2:
    image: jlesage/jdownloader-2
    ports:
      - "666:5800"
    volumes:
      - "/home/pe8er/docker/jdownloader2:/config:rw"
      - "/home/pe8er/Downloads:/output:rw"
    environment:
      - WEB_AUTHENTICATION_USERNAME=pe8er
      - WEB_AUTHENTICATION_PASSWORD=[PASSWORD]
      - MYJDOWNLOADER_DEVICE_NAME=jdownloader2

And JDownloader2 should be available at:

http://[SERVER IP]:666

ntfy.sh

I used Pushover for years until I switched to an Android phone and discovered that I need to pay for the Android app. Well, as it turns out one can self-host a notification server: ntfy.sh! Pushover worked well for me but ntfy seems to be much simpler in practice. Love it!

Before installing the docker image, I created necessary directories and grabbed the configuration file, which I ended up not using at all.

mkdir -p /home/pe8er/docker/ntfy/cache/ntfy
mkdir -p /home/pe8er/docker/ntfy/etc/ntfy
wget https://raw.githubusercontent.com/binwiederhier/ntfy/refs/heads/main/server/server.yml

And then comes the docker compose:

services:
  ntfy:
    image: binwiederhier/ntfy
    container_name: ntfy
    command:
      - serve
    environment:
      - TZ=Europe/Warsaw
    user: 1000:1000
    volumes:
      - /home/pe8er/docker/ntfy/cache/ntfy:/var/cache/ntfy
      - /home/pe8er/docker/ntfy/etc/ntfy:/etc/ntfy
    ports:
      - 8787:80
    healthcheck: # optional: remember to adapt the host:port to your environment
        test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1"]
        interval: 60s
        timeout: 10s
        retries: 3
        start_period: 40s
    restart: unless-stopped

It works by sending commands such as this:

curl -d "Dang 😀" 192.168.1.199:8787/all

Or it can get more elaborate, like this:

curl \
  -H "$TITLE" \
  -H "Tags: skull" \
  -d "$MESSAGE" \
  $NTFYSERVER

What is absolutely amazing for me is that I can send emoji with images, using emoji short codes. So much fun.