Sign inSign up

ludix0/lastoasis

By ludix0

•Updated 7 days ago

Dockerized 3-server dedicated cluster for Last Oasis, auto-updated via SteamCMD.

Image
0

449

ludix0/lastoasis repository overview

⁠Last Oasis — 3-Server Cluster (Docker)

🇬🇧 English⁠ | 🇫🇷 Français⁠


⁠English

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.

  • Docker Hub image: ludix0/lastoasis⁠ (single image, reused by all three services)
  • Ports used: 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:

  1. Start lastoasis-1 alone and wait until it is stable (logs stop scrolling / container reports healthy).
  2. Only then start 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.

⁠Requirements
  • Docker + Docker Compose
  • A real Steam account with the Last Oasis dedicated server tool — anonymous SteamCMD login does not work for this game
  • ~15 GB free disk space for the shared server install (shared by all 3 services, not 3x)
  • 3 MyRealm keys: one CUSTOMER_KEY (same for the whole realm) and one PROVIDER_KEY per server — see "Advanced notes" below
  • 6 UDP ports forwarded on your router if the cluster must be reachable from the internet
mkdir -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
⁠Method 2 — Build from source (GitHub)
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
⁠Environment variables

Common variables (same meaning on all 3 services):

VariableRequiredDescription
TZ, PUID, PGIDNoTimezone and host user/group to run the container as
STEAM_USER / STEAM_PASSWORDYesReal Steam account — Last Oasis has no anonymous SteamCMD login
UPDATE_ON_STARTNotrue on lastoasis-1 only; false on the other two (see startup order above)
CUSTOMER_KEYYesMyRealm customer key, same value on all 3 servers (set once in myrealm.env)
PROVIDER_KEY_1 / _2 / _3YesOne key per server, generated on myrealm.lastoasis.gg⁠ → Settings → "Self hosted game servers registration keys"
SERVER_SLOTYes1/2/3 — tells start_server.sh which PROVIDER_KEY_x to use for this container
SERVER_IDENTIFIERNoServer name shown in-game/on MyRealm, should differ per service
SLOTSNoPlayer slot limit
GAME_PORT / QUERY_PORTNoMust match the port actually published (see Ports table) — Last Oasis announces these values itself to MyRealm, there is no Docker-side redirection
EXTERNAL_IPNoLeave empty: detected automatically at startup
SERVER_PASSWORD / ADMIN_PASSWORDNoKept for consistency with other game servers, but not used by Last Oasis — access is controlled via CUSTOMER_KEY/PROVIDER_KEY, not a password
⁠Volumes
VolumeContentShared across the 3 servers?
/home/steam/lastoasis_serverServer binaries (installed by SteamCMD)Yes — one single install
/home/steam/lastoasis_server/Mist/SavedWorld save for that tile/zoneNo — one save folder per server (saves-1/2/3)
/home/steam/steamcmdSteamCMD installationYes — avoids downloading it 3 times
⁠Ports

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).

ServerGame portQuery port
lastoasis-17777/udp27003/udp
lastoasis-27776/udp27015/udp
lastoasis-37775/udp7774/udp
⁠Advanced notes
  • Shared SteamCMD install: 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.
  • One-time manual step after the very first startup: once all 3 servers have started successfully at least once, log in to MyRealm → "Realms" and place the 3 tiles adjacent to each other on the grid. This manual, website-side step is what actually enables seamless travel between the zones — nothing on the Docker side can do it for you.
  • App IDs: SteamCMD download uses App ID 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.

⁠Français

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é.

  • Image Docker Hub : ludix0/lastoasis⁠ (une seule image, réutilisée par les 3 services)
  • Ports utilisés : 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 :

  1. Démarrer lastoasis-1 seul et attendre qu'il soit stable (les logs cessent de défiler / le conteneur passe healthy).
  2. Démarrer ensuite seulement 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.

⁠Prérequis
  • Docker + Docker Compose
  • Un vrai compte Steam avec l'outil serveur dédié Last Oasis — la connexion SteamCMD anonyme ne fonctionne pas pour ce jeu
  • ~15 Go d'espace disque libre pour l'installation partagée (partagée entre les 3 services, pas x3)
  • 3 clés MyRealm : une CUSTOMER_KEY (identique pour tout le realm) et une PROVIDER_KEY par serveur — voir "Notes avancées" ci-dessous
  • 6 ports UDP redirigés sur votre routeur si le cluster doit être accessible depuis internet
⁠Méthode 1 — Installation rapide depuis Docker Hub (recommandé)
mkdir -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
⁠Méthode 2 — Build depuis les sources (GitHub)
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 d'environnement

Variables communes (même rôle sur les 3 services) :

VariableObligatoireDescription
TZ, PUID, PGIDNonFuseau horaire et utilisateur/groupe hôte pour le conteneur
STEAM_USER / STEAM_PASSWORDOuiVrai compte Steam — Last Oasis n'a pas de connexion SteamCMD anonyme
UPDATE_ON_STARTNontrue sur lastoasis-1 uniquement ; false sur les deux autres (voir ordre de démarrage ci-dessus)
CUSTOMER_KEYOuiClé client MyRealm, même valeur sur les 3 serveurs (à définir une fois dans myrealm.env)
PROVIDER_KEY_1 / _2 / _3OuiUne clé différente par serveur, générée sur myrealm.lastoasis.gg⁠ → Settings → "Self hosted game servers registration keys"
SERVER_SLOTOui1/2/3 — indique à start_server.sh quelle PROVIDER_KEY_x utiliser pour ce conteneur
SERVER_IDENTIFIERNonNom du serveur affiché en jeu/sur MyRealm, à différencier par service
SLOTSNonNombre maximum de joueurs
GAME_PORT / QUERY_PORTNonDoit 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_IPNonLaisser vide : détectée automatiquement au démarrage
SERVER_PASSWORD / ADMIN_PASSWORDNonPré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
⁠Volumes
VolumeContenuPartagé entre les 3 serveurs ?
/home/steam/lastoasis_serverBinaires du serveur (installés par SteamCMD)Oui — une seule installation
/home/steam/lastoasis_server/Mist/SavedSauvegarde de la tuile/zoneNon — un dossier de sauvegarde par serveur (saves-1/2/3)
/home/steam/steamcmdInstallation SteamCMDOui — évite de la télécharger 3 fois
⁠Ports

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).

ServeurPort jeuPort query
lastoasis-17777/udp27003/udp
lastoasis-27776/udp27015/udp
lastoasis-37775/udp7774/udp
⁠Notes avancées
  • Installation SteamCMD partagée : 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.
  • Étape manuelle unique après le tout premier démarrage : une fois les 3 serveurs démarrés avec succès au moins une fois, se connecter sur MyRealm → "Realms" et placer les 3 tuiles adjacentes les unes aux autres sur la grille. C'est cette étape manuelle, côté site web, qui active réellement le voyage sans coupure entre les zones — rien côté Docker ne peut la remplacer.
  • App ID : le téléchargement SteamCMD utilise l'App ID 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.

Tag summary

Content type

Image

Digest

sha256:eb2adc1ce…

Size

241.9 MB

Last updated

7 days ago

docker pull ludix0/lastoasis