FiveRP: the server from the hosting account, not the earlier one

Wrong server was published before. This is the one that runs on the
hosting account the video was made on: FiveRP - two-step registration
(account, then an identity printed onto a passport), login that returns
you to your resident, and a loading screen driven by the game's own
streaming events.

  resources/[local]/fiverp-auth          NUI + scrypt hashes + oxmysql
  resources/[local]/fiverp-characters    identity, character load, spawn
  resources/[local]/fiverp-loadscreen    loading screen
  sql/schema.sql                         accounts, characters
  docs/DESIGN.md                         the design system every screen follows
  docs/screens/                          shot from the live server

Only our own code is in here. cfx-server-data and oxmysql are fetched by
install.sh instead of being vendored, which keeps the repo at 3.7 MB.

install.sh does the whole box in one command: recommended FXServer
build, cfx-server-data, oxmysql, MariaDB with the schema, resources,
server.cfg (mode 600 - it carries the key and the database password),
boot entry, then it waits for the Cfx registration. Tested end to end on
a spare install root: 29 resources scanned, database and schema created,
and it stopped exactly where a wrong licence key should stop it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Claude Opus 5
2026-08-12 23:42:20 +00:00
co-authored by Claude Opus 5
parent 71856b15e9
commit c857979a55
88 changed files with 3904 additions and 7463 deletions
+8 -18
View File
@@ -1,43 +1,33 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: fivem
# Provides: fiverp
# Required-Start: $network mariadb
# Default-Start: 2 3 4 5
# Short-Description: Los Santos RP FXServer
# Short-Description: FiveRP (FXServer)
### END INIT INFO
NAME=fivem
DATA=/opt/fivem/data
SERVER=/opt/fivem/server
NAME=fiverp
DIR=/opt/fivem
LOG=/opt/fivem/logs/server.log
SUPPID=/run/$NAME.sup.pid
CHILDPID=/run/$NAME.child.pid
status() {
if [ -f $CHILDPID ] && kill -0 "$(cat $CHILDPID)" 2>/dev/null; then
echo "$NAME running (pid $(cat $CHILDPID))"
return 0
echo "$NAME running (pid $(cat $CHILDPID))"; return 0
fi
echo "$NAME not running"
return 3
echo "$NAME not running"; return 3
}
start() {
if status >/dev/null 2>&1; then echo "$NAME already running"; return 0; fi
# the database has to answer before resources start querying it
service mariadb start >/dev/null 2>&1
i=0
while ! mysqladmin ping >/dev/null 2>&1; do
i=$((i+1))
[ $i -gt 30 ] && echo "warning: mariadb did not come up" && break
i=$((i+1)); [ $i -gt 30 ] && echo "warning: mariadb did not come up" && break
sleep 1
done
cd $DATA || exit 1
setsid /opt/fivem/bin/supervise.sh "$NAME" "$LOG" \
$SERVER/run.sh +set citizen_dir $SERVER/alpine/opt/cfx-server/citizen/ \
+exec $DATA/server.cfg >/dev/null 2>&1 < /dev/null &
setsid $DIR/bin/run-server.sh $NAME $DIR $LOG >/dev/null 2>&1 < /dev/null &
sleep 2
echo "$NAME started"
}
+5 -4
View File
@@ -1,7 +1,8 @@
#!/bin/sh
# Send a command to the running FXServer console, e.g. rcon refresh
if [ ! -p /run/fivem.stdin ]; then
echo "server is not running (no console pipe)" >&2
# Send a command to the running FXServer console, e.g. rcon status
FIFO=${FIFO:-/run/fiverp.stdin}
if [ ! -p "$FIFO" ]; then
echo "server is not running (no console pipe at $FIFO)" >&2
exit 1
fi
printf '%s\n' "$*" > /run/fivem.stdin
printf '%s\n' "$*" > "$FIFO"
+43
View File
@@ -0,0 +1,43 @@
#!/bin/sh
# ---------------------------------------------------------------------------
# run-server.sh <name> <dir> <logfile>
#
# Keeps FXServer alive and gives it a console you can talk to.
#
# * FXServer reads its console from stdin and quits the moment stdin hits
# EOF, so it gets a FIFO whose write end this script holds open. That FIFO
# doubles as the command channel used by bin/rcon.
# * A server that dies instantly is usually failing for a reason that will
# not fix itself (bad licence key, database down). The restart delay backs
# off to 5 minutes so a broken server does not hammer Cfx, and resets once
# it has stayed up for a while.
# ---------------------------------------------------------------------------
NAME="$1"; DIR="$2"; LOG="$3"
FIFO="/run/$NAME.stdin"
MIN=5; MAX=300; HEALTHY=120
mkdir -p "$(dirname "$LOG")"
echo $$ > "/run/$NAME.sup.pid"
[ -p "$FIFO" ] || { rm -f "$FIFO"; mkfifo "$FIFO"; }
exec 9<> "$FIFO"
cleanup() { kill "$CHILD" 2>/dev/null; rm -f "/run/$NAME.sup.pid" "/run/$NAME.child.pid"; exit 0; }
trap cleanup TERM INT
delay=$MIN
while true; do
if [ -f "$LOG" ] && [ "$(stat -c %s "$LOG")" -gt 209715200 ]; then mv "$LOG" "$LOG.1"; fi
echo "=== $(date -Is) starting $NAME ===" >> "$LOG"
started=$(date +%s)
( cd "$DIR/server-data" && exec "$DIR/server/run.sh" +exec server.cfg ) >> "$LOG" 2>&1 <&9 &
CHILD=$!
echo $CHILD > "/run/$NAME.child.pid"
wait $CHILD
RC=$?
ran=$(( $(date +%s) - started ))
if [ "$ran" -ge "$HEALTHY" ]; then delay=$MIN; else delay=$(( delay * 2 )); [ "$delay" -gt "$MAX" ] && delay=$MAX; fi
echo "=== $(date -Is) $NAME exited (rc=$RC) after ${ran}s, restarting in ${delay}s ===" >> "$LOG"
sleep "$delay"
done
-66
View File
@@ -1,66 +0,0 @@
#!/bin/sh
# ---------------------------------------------------------------------------
# supervise.sh <name> <logfile> <command...>
#
# Keeps one process alive. There is no systemd in this container, so this is
# what restarts FXServer if it crashes.
#
# Two details that matter for FXServer specifically:
#
# * It reads its console from stdin and quits the moment stdin reaches EOF,
# so it is given a FIFO whose write end this script holds open forever.
# That doubles as a command channel - see /opt/fivem/bin/rcon.
#
# * A server that dies immediately is usually failing for a reason that will
# not fix itself (bad licence key, database down, Cfx rate limiting). The
# restart delay backs off so a broken server does not hammer an upstream
# service, and resets once it has stayed up for a while.
# ---------------------------------------------------------------------------
NAME="$1"; LOG="$2"; shift 2
FIFO="${FIFO:-/run/$NAME.stdin}"
MIN_DELAY=5
MAX_DELAY=300
HEALTHY_AFTER=120 # seconds of uptime that count as "it actually started"
mkdir -p "$(dirname "$LOG")"
echo $$ > "/run/$NAME.sup.pid"
[ -p "$FIFO" ] || { rm -f "$FIFO"; mkfifo "$FIFO"; }
# read-write open: holds the pipe open without blocking and without a helper process
exec 9<> "$FIFO"
cleanup() {
kill "$CHILD" 2>/dev/null
rm -f "/run/$NAME.sup.pid" "/run/$NAME.child.pid"
exit 0
}
trap cleanup TERM INT
delay=$MIN_DELAY
while true; do
if [ -f "$LOG" ] && [ "$(stat -c %s "$LOG")" -gt 209715200 ]; then
mv "$LOG" "$LOG.1"
fi
echo "=== $(date -Is) starting $NAME ===" >> "$LOG"
started=$(date +%s)
"$@" >> "$LOG" 2>&1 <&9 &
CHILD=$!
echo $CHILD > "/run/$NAME.child.pid"
wait $CHILD
RC=$?
ran=$(( $(date +%s) - started ))
if [ "$ran" -ge "$HEALTHY_AFTER" ]; then
delay=$MIN_DELAY
else
delay=$(( delay * 2 ))
[ "$delay" -gt "$MAX_DELAY" ] && delay=$MAX_DELAY
fi
echo "=== $(date -Is) $NAME exited (rc=$RC) after ${ran}s, restarting in ${delay}s ===" >> "$LOG"
sleep "$delay"
done