Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libcap2-bin libpcap0.8 \
ca-certificates \
python3 python3-venv python3-pip \
gosu \
&& (apt-get install -y --no-install-recommends libicu76 || apt-get install -y --no-install-recommends libicu72 || apt-get install -y --no-install-recommends libicu67) \
&& (apt-get install -y --no-install-recommends libsdl3-0 || apt-get install -y --no-install-recommends libsdl3-0-0) \
&& apt-get clean \
Expand Down
2 changes: 1 addition & 1 deletion examples/autopause/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ services:
SERVER_NAME: "palworld-server-docker/examples/autopause"
AUTO_PAUSE_ENABLED: true
AUTO_PAUSE_TIMEOUT_EST: 10 # Number of seconds before auto pausing.
#AUTO_PAUSE_LOG: true
AUTO_PAUSE_LOG: true
#AUTO_PAUSE_DEBUG: false
COMMUNITY: true
#PUBLIC_IP: "${PUBLIC_IP:-}"
Expand Down
6 changes: 3 additions & 3 deletions scripts/autopause/community/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ if isTrue "${COMMUNITY}" && isTrue "${AUTO_PAUSE_ENABLED}" && PlayerLogging_isEn

LogInfo "Launch proxy."
MITMPROXY_ADDONS_DIR="/home/steam/server/autopause/community/addons"
IGNORE_HOSTS="api.steamcmd.net,discord.com"
IGNORE_HOSTS_PATTERN=$(echo "$IGNORE_HOSTS" | tr ',' '\n' | sed 's/\./\\./g' | paste -sd '|' -)
IGNORE_HOSTS="api.steamcmd.net,discord.com,api.github.com,.sentry.io"
IGNORE_HOSTS_PATTERN="api\\.steamcmd\\.net|discord\\.com|api\\.github\\.com|(?:.*\\.)?sentry\\.io"
MITMPROXY_OPTIONS=(
"--set" "block_global=false"
"--ssl-insecure"
"--ignore-hosts" "^(${IGNORE_HOSTS_PATTERN})\$"
"-s" "${MITMPROXY_ADDONS_DIR}/PalCommCapture.py"
)
if isTrue "${AUTO_PAUSE_DEBUG}"; then
mitmweb --web-host 0.0.0.0 "${MITMPROXY_OPTIONS[@]}" &
PYTHONUNBUFFERED=1 mitmweb --web-host 0.0.0.0 "${MITMPROXY_OPTIONS[@]}" &
LogInfo "Web Interface URL: http://localhost:8081/"
else
mitmdump "${MITMPROXY_OPTIONS[@]}" > /var/log/mitmdump.log &
Expand Down
47 changes: 1 addition & 46 deletions scripts/autopause/functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ declare -r DATA_DIR="${DATA_DIR:-/palworld}"
declare -r AP_pause_file="${DATA_DIR}/.paused"
declare -r AP_request_file="${DATA_DIR}/.autopause-request"
declare -r AP_disable_file="${DATA_DIR}/.autopause-disabled" # for shutdown and reboot
declare -r AP_monitor_backend_file="/home/steam/server/autopause/.monitor-backend"

