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
- Prérequis
- Installation
- Paramétrage
- Pare-feu et ouverture du port
- Se connecter depuis le jeu
- Commandes en jeu
- Sécurité
- Sauvegarde et restauration
- Mise à jour
- Désinstallation
- Journaux
- Dépannage
Prérequis
- Linux avec systemd, processeur x86_64 ou aarch64, et un accès root ou
sudo. Installation testée sur Debian 13 aarch64 ; les autres distributions devraient convenir, sans avoir été vérifiées. - Un port TCP accessible par les joueurs, 25770 par défaut.
- Pour une installation depuis les sources : Rust 1.82 ou plus récent (testé avec 1.85), avec
cargo, et un compilateur C pour l'édition de liens (build-essentialsur Debian et Ubuntu). - Pour Docker : Docker et Docker Compose.
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ément | Emplacement |
|---|---|
| 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 service | bastide |
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
| Option | Effet | |
|---|---|---|
--port N | Port TCP, de 1024 à 65535 | |
--seed GRAINE | Graine du nouveau monde | |
| `--mode survie\ | creatif` | Mode de jeu |
--motd TEXTE | Message d'accueil | |
--view-distance N | Distance de vue en chunks | |
--max-players N | Nombre maximal de joueurs | |
--binary CHEMIN | Installe ce binaire | |
--from-source | Compile avec cargo | |
--no-start | N'active ni ne démarre le service (première installation) ; ne le redémarre pas (mise à jour) | |
--uninstall | Désinstalle, en gardant monde et configuration | |
--purge | Désinstalle et efface aussi monde, configuration et utilisateur | |
--yes | Confirme --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.
| Action | Commande |
|---|---|
| Journal | docker compose logs -f |
| Arrêter, données conservées | docker compose down |
Mettre à jour après un git pull | docker 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.
| Variable | Option | Défaut | Rôle |
|---|---|---|---|
BASTIDE_PORT | --port | 25770 | Port TCP |
BASTIDE_WORLD | --world | world ; /var/lib/bastide/world sous systemd | Dossier du monde |
BASTIDE_SEED | --seed | aléatoire | Graine du monde |
BASTIDE_VIEW_DISTANCE | --view-distance | 8 | Distance de vue, en chunks |
BASTIDE_MODE | --mode | survie | Mode à la connexion |
BASTIDE_MOTD | --motd | Bienvenue sur Bastide ! | Message d'accueil |
BASTIDE_MAX_PLAYERS | --max-players | 32 | Joueurs connectés au maximum |
BASTIDE_PASSWORD | --password | aucun | Mot de passe demandé à la connexion |
BASTIDE_ADMINS | --admins | aucun | Pseudos autorisés aux commandes de triche, séparés par des virgules |
Précisions :
BASTIDE_PORT: le serveur écoute sur toutes les interfaces IPv4 (0.0.0.0). On ne peut choisir ni l'interface ni l'IPv6. Une valeur invalide empêche le démarrage. Sous systemd, un port inférieur à 1024 est refusé, car l'unité retire toutes les capacités au service.BASTIDE_WORLD: le serveur ignore ses erreurs d'écriture. S'il ne peut pas écrire dans ce dossier, il tourne normalement, annonce même « monde sauvegardé », mais ne garde rien. Pour utiliser un autre dossier, donnez-le à l'utilisateurbastideet autorisez-le dans l'unité : puis ajoutez :sudo install -d -o bastide -g bastide /srv/bastide sudo systemctl edit bastide-server[Service] ReadWritePaths=/srv/bastideBASTIDE_SEED: un entier est utilisé tel quel, un texte est converti en nombre. La valeur0donne une graine aléatoire. La graine n'est lue qu'à la création du monde, puis conservée danslevel.txt: la changer ensuite n'a aucun effet, même si le serveur ne le signale pas. Pour repartir d'un nouveau monde, arrêtez le serveur et déplacez le dossierworld.BASTIDE_VIEW_DISTANCE: ramenée entre 2 et 32. Chaque cran augmente nettement la mémoire, le processeur et le débit réseau.BASTIDE_MODE: toute valeur commençant par uncminuscule donne le créatif, tout le reste la survie.Creatifavec une majuscule donne donc la survie. Le mode est celui de chaque joueur à sa connexion ; un changement par/gamemodene dure que jusqu'à la déconnexion.BASTIDE_MAX_PLAYERS: un joueur en trop reçoit « Serveur complet ». Une valeur non numérique empêche le démarrage.
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.
| Commande | Effet | |||
|---|---|---|---|---|
/who ou /list | Joueurs connectés | |||
/niveau | Son niveau et son expérience | |||
/xp nombre | Donne de l'expérience à soi-même | |||
/seed | Graine du monde | |||
/spawn | Retour au point de départ | |||
/village | Téléporte au village le plus proche (à moins de 4000 blocs) | |||
/terrespales ou /realm | Téléporte aux Terres Pâles | |||
/recif ou /sunken | Téléporte au Récif englouti | |||
/lieu | Téléporte au lieu à découvrir le plus proche | |||
| `/meteo clair\ | pluie\ | orage` | Change le temps pour tout le monde | |
/tp x y z | Té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 mobs | Retire 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.
- Mot de passe facultatif. Définissez
BASTIDE_PASSWORD: sans lui, le serveur accepte tout le monde. Il est commun à tous les joueurs et circule en clair. - Pseudos réservés. Le premier client qui utilise un pseudo le réserve avec un secret tiré à son premier lancement. Qui réinstalle le jeu perd ce secret : supprimez alors le fichier
players/<pseudo>.keydu monde pour libérer le pseudo. - Droits d'administration. Seuls les pseudos de
BASTIDE_ADMINSont/gamemode,/tp,/time,/summon,/meteoet/kill mobs. Réservez d'abord votre pseudo en vous connectant. - Pas de modération fine. Pas d'exclusion, pas de bannissement, pas de protection des constructions, et pas de console serveur.
- Aucun chiffrement. Le protocole circule en clair sur TCP, y compris le mot de passe et le chat.
- Limites réseau simples. Le nombre de connexions simultanées est plafonné à deux fois le nombre de joueurs plus 16, et une connexion muette est fermée après 10 secondes. Cela ne remplace pas un vrai filtrage contre une attaque déterminée.
En pratique, réservez le serveur à des personnes de confiance :
- Le mieux : ne pas ouvrir le port à Internet et faire passer les joueurs par un VPN (WireGuard, Tailscale, etc.).
- 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 - 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 :
systemctl status bastide-server: le service tourne-t-il ?sudo ss -ltnp | grep 25770: le port écoute-t-il, et est-ce bien le bon ?nc -vz 127.0.0.1 25770sur le serveur, puisnc -vz adresse 25770depuis 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 :
impossible d'ouvrir le port: port déjà pris, ou inférieur à 1024 (sudo ss -ltnppour trouver qui l'occupe) ;port invalide,distance invalide,nombre invalide: valeur incorrecte dansserver.env.
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.