Sign inSign up

ocelus/factoricord

By ocelus

•Updated 29 days ago

Serveur Factorio (vanilla, FSM ou collector seul) avec le collector FactoriCord

Image
1

1.3K

ocelus/factoricord repository overview

⁠FactoriCord — Factorio server for Docker

English | Français⁠

Headless Factorio server bundled with the FactoriCord collector, which sends the in-game events written by the FactoriCord mod (joins, deaths, research, rocket launches, victory...) to the FactoriCord API.

  • Game downloaded on first start: the image does not contain Factorio. It is installed into a volume on first start, then updated automatically.
  • FactoriCord mod included: installed and enabled automatically.
  • Mods volume: mods dropped into the folder are enabled automatically, and mods from the mod portal can be downloaded with a single variable.
  • Three modes: regular server, Factorio Server Manager⁠ (web UI), or collector only.

Source code: github.com/OcelusPRO/FactoriCordDocker⁠ · Support: FactoriCord Discord⁠

⁠Quick start

docker run -d --name factoricord \
  -p 34197:34197/udp \
  -e FACTORICORD_API_URL=https://api.example.com \
  -e FACTORICORD_TOKEN=my-token \
  -e FACTORICORD_SERVER_NAME="My server" \
  -v factorio-game:/opt/factorio \
  -v factorio-data:/factorio \
  --stop-timeout 60 \
  ocelus/factoricord

On first start, the container:

  1. downloads the latest stable version of Factorio and verifies its SHA256 checksum;
  2. installs the FactoriCord mod and generates a map if no save exists;
  3. starts the server, then the FactoriCord collector once the server is ready.

Later restarts reuse the game that is already installed.

⁠Docker Compose
services:
  factoricord:
    image: ocelus/factoricord:latest
    container_name: factoricord
    restart: unless-stopped
    stop_grace_period: 1m # gives Factorio time to save the map on shutdown
    environment:
      SERVER_MODE: vanilla # vanilla | fsm | none
      FACTORIO_VERSION: stable # stable | latest | 2.0.77
      FACTORICORD_API_URL: https://api.example.com
      FACTORICORD_TOKEN: my-token
      FACTORICORD_SERVER_NAME: My server
      # MODS_LIST: even-distribution, Squeak Through
      # FACTORIO_USERNAME: my-username
      # FACTORIO_TOKEN: my-factorio-token
    ports:
      - "34197:34197/udp"
    volumes:
      - factorio-game:/opt/factorio
      - factorio-data:/factorio
      - ./mods:/factorio/mods

volumes:
  factorio-game:
  factorio-data:

⁠Modes

The mode is selected with the SERVER_MODE variable.

SERVER_MODEWhat runsGame downloaded
vanilla (default)Headless Factorio server + FactoriCord collectoryes
fsmFactorio Server Manager (web UI) + Factorio server + collectoryes
noneFactoriCord collector only, on the volume of an existing serverno
⁠vanilla: regular server

The server loads the latest save (LOAD_LATEST_SAVE=true), or SAVE_NAME. If there is no save, a map is generated from config/map-gen-settings.json and config/map-settings.json, or from a preset (PRESET). Arguments given after the image name are passed to the Factorio binary.

⁠fsm: Factorio Server Manager
docker run -d --name factoricord \
  -e SERVER_MODE=fsm \
  -p 34197:34197/udp -p 8080:80/tcp \
  -e FACTORICORD_API_URL=https://api.example.com \
  -e FACTORICORD_TOKEN=my-token \
  -v factorio-game:/opt/factorio \
  -v factorio-data:/factorio \
  ocelus/factoricord
  • The web UI listens on the container's FSM_PORT (80 by default).

  • Credentials: on first start, FSM creates the admin user and prints its password in the logs. To find it:

    docker logs factoricord 2>&1 | grep -A1 "Username: admin"
    

    Remember to change this password from the web UI.

  • FSM_AUTOSTART=true (default): the server starts on the latest save together with the container. With false, it is started from the web UI.

  • The game port is set in the FSM web UI (34197 by default): the PORT variable is not used.

  • Behind an HTTPS reverse proxy, set FSM_SECURE_COOKIE=true.

  • FSM data (users, configuration, mod packs, factorio.com login) is stored in /factorio/fsm.

  • This mode only works on amd64.

⁠none: collector only

To add FactoriCord to a Factorio server that already runs elsewhere, for example in another container. Mount that server's data volume on /factorio. The collector reads the events in script-output/factoricord-logs, sends them to the API, then deletes the files it sent.

