#!/bin/bash # panel-native Factorio entrypoint. set -euo pipefail log() { printf '[panel-factorio] %s\n' "$*"; } if [[ "$(id -u)" = "0" ]]; then chown -R panel:panel /game /game-saves /home/panel 2>/dev/null || true exec setpriv --reuid=panel --regid=panel --clear-groups \ --inh-caps=-all --bounding-set=-all \ env HOME=/game-saves PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ RCON_PASSWORD="${RCON_PASSWORD:-panel_rcon}" \ GAME_PORT="${GAME_PORT:-34197}" \ RCON_PORT="${RCON_PORT:-27015}" \ /entrypoint.sh "$@" fi GAME_DIR=/game SAVE_DIR=/game-saves # factorio.com's headless tarball extracts into a `factorio/` subdir. Our # updater unpacks into /game, so we look for both. BIN="${GAME_DIR}/factorio/bin/x64/factorio" if [[ ! -x "${BIN}" ]]; then BIN="${GAME_DIR}/bin/x64/factorio" fi SAVE="${SAVE_DIR}/saves/default.zip" if [[ ! -x "${BIN}" ]]; then log "ERROR: Factorio binary not found at /game/{factorio/,}bin/x64/factorio." log " Run 'Update' in the panel to install Factorio (Direct provider)." exit 78 fi mkdir -p "${SAVE_DIR}/saves" "${SAVE_DIR}/mods" "${SAVE_DIR}/config" "${SAVE_DIR}/logs" # Seed server-settings.json from Factorio's shipped example on first boot. # Without this Factorio fails fast: "Hosting multiplayer game failed: # filesystem error: file_size(p): unknown error: No such file or directory # [/game-saves/config/server-settings.json]" — observed on smoke test. # The example tree lives next to the binary at /../../data/. DATA_DIR="$(dirname "${BIN}")/../../data" if [[ ! -f "${SAVE_DIR}/config/server-settings.json" && -f "${DATA_DIR}/server-settings.example.json" ]]; then log "seeding server-settings.json from example" cp "${DATA_DIR}/server-settings.example.json" "${SAVE_DIR}/config/server-settings.json" fi # map-gen-settings + map-settings aren't required for boot, but having the # examples in place means operators can edit them via the Files tab without # having to dig into the binary tree. for f in map-gen-settings.example.json map-settings.example.json; do base="${f%.example.json}.json" if [[ ! -f "${SAVE_DIR}/config/${base}" && -f "${DATA_DIR}/${f}" ]]; then cp "${DATA_DIR}/${f}" "${SAVE_DIR}/config/${base}" fi done # Create a default world on first boot — Factorio can't autostart from nothing. if [[ ! -s "${SAVE}" ]]; then log "no existing save — creating default map" "${BIN}" --create "${SAVE}" fi cd "$(dirname "${BIN}")/../.." GAME_PORT="${GAME_PORT:-34197}" RCON_PORT="${RCON_PORT:-27015}" log "starting Factorio headless server" log " save: ${SAVE}" log " settings: ${SAVE_DIR}/config/server-settings.json" log " game port: ${GAME_PORT}/udp" log " rcon port: ${RCON_PORT}/tcp" exec stdbuf -oL -eL "${BIN}" \ --start-server "${SAVE}" \ --server-settings "${SAVE_DIR}/config/server-settings.json" \ --port "${GAME_PORT}" \ --rcon-port "${RCON_PORT}" \ --rcon-password "${RCON_PASSWORD}" \ --mod-directory "${SAVE_DIR}/mods" \ --console-log "${SAVE_DIR}/logs/factorio.log"