#-------------------------------
# AutoPause Log
Expand Down Expand Up @@ -61,7 +60,7 @@ AP_isSleep() {

AP_do() {
if [[ "$(id -u)" -eq 0 ]]; then
gosu steam bash -c "${1}"
setpriv --reuid=steam --regid=steam --init-groups -- bash -c "${1}"
else
eval "${1}"
fi
Expand Down Expand Up @@ -134,47 +133,3 @@ AP_waitPullRequest()
APLog_debug "AP_waitPullRequest ... time out."
return 1
}

#-------------------------------
# AutoPause Monitor Backend
#-------------------------------

APMonitor_detectAvailableBackend() {
local monitorBackend
# Decide monitor backend at startup and persist it for services.sh.
# Priority:
# 1. NFLOG (requires iptables + tcpdump + NET_RAW,NET_ADMIN capability)
# 2. knockd (requires knockd binary + NET_RAW capability)
# 3. Error (no suitable backend available)
if command -v iptables > /dev/null 2>&1 && iptables -L > /dev/null 2>&1 && \
command -v tcpdump > /dev/null 2>&1 && tcpdump --version > /dev/null 2>&1; then
monitorBackend="nflog"
APLog "AUTO_PAUSE packet monitor: NFLOG (iptables+tcpdump) available."
else
APLog "AUTO_PAUSE packet monitor: NFLOG (iptables+tcpdump) unavailable."
APLog_warn "NET_ADMIN & NET_RAW capability required for NFLOG. e.g) podman run --cap-add=NET_ADMIN --cap-add=NET_RAW ..."
if command -v knockd > /dev/null 2>&1 && knockd --version > /dev/null 2>&1; then
monitorBackend="knockd"
APLog "AUTO_PAUSE packet monitor: knockd available."
else
APLog "AUTO_PAUSE packet monitor: knockd unavailable."
APLog_error "AUTO_PAUSE requires NET_RAW capability. e.g) podman run --cap-add=NET_RAW ..."
return 1
fi
fi

printf '%s\n' "${monitorBackend}" > "${AP_monitor_backend_file}"
chmod 0644 "${AP_monitor_backend_file}" || true
if [ "$(id -u)" -eq 0 ]; then
chown steam:steam "${AP_monitor_backend_file}" || true
fi
return 0
}

APMonitor_determineBackend() {
if [ -r "${AP_monitor_backend_file}" ]; then
cat "${AP_monitor_backend_file}"
else
echo "knockd"
fi
}
14 changes: 11 additions & 3 deletions scripts/autopause/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ if isTrue "${AUTO_PAUSE_ENABLED}"; then
exit 1
fi

if ! APMonitor_detectAvailableBackend; then
LogError "AUTO_PAUSE requires either KNOCKD or NFLOG to be available."
exit 1
if ! setpriv --reuid=steam --regid=steam --init-groups -- /usr/local/sbin/knockd-ctl check; then
# OMV8? (https://github.com/thijsvanloef/palworld-server-docker/issues/911)
FORCE_CAPS=("--inh-caps=+net_raw,+net_admin" "--ambient-caps=+net_raw,+net_admin")
if ! setpriv --reuid=steam --regid=steam --init-groups "${FORCE_CAPS[@]}" -- /usr/local/sbin/knockd-ctl check; then
LogError "AUTO_PAUSE requires capabilities the NET_RAW and NET_ADMIN."
LogError "See NOTE: https://palworld-server-docker.loef.dev/guides/automatic-server-pausing#network-interface-configuration"
exit 1
else
LogWarn "A capability issue #911 was detected."
LogWarn "Continuing with NET_RAW and NET_ADMIN capabilities enabled."
fi
fi

# shellcheck source=scripts/autopause/community/init.sh
Expand Down
51 changes: 51 additions & 0 deletions scripts/autopause/knockd-ctl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Knockd_interfaces="${AUTO_PAUSE_KNOCKD_IF:-auto}"
Nflog_interfaces=(any) # NFLOG backend always uses "any" to match all incoming packets via iptables rules.

declare -a Knockd_resolvedInterfaces=()
declare -r AP_monitor_backend_file="/home/steam/server/autopause/.monitor-backend"

# Add an interface to the Knockd_resolvedInterfaces array if it exists and is not already present.
# Validates interface exists via /sys/class/net and prevents duplicates.
Expand Down Expand Up @@ -370,6 +371,50 @@ Knockd_stopBackend() {
done
}

#-------------------------------
# AutoPause Monitor Backend
#-------------------------------

APMonitor_detectAvailableBackend() {
local monitorBackend
# Decide monitor backend at startup and persist it for services.sh.
# Priority:
# 1. NFLOG (requires iptables + tcpdump + NET_RAW,NET_ADMIN capability)
# 2. knockd (requires knockd binary + NET_RAW capability)
# 3. Error (no suitable backend available)
if command -v iptables > /dev/null 2>&1 && iptables -L > /dev/null 2>&1 && \
command -v tcpdump > /dev/null 2>&1 && tcpdump --version > /dev/null 2>&1; then
monitorBackend="nflog"
APLog "AUTO_PAUSE packet monitor: NFLOG (iptables+tcpdump) available."
else
APLog "AUTO_PAUSE packet monitor: NFLOG (iptables+tcpdump) unavailable."
APLog_warn "NET_ADMIN & NET_RAW capability required for NFLOG. e.g) podman run --cap-add=NET_ADMIN --cap-add=NET_RAW ..."
if command -v knockd > /dev/null 2>&1 && knockd --version > /dev/null 2>&1; then
monitorBackend="knockd"
APLog "AUTO_PAUSE packet monitor: knockd available."
else
APLog "AUTO_PAUSE packet monitor: knockd unavailable."
APLog_error "AUTO_PAUSE requires NET_RAW capability. e.g) podman run --cap-add=NET_RAW ..."
return 1
fi
fi

printf '%s\n' "${monitorBackend}" > "${AP_monitor_backend_file}"
chmod 0644 "${AP_monitor_backend_file}" || true
if [ "$(id -u)" -eq 0 ]; then
chown steam:steam "${AP_monitor_backend_file}" || true
fi
return 0
}

APMonitor_determineBackend() {
if [ -r "${AP_monitor_backend_file}" ]; then
cat "${AP_monitor_backend_file}"
else
echo "knockd"
fi
}

# ============================================================================
# Main Dispatcher
# ============================================================================
Expand All @@ -393,9 +438,15 @@ case "${COMMAND}" in
Knockd_stopBackend
fi
;;
"check")
APMonitor_detectAvailableBackend
;;
*)
echo "Usage: $(basename "${0}") <command>"
echo "command:"
echo " start ... launch NFLOG or knockd based on .monitor-backend"
echo " stop ... stop NFLOG or knockd"
echo " check ... detect available backend and write to .monitor-backend"
exit 1
;;
esac
1 change: 0 additions & 1 deletion scripts/helper_functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -423,4 +423,3 @@ get_latest_version() {

echo "$latest_version"
}

