Skip to main content

Setting Up Your Community

For community owners and department admins standing up Kestrel for the first time, or wiring up a FiveM server against an existing Kestrel organisation.

1. Web app: create your organisation and departments

From the admin console (Community Owner access):

  1. Create your organisation — name, timezone, which departments you're running (PD, Fire, EMS).
  2. Under Settings → Departments, set up the department slugs your FiveM resources will map jobs onto.
  3. Under Settings → Map, choose whether your organisation uses real GTA V coordinates (gta_v_tiles) or a static image. Live position tracking and automatic GPS waypoints for officers only work with gta_v_tiles — a static image has no in-game-meaningful coordinates to send.
  4. Set up each department's ranks — ordered highest-authority-first, with simple up/down reordering — and assign each department a callsign as a free-text value; there's no separate scheme builder to configure. Ranks are for display and hierarchy only and carry no permissions of their own — permissions are entirely role-based, covered in Roles & permissions below. Add your staff under Admin console → Staff management. Staff are deactivated, never hard-deleted, so history and audit attribution survive turnover.

The admin console also covers the permissions matrix, billing/subscription, and a searchable audit log — everything you need to run the community day to day beyond the initial setup above.

2. Create your FiveM integration credentials

Under Admin → Integrations, create the credentials your FiveM resources will authenticate with. You need two different kinds, because they authenticate two different kinds of caller:

  • A FiveM credential (New FiveM credential), used by kestrel-cad and kestrel-ers-bridge. These act on behalf of a specific linked, on-duty player — every request they make is gated on that.
  • An API credential (New credential → kind "API"), used by kestrel-anpr-bridge. A camera network isn't a player and can never satisfy the on-duty gate, so it authenticates as an org-wide service credential instead. Grant it exactly three scopesrecords.bolo.view, records.bolo.manage, and records.vehicle.view — and nothing more. This credential's secret lives on a game server, a larger attack surface than Kestrel's own backend, so keep its blast radius to exactly what ANPR needs.

Both secrets are shown exactly once at creation. Store them as convars in a gitignored file (e.g. convars.cfg) that you exec from server.cfg, rather than committing them into any resource's config file directly.

3. Install the FiveM resources

kestrel-cad

