Bastide

Héberger un serveur Bastide

Ce guide explique comment installer, régler et entretenir le serveur dédié bastide-server, en priorité sur Linux avec systemd.

À lire avant d'ouvrir un serveur à Internet : le mot de passe est facultatif et le trafic n'est pas chiffré. Voir Sécurité.

Sommaire

  1. Prérequis
  2. Installation
  3. Paramétrage
  4. Pare-feu et ouverture du port
  5. Se connecter depuis le jeu
  6. Commandes en jeu
  7. Sécurité
  8. Sauvegarde et restauration
  9. Mise à jour
  10. Désinstallation
  11. Journaux
  12. Dépannage

Prérequis

Le besoin en mémoire et en processeur n'a pas encore été mesuré avec de vrais joueurs. Il dépend surtout du nombre de joueurs et de la distance de vue. Sur le disque, seuls les chunks modifiés sont enregistrés : un monde peu construit reste petit.

Sous Windows et macOS, le binaire se lance à la main (options ci-dessous), mais install.sh et l'unité systemd ne concernent que Linux. Sous Windows, Ctrl+C et la fermeture de la console déclenchent une sauvegarde ; ce chemin n'a pas encore été testé sur une vraie machine Windows.

Installation

Les trois méthodes installent la même chose. Les deux premières utilisent install.sh, qui peut être relancé sans risque et place les fichiers ainsi :

ÉlémentEmplacement
Programme/usr/local/bin/bastide-server
Configuration (jamais écrasée)/etc/bastide/server.env
Monde/var/lib/bastide/world
Unité systemd/etc/systemd/system/bastide-server.service
Guide, exemple de configuration, copie d'install.sh/usr/local/share/bastide/
Utilisateur système du servicebastide

Depuis une archive (recommandé)

Fabriquer l'archive, sur une machine de développement avec le dépôt :

tools/server/package_linux.sh                  # x86_64 depuis un Mac, architecture locale sous Linux
tools/server/package_linux.sh --arch aarch64   # pour un serveur ARM

Le script écrit dist/bastide-server-<version>-linux-<arch>.tar.gz et son empreinte .sha256. Il compile nativement sous Linux, sinon dans Docker. Le build Docker donne un binaire statique, qui fonctionne sur toutes les distributions ; il est à préférer. Sous Linux sans la cible musl (rustup target add <arch>-unknown-linux-musl), le binaire exige une glibc au moins aussi récente que celle de la machine de compilation. Sur Mac, Docker est indispensable : le script explique ce qui manque s'il n'est pas lancé.

Installer sur le serveur :

scp dist/bastide-server-*-linux-x86_64.tar.gz moi@serveur:
ssh moi@serveur
tar xzf bastide-server-*-linux-x86_64.tar.gz
cd bastide-server-*-linux-x86_64
sudo ./install.sh --mode survie --motd "Bienvenue sur mon serveur"

Depuis les sources

Sur la machine serveur, avec Rust installé pour votre utilisateur ou pour le système :

git clone <adresse du dépôt> bastide
cd bastide
sudo tools/server/install.sh --mode survie

Sous sudo, la compilation se fait au nom de votre utilisateur (SUDO_USER), avec le cargo de ~/.cargo/bin s'il existe. --from-source force la compilation si un binaire est présent à côté du script, et --binary CHEMIN installe un binaire déjà compilé.

Options d'install.sh

OptionEffet
--port NPort TCP, de 1024 à 65535
--seed GRAINEGraine du nouveau monde
`--mode survie\creatif`Mode de jeu
--motd TEXTEMessage d'accueil
--view-distance NDistance de vue en chunks
--max-players NNombre maximal de joueurs
--binary CHEMINInstalle ce binaire
--from-sourceCompile avec cargo
--no-startN'active ni ne démarre le service (première installation) ; ne le redémarre pas (mise à jour)
--uninstallDésinstalle, en gardant monde et configuration
--purgeDésinstalle et efface aussi monde, configuration et utilisateur
--yesConfirme --purge sans question

Les six premières options ne servent qu'à créer /etc/bastide/server.env. Si ce fichier existe, il n'est pas modifié et le script signale les options ignorées : modifiez-le alors à la main.

Avec Docker

Depuis le dépôt :

cd tools/server
docker compose up -d --build

Le réglage se fait dans la section environment de tools/server/docker-compose.yml, avec les variables décrites ci-dessous. Après une modification, relancez docker compose up -d. Le monde est dans le volume bastide-data, monté sur /data, et Docker envoie SIGTERM à l'arrêt, avec 30 secondes pour sauvegarder (stop_grace_period). Ne changez pas BASTIDE_WORLD : l'image le règle sur /data/world, et ce volume ne couvre rien d'autre.