11 changes: 8 additions & 3 deletions scripts/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ if ! ValidateNegativeDeltaRecoverySetting; then
exit 1
fi

# Remove old FIFO
rm -f "${PalServerLog_fifo}"

if [ "${LOG_FILTER_ENABLED,,}" = true ]; then
# Recreate FIFO at every boot to avoid stale descriptors and permission drift.
rm -f "${PalServerLog_fifo}"

if ! mkfifo -m 600 "${PalServerLog_fifo}"; then
echo "ERROR: Failed to create log FIFO: ${PalServerLog_fifo}" >&2
exit 1
Expand Down Expand Up @@ -54,6 +55,8 @@ if ! [ -w "/palworld" ]; then
exit 1
fi

FORCE_CAPS=()

# shellcheck source=scripts/autopause/init.sh
source "/home/steam/server/autopause/init.sh"

Expand All @@ -74,10 +77,12 @@ term_handler() {
trap 'term_handler' SIGTERM

if [[ "$(id -u)" -eq 0 ]]; then
gosu steam ./start.sh &
# Only if the capabilities set on the executable do not work, we reluctantly add NET_ADMIN and NET_RAW capabilities.
setpriv --reuid=steam --regid=steam --init-groups "${FORCE_CAPS[@]}" ./start.sh &
else
./start.sh &
fi

# Process ID of start.sh
killpid="$!"
wait "$killpid"
Expand Down
12 changes: 10 additions & 2 deletions scripts/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,10 @@ if [ "${AUTO_REBOOT_ENABLED,,}" = true ] && [ "${REST_API_ENABLED,,}" = true ];
supercronic -quiet -test -no-reap "/home/steam/server/crontab" || exit
fi

CRON_PID=""
if [ -s "/home/steam/server/crontab" ]; then
supercronic -passthrough-logs -no-reap "/home/steam/server/crontab" &
CRON_PID=$!
LogInfo "Cronjobs started"
else
LogInfo "No Cronjobs found"
Expand All @@ -171,8 +173,8 @@ EOL

CHILD_PIDS=()
if PlayerLogging_isEnabled; then
if [[ "$(id -u)" -eq 0 ]]; then
gosu steam /home/steam/server/player_logging.sh &
if [ "$(id -u)" -eq 0 ]; then
setpriv --reuid=steam --regid=steam --init-groups "${FORCE_CAPS[@]}" /home/steam/server/player_logging.sh &
else
/home/steam/server/player_logging.sh &
fi
Expand All @@ -186,6 +188,12 @@ echo "${STARTCOMMAND[*]}"
"${STARTCOMMAND[@]}"

LogAction "Ending Server"

if [ -n "$CRON_PID" ]; then
LogInfo "Stopping cronjobs"
kill -SIGTERM "$CRON_PID" 2>/dev/null
fi

if [ ${#CHILD_PIDS[@]} -ne 0 ]; then
wait "${CHILD_PIDS[@]}"
fi
Expand Down
Loading