Merge remote-tracking branch 'origin/main'

# Conflicts:
#	scripts/package-native.sh
#	scripts/stage-build.sh
This commit is contained in:
Alexander Sellite 2026-08-12 11:23:46 -04:00
commit 0f1d931a7b
7 changed files with 96 additions and 10 deletions

View file

@ -4,6 +4,12 @@ This repository packages the headless NETfishing server produced by the main
game project. Gameplay and networking code remain in the `netfishing` game project. Gameplay and networking code remain in the `netfishing`
repository so clients and servers use the same protocol implementation. repository so clients and servers use the same protocol implementation.
Production tags follow the coordinated NETfishing release train. Package a
game release with the same `vX.Y.Z-alpha` tag checked out in this repository.
The package manifest records both the exact game commit and the exact dedicated
packaging commit; packaging refuses to run when its matching release tag does
not point to the current commit.
## Stage a build ## Stage a build
Export the `Linux Dedicated Server` preset from the game project, then stage Export the `Linux Dedicated Server` preset from the game project, then stage
@ -18,9 +24,9 @@ game_commit="$(git -C ../netfishing rev-parse HEAD)"
``` ```
The staged binaries under `dist/` are release inputs and are intentionally not The staged binaries under `dist/` are release inputs and are intentionally not
tracked by Git. `dist/BUILD_INFO` records the version, full game commit, export tracked by Git. `dist/BUILD_INFO` records the version, full game and packaging
preset, platform, and binary hashes. Packaging refuses a version mismatch or commits, export preset, platform, and binary hashes. Packaging refuses a
failed internal checksum. version mismatch, packaging-tag mismatch, or failed internal checksum.
Create a deterministic native archive after staging: Create a deterministic native archive after staging:
@ -61,8 +67,34 @@ to returning players.
Configuration is applied in this order: config file, environment variables, Configuration is applied in this order: config file, environment variables,
then command-line overrides. Supported command-line options are `--name`, then command-line overrides. Supported command-line options are `--name`,
`--bind`, `--port`, `--max-players`, `--data-dir`, `--discovery-url`, `--bind`, `--port`, `--max-players`, `--data-dir`, `--discovery-url`,
`--public`, and `--private`. Value options use `--option=value`. Keep the first `--operators`, `--public`, and `--private`. Value options use `--option=value`.
standalone `--` shown above; it separates Godot engine flags from server flags. Keep the first standalone `--` shown above; it separates Godot engine flags
from server flags.
### Headless operators
Headless moderation is granted by authenticated player identity, never by a
display name or shared password. A player can copy their complete 64-character
fingerprint from **Settings → Data & Identity → Copy Player Fingerprint**.
Add trusted fingerprints to `/etc/netfishing-server.cfg`:
```ini
[moderation]
operators=PackedStringArray("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
```
Alternatively, provide a comma-separated list through
`NETFISHING_SERVER_OPERATORS` or `--operators=fingerprint1,fingerprint2`.
Configuration file values are overridden by the environment, then by the
command line. Restart the server after changing the allowlist.
The server grants operator status only after the connecting player proves
ownership of that exact identity key. Operators can kick, ban, unban, and clear
shared session artwork through the in-game Players page. They cannot grant
operator access, revoke another operator, or moderate another operator. Keep
the server data directory persistent because it owns the server identity and
stored bans.
Public listing requires the discovery URL and a publicly reachable ENet UDP Public listing requires the discovery URL and a publicly reachable ENet UDP
port. Discovery makes a server findable but does not relay gameplay traffic. port. Discovery makes a server findable but does not relay gameplay traffic.
@ -97,9 +129,10 @@ docker compose up -d
``` ```
Set values such as `NETFISHING_SERVER_NAME`, `NETFISHING_SERVER_PORT`, Set values such as `NETFISHING_SERVER_NAME`, `NETFISHING_SERVER_PORT`,
`NETFISHING_SERVER_MAX_PLAYERS`, and `NETFISHING_SERVER_PUBLIC` in a local `NETFISHING_SERVER_MAX_PLAYERS`, `NETFISHING_SERVER_PUBLIC`, and the optional
`.env` file. The Compose service runs without Linux capabilities, uses a comma-separated `NETFISHING_SERVER_OPERATORS` in a local `.env` file. The
read-only root filesystem, and stores persistent state in a named volume. Compose service runs without Linux capabilities, uses a read-only root
filesystem, and stores persistent state in a named volume.
## Steam distribution ## Steam distribution