Core identity linking, duty sync, the MDT handoff, lookups, citations, arrests, BOLOs, civilian sync, live position tracking, waypoints, and station-zone auto duty detection.

  1. Copy the resource into resources/.

  2. Set these as convars in your gitignored file (per above), not inside config.lua directly:

    set kestrel_api_url "https://your-kestrel-deployment"
    set kestrel_web_base_url "https://your-kestrel-deployment"
    set kestrel_client_id "..."
    set kestrel_client_secret "..."
    set kestrel_cad_default_department_slug "police-department"

    kestrel_web_base_url is usually a different origin than kestrel_api_url — set it explicitly rather than assuming they match. Running more than one department off a single server (PD + Fire + EMS)? Add a second FiveM credential and its own numbered convar trio — kestrel_cad_credential_2_department_slug / _client_id / _client_secret — and keep going (_3_, _4_, ...) for each additional department.

  3. Edit shared/zones.lua (no secrets belong in this file — it's meant to be safe to commit) to map your server's job names onto department slugs, and optionally define station zones for auto duty clock-on/off, vehicle lockers, and armories:

    JobDutyMap = { police = "police-department", ambulance = "ems-department" }
    StationZones = {
    { label = "PD Station", departmentSlug = "police-department", coords = vector3(441.0, -982.0, 30.7), radius = 15.0 },
    }
  4. ensure kestrel-cad after your framework resource (es_extended / qb-core/qbx-core), so it can find it at startup.

For the full list of kestrel_cad_* convars — MDT keybinds and command names, live-position/waypoint polling intervals, station-zone behavior, and more — see FiveM Resource Configuration.

Real two-way voice radio is a separate resource, kestrel-radio, covered below.

kestrel-radio (optional)

Real two-way field↔dispatch voice radio. Officers keep their normal FXServer/voice-plugin microphone — this resource doesn't redirect or replace it; it only delivers dispatcher audio to a receive-only in-game overlay and maps your voice plugin's radio channels onto Kestrel talkgroups.

  1. Copy the resource into resources/.

  2. It shares kestrel-cad's credential and API URL convars — no separate credential to create. Add one more convar mapping your voice plugin's channel numbers to department slugs:

    set kestrel_radio_channel_map "police-department:1,fire-department:2"
  3. ensure kestrel-radio after kestrel-cad.

See FiveM Resource Configuration for the rest of its convars.

kestrel-ers-bridge (optional — only if you run night_ers)

Bridges night_ers callouts, flagged peds, and flagged vehicles into Kestrel automatically. Shares kestrel-cad's FiveM credential — no separate credential needed, just a department slug:

set kestrel_api_url "https://your-kestrel-deployment"
set kestrel_client_id "..."
set kestrel_client_secret "..."
set kestrel_cad_default_department_slug "police-department"

Two things worth setting deliberately before going live:

  • Leave kestrel_ers_duty_sync_enabled at its default of 0 if you're also running kestrel-cad (or anything else that manages duty state). Enabling it creates a second, uncoordinated place pushing duty changes to Kestrel, which reliably breaks kestrel-cad's MDT access, lookups, and BOLOs — see the resource's own README for the full mechanism if you need to understand why.
  • Edit the statute catalog. /erscite and /ersarrest pull codes from KestrelErsConfig.StatuteCatalog in server/config.lua, which ships with placeholder codes — replace them with your department's real codebook before staff start using the commands.

kestrel-anpr-bridge (optional)

An automated camera network that scans traffic and reports BOLO hits.

  1. Copy the resource into resources/.

  2. Set the convars using your API credential from step 2 (not the FiveM credential):

    set kestrel_anpr_enabled 1
    set kestrel_anpr_api_url "https://your-kestrel-deployment"
    set kestrel_anpr_client_id "..."
    set kestrel_anpr_client_secret "..."
  3. Edit shared/config.lua with your real camera locations. Stand where you want a camera and run /anprtest_camera to print a ready-to-paste coordinate line.

  4. ensure kestrel-anpr-bridge and watch the console for the startup banner with no credential/URL warnings.

If every BOLO cache refresh 403s on the vehicle lookup, the credential is missing records.vehicle.view — go back and add it.

4. Verify before going live

  • Have a linked, on-duty staff member run /runplate, /citation, and /bolo to confirm kestrel-cad is talking to your Kestrel instance.
  • If you run ERS, play through one real callout end-to-end and confirm the call, civilian/vehicle sync, and any BOLO show up on the dispatch board.
  • If you run ANPR, drive a BOLO'd plate through a configured camera and confirm a hit, timeline entry, and map pin appear on the real dispatch UI — not just in console logs.

5. Invites — bringing staff on board

Rather than adding every staff member by hand, an admin can generate an invite link and hand it out. Under Admin console → Invites, create an invite of one of three types:

Invite typeGrants
Community/ApplicationMembership in the organisation, into a baseline role
DepartmentMembership in a specific department
RoleA specific role assignment

Each invite has a few independent settings:

  • Expiry — never, or on a chosen date.
  • Use limit — unlimited, or a maximum number of redemptions.
  • Approval — whether a redemption takes effect immediately or needs an admin to sign off first.
  • Notes — optional free text, useful for remembering who an invite was made for.

Community invites default to auto-approve, but only into a restricted baseline role — an invite can never auto-approve someone straight into Administrator, Supervisor, or Officer. Department and Role invites default to requiring approval.

Save the link now

The invite link and its redemption code are shown exactly once, at the moment you create the invite. If you navigate away without copying it, it's gone — you'll need to create a new invite.

Existing invites can be revoked at any time, which stops any further redemptions without affecting people who already joined. The Pending redemptions tab lists everyone who redeemed a require-approval invite and hasn't been processed yet; from there an admin can Approve or Reject each one (rejection accepts an optional reason).

6. Personnel

Any member of your organisation can create their own character or characters — this isn't gated behind an admin permission by default. What the org.personnel.manage permission adds is visibility and control over other people's characters: seeing the full roster instead of just your own, renaming a character, retiring one, and assigning department memberships.

Retiring a character is reversible by support — it's never a hard delete, so history and audit attribution survive. There's also no separate "civilian" account type in Kestrel: a civilian is simply a character with zero department memberships.

7. Roles & permissions

Custom roles are how you shape who can do what beyond the built-in baseline. Creating one, under Admin console → Roles:

  1. Name it. The name can't be changed after creation, even for a role you created yourself — only its permission set can be edited later.
  2. Check off permissions from the platform's fixed permission catalogue, grouped by category. You can't invent new permissions — only combine the ones Kestrel ships.
  3. Choose its assignable scope — org-wide, department-scoped, or both.
Scope is permanent

Scope is set once, at creation, and can't be changed afterward. If you need a role available in a different scope, create a new one.

Granting a role is a separate step from creating it. A dedicated Assignments tab is where department-scoped grants are actually handed out: pick a character, pick the role, and pick which of that character's department memberships the grant applies to. Org-wide grants aren't managed from that same Assignments screen.

8. Community & organisation settings

Beyond what you set during initial creation (see step 1 above), the following stay editable at any time from Admin → Settings:

  • Organisation name
  • Timezone
  • Game platform — FiveM, Roblox, or Custom
  • Regional profile
  • Default locale

Two settings worth calling out specifically:

  • Report Policy controls whether closing a CAD call requires a report to be filed first: Disabled, Optional, or Required.
  • Configuration is a separate admin area for customizing your organisation's own reference catalogues — BOLO severity levels and warrant types — in addition to the broader reference-data catalogues under the Information plugin (10-codes, priorities, call types, disposition codes, penal codes, evidence categories, and locations).

9. Account settings

Everything above is admin-facing. Every staff member, admin or not, has their own Account Settings, where they can set a personal language/locale that overrides the community's default if they want something different.

tip

Security — password, MFA, sessions — is handled entirely through Ashmere ID, Kestrel's external identity provider. There's no separate password or MFA setup inside Kestrel itself.

10. Belonging to multiple organisations

A single Kestrel account isn't limited to one community. A dedicated screen lists every organisation the account belongs to and lets you:

  • Switch which organisation is currently active.
  • Join another organisation via an invite link.
  • Create an entirely new organisation from the same screen — not just at initial signup.
  • Leave an organisation you don't own. This is only available for the organisation that's currently active.