MinimServer on FreeBSD

How to run MinimServer, the UPnP music server, on FreeBSD or in a TrueNAS CORE jail.

MinimServer is Java, so it runs on FreeBSD, all but ohNet, the native UPnP library it uses. MinimServer ships ohNet only for Linux, Windows and macOS. ohnet-freebsd builds it for FreeBSD as a drop-in replacement for MinimServer's Linux copy. This page also covers FreeBSD's differences from Linux in MinimServer's start and stop scripts.

What you need

FreeBSD 13 has no packages anymore. FreeBSD 13 reached end of life, and its package repositories are gone, so pkg install fails on 13.x. TrueNAS CORE is based on FreeBSD 13, so its jails are 13.x too. A jail that already has Java can be used as it is. For a new jail, Java has to come from somewhere else, such as building it from the ports tree. On FreeBSD 14 and later, packages install normally.

A jail for MinimServer

A jail of its own keeps MinimServer apart from the rest of the system. On TrueNAS CORE, create one in the web UI or with iocage. Give it its own network stack (VNET), so that UPnP's multicast discovery reaches it. For example:

iocage create -n minim -r release vnet=1 dhcp=1 bpf=1 boot=1
iocage fstab -a minim /mnt/pool/music /media nullfs ro 0 0

Here release is a FreeBSD release your system offers, such as 13.1-RELEASE; see the note above about packages on 13.x. The second line makes your music folder visible in the jail as /media, read-only. Change /mnt/pool/music to where your music is. The commands in the rest of this page are run inside the jail, as root: iocage console minim.

Installing

  1. Install Java (and ffmpeg, if you want it):

    pkg install openjdk8-jre ffmpeg

    Unlike earlier FreeBSD builds of ohNet, these don't need lang/gcc, and fetch replaces wget.

  2. Create a user to run MinimServer, rather than running it as root:

    pw useradd minimserver -c MinimServer -d /nonexistent -s /usr/sbin/nologin

    It needs to be able to read your music folder. A read-only mount that everyone can read is enough.

  3. Download MinimServer from its Downloads page: the Linux build for Intel, MinimServer-2.2-linux-intel.tar.gz. The download asks you to accept MinimServer's license terms. Copy the file into the jail, for example into /tmp, and unpack it:

    tar xzf /tmp/MinimServer-2.2-linux-intel.tar.gz -C /usr/local/share
    chown -R minimserver:minimserver /usr/local/share/minimserver

    MinimServer keeps its settings and its updates in this folder, so the user running it has to own it.

  4. Install the service script:

    fetch -o /usr/local/etc/rc.d/minimserver \
        https://raw.githubusercontent.com/imush/ohnet-freebsd/main/rc.d/minimserver
    chmod 555 /usr/local/etc/rc.d/minimserver
    sysrc minimserver_enable=YES minimserver_user=minimserver

    MinimServer's own bin/stopall and bin/startd look for a running server in /proc or with Linux ps options, neither of which works on FreeBSD. This script starts MinimServer with startd, which also restarts it after an update, but finds and stops it by itself.

  5. Start it once, to let it update:

    service minimserver start

    On its first start, MinimServer updates itself to the latest version. The update brings the Linux ohNet, so after about half a minute it stops with this error in /usr/local/share/minimserver/data/minimserver.log:

    java.lang.UnsatisfiedLinkError: ... Shared object "libm.so.6" not found

    That's expected. The next step replaces it.

  6. Replace ohNet with the FreeBSD build. See which version MinimServer wants:

    service minimserver stop
    ls /usr/local/share/minimserver/libext/ohnet*

    Download the zip with that name from the releases page, saving it under MinimServer's name. For ohnet(linux-intel)-1.37.5521.2.zip:

    cd /usr/local/share/minimserver/libext
    fetch -o 'ohnet(linux-intel)-1.37.5521.2.zip' \
        https://github.com/imush/ohnet-freebsd/releases/download/v1.37.5521.2-2/ohnet.linux-intel.-1.37.5521.2.zip
    chown minimserver:minimserver 'ohnet(linux-intel)-1.37.5521.2.zip'
    sha256 'ohnet(linux-intel)-1.37.5521.2.zip'

    GitHub doesn't allow parentheses in download names, so the release lists the file with dots instead. Compare the checksum with the .sha256 file on the release page.

  7. Start MinimServer:

    service minimserver start
    service minimserver status

    MinimServer unpacks ohNet into tmp/native/ as it starts. The log ends with "Startup complete".

  8. Set it up in a browser at http://jail-address:9790. Accept the license terms, then choose your music folder: /media with the mount above. MinimServer scans it, and then appears in any UPnP control point on your network.

