FiveHub is a centralized platform for monitoring, auditing and operating FiveM servers.
Centralized FiveM logs with search, server filters and multi‑tenant separation. Built for staff and auditing.
Secure handling of in‑game generated images and audio (phone, bodycam, simulated CCTV), with server‑level access control.
True support for multiple FiveM servers (production, test, staging) with separated permissions for users and staff.
Access via Discord OAuth, without local passwords, with roles (admin, staff, viewer) managed server‑side.
CSRF protection, hardened sessions, rotatable API keys and full data isolation between servers.
Full tracking of administrative actions (server creation, API key rotation, deletions), with automatic retention.
FiveHub integrates natively with ox_lib and qbx_core as a centralized logging service, similarly to FiveManage or Grafana Loki.
server.cfg
Configure FiveHub as a logging service by setting the following convars.
# Enable ox_lib logger
set ox:logger "fivehub"
# Server API key (generated in FiveHub → Servers)
set fivehub:key "API_KEY_DEL_SERVER"
# Endpoint FiveHub (batch logging)
set fivehub:endpoint "https://fivehub.galad.it/api/logs/batch.php"
The API key uniquely identifies the FiveM server and can be rotated at any time from the FiveHub dashboard.
fivehub service
FiveHub operates as an ox_lib logging service.
You must add the following block to:
ox_lib/imports/logger/server.lua
if service == 'fivehub' then
local key = GetConvar('fivehub:key', '')
local endpoint = GetConvar('fivehub:endpoint', '')
if key ~= '' and endpoint ~= '' then
local buffer
local bufferSize = 0
local headers = {
['Content-Type'] = 'application/json',
['X-FIVEM-KEY'] = key,
['User-Agent'] = 'ox_lib',
}
local function flush()
PerformHttpRequest(endpoint, function(status, _, _, response)
if status ~= 200 then
print('[FiveHub] Log batch failed:', status, response)
end
end, 'POST', json.encode(buffer), headers)
buffer = nil
bufferSize = 0
end
function lib.logger(source, event, message, ...)
if not buffer then
buffer = {}
SetTimeout(500, flush)
end
local metadata = {
event = event,
source = source,
}
local player = source and exports.qbx_core:GetPlayer(source)
if player then
metadata.citizenid = player.PlayerData.citizenid
metadata.charname = player.PlayerData.charinfo.firstname
.. ' ' ..
player.PlayerData.charinfo.lastname
end
for _, arg in pairs({ ... }) do
if type(arg) == 'table' then
for k, v in pairs(arg) do
metadata[k] = v
end
elseif type(arg) == 'string' then
local k, v = string.strsplit(':', arg)
if k and v then
metadata[k] = v
end
end
end
bufferSize += 1
buffer[bufferSize] = {
level = 'info',
message = message,
resource = cache.resource,
metadata = metadata,
}
end
end
end
Logs are sent in batch mode every 500 ms to reduce load and improve performance, exactly like SaaS logging platforms.
Once FiveHub is enabled as the logger, simply use
lib.logger in any server‑side resource:
lib.logger(source, 'vehicle:spawn', 'Vehicle spawned successfully')
In the NPWD configuration file, apply the following changes.
"images": {
"url": "https://fivehub.galad.it/api/media/image.php",
"type": "image",
"imageEncoding": "webp",
"contentType": "multipart/form-data",
"useContentType": false,
"useWebhook": false,
"authorizationHeader": "Authorization",
"authorizationPrefix": "",
"useAuthorization": true,
"returnedDataIndexes": ["url"]
},
"voiceMessage": {
"enabled": true,
"authorizationHeader": "Authorization",
"url": "https://fivehub.galad.it/api/media/audio.php",
"returnedDataIndexes": ["url"]
},
Then add the required convars to server.cfg.
set SCREENSHOT_BASIC_TOKEN "TOKENCODE"
set NPWD_AUDIO_TOKEN "TOKENCODE"
POST https://fivehub.galad.it/api/logs/batch.php – logging batch (ox_lib)POST https://fivehub.galad.it/api/logs/event.php – logging singolo (debug / test)All timestamps are generated server‑side by FiveHub to ensure consistency, accuracy and auditability.