The server itself: repo now mirrors the machine it runs on, plus install.sh

The repository carried two different servers side by side - the early
`justrp` prototype with its Python auth API, and a snapshot of the real
one under `server-code/`. Only the second one is a server anyone should
start from, so the prototype is gone and the real one moved to the root.

Taken from the live box, so the UI is the finished version (the tokens,
the county-records sheets and the variable fonts landed after the last
snapshot was pushed):

  resources/[rp]/   rp_db, rp_core, rp_session, rp_loading, rp_ui,
                    rp_selftest, rp_dbtest
  bin/              supervise.sh (keep-alive + console FIFO), rcon, init script
  etc/schema.sql    accounts, characters, transactions, inventory, vehicles
  assets/fonts/     the bundled subsets
  docs/SERVER.md    how it is put together, resource by resource

install.sh turns a clean Ubuntu/Debian box into this server in one
command: recommended FXServer build, MariaDB with the schema, resources,
server.cfg + a generated database password, boot entry (systemd or
init.d), then it waits for the Cfx registration. --name/--port/--db-name
let a second server live on the same machine. Tested end to end on a
spare install root: build 25770 fetched, schema applied, boot entry
written, FXServer started and stopped exactly where a wrong licence key
should stop it.

No secrets travel with it: the licence key and the database password live
in data/secrets.cfg on the machine, and .gitignore now names it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Claude Opus 5
2026-08-12 23:23:33 +00:00
co-authored by Claude Opus 5
parent 80c1d75d2f
commit 71856b15e9
66 changed files with 2030 additions and 3814 deletions
+99
View File
@@ -0,0 +1,99 @@
# Los Santos RP — server notes
Everything here was written for this server. No ESX, no QBCore, no downloaded
resources: `cfx-server-data` is not used at all, and the bundled `chat` and
`monitor` resources are not started.
## Layout
/opt/fivem/server FXServer artefacts (build 25770, the recommended one)
/opt/fivem/data server-data root; run FXServer with this as cwd
server.cfg main config
secrets.cfg licence key + DB credentials, mode 600
resources/[rp]/ our resources
/opt/fivem/bin supervise.sh (keep-alive), rcon (console pipe)
/opt/fivem/logs server.log, rotated at 200MB
/opt/fivem/etc/schema.sql the database schema
## Resources
| resource | what it is |
|---------------|------------|
| `rp_db` | MariaDB client speaking the MySQL wire protocol directly over a TCP socket — handshake, `mysql_native_password`, text result sets, connection pool, transactions. No npm packages. Lua front end in `lib/db.lua`. |
| `rp_core` | Config, shared validation, appearance model, scrypt password hashing, the player registry, and the client/server request bridge. |
| `rp_session` | Connection gate (bans, capacity), accounts, characters, spawn. Every decision is made here; the client can only ask. |
| `rp_loading` | Loading screen: procedural night-city flyover on canvas, progress bound to the game's real load events, ambience synthesised with the Web Audio API. |
| `rp_ui` | Sign in / register, character creation with a live ped preview, spawn picker. Scripted cameras live in `client/camera.lua`. |
| `rp_selftest` | Checks the account/character data path on every boot and proves it survived the restart. |
| `rp_dbtest` | Driver test suite. Not started by default; `ensure rp_dbtest` to run it. |
## The look
The interface is the paperwork side of a life in Los Santos: every screen is a
sheet from the city's Office of Vital Records, lying on a dark desk while the
game runs on behind it. Paper is the only surface we draw; the game is the room
the desk is in. That is why the NUI body stays transparent and the sheets are
opaque - an opaque sheet stays legible over a bright daylight city, where a dark
glass panel would not.
`html/tokens.css` is shared verbatim by `rp_ui` and `rp_loading` and holds the
whole system. Three typographic voices, and the rule between them is literal:
| voice | face | what it is |
|-------|------|------------|
| preprinted | Archivo, expanded, caps | what the form was printed with: headings, field captions, buttons |
| typed | IBM Plex Mono | what somebody entered on it: values, serials, names, user input |
| prose | IBM Plex Sans | the plain-English notes in the margin: blurbs and hints |
Three inks, each with exactly one job and never used decoratively: `--canary`
(municipal form yellow) is what is selected right now, `--stamp` (oxblood) is
filed / refused / destroyed, `--verdi` (municipal teal) is checked and valid.
The one loud thing is the rubber stamp, and it only ever marks a real change of
state: the file opened, the application approved, the placement issued. It is
masked with SVG turbulence so the ink lands unevenly, and the paper on the desk
takes the hit with it.
Fonts are bundled, never fetched: a NUI page has no guaranteed internet. Any
glyph used in `content:` must exist in the shipped latin subset, which is why
the validation tick is drawn from borders rather than U+2713.
Screens can be looked at without launching the game: `python3 /opt/preview/build.py`
stubs the NUI bridge, pushes each screen into a representative state, and writes
standalone pages to `/opt/preview/out` for headless Chrome to shoot.
## Operating it
service fivem start|stop|restart|status
rcon <command> # e.g. rcon refresh, rcon status
tail -f /opt/fivem/logs/server.log
`supervise.sh` restarts FXServer if it dies, backing off from 5s up to 5min so
a server that cannot start (bad key, database down) does not hammer Cfx. It
also holds a FIFO open on the server's stdin — FXServer quits the moment stdin
reaches EOF, and that FIFO is what `rcon` writes to.
## Starting on boot
There is no systemd in this container. The platform runs a login shell as PID 1,
which sources `/etc/profile.d/redl-autostart.sh`, which starts everything marked
in `/etc/redl/enabled`. Both `mariadb` and `fivem` are marked, and `/etc/init.d/fivem`
waits for MariaDB to answer before starting the server.
## Database
MariaDB, database `rp`, application user `rp@127.0.0.1` with only
SELECT/INSERT/UPDATE/DELETE. Passwords are scrypt with a per-password salt and
the cost parameters stored in the hash. Tables: `accounts`, `auth_attempts`,
`characters`, `transactions`, `inventory`, `vehicles`.
Every query goes through `DB.Query`/`DB.Insert`/... with `?` parameters.
`CLIENT_MULTI_STATEMENTS` is deliberately not negotiated, so even a failure of
the escaper could not turn a parameter into a second statement.
## Not yet built
The pre-spawn experience and the framework underneath it are done. Gameplay on
top of it — chat, HUD, inventory, jobs, vehicles, policing, medical — is not.
`characters`, `transactions`, `inventory` and `vehicles` already have their
tables and the money API in `rp_core/server/player.lua` is journalled and ready.