services:
  factoricord-collector:
    image: ocelus/factoricord:latest
    restart: unless-stopped
    environment:
      SERVER_MODE: none
      FACTORICORD_API_URL: https://api.example.com
      FACTORICORD_TOKEN: my-token
      PUID: 845 # same user as the Factorio server, so the collector can delete the files it read
      PGID: 845
    volumes:
      - factorio-data:/factorio # data volume of the existing Factorio server

The FactoriCord mod must be installed on that server. This mode downloads nothing.

⁠Volumes

PathContent
/opt/factorioThe game: binary, data/, config/config.ini. Downloaded on first start
/factorioServer data, detailed below
/factorio/modsMods and mod-list.json. Can be mounted separately (a host folder, for example)

Content of /factorio:

  • saves/: the maps;
  • config/: server-settings.json, map-gen-settings.json, map-settings.json, server-adminlist.json, server-banlist.json, server-whitelist.json, rconpw;
  • script-output/: files written by mods, including the FactoriCord events;
  • factoricord/: the FactoriCord client and its config.json;
  • fsm/: Factorio Server Manager data.

Configuration files are created from the game's examples if they don't exist. Edit them and restart the container, for example to name the server, make it public or set a password in server-settings.json.

⁠Factorio version

FACTORIO_VERSION accepts three forms:

  • stable (default): the latest stable version;
  • latest: the latest experimental version;
  • a specific version, such as 2.0.77.

On each start, the game is downloaded again only if the installed version is not the requested one. If factorio.com is unreachable, the installed version is kept. To go back to an older version, set that version.

The Space Age DLC mods (space-age, quality, elevated-rails) are enabled by default. This is controlled with DLC_SPACE_AGE:

  • false disables the DLC;
  • a list enables only some mods, for example DLC_SPACE_AGE="quality elevated-rails".

⁠Mods

On each start (vanilla and fsm modes):

  1. FactoriCord mod: the version shipped with the image is copied to the mods folder, unless a newer version is already there.
  2. MODS_LIST: listed mods that are missing are downloaded from the mod portal⁠, together with their required dependencies. Names are comma-separated, for example MODS_LIST="even-distribution, Squeak Through". A factorio.com account is required (see below).
  3. Automatic enabling: every mod in the folder is added to mod-list.json and enabled, whether it is a name_x.y.z.zip file or an unpacked folder. A mod already listed keeps its state: a mod disabled by hand in mod-list.json stays disabled. Only FactoriCord is always re-enabled.

To add a mod by hand, drop its zip into the mods folder and restart the container.

UPDATE_MODS_ON_START=true also updates all enabled mods to their latest compatible version. Some mods can be excluded with UPDATE_IGNORE (comma-separated names).

factorio.com credentials: downloading mods requires your username and token, shown on factorio.com/profile⁠. They are read in this order of priority:

  1. the Docker secrets username and token;
  2. the FACTORIO_USERNAME and FACTORIO_TOKEN variables;
  3. the username and token fields of server-settings.json.

⁠FactoriCord client

The collector is configured with environment variables. Its config.json is generated in /factorio/factoricord on each start:

  • variables that are set override the existing values;
  • fields managed by the client (registration, version) are kept;
  • after the first start, the token can therefore be removed from the environment;
  • changing the token or the API URL triggers a new registration of the server.

The client updates itself from the FactoriCord API. The update is kept in the volume: it survives container recreation and image updates, as long as the image does not ship a newer version. After an update, the collector is restarted automatically.

If FACTORICORD_TOKEN or FACTORICORD_API_URL is missing, the collector is not started. The server still runs in vanilla and fsm modes, whereas none mode stops with an error.

⁠Environment variables

General

VariableDefaultDescription
SERVER_MODEvanillavanilla, fsm or none
FACTORIO_VERSIONstablestable, latest (experimental) or a specific version (2.0.77)
PUID / PGID845 / 845UID/GID of the user running the server and the collector
DEBUGfalsetrue prints every command run by the scripts

FactoriCord

VariableDefaultDescription
FACTORICORD_API_URLFactoriCord API URL (required)
FACTORICORD_TOKENServer token (required). Alternatives: FACTORICORD_TOKEN_FILE (path to a file) or the Docker secret factoricord_token
FACTORICORD_SERVER_NAMEServer name
FACTORICORD_UPDATE_INTERVAL10Interval between event uploads, in seconds
FACTORICORD_UPDATE_CHECK_INTERVAL3600Interval between client update checks, in seconds
FACTORICORD_LOGS_DIR/factorio/script-output/factoricord-logsEvent folder read by the collector
FACTORICORD_HOME/factorio/factoricordLocation of the client and its config.json

Server (vanilla and fsm modes)

VariableDefaultDescription
PORT34197Game UDP port (vanilla mode)
RCON_PORT27015RCON port (password in config/rconpw)
LOAD_LATEST_SAVEtrueLoads the most recent save. With false, loads SAVE_NAME
SAVE_NAMEName of the save to load or generate
GENERATE_NEW_SAVEfalseGenerates the SAVE_NAME map if it doesn't exist
PRESETMap generation preset (rich-resources, death-world, rail-world...)
BINDIP address the server listens on
CONSOLE_LOG_LOCATIONFile to write the server console to
DLC_SPACE_AGEtruetrue, false or a list of DLC mods
MODS_LISTMod portal mods to install, comma-separated
FACTORIO_USERNAME / FACTORIO_TOKENfactorio.com credentials, to download mods
UPDATE_MODS_ON_STARTfalseUpdates the enabled mods on each start
UPDATE_IGNOREMods excluded from updates, comma-separated

Factorio Server Manager (fsm mode)

VariableDefaultDescription
FSM_PORT80Web UI port inside the container
FSM_AUTOSTARTtrueStarts the Factorio server together with the container
FSM_SECURE_COOKIEfalsetrue behind an HTTPS reverse proxy

⁠Ports

PortUsage
34197/udpGame
27015/tcpRCON (no need to publish it to use the container's rcon command)
80/tcpFSM web UI (fsm mode)

⁠Useful commands

# Server console through RCON
docker exec factoricord rcon /players
docker exec factoricord rcon "/c game.print('Hello')"

# Exit code 75 if players are online (watchtower pre-update hook)
docker exec factoricord /opt/factoricord/scripts/players-online.sh

# Start a scenario, or convert a scenario into a map
docker run --rm -v factorio-game:/opt/factorio -v factorio-data:/factorio \
  --entrypoint /opt/factoricord/scripts/scenario2map.sh ocelus/factoricord my-scenario

⁠Shutdown and saving

When the container stops (docker stop), the server receives the stop signal and saves the map before exiting. Give it enough time: --stop-timeout 60 with docker run, or stop_grace_period: 1m with Compose.

⁠Tags and architectures

Each version tag combines the version of the FactoriCord client (the agent) and the version of the FactoriCord mod: <client>-<mod>.

TagContent
latestThe latest published version
1.0.1-1.1.1FactoriCord client 1.0.1 + FactoriCord mod 1.1.1 (rebuilt if the image changes without a version change)
sha-<commit>Build of a specific commit, immutable

To pin an installation, use a <client>-<mod> tag rather than latest.

Images are published for linux/amd64 and linux/arm64. On arm64, Factorio runs through the box64⁠ emulator (slower) and fsm mode is not available.

⁠Building the image

The image is built from FactoriCordClient.zip (the client, extracted during the build) and FactoriCord_x.y.z.zip (the mod). To move to a new version:

  • client: replace FactoriCordClient.zip, then update ARG FACTORICORD_CLIENT_VERSION in the Dockerfile;
  • mod: replace FactoriCord_x.y.z.zip. The repository must contain a single mod zip, and the version in its info.json must match the file name.
docker build -t ocelus/factoricord:1.0.1-1.1.1 .
Build argumentDefaultDescription
FACTORICORD_CLIENT_VERSION1.0.1Version of the client in FactoriCordClient.zip
FSM_IMAGEofsm/ofsm:developImage the FSM binary is taken from
BASE_IMAGEpython:3.12-slim-trixieBase image
PUID / PGID845Default UID/GID of the factorio user
⁠Tests

tests/smoke-test.sh runs the image in all three modes against a fake FactoriCord API. It checks the game installation, collector registration, event upload, RCON, the FSM web UI and clean shutdown:

docker build -t factoricord:test . && bash tests/smoke-test.sh factoricord:test
⁠Publishing (GitHub Actions)
  • Pushes and pull requests: the image is built and the smoke test runs. Nothing is published.
  • Published GitHub release, or manual run of the Docker image workflow on main: the image is built and tested, then published for amd64 and arm64 with the <client>-<mod>, latest and sha-<commit> tags. A pre-release does not move latest. The release name is free, but v1.0.1-1.1.1 is recommended.
  • Docker Hub description: this README is published as the image description on every change on main and on every release.

Secrets to define in the GitHub repository (Settings > Secrets and variables > Actions):

SecretValue
DOCKER_USERNAMEDocker Hub account that owns (or administers) ocelus/factoricord
DOCKER_PASSWORDAccount password, or an access token with the Read, Write, Delete scope (a Read & Write token is enough to push the image, but not to update the description)

If it fails, the Docker Hub description workflow reports the cause: rejected credentials, insufficient permissions on the repository, or README content blocked by the Docker Hub firewall.

Tag summary

Content type

Image

Digest

sha256:d2787ea60…

Size

69.3 MB

Last updated

29 days ago

docker pull ocelus/factoricord