ActionCommande
Journaldocker compose logs -f
Arrêter, données conservéesdocker compose down
Mettre à jour après un git pulldocker compose up -d --build

N'ajoutez pas -v à docker compose down : cette option efface le monde.

Docker publie le port en contournant souvent ufw : vérifiez depuis l'extérieur ce qui est réellement accessible.

Paramétrage

Sous systemd, modifiez /etc/bastide/server.env puis appliquez :

sudo systemctl restart bastide-server

Syntaxe du fichier : VARIABLE=valeur, sans espace autour du =, guillemets doubles si la valeur contient des espaces, et commentaires sur leur propre ligne. Une variable vide vaut une variable absente. Toutes les variables reconnues par le serveur sont listées ici. Chacune a une option équivalente en ligne de commande, prioritaire sur la variable.

VariableOptionDéfautRôle
BASTIDE_PORT--port25770Port TCP
BASTIDE_WORLD--worldworld ; /var/lib/bastide/world sous systemdDossier du monde
BASTIDE_SEED--seedaléatoireGraine du monde
BASTIDE_VIEW_DISTANCE--view-distance8Distance de vue, en chunks
BASTIDE_MODE--modesurvieMode à la connexion
BASTIDE_MOTD--motdBienvenue sur Bastide !Message d'accueil
BASTIDE_MAX_PLAYERS--max-players32Joueurs connectés au maximum
BASTIDE_PASSWORD--passwordaucunMot de passe demandé à la connexion
BASTIDE_ADMINS--adminsaucunPseudos autorisés aux commandes de triche, séparés par des virgules

Précisions :

Pare-feu et ouverture du port

Seul le port TCP (25770 par défaut) est utilisé, et aucun UDP. Le script d'installation ne touche pas au pare-feu. Adaptez le numéro si vous l'avez changé.

ufw (Debian, Ubuntu) :

sudo ufw allow 25770/tcp

firewalld (Fedora, Rocky, AlmaLinux) :

sudo firewall-cmd --permanent --add-port=25770/tcp
sudo firewall-cmd --reload

nftables, si vous gérez une table inet filter à la main :

sudo nft add rule inet filter input tcp dport 25770 accept

VPS ou cloud : ouvrez aussi le port dans le pare-feu de l'hébergeur (groupe de sécurité), qui s'ajoute à celui de la machine.

À domicile : sur la box, redirigez le port TCP 25770 externe vers l'adresse locale du serveur, et donnez à celui-ci une adresse locale fixe. Certains accès (CGNAT) ne permettent pas de recevoir de connexions : un VPN, ou un VPS, est alors nécessaire.

Vérifier, sur le serveur puis depuis une autre machine :

sudo ss -ltnp | grep 25770
nc -vz adresse-du-serveur 25770

Se connecter depuis le jeu

Dans l'écran d'accueil, renseignez Pseudo, Serveur et, s'il y en a un, Mot de passe, puis choisissez Rejoindre le serveur. Le premier joueur qui utilise un pseudo se le réserve : ce pseudo est ensuite lié à son installation du jeu. Sans port dans l'adresse, le jeu utilise 25770. Un autre port s'indique ainsi : exemple.fr:30000.

En ligne de commande :

bastide --connect exemple.fr --name MonPseudo

Commandes en jeu

Touche T ou / pour ouvrir la saisie. Le serveur n'a pas de console : ces commandes ne s'utilisent qu'en jeu. Sur un serveur dédié, seuls /who, /seed, /niveau et /aide sont ouverts à tous : le reste est réservé aux pseudos de BASTIDE_ADMINS. En solo, toutes les commandes sont disponibles.

CommandeEffet
/who ou /listJoueurs connectés
/niveauSon niveau et son expérience
/xp nombreDonne de l'expérience à soi-même
/seedGraine du monde
/spawnRetour au point de départ
/villageTéléporte au village le plus proche (à moins de 4000 blocs)
/terrespales ou /realmTéléporte aux Terres Pâles
/recif ou /sunkenTéléporte au Récif englouti
/lieuTéléporte au lieu à découvrir le plus proche
`/meteo clair\pluie\orage`Change le temps pour tout le monde
/tp x y zTéléporte aux coordonnées
`/gamemode creatif\survie ou /gm`Change son propre mode
`/time jour\midi\soir\nuit`Change l'heure pour tout le monde
/summon nom [x y z]Fait apparaître une créature (/summon seul donne la liste)
/kill mobsRetire toutes les créatures du monde

Sécurité : à lire avant d'ouvrir à Internet

Voici ce que le code du serveur fait réellement aujourd'hui.

En pratique, réservez le serveur à des personnes de confiance :

  1. Le mieux : ne pas ouvrir le port à Internet et faire passer les joueurs par un VPN (WireGuard, Tailscale, etc.).
  2. Sinon : n'autoriser que les adresses de vos joueurs. Avec ufw :
    sudo ufw allow from 203.0.113.10 to any port 25770 proto tcp
  3. Dans tous les cas : sauvegardez régulièrement le monde, seul recours contre le vandalisme.

Côté système, le service tourne sous un utilisateur dédié, sans capacités, avec un système de fichiers en lecture seule sauf /var/lib/bastide. Cela limite les dégâts d'une éventuelle faille du serveur, mais ne protège pas le monde contre les joueurs.

Sauvegarde et restauration du monde

Le serveur sauvegarde automatiquement toutes les 30 secondes, et à l'arrêt propre (systemctl stop, docker stop, Ctrl+C). Un arrêt brutal (kill -9, coupure de courant) perd ce qui a changé depuis la dernière sauvegarde automatique. Les créatures et les objets au sol ne sont pas enregistrés et disparaissent à chaque redémarrage, même propre.

Contenu du dossier world : level.txt (graine), time.txt (heure), containers.txt (coffres et fours), crops.txt (cultures), chunks/ (blocs modifiés), players/ (position, inventaire, lit, quêtes, niveau, pseudo réservé).

Une écriture impossible (droits, disque plein) apparaît dans le journal sous la forme ERREUR : ..., et les chunks concernés sont retentés à la sauvegarde suivante. Si la boucle de jeu s'arrête sur une erreur interne, le processus se termine en échec et systemd le relance.

Sauvegarder. Le serveur ne propose pas de suspendre ses écritures : pour une copie cohérente, arrêtez-le quelques instants.

sudo systemctl stop bastide-server
sudo tar czf "bastide-world-$(date +%F-%H%M).tar.gz" -C /var/lib/bastide world
sudo systemctl start bastide-server

Copiez l'archive sur une autre machine : une sauvegarde sur le même disque ne protège pas d'une panne.

Restaurer :

sudo systemctl stop bastide-server
sudo mv /var/lib/bastide/world "/var/lib/bastide/world.avant-restauration"
sudo tar xzf bastide-world-AAAA-MM-JJ-HHMM.tar.gz -C /var/lib/bastide
sudo chown -R bastide:bastide /var/lib/bastide
sudo systemctl start bastide-server

N'oubliez pas le chown : sans lui, le serveur ne peut pas écrire et ne le signale pas. Quand tout est vérifié, supprimez world.avant-restauration.

Avec Docker. Le nom complet du volume est préfixé par le projet Compose, soit server_bastide-data depuis tools/server (vérifiez avec docker volume ls).

cd tools/server
docker compose stop
docker run --rm -v server_bastide-data:/data -v "$PWD":/sauvegarde debian:bookworm-slim \
    tar czf /sauvegarde/bastide-world.tar.gz -C /data world
docker compose start

Pour restaurer, après docker compose stop :

docker run --rm -v server_bastide-data:/data -v "$PWD":/sauvegarde debian:bookworm-slim \
    sh -c 'rm -rf /data/world && tar xzf /sauvegarde/bastide-world.tar.gz -C /data && chown -R 1000:1000 /data'
docker compose start

Mise à jour

Une version du serveur ne fonctionne qu'avec les clients du même PROTOCOL_VERSION : mettez à jour le jeu des joueurs en même temps si ce numéro change. Le fichier VERSION de l'archive l'indique.

Par précaution, sauvegardez le monde, puis :

tar xzf bastide-server-<version>-linux-<arch>.tar.gz
cd bastide-server-<version>-linux-<arch>
sudo ./install.sh

Depuis les sources : git pull puis sudo tools/server/install.sh.

Le script vérifie d'abord que le nouveau binaire s'exécute sur la machine. Il arrête ensuite le service (ce qui sauvegarde le monde), remplace le programme et l'unité, puis redémarre le service s'il était lancé ou en échec. Un service arrêté volontairement le reste. Le monde et server.env ne sont pas touchés. Comparez votre configuration à l'exemple livré pour repérer d'éventuelles nouveautés :

sudo diff /etc/bastide/server.env /usr/local/share/bastide/server.env.example

L'unité systemd est remplacée à chaque mise à jour : placez vos adaptations dans systemctl edit bastide-server.

Désinstallation

Une copie du script reste dans /usr/local/share/bastide/ :