View file

@ -18,6 +18,7 @@ services:
NETFISHING_SERVER_PUBLIC: "${NETFISHING_SERVER_PUBLIC:-false}" NETFISHING_SERVER_PUBLIC: "${NETFISHING_SERVER_PUBLIC:-false}"
NETFISHING_DISCOVERY_URL: "${NETFISHING_DISCOVERY_URL:-https://discovery.netfishing.org}" NETFISHING_DISCOVERY_URL: "${NETFISHING_DISCOVERY_URL:-https://discovery.netfishing.org}"
NETFISHING_DATA_DIR: /var/lib/netfishing-server NETFISHING_DATA_DIR: /var/lib/netfishing-server
NETFISHING_SERVER_OPERATORS: "${NETFISHING_SERVER_OPERATORS:-}"
volumes: volumes:
- netfishing-server-data:/var/lib/netfishing-server - netfishing-server-data:/var/lib/netfishing-server
tmpfs: tmpfs:

View file

@ -5,3 +5,4 @@ NETFISHING_SERVER_MAX_PLAYERS=8
NETFISHING_SERVER_PUBLIC=false NETFISHING_SERVER_PUBLIC=false
NETFISHING_DISCOVERY_URL=https://discovery.netfishing.org NETFISHING_DISCOVERY_URL=https://discovery.netfishing.org
NETFISHING_DATA_DIR=/var/lib/netfishing-server NETFISHING_DATA_DIR=/var/lib/netfishing-server
NETFISHING_SERVER_OPERATORS=

View file

@ -8,3 +8,6 @@ data_directory="/var/lib/netfishing-server"
[discovery] [discovery]
url="https://discovery.netfishing.org" url="https://discovery.netfishing.org"
[moderation]
operators=PackedStringArray()

View file

@ -116,8 +116,9 @@ manifest_value() {
manifest_version="$(manifest_value manifest_version)" manifest_version="$(manifest_value manifest_version)"
game_version="$(manifest_value game_version)" game_version="$(manifest_value game_version)"
game_commit="$(manifest_value game_commit)" game_commit="$(manifest_value game_commit)"
packaging_commit="$(manifest_value packaging_commit)"
platform="$(manifest_value platform)" platform="$(manifest_value platform)"
if [[ "${manifest_version}" != "1" ]]; then if [[ "${manifest_version}" != "1" && "${manifest_version}" != "2" ]]; then
echo "Unsupported BUILD_INFO format." >&2 echo "Unsupported BUILD_INFO format." >&2
exit 1 exit 1
fi fi
@ -129,6 +130,11 @@ if [[ ! "${game_commit}" =~ ^[0-9a-f]{40}$ ]]; then
echo "Invalid game commit in BUILD_INFO." >&2 echo "Invalid game commit in BUILD_INFO." >&2
exit 1 exit 1
fi fi
if [[ "${manifest_version}" == "2" \
&& ! "${packaging_commit}" =~ ^[0-9a-f]{40}$ ]]; then
echo "Invalid packaging commit in BUILD_INFO." >&2
exit 1
fi
if [[ "${platform}" != "linux-x86_64" ]]; then if [[ "${platform}" != "linux-x86_64" ]]; then
echo "This installer only accepts linux-x86_64 packages." >&2 echo "This installer only accepts linux-x86_64 packages." >&2
exit 1 exit 1
@ -227,6 +233,9 @@ if [[ -n "${old_current}" && "${old_current}" != "${release_dir}" ]]; then
fi fi
echo "Installed NETfishing dedicated server ${game_version} (${game_commit})." echo "Installed NETfishing dedicated server ${game_version} (${game_commit})."
if [[ -n "${packaging_commit}" ]]; then
echo "Dedicated packaging commit: ${packaging_commit}."
fi
if ${service_exists} && ! ${service_active}; then if ${service_exists} && ! ${service_active}; then
echo "${service_name} was inactive and was not started." echo "${service_name} was inactive and was not started."
fi fi

View file

@ -18,6 +18,12 @@ package_name="netfishing-dedicated-server-${version}-linux-x86_64"
staging_dir="$(mktemp -d)" staging_dir="$(mktemp -d)"
trap 'rm -rf -- "${staging_dir}"' EXIT trap 'rm -rf -- "${staging_dir}"' EXIT
if ! git -C "${repository_dir}" diff --quiet \
|| ! git -C "${repository_dir}" diff --cached --quiet; then
echo "Commit dedicated packaging changes before creating a release." >&2
exit 1
fi
for filename in \ for filename in \
NETfishingServer.x86_64 \ NETfishingServer.x86_64 \
NETfishingServer.pck \ NETfishingServer.pck \
@ -44,6 +50,26 @@ if ! grep -Fxq "game_version=${version}" "${dist_dir}/BUILD_INFO"; then
echo "Staged BUILD_INFO does not match package version ${version}." >&2 echo "Staged BUILD_INFO does not match package version ${version}." >&2
exit 1 exit 1
fi fi
packaging_commit="$(
awk -F= '$1 == "packaging_commit" {print tolower($2); exit}' \
"${dist_dir}/BUILD_INFO"
)"
current_packaging_commit="$(git -C "${repository_dir}" rev-parse HEAD)"
if [[ "${packaging_commit}" != "${current_packaging_commit}" ]]; then
echo "Staged BUILD_INFO does not match the current packaging commit." >&2
exit 1
fi
release_tag="v${version}"
if ! release_commit="$(
git -C "${repository_dir}" rev-parse --verify "refs/tags/${release_tag}^{commit}"
)"; then
echo "Dedicated packaging tag ${release_tag} does not exist." >&2
exit 1
fi
if [[ "${release_commit}" != "${current_packaging_commit}" ]]; then
echo "Dedicated packaging tag ${release_tag} does not point to HEAD." >&2
exit 1
fi
(cd -- "${dist_dir}" && sha256sum -c SHA256SUMS) (cd -- "${dist_dir}" && sha256sum -c SHA256SUMS)
install -d "${staging_dir}/${package_name}" install -d "${staging_dir}/${package_name}"

