Thursday, March 19, 2015

Automatically Start Local Minecraft Server on Linux (Fedora) At Boot

Running your own Minecraft server on Linux is pretty simple.  You simply download the jar file from Minecraft.net and run it from the command line.  However, if you run it straight from the command line you'll need to stay logged in and not kill the terminal otherwise it will stop the Minecraft server.

The way to work around it is to use something like tmux or screen and run Minecraft from there.  That allows you to detach the session, logout, and come back to it at a later time so you now have a "headless" Mindcraft server running.

The final step is to make it so that it automatically starts when the server boots up and shut it down when the server shuts down.  On Fedora, that means using systemd.

I'm assuming you're running Minecraft as user minecraft and the Minecraft jar file is located in ~minecraft.

First, let's create a start-up script in $HOME/start_server.sh:

#!/bin/sh
/usr/bin/tmux new-session -s minecraft -d
tmux send -t minecraft "/usr/bin/java -Xmx1024M -Xms1024M -jar $HOME/minecraft_server.1.8.3.jar --nogui" ENTER
This starts a new tmux session in detached mode and calling the session minecraft.  Then it sends to the tmux session the command to start the Minecraft server in text (non-gui) mode.

Let's make a shutdown script in $HOME/minecraft/stop_server.sh:

#!/bin/sh
/usr/bin/tmux send -t minecraft /save-all ENTER
/usr/bin/tmux send -t minecraft /stop ENTER
echo "Killing minecraft session"
/usr/bin/tmux kill-session -t minecraft
This sends a command to the tmux session named minecraft to
  1. Save the current state of the server (save-all).
  2. Shutdown the minecraft server (/stop).
  3. Stop the tmux session.
Make both scripts executable:

chmod u+x start_server.sh
chmod u+x stop_server.sh
To automatically start and stop the tmux session for Minecraft, create /usr/lib/systemd/system/minecraft.service:

[Unit]
Description=Start tmux in detached session running Minecraft.

[Service]
Type=forking
User=minecraft
ExecStart=/home/minecraft/start_server.sh
ExecStop=/home/minecraft/stop_server.sh
WorkingDirectory=/home/minecraft

[Install]
WantedBy=multi-user.target
Now link it to the right place:

cd /etc/systemd/system
ln -s /usr/lib/systemd/system/minecraft.service minecraft.service
Finally, you want to start it and enable it to start at boot:

systemctl start minecraft.service
systemctl enable minecraft.service
I also suggest having a backup script that regularly back up your world:

#!/bin/sh
printf "Starting backup..."
date +%D
cd /home/minecraft
tmux send -t minecraft /save-off ENTER
tar -czvf backup/world-`date +%m%d%y_%H_%M_%S`.tar.gz world
tmux send -t minecraft /save-on ENTER
With a cron job as follows:

0 15 * * * /home/minecraft/backup.sh >> /home/minecraft/backup/backup.log 2>&1

This says to run the job at 3pm every day and copy the output to backup.log.

The saved archive (even compressed) can get pretty big and can easily eat up disk space so you might want to only keep the a few of the most recent save and automatically delete the old ones (or move old archives somewhere else).  That can be done with another cron job with a one line script:

ls -tr world-*.tar.gz | head -n -5 | xargs --no-run-if-empty rm
This will delete all but the 5 most recent files and do nothing if there are less then 5 archive files.  This can be put into a script with some logging /home/minecraft/cleanup_backup.sh:

#!/bin/sh
printf "Deleting old backups..."
date +%D
cd /home/minecraft/backup
ls -tr world-*.tar.gz | head -n -5 | xargs --no-run-if-empty rm -v
and have a cron job as follows to run nightly:

# Delete old backup files at 11:20pm but keeping a few most recent ones.
20 23 * * * /home/minecraft/cleanup_backup.sh >> /home/minecraft/backup/backup.log 2>&1

Now each time your server boots, it will automatically run the Minecraft server as user minecraft and once a day it will back up your Minecraft data while removing old archives.

Wednesday, March 4, 2015

Mounting Shared Drive on Linux and Headless Bittorent Daemon

There are a number of different ways to automate the download of bittorrent files.  Many bittorrent clients have the ability to "watch" a directory and if a torrent files get added there then the bittorrent will automatically begin to download.  Some even don't need to download the file as it can subscribe to a feed directly.

GUI Way

What I did before was to log into a machine, connect to a shared drive and then open Transmission which was configured to look at the shared drive for any new torrent files.  I even wrote a program that grab checked and downloaded new torrent files every 24 hours.  Setting this up was extremely simple.  As part of my login items on OSX, I had it connected to my shared drive.  Then I would start Transmission and have it point to the shared drive to automatically download the torrents.  I used watch to execute my torrent downloads:

watch -n 72000 <program to download torrents>
I didn't use cron or anything because this was originally on a OSX laptop.

When I switched to a Linux machine that is kept on, I did the exact same thing.  The problem with this is that you're expected to be logged in to the system and keeping the programs running.  If someone else need to use the computer then everything stops since you'd have to log out.

Terminal Way

