Blog de Norore
Geek en perdition dans un monde qui va trop vite

Monter un serveur Minecraft sous Linux

24 May 2026 - Norore

Ça me reprend depuis plusieurs mois, et si je montais mon propre serveur Minecraft ? Juste pour moi et y inviter des potes ? Ma moitié ayant un serveur qui dort dans la baie, il m’a gentiment proposé de m’y installer une VM dédiée. J’ai d’anciens scripts qui dorment, et je trouvais un peu dommage de passer par la commande screen pour pouvoir interagir avec le serveur depuis la console Linux. Du coup, il m’a été soufflé l’idée de monter un service systemd, que je connais déjà un peu, et de voir comment me passer de mon vieux script en bash. Je vous explique ici ce que j’ai réussi à mettre en place, à adapter selon vos besoins, sachant que c’est très certainement améliorable.

Préparation du serveur

Installation de la version de Java en fonction de la version du jeu que l’on veut mettre en serveur. Pour Minecraft 26.1.2, il faut Java 25. On a juste besoin de la version headless, plus légère, et qui suffit à exécuter du code Java compilé.

apt install openjdk-25-jre-headless

Comme je veux utiliser un service systemd, je vais aussi créer un groupe et un utilisateur dédiés pour faire tourner le serveur Minecraft. J’en profite pour lui créer les répertoires pour le serveur, les sauvegardes du monde, et les scripts éventuels, comme un script d’arrêt ou un script de… sauvegarde.

groupadd -r minecraft  
useradd -r -g minecraft -d "/home/mineternity" -s "/bin/bash" mineternity
mkdir -p /home/mineternity/{backup,scripts,server}
chown -R mineternity:minecraft /home/mineternity/

Puis je récupère le fichier .jar pour le serveur de la version que je veux mettre en place depuis le site officiel :

curl -o /home/mineternity/server/minecraft_server.jar ${url_de_mojang}/server.jar

Création du service systemd

On crée le service systemd dans /usr/lib/systemd/system/mineternity.service :

[Unit]
Description=Mineternity Minecraft Server Service
Wants=network.target
After=network.target

[Service]
Type=simple
Nice=5
KillMode=mixed
SuccessExitStatus=0 1

User=mineternity
Group=minecraft

Sockets=mineternity.socket
StandardInput=socket
StandardOutput=journal
StandardError=journal

ProtectSystem=full
PrivateDevices=true
NoNewPrivileges=true
PrivateTmp=true
InaccessibleDirectories=/root /var /sys /srv -/opt /media -/lost+found
ReadWriteDirectories=/home/mineternity/server /home/mineternity/scripts /run/minecraft
WorkingDirectory=/home/mineternity/server

ExecStart=java -Xmx2G -Xms1G -jar minecraft_server.jar -nogui
ExecStop=/home/mineternity/scripts/stop_server.sh

[Install]
WantedBy=multi-user.target
Alias=mineternity.service

Une fois votre service créé, il est possible que systemd vous indique que vous devez recharger le daemon, faites-le :

systemd daemon-reload

À chaque modification que vous apporterez à votre service, il faudra penser à recharger le daemon, systemd devrait normalement être configuré pour vous avertir dans ce cas.

J’avoue, j’ai triché. J’ai trouvé une bonne partie de ces lignes, ainsi que celles de la partie précédente, dans un billet de blog : https://teilgedanken.de/Blog/post/setting-up-a-minecraft-server-using-systemd/

Ce que j’ai trouvé de plus particulièrement intéressant dans ce billet, c’est la partie sécurité, en cherchant à éviter un potentiel attaquant de remonter dans les répertoires systèmes. Je ne dis pas que c’est la meilleure solution ou configuration, mais elle m’aura appris plein de choses qui me donnent envie d’essayer d’autres trucs !

Comment fonctionne le service ?

Le service ne peut faire tourner le serveur qu’en étant l’utilisateur mineternity du groupe minecraft et il ne peut travailler que dans le répertoire /home/mineternity/server, ça évite de pourrir la racine du serveur et les bêtises potentielles. (Been there, done that… Vous ne voulez pas nettoyer derrière 😀 !) Il ne peut lire et écrire que dans les répertoires :

  • /home/mineternity/server
  • /home/mineternity/scripts
  • /run/minecraft

Il ne peut pas obtenir d’autres privilèges que ceux donnés au groupe et à l’utilisateur (directive NoNewPriveleges). Le système ne lui est pas non plus autorisé. Les points de montage (devices) lui sont privés (au sens seul l’utilisateur et son groupe y sont autorisés). Il a également un répertoire temporaire privé.

On lui indique également quels sont les répertoires auxquels il n’a pas accès. J’ai donc choisi de lui limiter le plus possible ses accès, je verrai sur le long terme si c’est trop ou pas assez.

