Skip to content

About

Trackmania Forever dedicated server with the Trakman TypeScript controller (https://github.com/lythx/trakman), packaged as a Docker image and wired for a full stack (game server + PostgreSQL) via Docker Compose

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Trackmania Forever Dedicated Server

Trackmania Forever dedicated server with the Trakman TypeScript controller, packaged as a Docker image and wired for a full stack (game server + PostgreSQL) via Docker Compose.

Coming from an XAseco server? Your players, records, karma votes and donations can be carried over, see migration/MIGRATION.md.

About this fork

The controller in trakman/ started as Trakman 1.6 and has been significantly reworked since. It's versioned separately, starting at 2.0.0. Highlights:

  • Docker deployment: dedicated server, Trakman and PostgreSQL via Docker Compose, configured from .env, with a self-hosted UI icon server.
  • Configuration: JSON overrides in config/ that apply while the server runs, and plugins that can be enabled, disabled or restarted in-game with //plugin. Feature widgets now live in their own plugins.
  • New features: //disabletimer / //enabletimer, movable BestCps / BestFinishes / CpCounter widgets, a public API fallback for author nicknames and flags, and direct map writes (up to 5MB) with manual map loading.
  • Bug fixes: crashes on Highlands and other modded maps, juked maps playing twice, duplicate records, stale local ranks, /list search on styled names, TMX screenshots, blank widget icons, and webservices errors without credentials.
  • XAseco migration: see migration/MIGRATION.md.

The full list is in trakman/CHANGELOG.md, also shown in-game with /changes. Because of these changes, upstream releases can't be copied over directly, see Updating Trakman.

Quick start

  1. Install Docker with the Compose plugin.
  2. cp .env.example .env and fill in the required values.
  3. Put your .Challenge.Gbx files in tracks/.
  4. docker compose up -d --build

To stop: docker compose down

Layout

Path Purpose
trakman/ Vendored Trakman source, forked from 1.6 and reworked, see About this fork. Its config files (trakman/config/, trakman/plugins/**/*Config*.js) are the defaults.
config/ Trakman config overrides as JSON, mounted into the container. See config/README.md.
docker/entrypoint.sh Renders server config from env, then runs the dedicated server and Trakman together. If either exits the container exits and Compose restarts it.
docker/templates/ dedicated_cfg and MatchSettings templates (@VAR@ placeholders). They're rendered into the image filesystem at start and never into a mounted volume.
migration/ One-shot XAseco MySQL → PostgreSQL migration, see migration/MIGRATION.md.
tracks/ .Challenge.Gbx files, mounted at GameData/Tracks/Challenges/Custom. Every map in it is played. Two example tracks are included.
music/ .ogg files, mounted at GameData/Music. Not committed.
icons/ Self-hosted copy of Trakman's UI icons, served by docker/icon-server.mjs (see below).

The dedicated server binary is downloaded from Nadeo's official 2011-02-21 release at build time and checked against a pinned SHA-256.

Services and ports

Service Purpose
postgres PostgreSQL 16, data in the trackmania_postgres_data volume. Not published to the host.
tmuf-server Dedicated server + Trakman + UI icon server
legacy-mysql, migrate Only started with --profile migrate, for the XAseco migration.

Published ports: 2350 and 3450 (UDP and TCP), and 8080 (TCP) for UI icons. XML-RPC (5000) stays inside the container.

Environment variables

See .env.example for the full list. Required:

  • SERVER_LOGIN / SERVER_LOGIN_PASSWORD: a dedicated server account.
  • SERVER_SA_PASSWORD: SuperAdmin password. Trakman logs in as SuperAdmin with it.
  • MASTERADMIN_LOGIN: becomes the Trakman owner. Add other admins in-game with //addadmin <login> (stored in the database).
  • DB_PASSWORD: PostgreSQL password (plus optional DB_USER / DB_NAME).

Optional: server name, password and limits (SERVER_*, MAX_PLAYERS), game mode settings (GAMEMODE and the per-mode limits), CUSTOM_MUSIC_ENABLED, DEDIMANIA_PASSWORD (defaults to SERVER_LOGIN_PASSWORD), WEBSERVICES_LOGIN / WEBSERVICES_PASSWORD, ICONS_URL, LOG_LEVEL and TZ.

Tracks

Copy .Challenge.Gbx files into tracks/ (subfolders work too) and restart the container with docker compose restart tmuf-server. On every start the container puts every map in tracks/ into the server's map list, so there's no playlist to maintain, and maps added in-game through TMX stay in rotation after a restart. To take a map out of rotation, remove its file. The two included tracks are only examples, remove them if you don't want them. If tracks/ has no maps, the server falls back to the Nations campaign.

UI icons

Players' game clients download every widget icon over HTTP. Trakman normally points them at trakman.ptrk.eu, where downloads can fail partway and leave blank buttons, a different set for each player. The container serves its own copy from icons/ on port 8080. Set ICONS_URL to the address players can reach, e.g. ICONS_URL=http://your.server.host:8080/icons, and open TCP 8080 in the host firewall. When ICONS_URL is empty, Trakman uses trakman.ptrk.eu.

To use your own banner on the end-of-map screen, add an image (around 4:1) to icons/ and name it in config/plugins/donations/ui/BannerWidget.config.json, e.g. { "image": "MyBanner.png" }. A plain file name is loaded from the icon host, a full URL is used as is. The default is CrazyTrakman.png. Files in icons/ are copied into the image, so rebuild after adding one.

Custom music

  1. Copy .ogg (or .mux) files into music/. Any file name works.

  2. Add one entry per song to config/plugins/music/SongList.json (create it if it doesn't exist). url is Music/<file name>, a path the server serves from GameData, so no web server is needed:

    [
      { "name": "Song Title", "author": "Artist", "url": "Music/Artist - Song Title.ogg" },
      { "name": "Another Song", "author": "Someone Else", "url": "Music/another-song.ogg" }
    ]
  3. The first time, set CUSTOM_MUSIC_ENABLED=True in .env and recreate the container with docker compose up -d.

After that, edits to SongList.json apply while the server runs: the music plugin restarts with the new list. music/ is mounted, so new files don't need a rebuild either.

//addsong <name> <author> <url> adds a song in-game, but only until the next restart. Add songs you want to keep to SongList.json.

Other music settings go in config/plugins/music/Config.json (defaults in trakman/plugins/music/Config.js).

Plugins

Plugins are registered in trakman/Plugins.ts. Whether one starts is set by isEnabled in config/plugins/<name>/Config.json (see config/README.md), and can be changed at runtime without a restart:

Command Effect
/plugins Window listing every plugin with its status. Masteradmins get enable/disable and restart buttons.
//plugin list Same list in chat.
//plugin enable <name> / //plugin disable <name> Starts or stops a plugin. Disabling a plugin stops the plugins that depend on it, enabling it starts them again. The choice is saved in the database and overrides isEnabled until reset.
//plugin restart <name> Restarts a plugin and the plugins depending on it.
//plugin reset <name> Forgets the saved choice, so isEnabled from the config applies again.
//reloadconfig Re-reads config/ and restarts the plugins whose config changed. Edits are also picked up automatically while the server runs.

ui, vote and actions are required and can't be disabled. ui only holds the shared widgets and the building blocks for windows; feature widgets live in their plugin's ui/ folder (e.g. plugins/dedimania/ui/) and disappear when it's disabled. Skip, replay and time-extension votes and payments are handled by the vote plugin, with their limits, costs and commands in plugins/vote/MapVotes.config.js (override: config/plugins/vote/MapVotes.config.json). The privilege needed is plugins.privilege in config/config/Config.json (default 3, masteradmin).

Keeping your own server's customizations

Everything server-specific lives in data files rather than code, so you can keep your setup in git next to this repo without forking the code:

What Where
Trakman settings, song list, banner config/**/*.json (see config/README.md)
Tracks tracks/
Banner and other images icons/<your file>
Deployment your CI file, e.g. .gitlab-ci.yml
Secrets .env, never committed

A clean way to manage this is one local clone with two branches and two remotes:

  • main tracks this repo and only ever gets code changes.
  • live is main plus your customization commits, pushed to a private remote that your server deploys from.
git remote add private <your private repo URL>
git switch -c live
# add your tracks, config/*.json, icons, CI file
git add -A && git commit -m "Server customizations"
git push -u private live

To update, pull or make code changes on main, then git switch live && git merge main && git push. Because live only adds data files, merges from main don't conflict. Make changes that belong to everyone on main, never on live.

To make sure live can't be pushed to the public remote by accident, add a .git/hooks/pre-push hook:

#!/bin/sh
# Refuse to push the live branch anywhere except the private remote
[ "$1" = private ] && exit 0
while read -r local_ref _ _ _; do
  if [ "$local_ref" = refs/heads/live ]; then
    echo "pre-push: live only goes to the private remote" >&2
    exit 1
  fi
done

Updating Trakman

Plugins here are restructured for runtime enable/disable (each entry file exports a plugin definition with start/stop, and src/plugins/ tracks what they register), so upstream releases can't be copied over wholesale. Port upstream changes file by file, keeping src/ConfigLoader.ts, src/plugins/, config/Titles.js and plugins/music/SongList.js. For new config files, run node scripts/wrap-trakman-configs.cjs so they read the overrides in config/. Check the upstream CHANGELOG.md for renamed config keys, since Trakman warns about overrides that no longer match. Then rebuild.

Deployment

Any Docker host works: clone the repo, add your .env, tracks and music, and run docker compose up -d --build. Tracks added in-game through TMX are written to tracks/ on the host. If your deployment syncs the repo over the host's tracks/ and deletes extra files (e.g. rsync --delete), they'll be removed unless they're also committed.

License

See LICENSE. Trakman and the migration script keep their own licenses in trakman/LICENSE and migration/LICENSE.

About

Trackmania Forever dedicated server with the Trakman TypeScript controller (https://github.com/lythx/trakman), packaged as a Docker image and wired for a full stack (game server + PostgreSQL) via Docker Compose

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages