Dockerized 3-server dedicated cluster for Last Oasis, auto-updated via SteamCMD.
449
Docker cluster of three Last Oasis dedicated servers (lastoasis-1/2/3), each hosting one adjacent map tile so players can sail from one zone to the next without a loading break. SteamCMD App ID 920720 (installer) / 903950 (runtime), running as an unprivileged steam user.
ludix0/lastoasis (single image, reused by all three services)7777/udp + 27003/udp (server 1), 7776/udp + 27015/udp (server 2), 7775/udp + 7774/udp (server 3)⚠️ Strict startup order. The three services share one install folder (filesServer) and one SteamCMD cache. Only lastoasis-1 is allowed to update it (UPDATE_ON_START=true); lastoasis-2 and lastoasis-3 only launch the binary that is already there (UPDATE_ON_START=false). You must always:
lastoasis-1 alone and wait until it is stable (logs stop scrolling / container reports healthy).lastoasis-2 and lastoasis-3.Starting server 2 or 3 too early risks launching a binary that SteamCMD is still mid-update on — a broken/incomplete server. A Docker HEALTHCHECK (based on the game process actually running) is used as the depends_on: condition: service_healthy gate for servers 2 and 3 in the example below, but you should still watch the logs of server 1 the first time.
CUSTOMER_KEY (same for the whole realm) and one PROVIDER_KEY per server — see "Advanced notes" belowmkdir -p ~/lastoasis && cd ~/lastoasis
Create a myrealm.env (your MyRealm keys — never commit this file):
CUSTOMER_KEY=your_customer_key
PROVIDER_KEY_1=your_provider_key_for_server_1
PROVIDER_KEY_2=your_provider_key_for_server_2
PROVIDER_KEY_3=your_provider_key_for_server_3
Create a docker-compose.yml:
services:
lastoasis-1:
image: ludix0/lastoasis:latest
container_name: lastoasis-1
restart: unless-stopped
volumes:
# filesServer and steamcmd are SHARED between the 3 servers: one
# single install/update, no redundant download.
- ./filesServer:/home/steam/lastoasis_server
- ./saves-1:/home/steam/lastoasis_server/Mist/Saved
- ./steamcmd:/home/steam/steamcmd
env_file:
- myrealm.env
environment:
- TZ=Europe/Paris
- PUID=1000
- PGID=1000
# Only server 1 updates the shared install folder.
- UPDATE_ON_START=true
- STEAM_USER=
- STEAM_PASSWORD=
- SERVER_SLOT=1
- SERVER_IDENTIFIER=My_LastOasis_01
- SLOTS=50
- GAME_PORT=7777
- QUERY_PORT=27003
- EXTERNAL_IP=
ports:
- "7777:7777/udp"
- "27003:27003/udp"
lastoasis-2:
image: ludix0/lastoasis:latest
container_name: lastoasis-2
restart: unless-stopped
# Waits for lastoasis-1 to report "healthy" so it never reads the shared
# folder while server 1 is mid-update.
depends_on:
lastoasis-1:
condition: service_healthy
volumes:
- ./filesServer:/home/steam/lastoasis_server
- ./saves-2:/home/steam/lastoasis_server/Mist/Saved
- ./steamcmd:/home/steam/steamcmd
env_file:
- myrealm.env
environment:
- TZ=Europe/Paris
- PUID=1000
- PGID=1000
- UPDATE_ON_START=false
- STEAM_USER=
- STEAM_PASSWORD=
- SERVER_SLOT=2
- SERVER_IDENTIFIER=My_LastOasis_02
- SLOTS=50
- GAME_PORT=7776
- QUERY_PORT=27015
- EXTERNAL_IP=
ports:
- "7776:7776/udp"
- "27015:27015/udp"
lastoasis-3:
image: ludix0/lastoasis:latest
container_name: lastoasis-3
restart: unless-stopped
depends_on:
lastoasis-1:
condition: service_healthy
volumes:
- ./filesServer:/home/steam/lastoasis_server
- ./saves-3:/home/steam/lastoasis_server/Mist/Saved
- ./steamcmd:/home/steam/steamcmd
env_file:
- myrealm.env
environment:
- TZ=Europe/Paris
- PUID=1000
- PGID=1000
- UPDATE_ON_START=false
- STEAM_USER=
- STEAM_PASSWORD=
- SERVER_SLOT=3
- SERVER_IDENTIFIER=My_LastOasis_03
- SLOTS=50
- GAME_PORT=7775
- QUERY_PORT=7774
- EXTERNAL_IP=
ports:
- "7775:7775/udp"
- "7774:7774/udp"
Deploy in the required order — do not use a plain docker compose up -d for the whole stack the first time:
# 1. Start server 1 alone (it owns the shared install/update)
docker compose up -d lastoasis-1
docker compose logs -f lastoasis-1
# → if Steam Guard asks for a code (rare once already authenticated once),
# stop it (Ctrl+C, docker compose stop lastoasis-1) and rerun interactively:
# docker compose run --rm -it lastoasis-1
# → wait for the logs to settle (Paks finished loading) before continuing
# 2. Once lastoasis-1 is stable, start the other two
docker compose up -d lastoasis-2 lastoasis-3
# 3. Follow the logs (all services, or one with -f service-name)
docker compose logs -f
git clone https://github.com/ludix0/lost-oasis.git
cd lost-oasis
ln -sf /path/to/your/secrets.env .env # or create a .env with STEAM_USER/STEAM_PASSWORD/etc.
# fill in myrealm.env with your CUSTOMER_KEY and PROVIDER_KEY_1/2/3
docker build -t ludix0/lastoasis:latest .
docker compose up -d lastoasis-1
# wait for it to be stable, then:
docker compose up -d lastoasis-2 lastoasis-3
Common variables (same meaning on all 3 services):
| Variable | Required | Description |
|---|---|---|
TZ, PUID, PGID | No | Timezone and host user/group to run the container as |
STEAM_USER / STEAM_PASSWORD | Yes | Real Steam account — Last Oasis has no anonymous SteamCMD login |
UPDATE_ON_START | No | true on lastoasis-1 only; false on the other two (see startup order above) |
CUSTOMER_KEY | Yes | MyRealm customer key, same value on all 3 servers (set once in myrealm.env) |
PROVIDER_KEY_1 / _2 / _3 | Yes | One key per server, generated on myrealm.lastoasis.gg → Settings → "Self hosted game servers registration keys" |
SERVER_SLOT | Yes | 1/2/3 — tells start_server.sh which PROVIDER_KEY_x to use for this container |
SERVER_IDENTIFIER | No | Server name shown in-game/on MyRealm, should differ per service |
SLOTS | No | Player slot limit |
GAME_PORT / QUERY_PORT | No | Must match the port actually published (see Ports table) — Last Oasis announces these values itself to MyRealm, there is no Docker-side redirection |
EXTERNAL_IP | No | Leave empty: detected automatically at startup |
SERVER_PASSWORD / ADMIN_PASSWORD | No | Kept for consistency with other game servers, but not used by Last Oasis — access is controlled via CUSTOMER_KEY/PROVIDER_KEY, not a password |
| Volume | Content | Shared across the 3 servers? |
|---|---|---|
/home/steam/lastoasis_server | Server binaries (installed by SteamCMD) | Yes — one single install |
/home/steam/lastoasis_server/Mist/Saved | World save for that tile/zone | No — one save folder per server (saves-1/2/3) |
/home/steam/steamcmd | SteamCMD installation | Yes — avoids downloading it 3 times |
All ports are UDP; the container-internal port is always identical to the published host port, since Last Oasis announces its own -port/-QueryPort value to MyRealm as the connect address (no Docker port-mapping awareness).
| Server | Game port | Query port |
|---|---|---|
lastoasis-1 | 7777/udp | 27003/udp |
lastoasis-2 | 7776/udp | 27015/udp |
lastoasis-3 | 7775/udp | 7774/udp |
filesServer and steamcmd are mounted into all 3 containers. Only lastoasis-1 runs SteamCMD (UPDATE_ON_START=true); the other two simply exec the binary that is already on disk. This avoids 3 concurrent downloads of the same ~15 GB install and 3 copies on disk.myrealm.env: create this file yourself (never commit it — it holds secrets). It needs CUSTOMER_KEY (one value, shared) and PROVIDER_KEY_1/PROVIDER_KEY_2/PROVIDER_KEY_3 (one distinct key per server). Generate the provider keys on myrealm.lastoasis.gg → Settings → "Self hosted game servers registration keys" — one new key is needed for each server you add to the cluster.920720 ("Last Oasis - Dedicated Server" tool); the running binary authenticates to Steamworks with App ID 903950 (the game itself), written automatically to Mist/Binaries/Linux/steam_appid.txt by start_server.sh.Cluster Docker de trois serveurs dédiés Last Oasis (lastoasis-1/2/3), chacun hébergeant une tuile de carte adjacente, pour permettre aux joueurs de naviguer d'une zone à l'autre sans coupure. App ID SteamCMD 920720 (installateur) / 903950 (exécution), lancé avec un utilisateur steam non privilégié.
ludix0/lastoasis (une seule image, réutilisée par les 3 services)7777/udp + 27003/udp (serveur 1), 7776/udp + 27015/udp (serveur 2), 7775/udp + 7774/udp (serveur 3)⚠️ Ordre de démarrage strict. Les trois services partagent un seul dossier d'installation (filesServer) et un seul cache SteamCMD. Seul lastoasis-1 est autorisé à le mettre à jour (UPDATE_ON_START=true) ; lastoasis-2 et lastoasis-3 se contentent de lancer le binaire déjà présent (UPDATE_ON_START=false). Il faut toujours :
lastoasis-1 seul et attendre qu'il soit stable (les logs cessent de défiler / le conteneur passe healthy).lastoasis-2 et lastoasis-3.Démarrer le serveur 2 ou 3 trop tôt risque de lancer un binaire en cours de mise à jour par SteamCMD — un serveur cassé/incomplet. Un HEALTHCHECK Docker (basé sur le processus du jeu réellement lancé) sert de condition depends_on: condition: service_healthy pour les serveurs 2 et 3 dans l'exemple ci-dessous, mais il faut quand même surveiller les logs du serveur 1 la première fois.
CUSTOMER_KEY (identique pour tout le realm) et une PROVIDER_KEY par serveur — voir "Notes avancées" ci-dessousmkdir -p ~/lastoasis && cd ~/lastoasis
Créer un myrealm.env (vos clés MyRealm — ne jamais commiter ce fichier) :
CUSTOMER_KEY=votre_customer_key
PROVIDER_KEY_1=votre_provider_key_serveur_1
PROVIDER_KEY_2=votre_provider_key_serveur_2
PROVIDER_KEY_3=votre_provider_key_serveur_3
Créer un docker-compose.yml :
services:
lastoasis-1:
image: ludix0/lastoasis:latest
container_name: lastoasis-1
restart: unless-stopped
volumes:
# filesServer et steamcmd sont PARTAGÉS entre les 3 serveurs : une
# seule installation/mise à jour, pas de téléchargement redondant.
- ./filesServer:/home/steam/lastoasis_server
- ./saves-1:/home/steam/lastoasis_server/Mist/Saved
- ./steamcmd:/home/steam/steamcmd
env_file:
- myrealm.env
environment:
- TZ=Europe/Paris
- PUID=1000
- PGID=1000
# Seul le serveur 1 met à jour le dossier partagé.
- UPDATE_ON_START=true
- STEAM_USER=
- STEAM_PASSWORD=
- SERVER_SLOT=1
- SERVER_IDENTIFIER=Mon_LastOasis_01
- SLOTS=50
- GAME_PORT=7777
- QUERY_PORT=27003
- EXTERNAL_IP=
ports:
- "7777:7777/udp"
- "27003:27003/udp"
lastoasis-2:
image: ludix0/lastoasis:latest
container_name: lastoasis-2
restart: unless-stopped
# Attend que lastoasis-1 soit "healthy" pour ne jamais lire le dossier
# partagé pendant que le serveur 1 est en train de le mettre à jour.
depends_on:
lastoasis-1:
condition: service_healthy
volumes:
- ./filesServer:/home/steam/lastoasis_server
- ./saves-2:/home/steam/lastoasis_server/Mist/Saved
- ./steamcmd:/home/steam/steamcmd
env_file:
- myrealm.env
environment:
- TZ=Europe/Paris
- PUID=1000
- PGID=1000
- UPDATE_ON_START=false
- STEAM_USER=
- STEAM_PASSWORD=
- SERVER_SLOT=2
- SERVER_IDENTIFIER=Mon_LastOasis_02
- SLOTS=50
- GAME_PORT=7776
- QUERY_PORT=27015
- EXTERNAL_IP=
ports:
- "7776:7776/udp"
- "27015:27015/udp"
lastoasis-3:
image: ludix0/lastoasis:latest
container_name: lastoasis-3
restart: unless-stopped
depends_on:
lastoasis-1:
condition: service_healthy
volumes:
- ./filesServer:/home/steam/lastoasis_server
- ./saves-3:/home/steam/lastoasis_server/Mist/Saved
- ./steamcmd:/home/steam/steamcmd
env_file:
- myrealm.env
environment:
- TZ=Europe/Paris
- PUID=1000
- PGID=1000
- UPDATE_ON_START=false
- STEAM_USER=
- STEAM_PASSWORD=
- SERVER_SLOT=3
- SERVER_IDENTIFIER=Mon_LastOasis_03
- SLOTS=50
- GAME_PORT=7775
- QUERY_PORT=7774
- EXTERNAL_IP=
ports:
- "7775:7775/udp"
- "7774:7774/udp"
Déployer dans l'ordre requis — ne pas faire un simple docker compose up -d sur toute la stack la première fois :
# 1. Démarrer le serveur 1 seul (il gère la mise à jour du dossier partagé)
docker compose up -d lastoasis-1
docker compose logs -f lastoasis-1
# → si un code Steam Guard est demandé (rare si déjà connecté une fois),
# arrêter (Ctrl+C, docker compose stop lastoasis-1) et relancer en
# interactif : docker compose run --rm -it lastoasis-1
# → attendre que les logs se stabilisent (fin du chargement des Paks)
# 2. Une fois lastoasis-1 stable, démarrer les deux autres
docker compose up -d lastoasis-2 lastoasis-3
# 3. Suivre les logs (tous les services, ou un seul avec -f nom-service)
docker compose logs -f
git clone https://github.com/ludix0/lost-oasis.git
cd lost-oasis
ln -sf /chemin/vers/votre/secrets.env .env # ou créer un .env avec STEAM_USER/STEAM_PASSWORD/etc.
# remplir myrealm.env avec votre CUSTOMER_KEY et PROVIDER_KEY_1/2/3
docker build -t ludix0/lastoasis:latest .
docker compose up -d lastoasis-1
# attendre qu'il soit stable, puis :
docker compose up -d lastoasis-2 lastoasis-3
Variables communes (même rôle sur les 3 services) :
| Variable | Obligatoire | Description |
|---|---|---|
TZ, PUID, PGID | Non | Fuseau horaire et utilisateur/groupe hôte pour le conteneur |
STEAM_USER / STEAM_PASSWORD | Oui | Vrai compte Steam — Last Oasis n'a pas de connexion SteamCMD anonyme |
UPDATE_ON_START | Non | true sur lastoasis-1 uniquement ; false sur les deux autres (voir ordre de démarrage ci-dessus) |
CUSTOMER_KEY | Oui | Clé client MyRealm, même valeur sur les 3 serveurs (à définir une fois dans myrealm.env) |
PROVIDER_KEY_1 / _2 / _3 | Oui | Une clé différente par serveur, générée sur myrealm.lastoasis.gg → Settings → "Self hosted game servers registration keys" |
SERVER_SLOT | Oui | 1/2/3 — indique à start_server.sh quelle PROVIDER_KEY_x utiliser pour ce conteneur |
SERVER_IDENTIFIER | Non | Nom du serveur affiché en jeu/sur MyRealm, à différencier par service |
SLOTS | Non | Nombre maximum de joueurs |
GAME_PORT / QUERY_PORT | Non | Doit correspondre au port réellement publié (voir tableau Ports) — Last Oasis annonce lui-même ces valeurs à MyRealm, sans notion de redirection côté Docker |
EXTERNAL_IP | Non | Laisser vide : détectée automatiquement au démarrage |
SERVER_PASSWORD / ADMIN_PASSWORD | Non | Présentes pour cohérence avec les autres serveurs de jeu, mais non utilisées par Last Oasis — l'accès est géré via CUSTOMER_KEY/PROVIDER_KEY, pas par mot de passe |
| Volume | Contenu | Partagé entre les 3 serveurs ? |
|---|---|---|
/home/steam/lastoasis_server | Binaires du serveur (installés par SteamCMD) | Oui — une seule installation |
/home/steam/lastoasis_server/Mist/Saved | Sauvegarde de la tuile/zone | Non — un dossier de sauvegarde par serveur (saves-1/2/3) |
/home/steam/steamcmd | Installation SteamCMD | Oui — évite de la télécharger 3 fois |
Tous les ports sont en UDP ; le port interne du conteneur est toujours identique au port hôte exposé, car Last Oasis annonce lui-même sa valeur -port/-QueryPort à MyRealm comme adresse de connexion (aucune notion de redirection Docker côté jeu).
| Serveur | Port jeu | Port query |
|---|---|---|
lastoasis-1 | 7777/udp | 27003/udp |
lastoasis-2 | 7776/udp | 27015/udp |
lastoasis-3 | 7775/udp | 7774/udp |
filesServer et steamcmd sont montés dans les 3 conteneurs. Seul lastoasis-1 exécute SteamCMD (UPDATE_ON_START=true) ; les deux autres se contentent de lancer le binaire déjà présent sur le disque. Cela évite 3 téléchargements concurrents de la même installation (~15 Go) et 3 copies sur le disque.myrealm.env : ce fichier est à créer soi-même (ne jamais le commiter — il contient des secrets). Il doit contenir CUSTOMER_KEY (une seule valeur, partagée) et PROVIDER_KEY_1/PROVIDER_KEY_2/PROVIDER_KEY_3 (une clé distincte par serveur). Les clés provider se génèrent sur myrealm.lastoasis.gg → Settings → "Self hosted game servers registration keys" — une nouvelle clé est nécessaire pour chaque serveur ajouté au cluster.920720 (outil "Last Oasis - Dedicated Server") ; le binaire en cours d'exécution s'authentifie auprès de Steamworks avec l'App ID 903950 (le jeu lui-même), écrit automatiquement dans Mist/Binaries/Linux/steam_appid.txt par start_server.sh.Content type
Image
Digest
sha256:eb2adc1ce…
Size
241.9 MB
Last updated
7 days ago
docker pull ludix0/lastoasis