sudo /usr/local/share/bastide/install.sh --uninstall           # garde monde, configuration, utilisateur
sudo /usr/local/share/bastide/install.sh --uninstall --purge   # efface tout, sans retour possible

--purge demande de taper « oui », ou exige --yes hors d'un terminal. Un monde placé hors de /var/lib/bastide n'est jamais effacé.

Journaux

journalctl -u bastide-server -f              # en direct
journalctl -u bastide-server -n 100          # 100 dernières lignes
journalctl -u bastide-server --since today   # depuis ce matin
systemctl status bastide-server              # état du service

Lignes utiles : à l'écoute sur (démarrage), monde « … », graine …, mode … (réglages appliqués), connexion de et départ de (joueurs), <pseudo> texte (chat), N chunk(s) sauvegardé(s), arrêt, monde sauvegardé (arrêt propre) et panicked (plantage). Les tentatives refusées pour version incompatible ne sont pas journalisées.

Dépannage

« Version incompatible (serveur X, client Y) »

Le jeu et le serveur n'ont pas le même PROTOCOL_VERSION (crates/common/src/lib.rs), et ce numéro doit être strictement identique. Le message donne les deux valeurs : installez sur le serveur, ou sur le poste du joueur, une version construite avec le même numéro. Sur le serveur, le numéro de l'archive installée se lit avec cat /usr/local/share/bastide/VERSION ; ce fichier n'existe pas après une installation depuis les sources.

« Connexion impossible »

Testez dans l'ordre :

  1. systemctl status bastide-server : le service tourne-t-il ?
  2. sudo ss -ltnp | grep 25770 : le port écoute-t-il, et est-ce bien le bon ?
  3. nc -vz 127.0.0.1 25770 sur le serveur, puis nc -vz adresse 25770 depuis l'extérieur. Si le premier réussit et pas le second, cherchez du côté du pare-feu, de l'hébergeur ou de la box.

« Serveur complet » ou « … est déjà connecté »

Le premier message : augmentez BASTIDE_MAX_PLAYERS. Le second : ce pseudo est utilisé (sans distinction de casse), ou une ancienne connexion n'est pas encore fermée ; changez de pseudo ou réessayez un peu plus tard.

Le service ne démarre pas

Lisez journalctl -u bastide-server -n 50. Le serveur s'arrête sur un message de plantage dans ces cas :

Après 5 démarrages en 5 minutes, relances manuelles comprises, systemd refuse de continuer (start-limit-hit, ou « Start request repeated too quickly »). Une fois le problème corrigé :

sudo systemctl reset-failed bastide-server
sudo systemctl start bastide-server

Le service paraît actif mais les joueurs sont déconnectés aussitôt

Si le cœur du serveur plante, le processus reste vivant : le port répond et systemctl status indique active, mais la partie ne fonctionne plus et Restart=on-failure ne se déclenche pas. Cherchez panicked dans le journal, puis redémarrez. Ce qui a changé depuis la dernière sauvegarde automatique est perdu. Merci de signaler le message.

journalctl -u bastide-server | grep -A3 panicked
sudo systemctl restart bastide-server

Le monde ne se sauvegarde pas ou revient en arrière

Le serveur n'affiche pas d'erreur quand une écriture échoue. Vérifiez :

sudo find /var/lib/bastide ! -user bastide | head   # ne doit rien afficher
df -h /var/lib/bastide                              # disque plein ?
grep BASTIDE_WORLD /etc/bastide/server.env          # dossier attendu ?
ls -l --time-style=full-iso /var/lib/bastide/world/time.txt   # date récente, serveur lancé ?

time.txt est réécrit à chaque sauvegarde : s'il n'est pas à jour, le serveur n'écrit pas. Corrigez les droits avec sudo chown -R bastide:bastide /var/lib/bastide.

bastide-server « ne s'exécute pas sur cette machine »

Message d'install.sh. L'archive ne correspond pas à l'architecture (uname -m), ou le binaire a été lié à une glibc plus récente que celle du serveur. Utilisez une archive de la bonne architecture, construite par Docker pour qu'elle soit statique, ou installez depuis les sources.

Connaître sa version

bastide-server --version affiche la version et le numéro de protocole, sans lancer le serveur.

« Le pseudo appartient à un autre joueur »

Ce pseudo est réservé par une autre installation du jeu. Changez de pseudo, ou, si c'est bien le vôtre, supprimez players/<pseudo>.key dans le dossier du monde.

« Commande réservée aux administrateurs »

Ajoutez le pseudo à BASTIDE_ADMINS et redémarrez le service.