Pour en savoir plus sur les directives des services systemd : https://www.freedesktop.org/software/systemd/man/latest/systemd.directives.html (CTRL+F est votre meilleur ami sur cette page, il n’y a que 7031 termes…)

Mais euh, comment il fait pour écrire au serveur du jeu ?

Le serveur Minecraft est configuré pour lire les commandes (say, tell, op, deop, whitelist…) qui lui sont envoyées (non, il ne manque pas le / dans ces commandes). C’est là que le socket systemd intervient !

À chaque fois que le service va vouloir écrire sur le serveur ouvert, il va écrire (StandardInput) dans le socket ouvert mineternity.socket.

OK. Et pour lire ce qu’il se passe ?

C’est un service systemd, vous pouvez donc lire les entrées de journalctl pour l’unité concernée. Voici comment vous pouvez faire pour lire en temps réel :

journalctl -u mineternity -f

Rien ne vous empêche d’avoir un tmux ouvert quelque part avec la lecture de journalctl en arrière-plan si vous en ressentez le besoin.

Création du socket

Là, c’est la partie un peu plus casse-tête que j’ai eu, mais j’ai fini par trouver un code source qui m’a été d’une grande aide !

[Unit]
BindsTo=mineternity.service

[Socket]
ListenFIFO=/run/minecraft/mineternity.stdin
Service=mineternity.service
SocketUser=mineternity
SocketGroup=minecraft
RemoveOnStop=true
SocketMode=0660

Le socket avec lequel je vais vouloir interagir écoute sur le fichier /run/minecraft/mineternity.stdin. Tout ce qui entre dedans va réagir comme si vous entriez une instruction dans le chat du jeu.

Encore une fois, on limite qui peut interagir avec le socket. On configure le chmod du socket (SocketMode) pour plus de sécurité et de contrôle. Enfin, on précise à systemd que lorsque le service auquel il est relié (BindsTo) est arrêté, on supprime le fichier stdin.

La source d’origine vient de ce dépôt GitHub : https://github.com/mfnalex/minecraft-systemd/

Et c’est aussi de là que viennent les lignes, dans le service, qui permettent d’interagir avec le socket.

Ouvrir le port

Je ne connais pas du tout nftables ! Déjà qu’iptables me faisait peur, là, j’ai encore plus peur. Mais j’ai trouvé comment faire pour ouvrir un port, même si c’est une bête ligne à ajouter…

Éditer le fichier /etc/nftables.conf :

[...]
table inet filter {
    chain input {
        [...]
        tcp dport 25565 accept comment "minecraft";
    }
    [...]
}

Une fois le fichier modifié, il faut recharger nftables :

systemd reload nftables

J’ai pu tester, ça fonctionne, même si j’ai eu un peu peur de me retrouver dehors…

Script d’arrêt

Parce que j’ai beau ne pas être à l’aise socialement, je ne suis pas encore totalement sauvage. J’ai donc écrit un script, à la rache, pour prévenir les joueurs quand je coupe le serveur, pour une raison ou pour une autre.

#!/bin/bash

STDIN="/run/minecraft/mineternity.stdin"

echo "say Arret du serveur dans 10 secondes." > $STDIN
sleep 5
echo "say Arret du serveur dans 5 secondes." > $STDIN
sleep 1
echo "say Arret du serveur dans 4 secondes." > $STDIN
sleep 1
echo "say Arret du serveur dans 3 secondes." > $STDIN
sleep 1
echo "say Arret du serveur dans 2 secondes." > $STDIN
sleep 1
echo "say Arret du serveur dans 1 seconde." > $STDIN
sleep 1
echo "say Arret du serveur." > $STDIN
sleep .1
echo "stop" > $STDIN
sleep 10

(J’ai mon certificat de La Rache, c’est bon, j’ai le droit 😤 !)

Pour aller plus loin

Je n’ai pas encore ré-écrit le script pour les sauvegardes, mais le principe reste le même. Il faudra juste préciser dans le service que l’utilisateur doit pouvoir lire et écrire dans le répertoire qui contiendra les sauvegardes. Ce qui impliquera un arrêt du service, un rechargement du daemon, puis un lancement du service. Bien sûr, pour bien faire ce script devra également être exécuté à intervalles réguliers, pour cela, il faudra passer par une tâche CRON.

Pour vous aider à écrire une tâche CRON, vous pouvez passer par le site crontab guru.

Enfin, n’oubliez pas d’ajouter votre nouveau service dans les services enabled de systemd, ainsi en cas de redémarrage de la machine ou de la machine, votre serveur Minecraft sera relancé automatiquement sans intervention de votre part.

systemd enable mineternity.service

Quelques sources

En français :

En anglais :