Before you buy or install a FiveM script, test it like a QA lead: run it in an isolated Docker “Test City”, work through the acceptance checklist, score the risk from 0-100, and vet the vendor before money changes hands. This guide gives server owners and developers the full workflow — a copy-paste FXServer + MariaDB docker compose stack, resmon performance limits, security checks, and a maintenance playbook for after you ship.
TL;DR
- Uruchom Test City (Docker) aby bezpiecznie izolować i testować wydajność dowolnego skryptu.
- Uruchom Lista kontrolna akceptacji zanim zmieni właściciela choćby grosz.
- Użyj Wskaźnik ryzyka (0–100) aby zdecydować: wysłać/wstrzymać/odrzucić.
- Sprawdź sprzedawców za pomocą Rubryka Sprzedawcy (nie pomijaj tego).
- Jeśli kupujesz, wybieraj renomowane sklepy — zobacz nasze rekomendacje: Najlepsze sklepy Tebex.
Część 1 — “Test City” (Docker) do bezpiecznej i powtarzalnej kontroli jakości skryptów
Co otrzymujesz
- Konteneryzowany FXServer + MariaDB (+ Adminer)
- Czyste server.cfg z
oxmysqli podstawowe zasoby - Zamontowane przez bind mount
resources/customgdzie umieszczasz testowany skrypt - Deterministyczne nazwy sieci/porty dla prostych ciągów DB
Pobierz test-city.zip (Github)
Jak używać:
- Rozpakuj →
cd test-city - Kopiuj
.env.exampledo.envi ustaw swojeLICENSE_KEY(i dane do bazy danych, jeśli chcesz). - Wrzuć
oxmysqldoserver-data/resources/[standalone]/oxmysql/. - Umieść testowany skrypt w
server-data/resources/custom/<scriptname>/i dodajensure <scriptname>doserver.cfg. docker compose build && docker compose up -d→ połącz przez Direct Connect zlocalhost:30120.
Wymagania wstępne: Docker + Docker Compose, klucz licencyjny cfx oraz
oxmysqlkopię zasobu (wrzuć doserver-data/resources/[standalone]/oxmysql).
Układ folderów
test-city/ ├─ docker-compose.yml ├─ fxserver/ │ ├─ Dockerfile │ └─ entrypoint.sh ├─ server-data/ │ ├─ server.cfg │ └─ resources/ │ ├─ [standalone]/oxmysql/ # place oxmysql here │ └─ custom/ # put the script under test here (e.g., myscript/) └─ .env
.env (przykład)
LICENSE_KEY=changeme_cfx_license_key MYSQL_DATABASE=fivem MYSQL_USER=fivem MYSQL_PASSWORD=fivempw MYSQL_ROOT_PASSWORD=rootpw FX_ARTIFACT_URL=https://runtime.fivem.net/artifacts/fivem/build_proot_linux/master/LATEST.tar.xz # Tip: replace with a specific artifact URL you trust for reproducibility.
docker-compose.yml
version: "3.9"
networks:
testcity:
volumes:
db_data:
services:
db:
image: mariadb:10.11
restart: unless-stopped
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
command: >
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
--innodb_buffer_pool_size=256M
volumes:
- db_data:/var/lib/mysql
networks: [testcity]
adminer:
image: adminer:4
restart: unless-stopped
ports:
- "8080:8080"
networks: [testcity]
depends_on: [db]
fxserver:
build:
context: ./fxserver
args:
FX_ARTIFACT_URL: ${FX_ARTIFACT_URL}
restart: unless-stopped
environment:
LICENSE_KEY: ${LICENSE_KEY}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
depends_on: [db]
networks: [testcity]
ports:
- "30120:30120/udp"
- "30120:30120/tcp"
- "40120:40120/tcp" # txAdmin (optional)
volumes:
- ./server-data:/opt/fivem/server-data
fxserver/Dockerfile
FROM debian:bookworm-slim ARG FX_ARTIFACT_URL ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends xz-utils curl ca-certificates tini bash && rm -rf /var/lib/apt/lists/* # Fetch & extract FXServer artifact (URL provided via build-arg) RUN mkdir -p /opt/fivem && curl -fsSL "$FX_ARTIFACT_URL" -o /opt/fivem/fx.tar.xz && tar -xJf /opt/fivem/fx.tar.xz -C /opt/fivem && rm -f /opt/fivem/fx.tar.xz # Non-root RUN useradd -ms /bin/bash fivem USER fivem WORKDIR /opt/fivem COPY --chown=fivem:fivem ../server-data /opt/fivem/server-data COPY --chown=fivem:fivem entrypoint.sh /entrypoint.sh ENTRYPOINT ["/usr/bin/tini","--"] CMD ["/bin/bash","/entrypoint.sh"]
fxserver/entrypoint.sh
#!/usr/bin/env bash set -euo pipefail # Provide DB string for oxmysql via server.cfg (already set there), # just ensure the DB is reachable before boot to avoid spam errors. echo "Waiting for database..." until nc -z db 3306; do sleep 1; done echo "DB ready." # Run FXServer with our server.cfg # Most Linux artifacts ship a run.sh in the artifact root. exec bash /opt/fivem/run.sh +exec /opt/fivem/server-data/server.cfg
Jeśli twój artefakt używa innej ścieżki uruchamiania, dostosuj ostatnią linię odpowiednio (np.,
/opt/fivem/alpine/opt/cfx-server/run.sh).
server-data/server.cfg (chudy, gotowy do testów)
# ---------- Identity ---------- sv_licenseKey "%LICENSE_KEY%" # injected by env in entrypoint command or replace manually sv_hostname "Test City — Script QA" sets tags "qa,testing,fivemx" sv_maxclients 2 onesync on sv_scriptHookAllowed 0 sv_enforceGameBuild 3095 # ---------- Networking ---------- endpoint_add_tcp "0.0.0.0:30120" endpoint_add_udp "0.0.0.0:30120" # ---------- Database (oxmysql) ---------- set mysql_connection_string "mysql://%MYSQL_USER%:%MYSQL_PASSWORD%@db:3306/%MYSQL_DATABASE%?charset=utf8mb4" # ---------- Core / Base resources ---------- ensure mapmanager ensure chat ensure spawnmanager ensure sessionmanager ensure hardcap ensure baseevents # ---------- Datastore ---------- ensure oxmysql # ---------- Under test ---------- # Drop your script folder into resources/custom/<scriptname> and enable here: # ensure myscript # ---------- QA helpers ---------- # Verbose logging in dev setr con_minSeverity info # Enable txAdmin panel (optional) setr txAdminPort 40120
Włącz swój skrypt: skopiuj go do
server-data/resources/custom/myscript/i dodajensure myscriptdo dolnego bloku.
Uruchom to
cd test-city docker compose build docker compose up -d # Adminer at http://localhost:8080 (server: db, user: fivem, pass: fivempw) # Connect FiveM client → Direct Connect: your-docker-host:30120
Część 2 — Lista kontrolna akceptacji skryptu (Nie pomijaj)
Używaj tego za każdym razem. Skopiuj do swojego trackera i odznaczaj elementy.
A. Kontrola wstępna (przed instalacją)
- Typ źródła: Otwarte źródło \/ częściowo otwarte \/ tylko escrow.
- Wymienione zależności: framework (ESX\/QBCore\/QBOX),
ox_lib,oxmysql,PolyZone, itp. - fxmanifest.lua:
lua54 'yes', poprawnygame 'gta5',fx_versionnie przestarzały. - Dokumentacja: kroki instalacji, przykłady konfiguracji, uprawnienia, lokalizacje, znane konflikty.
- Licencja/Regulamin: prawa użytkowania, polityka zwrotów, aktualizacje, kanał wsparcia.
B. Instalowalność
- Brak błędów konsoli przy
ensure: zero śladów stosu lub spam o brakujących zasobach. - Brak
deprecated nativesspamu. - Konfiguracja ładuje się czysto: brak błędów składni JSON/Lua.
- Migracje bazy danych: tworzenie tabel raz; ponowne uruchomienia nie stosują ponownie ani nie psują.
C. Funkcjonalność
- Rdzeń przepływy działają: przetestowana ścieżka szczęśliwa (np. zakup, przepływ pracy, crafting).
- Przypadki brzegowe: nieprawidłowe dane wejściowe, brakujące uprawnienia, ilości poza zakresem.
- Lokalizacja: brak zakodowanych na stałe ciągów, jeśli obiecano lokalizacje.
- Uprawnienia: komendy dla personelu/admina zabezpieczone; brak swobodnego dostępu po stronie klienta.
D. Wydajność (klient i serwer)
resmon: bezczynność ≤ 0.10ms, aktywny ≤ 0.50ms (klient).- Stan serwera: brak długich ostrzeżeń o zacięciach podczas normalnego użytkowania.
- Zapytania do bazy danych: brak ciasnych pętli; używane przygotowane instrukcje; minimalne N+1.
E. Bezpieczeństwo
- Walidacja po stronie serwera: każde zdarzenie serwera jest walidowane
source, uprawnienia i typy wejścia. - Brak zaufania do klienta: zmiany pieniędzy/inwentarza tylko z logiki serwera.
- Brak eval/
loadstring/kod zdalny wzory. - Anty-nadużycia: limity szybkości/throttling na spamerskich punktach końcowych.
- Integralność szyfrowania: brak ukrytych drzwi w niezaszyfrowanych modułach ładowania konfiguracji.
Dobry wzorzec zdarzeń (przykład):
RegisterNetEvent('myscript:buy', function(item, amount)
local src = source
if type(item) ~= 'string' or type(amount) ~= 'number' or amount < 1 then return end
if not HasPermission(src, 'shop.buy') then return end
local xPlayer = GetPlayer(src) -- framework adapter
if not xPlayer then return end
-- validate price server-side, check inventory limits, do DB in a transaction
end)
F. Kompatybilność i czystość
- Obecne adaptery frameworków (ESX/QBCore/QBOX) lub jasno zadeklarowane jako nieobsługiwane.
- Brak wycieku globalnych, unikalne nazwy zdarzeń, brak założeń co do nazwy zasobu.
- Czysta deinstalacja: usunięcie zasobu nie psuje innych.
Część 3 — Model ilościowej oceny ryzyka (0–100)
Użyj tego do podjęcia decyzji “wysłać/zatrzymać/odrzucić”. Niższy wynik jest lepszy.
| Czynnik | Waga | Jak oceniać (0=dobrze → 5=źle) |
|---|---|---|
| Wydajność | 0.20 | resmon bezczynność: 0=≤0.10ms, 1=≤0.20, 3=≤0.50, 5=>0.50; skoki dodają +1 |
| Bezpieczeństwo | 0.25 | 0=wszystko zweryfikowane przez serwer + limity; 3=niektóre luki; 5=ufność do klienta / niebezpieczne zdarzenia |
| Stabilność | 0.15 | 0=brak błędów; 3=sporadyczne ostrzeżenia; 5=częste błędy/zacięcia |
| Zgodność | 0.10 | 0=adaptery/testy; 3=tylko jeden framework; 5=łamie wspólne zależności |
| Utrzymanie | 0.10 | 0=docs/changelog/wersje semantyczne; 5=brak dokumentacji/porzucone |
| Łańcuch dostaw/Dostawca | 0.20 | 0=renomowany, historia, zwroty; 5=nieznany, brak polityki |
Formuła
RiskScore = 100 * Σ(weight_i * (score_i / 5))
Zespoły i Akcje
- 0–24 (Niskie): Wyślij do środowiska staging, monitoruj.
- 25–49 (Umiarkowany): Poprawki wymagane przed uruchomieniem.
- 50–74 (Wysoki): Przytrzymaj; poproś o poprawki od dostawcy lub wymień.
- 75–100 (Krytyczne): Odrzuć.
Przykład
- Wydajność=1, Bezpieczeństwo=3, Stabilność=1, Kompatybilność=1, Utrzymanie=2, Dostawca=1
- Ryzyko = 100*(.2*.2 + .25*.6 + .15*.2 + .1*.2 + .1*.4 + .2*.2) = 34 → Umiarkowany
Część 4 — Kryteria oceny dostawcy (oceniaj każdy od 0 do 5, im wyżej, tym lepszy)
| Criterion | Jak wygląda “dobrze” | Uwagi |
|---|---|---|
| Tożsamość i Historia | Wyraźna marka, lata aktywności, spójny uchwyt | Unikaj tymczasowych sklepów |
| Dokumentacja | Instalacja + konfiguracja + uprawnienia + rozwiązywanie problemów | Zrzuty ekranu/gify pomagają |
| Częstotliwość aktualizacji | Changelog, wersje semantyczne, ostatnie commity/wydania | Kwartalnie lub częściej jest w porządku |
| Jakość wsparcia | SLA dla zgłoszeń/Discord, powtarzalne poprawki, nie tylko “restart” | Przykładowe odpowiedzi |
| Przejrzystość problemów | Znane problemy publiczne i plan działania | Uczciwość > perfekcja |
| Wyjaśnienie zwrotów/warunków sprzedaży | Okres zwrotu, warunki, warunki licencji | Żadnych ciemnych wzorców |
| Dowód testowania | Wideo ze środowiska staging, metryki wydajności, lista frameworków | Jeszcze lepiej: serwer demonstracyjny |
| Higiena bezpieczeństwa | Wspomina o kontrolach po stronie serwera, brak wrażliwych kluczy, brak eval | Zapytaj o audyty |
| Polityka zgodności | ESX/QBCore/QBOX podano, adaptery, macierz wersji | Obsługiwane przez państwo wersje |
| Ceny i wartość | Uczciwe jak na złożoność, bez płatnych zależności | Uważaj na pułapki sprzedażowe |
Ocena w skali (0–50):
- 40–50: Silny — preferowany dostawca
- 30–39: Akceptowalne — monitoruj
- 20–29: Słaby — postępuj ostrożnie
- <20: Unikaj
Wskazówka pro: Sprawdź z renomowanymi platformami. Zacznij tutaj: Najlepsze sklepy Tebex.
Część 5 — Podręcznik utrzymania (po wdrożeniu)
- Przypinanie wersji: blokuj wydania skryptów + wersje zależności (np.,
oxmysql,ox_lib). - Najpierw staging: wszystkie aktualizacje trafiają do Test City; uruchom ponownie listę kontrolną akceptacji.
- Kopie zapasowe i przywracanie: Kopia zapasowa bazy danych + pliki zasobów przed każdą aktualizacją. Zachowaj Rollback.md z dokładnymi krokami.
- Test dymny CI (opcjonalny, zalecany): Połączenie klienta headless + makro poleceń do głównych przepływów; parsowanie konsoli serwera pod kątem błędów.
- Metryki operacyjne: prowadź prosty dziennik dla każdego skryptu: średni resmon (bezczynny/aktywny), liczba błędów/sesja, uwagi dotyczące incydentów.
- Dyscyplina dziennika zmian: wymagaj dzienników zmian dostawcy; zachowaj własne notatki dotyczące integracji.
- Zmniejsz ryzyko zaplanowanych zdarzeń: aktualizuj poza godzinami szczytu; ogłaszaj okna konserwacyjne.
Część 6 — Szablony, które możesz skopiować
A. Plan testów (na skrypt)
# Script Test Plan — <name> <version> ## Context Framework(s): ESX/QBCore/QBOX Dependencies: oxmysql vX, ox_lib vY, PolyZone vZ DB Migrations: yes/no Escrow: yes/no ## Functional Cases - [ ] Case 1: - [ ] Case 2: - [ ] Negative 1: ## Performance resmon idle: ____ ms resmon active: ____ ms (scenario: ______) ## Security Checks - [ ] All server events validate source/perm/input - [ ] Rate limits present - [ ] No client-trusted money/inventory mutations ## Logs & Errors Paste snippet (server + F8): ## Result Pass/Fail + Notes
B. Rollback.md (szkielet)
# Rollback — <date> <script> <from→to> 1) Disable script: `stop <resource>` 2) Restore resource files from backup: <path> 3) Restore DB snapshot: <path/command> 4) Restart FXServer 5) Verify: console clean, perf normal, flows ok
C. Szablon zgłoszenia
**Summary** What happened vs expected, with timestamps. **Repro Steps** 1) ... 2) ... **Env** Artifact build: Framework & versions: Script version: Other deps: **Logs** Server console: F8: **Attachments** Screens/video if possible.
Jak efektywnie korzystać z tego przewodnika
- Bootstrap Test City raz, zachowaj czystość.
- Dla każdego kandydującego skryptu:
- Wprowadź
resources/custom/, włącz wserver.cfg. - Uruchom Lista kontrolna akceptacji.
- Oblicz Wynik ryzyka.
- Zweryfikuj sprzedawcę za pomocą Rubryka Sprzedawcy.
- Wprowadź
- Jeśli przejdzie, scal z gałęzią staging; jeśli nie, poproś o poprawki lub zrezygnuj.
Potrzebujesz więcej przewodników po testach? Learn how to measure script performance with Resmon in FiveM, fix server thread hitch warnings, and build the Part 1 test server with Docker for FiveM.
After the test workflow is ready, compare the exact framework, dependencies, delivered files and setup notes in the FiveM scripts marketplace.
