Good questions. When it comes to running things on Unix I can offer some advice;
a. Should I create an unix account called “minecraft” to launch the servers ?
You should create an account for each server that you wish to run. It will cost you nothing and segregate all the files and processes to that user. In the future, if you ever collaborate with other users on your machine, you can share this account without fear as long as you trust them. But that is rare. It goes to the permissions question you ask later though. But in general, yes. Make a user for the server, not just for ‘minecraft’. Also, in Unix, it’s generally practice to keep user names under 8 characters and even less is best. (When I write server I mean the actual process running the game, not the hardware on which the process is running. I know it means both and can mean more. But I meant one user per server process ie., per “game”)
In the following, the #
is the shell prompt of root
(UID = 0)… I started using Unix decades before we had sudo
so I don’t believe in it. I don’t need it. If I needed that extra guard rail on how I do “things as root” you might as well wheel me into the old-folks home now. But you’re not going to do that.
IMHO, If you’re root
, then you’re root.
Be a big boy. On the other hand, never, absolutely NEVER give the root
password to anyone. Not your mom, not your girlfriend, not anyone. Ever. If you have to share responsibility to do admin things with other users and YOU have the root password, then let them use sudo
. Gone are the days we trust people with root
password. I remember those days, good times.
If you see $
prompt, it means the shell prompt of a non-root user (UID != 0)
Also, some other conventions… when you see a path /etc/blah
we pronouce it /et-see/
We do not say /et-cet-era/
OK, now that is done and out of the way, let’s continue, shall we!
The command is simple:
# adduser foo
On Linux systems this usually does a few things.
- It creates a user
foo
in the /etc/passwd
file.
- It creates a home directory (typically)
/home/foo
- It creates a
group
called foo
and that is added to the /etc/group
- It puts the user
foo
in the group foo
The group foo
and the user foo
are not the same. Different things.
If you wanted to make a new group that had a name bar
then you can add that group to the system (before making the user foo
)
# addgroup bar
Back to adduser
: There are usually flags you can give the command to simultaneously add the user foo
into group bar
(users can be members of multiple groups)
(The man page for commands is the best place to look. For Linux, the synopsis is as follows:
adduser [options] [--home DIR] [--shell SHELL] [--no-create-home]
[--uid ID] [--firstuid ID] [--lastuid ID] [--ingroup GROUP | --gid ID]
[--disabled-password] [--disabled-login] [--gecos GECOS]
[--add_extra_groups] [--encrypt-home] user
So thus, the command before to add foo
user into group bar
would look like:
# addgroup bar
# adduser --ingroup bar foo
Now foo
is added as a user, and they belong to group bar
. This fine difference can be helpful if you have multiple files/servers where SOME of the files are group-owned by bar
but have user-ownership that is more finely sliced. Most of the time, most people just make new users and take the default action of a new group created per user. That wasn’t always the case. Back in the day, on university servers we’d make accounts per user, but they were all added to group students
so that we could setup directories for them where they had group-wise permission as students
. It’s a nuanced thing now days since most don’t work exclusively IN the Unix environment alone. That wasn’t always the case.
Anyway, I digress.
Make a user per MC Server. If the hardware has two servers running on it, you have two users, etc…
b. Where should I put the servers folders ? (I mean the recommended location, probably not
/ or
/home/admin/ for e.g.)
Your system has a mount-table. To view it, type:
$ mount
Depending on how your Unix system was setup, you’ll probably have a handful of filesystems. Each mount point (directory) is the access to the filesystem.
N mount points means N filesystems. You might have more filesystems than what is mounted, but if they aren’t mounted, you won’t see them via mount(1)
Oh and another habit – when you see a (number)
right after a command, it means what section the command is in. Section 1 are user commands. Section 8 are system-admin commands. Section 6 (my favorite) is games. Yup, look it up.
So, on your biggest filesystem, probably /
if it’s a typical Ubuntu server is where you will make a new directory: /data/servers
# mkdir -p /data/servers
What does the -p
flag do? It makes all the prerequisite directories before making the final one (servers
)
This is a compromise though. If the system had already setup the partition table for you, then you have no choice but to put the servers all on the biggest partition you got.
On the other hand, if you’re making the system yourself, you can absolutely setup different partitions (different filesystems) and name them and mount them separately.
Not common and comes with a few gotchas:
-
You have to know in advance how much data each filesystem will need. How does anyone know this? You can guess “big” and waste a lot of space or guess “small” and find yourself in the worse condition having to figure out how to merge data into a larger filesystem. I don’t like either case.
-
On the flip side, having a separate filesystem for just minecraft gives you one benefit among many - but the one benefit is that IF for instance the system became screwed up so badly you had to re-image new Linux on it, you can leave the filesystem with the minecraft data UNTOUCHED. Nothing will affect it unless you literally mkfs(8)
the data away. We used to make the root partition (/
) as small as possible to hold the system files and then made a fat filesystem for data filesystems like /data
and then symlink things to /data
as necessary.
-
If you use /
as the filesystem to hold a sub-directory (/data/servers) then you avoid the #1 problem, but you’re taking a risk on #2. Good news: #2 doesn’t happen more often than the hardware failing. So go with #1.
What you didn’t ask about but should have asked about is how to investigate the remaining space on the filesystems:
$ df
And to find out how much data is being stored in a particular path then use the df
command. Then with a bit of shell you can do nifty things like this:
$ cd /place/with/lots/of/data_and_files_and_directories
$ du -s * | sort -nr
I’ll let you figure out what that will do.
c. What should be the permissions of the servers files ?
You don’t get to worry about this unless you need to worry about this.
There’s a couple of concepts we need to cover first. Some of them you may already know, and some you probably haven’t given the nature of your questions. First what you probably don’t already know:
When files get created by a user, the permissions on the file are not just set to some default value. They are set in accordance with the default umask
of the shell environment. Yep, it’s per shell environment. Log out of the shell, then the umask
settings are gone until you re-set them the next time you login. This is why some users put the settings into their ~/.bashrc
or whatever “run-commands - rc” file they have for the shell they use.
The mask is bit-wise and’d with the default 0666
. Here’s a little experiment:
$ mkdir experiment ; cd experiment
$ umask
$ touch a
$ umask 0022
$ touch b
$ umask 0222
$ touch c
$ ls -l
The numbering scheme is the same used for chmod
… (Say: /shmod/)
Each file permission is a Four groups of Three bits. We’ll not worry about the very first group yet. The problems there are sticky, pun intended.
Lets worry about the three groups that deal with USER (u), GROUP (g), and OTHER (o).
The three bits each for u, g and o range from 0-7
The bits correspond to the file permissions READ ®, WRITE (w), and EXEC (x)
They are in this order rwx
r
is bit 2, or 2^2 = 4
w
is bit 1 or 2^1 = 2
x
is bit 0 or 2^0 = 1
If all three bits are set (rwx) then the numeric value of that group of bits is 7.
r + w + x = 4 + 2 + 1 = 7
USER, GROUP, OTHER Three sets of permission bits. Each set has 3 bits.
So the mode of a file 755
means:
USER permissions (USER means the owner of the file, always) = rwx (4 +2 +1) = 7
GROUP permissions = r-x ( 4 + 0 + 1 ) = 5
OTHER (OTHER means users NOT in the group that is the group-owner and not the USER (owner)) = r-x (4 + 0 + 1) = 5
Oh did we forget something?
Files have owners (that’s USER) Unix stores the owner of the file as the USER’s UID.
Files have group-owners (that’s GROUP) Unix stores the group-owner of the file as the GID (see /etc/group, the numeric field after the group-name)
and everyone else with respect to the file is OTHER
So, file permissions – a complex numbering scheme of 4 3-bit numbers. We are leaving out the first set because it’s not going to be helpful. Just the set for USER (u),
GROUP (g) and OTHER (o).
Back to our experiment:
$ mkdir experiment ; cd experiment
$ umask
$ touch a
$ umask 0022
$ touch b
$ umask 0222
$ touch c
$ ls -l
The modes you see are the permissions of the files. When I did the experiment I get this:
foo@skynet:~/ff$ umask
0002
foo@skynet:~/ff$ umask 0002
foo@skynet:~/ff$ touch a
foo@skynet:~/ff$ umask 0022
foo@skynet:~/ff$ touch b
foo@skynet:~/ff$ umask 0222
foo@skynet:~/ff$ touch c
foo@skynet:~/ff$ ls -l
total 0
-rw-rw-r-- 1 foo bar 0 Jan 3 20:45 a
-rw-r--r-- 1 foo bar 0 Jan 3 20:45 b
-r--r--r-- 1 foo bar 0 Jan 3 20:45 c
The user foo
owns all three files. That’s what column 3 shows.
The group bar
group-owns all three files. That’s what column 4 shows.
All were created on Jan 3 around 20:45.
The permissions of the files, in order are:
664
644
444
Remember the umask
is going to mask off the bits from each group of permissions. The u
, the g
and the o
groups were 6
each. The umask
was originally 0002
(ignore the leading 0
, the last three digits are the u
, g
, and o
umask
bits respectfully).
The 2
in the original umask
removes the w
permission from the o
mode of 6
It’s sort of like a bit-clear operation. We’re clearing the 2
(w
) bit from the 6
mode of the o
permission. The 6
becomes a 4
Second test, umask 0022
This is setting the mask to remove the 2 (w)
bit from the 6
mode of the g
and o
permissions. The 6's
become 4's
The u
was unaffected because 6 &= ~(0)
leaves the value unchanged for u
Third test, umask 0222
. This is going to remove write permission from the u
, g
and o
permissions. NO ONE will be able to write to the file. Not even the owner of the file.
So, where’s this all leading…
It’s all about your umask
.
By default, most shells set the umask
to 0002
which means only the owner and group-owner of the file can WRITE to the file. OTHER cannot. And this is a reasonable default to have for a multi-user system like Unix - Linux, etc…
BUT, if you’re going to have groups – groups that have some sort of groupwise permission across different servers then you will need to know what umask
is so you can configure the shell environment
of the users to set their umask
correctly.
I left out one more thing about permissions. That x
bit. It means different things depending on the kind of file it is.
Let’s get another thing out of the way. Everything in Unix. EVERYTHING. Everything is a file, in Unix. Some files are special, and we call them (you guessed it) special files. Some files are not special, and we just call them files.
A directory is a file.
A file is a file.
A socket is a file.
“stdout”, “stdin”, and “stderr” all are files.
The /dev/sda1
device you see in /dev/
is a file.
Even /proc
is a file
Everything is a file.
And since everything is a file, you can perform C.R.U.D. (create, read, update, delete) on them.
So, the special file that we call “a directory” is a file that uses the x
bit to allow the user involved to search the directory.
There’s nuance here.
Let’s say the file was this:
foo@skynet:~/ff$ mkdir baz
foo@skynet:~/ff$ ls -ld baz
dr-xr-xr-x 2 foo bar 4096 Jan 3 21:02 baz
The directory has mode 555
The directory is named baz
. It’s owned by user foo
. It’s group-owned by bar
We can check WHICH groups the user foo
is in just to make sure this setup is what we want:
$ groups foo
foo : bar
The r-x
permission under u
(the first of the three) means that foo
can read and search the directory. By search we mean to descend into the directory. The group-owner bar
also has r-x
. That means ANY user in group bar
can also, likewise read and search the directory. And to top it off, r-x
is also applied to OTHER – so if the user isn’t the owner, and isn’t the group-owner, they can read and search. Pretty much open season – anyone can see anything IN that directory itself.
No users (not even the owner) can write to the directory though. That’s not really cool or what we want…
If we want to make sure only the owner (foo
) and the group-owner (bar
) can read and search it, then we need to change the mode. We can change the mode like this:
$ chmod 550 baz
$ ls -ld baz
foo@skynet:~/ff$ ls -ld baz
dr-xr-x--- 2 foo bar 4096 Jan 3 21:02 baz
Now only the owner foo
and the group-owner bar
can read and search it. Other users cannot. And NO ONE not even the owner can write files in the directory.
Let’s fix that bit
$ chmod 750 baz
$ ls -ld baz
foo@skynet:~/ff$ ls -ld baz
drwxr-x--- 2 foo baz 4096 Jan 3 21:02 baz
Much better. foo
user can write files all day long, search it, read it, etc… Group owner bar
has a small part to play. They can just inspect (read and search), but cannot make files IN the directory. Other users – shut out completely.
So, going all the way now back to the first question – should you make a user? YES.
And when you make the directory to HOLD the server data, what permission mode are you going to make it?
Let’s say the server is called: DarkerRealms
and that is where the minecraft.properties
file lives, etc…
# addgroup realms
# adduser --ingroup realms darker
# chown -R darker.realms /data/servers/DarkerRealms
# chgrp realms /data/servers
# su darker
darker$ cat >> ~/.bashrc <<EOF
umask 0002
EOF
darker$ cd /data/servers/DarkerRealms
darker$ chmod 750 .
darker$ exit
# exit
Then setup your server there.
Etc…
See a command I didn’t talk about:
$ man COMMAND
More later on this because your other questions also affect the decisions, let’s go!
d. Should I use cron to restart the servers ?
Yes and no. Cron is the best way to schedule things the simplest way. But it can also bite you in the ass. You need to write a shell script that is invoked by cron and IN the shell script you test things to decide whether or not to start the server or not. But cron itself should never actually run java -jar ...
to start the server.
Best course of action to take:
You mentioned screen(1)
, right? So you need to work out a shell script that if run will check:
- Is the screen running?
- If it is, what’s the state of the server? (crash log – more
grep
and other shell script work)
- If it is running and not crashed, do you want it killed? stopped?
- If it is not running, do you want it started?
- Is your dog happy?
- Are these too many questions?
Yes. There’s a better way, IMHO, and that’s to involve both screen
and expect
.
If you don’t like expect
then you can probably get by with just a shell script that will kill off the server, and re-start it. I don’t like that method. I’d prefer expect
so I can actually send the stop
command to the server via the screen. It’s up to you and I am running out of gas in this long post to work out the script. Maybe tomorrow when I am rested. PING ME later. I’ve used expect
to communicate with the server console to issue a large number of commands in order (like setup permission nodes) from a shell script. It’s doable, but you need to do it carefully. I’ll look around for my sample.
But the nuts and bolts of the thing is – if you use cron
to setup jobs to run, then you’ll need to organize a shell script that governs what happens when the java
process exits (due to a crash or stoppage) – leaves a breadcrumb file to be checked by the cron-job and then based on the data there, decide if it should re-fire up the screen
again and so on.
My advice is to work it out in shell scripts that run manually. Simulate the server stopping and inspect that your script systems are properly picking up the crumbs to determine what to do next. Then wrap it up so that your cron-job is merely checking the state and leaving new crumbs behind based on that analysis. Let the script that spawned the screen do the “infinite loop” that can exit only based on the heuristic you’ve designed by the way the scripts leave data behind. Use the filesystem as your data-storage to leave behind information on the next iteration of the loop that will kick off the server again.
e. Should I create an unix service called “minecraft” ? (I don’t why, but I’ve seen it somewhere)
No. No need for that. And, by the way, there is no such thing as a ‘unix service’. It’s called a process and if the process has lost it’s controlling tty, we call that a daemon
. See also: “what is a daemon, zombie and orphan” in Unix.
f. Should I use Docker ? (I don’t know how)
I will risk the hate mail. No. Do not use Docker.
You don’t need Docker for this. But if you want to learn how to use Docker to do this, go ahead. I would caution you that the details of bridging between the non-virtual image (the Docker image) and the real system are not trivial. But I merely use docker
time to time when I am forced to, not voluntarily.
You asked a lot of good questions and it drew out a very long response only because
- You mentioned Unix and that’s my thing.
- You asked questions seldom asked.
Good luck and keep me aware of your progress.