View file

@ -12,6 +12,13 @@ game_commit="${3,,}"
repository_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" repository_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
destination_dir="${repository_dir}/dist" destination_dir="${repository_dir}/dist"
licenses_dir="${destination_dir}/licenses" licenses_dir="${destination_dir}/licenses"
packaging_commit="$(git -C "${repository_dir}" rev-parse HEAD)"
if ! git -C "${repository_dir}" diff --quiet \
|| ! git -C "${repository_dir}" diff --cached --quiet; then
echo "Commit dedicated packaging changes before staging a release." >&2
exit 1
fi
if [[ ! "${game_version}" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then if [[ ! "${game_version}" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then
echo "GAME_VERSION must contain only letters, numbers, dots, underscores, or hyphens." >&2 echo "GAME_VERSION must contain only letters, numbers, dots, underscores, or hyphens." >&2
@ -21,6 +28,10 @@ if [[ ! "${game_commit}" =~ ^[0-9a-f]{40}$ ]]; then
echo "GAME_COMMIT must be the full 40-character Git commit." >&2 echo "GAME_COMMIT must be the full 40-character Git commit." >&2
exit 2 exit 2
fi fi
if [[ ! "${packaging_commit}" =~ ^[0-9a-f]{40}$ ]]; then
echo "Could not resolve the dedicated packaging Git commit." >&2
exit 2
fi
for filename in NETfishingServer.x86_64 NETfishingServer.pck; do for filename in NETfishingServer.x86_64 NETfishingServer.pck; do
if [[ ! -f "${source_dir}/${filename}" ]]; then if [[ ! -f "${source_dir}/${filename}" ]]; then
@ -53,9 +64,10 @@ pck_sha256="$(sha256sum NETfishingServer.pck | awk '{print $1}')"
apply_umask="$(umask)" apply_umask="$(umask)"
umask 022 umask 022
printf '%s\n' \ printf '%s\n' \
"manifest_version=1" \ "manifest_version=2" \
"game_version=${game_version}" \ "game_version=${game_version}" \
"game_commit=${game_commit}" \ "game_commit=${game_commit}" \
"packaging_commit=${packaging_commit}" \
"export_preset=Linux Dedicated Server" \ "export_preset=Linux Dedicated Server" \
"platform=linux-x86_64" \ "platform=linux-x86_64" \
"executable_sha256=${executable_sha256}" \ "executable_sha256=${executable_sha256}" \
@ -71,6 +83,7 @@ Exact game source revision: ${game_commit}
Packaging source: Packaging source:
https://forge.makearmy.io/woofmeow/netfishing-dedicated-server https://forge.makearmy.io/woofmeow/netfishing-dedicated-server
Exact packaging source revision: ${packaging_commit}
EOF EOF
umask "${apply_umask}" umask "${apply_umask}"
sha256sum \ sha256sum \