====== Installation et configuration d'un serveur Minecraft sous Linux ====== ===== Avant-propos ===== Mettre en place un serveur Minecraft (//Vanilla//) n'a rien de compliqué en soi : télécharger le JAR, l'exécuter et jouer. Cependant, la plupart des tutoriels que l'on trouve à ce sujet sont parcellaires et négligent bien souvent des points pourtant cruciaux (du moins pour moi), comme la sécurité. Ainsi, l'objectif de cette page est de mettre en place un serveur Minecraft **privé** sur une machine Linux **sans** interface graphique en respectant les contraintes suivantes : * **Sécurité** * Utilisateur dédié et non-root (pour limiter les accès et les dégâts possibles en cas de compromission du serveur) * Configurations adaptées * Utilisation d'une liste blanche pour définir les joueurs autorisés * Ouverture du port dans le pare-feu/''iptables'' * **Fiabilité** * Sauvegardes régulières (quotidiennes) * Arrêt propre du serveur (pas de ''kill -9'' sauvages...) * Utilisation des mécanismes natifs de l'OS (''systemd'', ''cron''...) * **Autonomie** (//"fire and forget"//) * Lancement automatique au démarrage (service) * Fonctionnement en arrière-plan (''screen'') * Accès distant par SSH pour maintenance * **Performances** * La meilleure fluidité possible pour accueillir environ 2-5 utilisateurs simultanés (mais aura de la marge pour en accueillir plus ;-)) En résumé, je souhaite que le serveur Minecraft soit capable d'accueillir entre 2 et 5 personnes dans les meilleures conditions possibles, tout en épargnant les ressources de la machine (partagées avec d'autres services) et sans en négliger les aspects liés à la sécurité. Pour ce faire, je me suis inspiré de plusieurs sources, principalement le projet https://github.com/TheRemote/RaspberryPiMinecraft/ (documenté dans [[https://jamesachambers.com/raspberry-pi-minecraft-server-script-with-startup-service/|cet article]]). ===== Situation initiale ===== Voici les caractéristiques de la machine : ^ CPU | Intel Core i3-4160 CPU @ 3.60GHz | ^ Architecture | x86-64 | ^ RAM | 8 Go | ^ OS | Debian 9 (stretch), 64-bit | ^ Disque | HDD Western Digital Black, 640 Go | ^ Réseau | Gigabit Ethernet, IP statique | À noter que cette machine héberge d'autres services, donc l'objectif n'est pas d'assigner toute la RAM au seul serveur Minecraft ;-) En outre : * ''iptables'' est configuré pour n'autoriser que les seuls ports nécessaires en entrée. * SSH est activé et l'utilisateur root est interdit de connexion. * ''ddclient'' est le client DNS dynamique utilisé afin qu'un (sous-)domaine pointe sur mon IP publique. En savoir plus sur l'environnement configuré : https://wiki.vuilleumier.tv/doku.php?id=server:installation ===== Installation des dépendances ===== Pour commencer, nous installons les dépendances requises pour faire tourner Minecraft en arrière-plan : sudo apt update sudo apt install screen wget -y sudo apt install net-tools -y ==== Installation de Java ==== Sans surprise, //Minecraft Java Edition// ne pourrait pas tourner sans la présence de Java ;-) Nous choisissons ici la variante open-source OpenJDK prévue pour les systèmes d'exploitation sans interface graphique (//headless//). Il est recommandé d'utiliser la version 11 (LTS) au minimum, car elle offre de meilleures performances notamment grâce à son ramasse-miettes //G1GC//. Malheureusement, cette version n'est pas disponible nativement dans les dépôts de Debian 9, alors il nous faut ajouter le dépôt officiel //stretch-backports//. Pour ce faire, éditer le fichier ''sources.list'' : sudo nano /etc/apt/sources.list Et y ajouter la ligne : deb http://deb.debian.org/debian stretch-backports main Maintenant, nous pouvons installer Java 11 : sudo apt install openjdk-11-jdk-headless Si une autre version de Java était déjà installée, vous pourriez avoir besoin de changer la version utilisée par défaut : sudo update-alternatives --config java Cette commande permet de vérifier la version de Java actuellement utilisée : java --version ou (en Java 8) java -version ===== Création du compte utilisateur ===== Pour des raisons évidentes de sécurité, nous n'allons pas faire tourner le processus serveur avec le compte //root// ni un compte possédant les pouvoirs ''su'', mais un utilisateur créé spécialement pour cette occasion. Ainsi, si le serveur est compromis et qu'un attaquant arrive à exécuter des commandes, ses actions seront limitées aux seuls droits et fichiers de ce compte. Pour commencer, nous créons l'utilisateur ''minecraft'' (vous êtes libre de l'appeler ''mcs'', ''mcadmin'' ou ce que vous voulez) : sudo adduser minecraft Comme ce compte sera accessible par SSH, un mot de passe (fort !) doit absolument être défini (on peut laisser les autres informations vides). Le répertoire utilisateur ''/home/minecraft'' et le groupe ''minecraft'' sont automatiquement créés. ===== Configuration de SSH ===== Le système d'exploitation hébergeant le serveur étant dépourvu d'interface graphique, il est indispensable d'autoriser l'utilisateur ''minecraft'' à se connecter en SSH. De plus, cela permet une gestion distante, ce qui est souhaité. Pour cela, nous devons éditer le fichier ''/etc/ssh/sshd_config'' et y ajouter ''minecraft'' à la ligne ''AllowUsers''. Par exemple : AllowUsers admin minecraft Pour terminer, redémarrer le service SSH pour prendre en compte la modification : sudo service ssh restart ===== Téléchargement du serveur Minecraft ===== Il nous faut à présent télécharger le JAR (fichier exécutable Java) du serveur Minecraft et le placer dans le répertoire désiré. Pour ma part, j'ai choisi que ce serait le répertoire home de ''minecraft'', alors on commence par se placer dans celui-ci : cd /home/minecraft Notez que j'ai décidé de continuer de travailler avec le compte admin pour le moment en agissant en tant que ''minecraft'' (avec ''sudo -u minecraft''). Premièrement, il est nécessaire de connaître l'URL de téléchargement de la dernière version du serveur Minecraft (1.16.3, à l'heure où j'écris) en vous rendant à ce lien : https://www.minecraft.net/fr-fr/download/server/ En l'occurrence, nous constatons que l'URL est https://launcher.mojang.com/v1/objects/f02f4473dbf152c23d7d484952121db0b36698cb/server.jar alors nous le téléchargeons : sudo -u minecraft wget -O server.jar https://launcher.mojang.com/v1/objects/f02f4473dbf152c23d7d484952121db0b36698cb/server.jar Lançons le serveur Minecraft une première fois afin qu'il crée sa structure et ses fichiers de base : sudo -u minecraft java -jar -Xms400M -Xmx2G server.jar Le serveur se termine de lui-même, prévenant que nous devons accepter les conditions d'utilisation (EULA), ce que nous faisons : sudo -u minecraft nano eula.txt eula=true ===== Configuration du serveur (server.properties) ===== La configuration du serveur Minecraft se fait par le fichier ''server.properties'', créé automatiquement au lancement. La documentation est trouvable à [[https://minecraft.gamepedia.com/Server.properties|cette adresse]]. Les valeurs par défaut sont majoritairement adaptées, moyennant les personnalisations usuelles (''motd'', difficulté, mode de jeu...), laissées à la libre appréciation de chacun. Toutefois, certains paramètres "avancés" doivent être changés pour correspondre aux exigences précédemment décrites : op-permission-level=3 Par défaut, la valeur est à 4, ce qui signifie que les opérateurs (ops) peuvent utiliser **toutes** les commandes du serveur, y compris ''/stop'', ''/save-all'', ''/save-on'' et ''/save-off''. Ce n'est pas désirable dans notre cas de figure, car seul l'administrateur doit être capable d'arrêter le serveur (avec les mécanismes mis en place dans cette procédure). white-list=true Nous souhaitons restreindre l'accès du serveur aux seuls joueurs autorisés, alors une liste blanche est utilisée (les utilisateurs seront ajoutés à une étape ultérieure). snooper-enabled=false Facultatif. Désactive le "snooping", l'envoi de données de télémétrie du serveur à Mojang/Microsoft. ===== Mise en place des scripts ===== Nous allons à présent créer les scripts de démarrage et d'arrêt du serveur Minecraft ainsi que son service (''systemd'') associé, afin qu'il se lance automatiquement au démarrage de la machine. Avant tout, connectons-nous avec l'utilisateur ''minecraft'' : su - minecraft ==== Script de démarrage ==== Ce script sauvegarde les fichiers du serveur (dans le sous-répertoire ''backups''), puis le démarre avec les bons flags (inspirés de [[https://aikar.co/2018/07/02/tuning-the-jvm-g1gc-garbage-collector-flags-for-minecraft/|cet article de référence]]). Un test s'assure au préalable que le serveur n'est pas déjà en cours de fonctionnement. Le serveur est démarré en arrière-plan avec ''screen'' dans un écran nommé ''mcs''. Nous allons donc créer le fichier ''start.sh'' à la racine du dossier du serveur : #!/bin/bash # Minecraft Server startup script using screen # Check if server is already running if screen -list | grep -q "mcs"; then echo "Server is already running! Type screen -r mcs to open the console" exit 1 fi # Switch to server directory cd /home/minecraft/ # Back up server if [ -d "world" ]; then echo "Backing up server (to minecraft/backups folder)" tar --exclude='backups' --exclude='logs' --exclude='server.jar' -pzcf backups/$(date +%Y.%m.%d.%H.%M.%S).tar.gz * fi echo "Starting Minecraft server. To view window type screen -r mcs." echo "To minimize the window and let the server run in the background, press Ctrl+A then Ctrl+D" screen -dmS mcs java -Xms1G -Xmx3G -XX:+ParallelRefProcEnabled -XX:+DisableExplicitGC -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=30 -XX:G1HeapRegionSize=8M -XX:+PerfDisableSharedMem -jar /home/minecraft/server.jar nogui Adaptez ''Xms'' et ''Xmx'' en fonction de la quantité de mémoire vive que vous souhaitez assigner au serveur Minecraft et selon les caractéristiques matérielles de votre machine ! On doit attribuer au script les droits d'exécution : chmod +x start.sh ==== Script d'arrêt ==== Adapté de [[https://github.com/TheRemote/RaspberryPiMinecraft/blob/master/stop.sh|ce script]], il permet d'arrêter le serveur proprement (en y envoyant la commande ''stop''). Cet arrêt est annoncé 30 secondes avant aux joueurs par le canal de discussions. Nous allons créer le fichier ''stop.sh'' dans le dossier du serveur : #!/bin/bash # James Chambers - March 2nd 2019 # Minecraft Server stop script - primarily called by minecraft service but can be ran manually # Check if server is running if ! screen -list | grep -q "mcs"; then echo "Server is not currently running!" exit 1 fi # Stop the server #if [ "$1" == "announce" ]; then echo "Sending stop notifications to server..." screen -Rd mcs -X stuff "say Server is stopping in 30 seconds! $(printf '\r')" sleep 23s screen -Rd mcs -X stuff "say Server is stopping in 7 seconds! $(printf '\r')" sleep 1s screen -Rd mcs -X stuff "say Server is stopping in 6 seconds! $(printf '\r')" sleep 1s screen -Rd mcs -X stuff "say Server is stopping in 5 seconds! $(printf '\r')" sleep 1s screen -Rd mcs -X stuff "say Server is stopping in 4 seconds! $(printf '\r')" sleep 1s screen -Rd mcs -X stuff "say Server is stopping in 3 seconds! $(printf '\r')" sleep 1s screen -Rd mcs -X stuff "say Server is stopping in 2 seconds! $(printf '\r')" sleep 1s screen -Rd mcs -X stuff "say Server is stopping in 1 second! $(printf '\r')" sleep 1s #fi echo "Stopping Minecraft server ..." screen -Rd mcs -X stuff "say Closing server (stop.sh called)...$(printf '\r')" screen -Rd mcs -X stuff "stop$(printf '\r')" # Wait up to 30 seconds for server to close StopChecks=0 while [ $StopChecks -lt 30 ]; do if ! screen -list | grep -q "mcs"; then break fi sleep 1; StopChecks=$((StopChecks+1)) done # Force quit if server is still open if screen -list | grep -q "mcs"; then echo "Minecraft server still hasn't closed after 30 seconds, closing screen manually" screen -S mcs -X quit fi echo "Minecraft server stopped." # Sync all filesystem changes out of temporary RAM sync Ne pas oublier une fois encore de lui attribuer les droits d'exécution : chmod +x stop.sh Se déconnecter de l'utilisateur ''minecraft'' avec logout ===== Création du service ===== À ce stade, il est déjà possible de démarrer et d'arrêter le serveur avec les scripts que nous venons de créer. Seulement, nous souhaitons que celui-ci se lance automatiquement au démarrage de la machine, raison pour laquelle un service ''systemd'' est mis en place. Il est nécessaire d'être connecté avec un compte possédant les droits administrateur (''su'') à cette étape. Nous allons tout d'abord créer le fichier ''/etc/systemd/system/minecraft.service'' : [Unit] Description=minecraft server service After=network-online.target [Service] User=minecraft WorkingDirectory=/home/minecraft ProtectSystem=full Type=forking ExecStart=/bin/bash /home/minecraft/start.sh ExecStop=/bin/bash /home/minecraft/stop.sh GuessMainPID=no TimeoutStartSec=600 [Install] WantedBy=multi-user.target Ne pas oublier de changer ''User'' et les chemins ''WorkingDirectory'', ''ExecStart'' et ''ExecStop'' en conséquence si vous un autre utilisateur ou un autre répertoire racine ont été choisis. Comme les scripts, ce fichier doit avoir les droits d'exécution : sudo chmod +x minecraft.service Nous activons à présent le service afin qu'il puisse démarrer automatiquement : sudo systemctl enable minecraft.service Nous démarrons le service (ce qui lancera le serveur) : sudo systemctl start minecraft.service Finalement, nous planifions le redémarrage du serveur tous les jours à 4 heures du matin (sauvegarde quotidienne) : sudo crontab -e 0 4 * * * /bin/systemctl restart minecraft.service ===== Ouverture du port ===== Le serveur est démarré, le service opérationnel, il ne reste plus qu'à ouvrir le bon port (25565) dans le "pare-feu" (ici, ''iptables''). C'est bien entendu facultatif si vous n'en possédez pas. Nous allons par conséquent éditer le fichier ''/etc/iptables/rules.v4'' afin d'y ajouter la ligne suivante : # Accept Minecraft Server -A INPUT -p tcp -m tcp --dport 25565 -j ACCEPT ===== Configuration de la liste blanche et des opérateurs ===== À ce stade, le serveur est prêt et fonctionnel. Il ne reste plus qu'à ajouter les joueurs autorisés à la liste blanche et définir qui est opérateur (op). On se connecte tout d'abord à la console du serveur depuis le compte ''minecraft'' : screen -r mcs Ensuite, on autorise les joueurs ''player1'' et ''player2'' (les pseudos renseignés doivent exister) : whitelist add player1 player2 Et on ajoute ''toto'' aux opérateurs (ils sont automatiquement en liste blanche) : op toto Pour finir, on utilise la combinaison de touches ''Ctrl+A'' et ''Ctrl+D'' pour réduire la console (ne surtout pas la fermer, sinon le serveur sera arrêté !). ---- ===== Erreurs et solutions ===== Voici quelques erreurs que j'ai rencontrées et leurs solutions. ==== Échec de connexion au serveur (authentification impossible) ==== À la connexion au serveur, certains utilisateurs rencontraient l'erreur "//Minecraft server authentication servers are down. please try again later sorry//". La solution consiste à mettre à jour la liste des certificats Java du serveur à l'aide de ces deux commandes : sudo dpkg --purge --force-depends ca-certificates-java sudo apt install ca-certificates-java Source : https://www.reddit.com/r/Minecraft/comments/8fpy67/failure_to_connect_to_authentication_servers_on/ ---- ===== Améliorations possibles ===== * Utilisation du serveur PaperMC (plus fluide, compatible avec les mods Spigot et Bukkit) * Activation de rcon pour la gestion du serveur à distance ---- ===== Commandes utiles ===== ==== Se connecter à la console du serveur ==== Depuis le compte ''minecraft'' : minecraft$ screen -r mcs Puis ''Ctrl+A'' et ''Ctrl+D'' pour réduire la fenêtre (ne surtout pas la fermer, sinon le serveur sera arrêté !). ==== Démarrer le serveur ==== admin$ sudo systemctl start minecraft.service ==== Arrêter le serveur ==== admin$ sudo systemctl stop minecraft.service Rappel : il faut compter au minimum 30 secondes pour son arrêt complet. ==== Mettre à jour le serveur (server.jar) ==== Tout d'abord, arrêter le serveur avec la commande précédente. Ensuite, télécharger le nouvelle version du serveur (se mettre dans ''/home/minecraft'' au préalable) : admin$ sudo -u minecraft wget -O server.jar URL L'URL est trouvable sur cette page : https://www.minecraft.net/fr-fr/download/server/ Historique : * 1.15.2 : https://launcher.mojang.com/v1/objects/bb2b6b1aefcd70dfd1892149ac3a215f6c636b07/server.jar * 1.16 : https://launcher.mojang.com/v1/objects/a0d03225615ba897619220e256a266cb33a44b6b/server.jar * 1.16.1 : https://launcher.mojang.com/v1/objects/a412fd69db1f81db3f511c1463fd304675244077/server.jar * 1.16.3 : https://launcher.mojang.com/v1/objects/f02f4473dbf152c23d7d484952121db0b36698cb/server.jar * 1.16.4 : https://launcher.mojang.com/v1/objects/35139deedbd5182953cf1caa23835da59ca3d7cd/server.jar * 1.16.5 : https://launcher.mojang.com/v1/objects/1b557e7b033b583cd9f66746b7a9ab1ec1673ced/server.jar * 1.17.1 : https://launcher.mojang.com/v1/objects/a16d67e5807f57fc4e550299cf20226194497dc2/server.jar * 1.18 : https://launcher.mojang.com/v1/objects/3cf24a8694aca6267883b17d934efacc5e44440d/server.jar * 1.18.1 : https://launcher.mojang.com/v1/objects/125e5adf40c659fd3bce3e66e67a16bb49ecc1b9/server.jar Finalement, redémarrer le serveur avec la commande indiquée ci-dessus. ==== Se connecter à l'utilisateur minecraft depuis un autre compte ==== admin$ su - minecraft ==== Lister les écrans screen ==== minecraft$ screen -list