This similar to the GUI way described above except you do it in a terminal running in a tmux session so that you can disconnect without loosing your transmission job.  To connect to the shared smb drive without the GUI by using transmission-cli tool.

tmux
dbus-launch bash
gvfs-mount smb://<user>@<host>/<path-to-shared-drive>
sudo yum install transmission-cli
transmission-cli
You'd put in your user name and password as it prompts you when you mount the shared drive.  You'll need to configure transmission.

Headless Way

This doesn't require any GUI or terminal and can automatically starts at each boot.

Install the transmission-daemon

sudo yum install transmission-daemon
sudo systemctl start transmission-daemon.service
sudo systemctl stop transmission-daemon.service
The service file is in /usr/lib/systemd/system/transmission-daemon.service.

I started and stopped the daemon because you need to configure it through the /var/lib/transmission/.config/transmission-daemon/settings.json and this gets created when you first start (for other locations of Transmission files click here).  This will also install the transmission user

Next you need to mount the shared drive in order for transmission to access and ONLY transmission:

sudo mount -t cifs -o -credential=<path-to-credential>,gid=`id -g transmission`,uid=`id -u transmission` <mount point>
The credential value points to a file that contains your username, password and domain for logging into the shared drive.  Make sure wherever you store it that it's not readable by others.

The gid and uid belongs to the user you want to be able to do read-and-writes to the shared drive otherwise it'll only be root that can do it.  For Fedora, the user is "transmission"

If it works and you can read-and-write, you can move this into /etc/fstab:

//<host>/<path-to-file> <mount-point> cifs credentials=<path-to-cred>,uid={user id},gid={group id}
and then reload fstab:

sudo mount -a
Once you configure the /var/lib/transmission/.config/transmission-daemon/settings.json to your liking then fire up:

sudo systemctl start transmission-daemon.service
sudo systemctl enable transmission-daemon.service
This starts up the service now and also at each machine reboot.  The one issue is that transmission-daemon might start before the drive is mounted and then it won't look for the changes.  It needs to be told to wait.

Systemd will look at /etc/fstab and automatically create an unit that can be added to the service file to tell it to wait.  Running the systemctl command will show you an unit that can be used (it'll be something with a .mount suffix).

Add that unit to the After line:

After=network.target <mount unit>

Finally, set up a cron job to regularly check for new torrents:

crontab -u <transmission user> -e
With the value being something like:

0 23 * * * <path-to-program-to-run> >> /var/lib/transmission/download.log 2>&1
which says to execute the program every night at 11pm and store the out put in /var/lib/transmission/download.log.

Since the transmission users is disabled for an interactive shell, to execute commands as the transmission user, use:

sudo -u <transmission user> <command>

Monday, March 2, 2015

Thoughts on setting up Murmur and Mumble.

Following my experiences of compiling and setting up Synergy, I found myself setting up Murmur/Mumble this past weekend.  It was a sharp contrast in experience.  Mumble seems to want folks to be able to build and run their software.  Mumble is an open source VOIP solution used often by gamers to talk to each other while playing games and Murmur is the server portion.  I needed Windows and Linux clients since those are the system that people are on when playing and a Linux version of Murmur since that's what I'm going to be running the server on.

In most cases, setting this up on Linux is as simple as using whatever package manager is used by the distro and installing the Mumble package(s), but I ran into a problem with Fedora 21.  There are no packages for Mumble since it was retired after Fedora 20.  That means compiling from source which is normally not a big deal since this is open source, but to just make things a little more difficult some packages that Mumble depends on were also retired so those needed to be built and installed as well.

In the end, I cheated and grabbed the rpm from Fedora since they still had the RPMs from before they decided to retire it from the repo.  Mumble also requires the Ice package which was also retired so make sure to install it as well.

Now, the next step was getting a Windows client and this was when things got interesting.  The Mumble team provides pre-built binaries that are hosted on Sourceforge (development snapshot are available directly from their snapshop location).   I've been fairly distrustful of Sourceforge following what happened with Filezilla and malware and reluctant to use anything hosted there especially Windows binaries so the alternative was to try to compile the client myself.  I approached with some trepidation as there is a reason that on Windows people distribute binaries more then source code.

Compiling other people's code on Windows is not easy!  In the past, the tooling was not always available but that's gotten a little better when Microsoft decided to make free "Express" editions of Visual Studios available.  Still, the effort required to build something like Mumble wasn't trivial, but I have to give kudos to the Mumble guys who has done a very good job documenting how to build Mumble on Windows.  I went though their instructions and they document a lot of potential gotchas that helped get over issues that I ran into and while it took the entire morning (a lot of time was spent just waiting on the build), I was able to get a working client running that talked to the server running on the Linux box.

Misc Thoughts

I didn't know anything about Mumble before the weekend and came across it while I was looking for something to meet my needs.  Once I found Mumble and started looking at how to get the client, I also found mumble.com which looked and sounded like Mumble (it has the binaries, let's you buy the server software, etc.) but in small fine print at the bottom it says it isn't affiliated with Mumbo.info.

It's these kind of things that always bothered me and where a trademark would actually be very helpful.