Upgrading

MinimServer updates

MinimServer updates itself as it starts, unless automatic updates are turned off in its settings. You can also update it from its web page at http://jail-address:9790. When an update is available, the page offers it with an Install button, and MinimServer restarts itself afterwards.

Most updates leave ohNet alone. An update that keeps the same ohNet version keeps your FreeBSD zip: for example, going from update 272 to 275 kept it. An update that moves to a new ohNet version brings that version's Linux zip, and MinimServer then fails to start with the libm.so.6 error. To update safely:

  1. Before updating, look in MinimServer's release notes for a line like "Update ohNet to version …" in any update newer than yours. If there is one, check that the releases page has a FreeBSD zip for that version. If there isn't one yet, wait to update, or open an issue.

  2. Keep a copy of the current zip, in case you need to go back:

    mkdir -p /root/ohnet-backup
    cp -p /usr/local/share/minimserver/libext/ohnet*.zip /root/ohnet-backup/
  3. Install the update from the web page, or with service minimserver restart if automatic updates are on.

  4. Check which ohNet MinimServer has now:

    cd /usr/local/share/minimserver/libext
    for z in ohnet*.zip; do echo "$z"; unzip -p "$z" libohNet.so.64 | file -; done

    A FreeBSD zip shows (FreeBSD). If it shows (SYSV), it's the Linux zip: replace it with the FreeBSD zip of the same name, as in step 6, and start MinimServer again.

A new build of the same ohNet version

A new release here with the same zip name, such as a fixed build, is installed the same way: stop MinimServer, replace the zip, and start it.

The service script

To get the latest version of the service script:

fetch -o /usr/local/etc/rc.d/minimserver \
    https://raw.githubusercontent.com/imush/ohnet-freebsd/main/rc.d/minimserver
service minimserver restart

Your settings in /etc/rc.conf carry over.

Java and FreeBSD

On FreeBSD 14 and later, Java updates with the rest of the jail's packages: pkg upgrade, then service minimserver restart. The zips are built on FreeBSD 13.2 and work on later releases: they're tested on 13.1, 14 and 15, with OpenJDK 8 and 21. So upgrading the jail to a newer FreeBSD needs no new zip.

Going back

To return to the zip you saved before an update:

service minimserver stop
cp -p /root/ohnet-backup/ohnet*.zip /usr/local/share/minimserver/libext/
service minimserver start

This puts back the zip, not the MinimServer version. An ohNet zip works only with the MinimServer updates that use that ohNet version.

Moving an existing install to these builds

If you followed the earlier tutorial in the MinimServer forum:

  1. Replace /etc/rc.d/minimserver with the new script, so stopping works without patching stopall after each update:

    service minimserver stop
    pgrep -f mserver.jar && echo "still running: stop it first"
    rm /etc/rc.d/minimserver
    fetch -o /usr/local/etc/rc.d/minimserver \
        https://raw.githubusercontent.com/imush/ohnet-freebsd/main/rc.d/minimserver
    chmod 555 /usr/local/etc/rc.d/minimserver

    If the old stop didn't stop it (the pgrep line prints a number), MinimServer's update replaced the patched stopall. Stop it with kill on that number, then carry on. The new script runs MinimServer as root, as before, unless you set minimserver_user.

  2. Keep a copy of your current zip, then replace it as in step 6:

    mkdir -p /root/ohnet-backup
    cp -p /usr/local/share/minimserver/libext/ohnet*.zip /root/ohnet-backup/
  3. Start MinimServer with service minimserver start.

The new zips don't use lang/gcc. You can remove it if nothing else in the jail needs it.

Troubleshooting

Shared object "libm.so.6" not found

MinimServer is using a Linux ohNet. This happens after an update brings a new one, or if the FreeBSD zip was saved under the wrong name. Check which zip it has, and that its name in libext/ is exactly MinimServer's, then see step 6.

Unable to create symbolic link /tmp/.minimserver/...

MinimServer was run earlier as a different user, such as root. Stop it, remove /tmp/.minimserver and start it again.

The server doesn't show up in control points

Check that it's running with service minimserver status, and look at the end of data/minimserver.log. Discovery uses multicast, so a jail needs VNET, and the jail and your control points must be on the same network.

Something else

Ask in the FreeBSD thread of the MinimServer forum, or open an issue on GitHub.