Configuration

Every setting in oxide-phone, what it does in game, its default value and where to find it in the /phone settings menu — plus how database-backed settings work, the o-link map mode and the app ID reference.

This page lists every setting in oxide-phone, what it does in game, its default value, and where to find it in the /phone settings menu. Start with How Settings Work: the phone saves its settings in your database, so editing the config file does not always do what you expect.

How Settings Work

The Short Version

  • The first time oxide-phone starts, it copies every setting from shared/config.lua into a database table called oxide_settings.
  • From then on, the database decides. Editing shared/config.lua does not change a setting that is already saved in the database.
  • To change settings after the first start, join the server as an admin and type /phone settings.
  • Changes you save in that menu are stored in the database straight away, and almost all of them work immediately, without a restart.

The First Start

Optional: open shared/config.lua (the settings file) and change anything you want before starting the phone for the first time. You can also skip this and do everything in game later.

Start your server.

oxide-phone creates the oxide_settings table if it does not exist yet. Other Oxide resources may use the same table; each one keeps its own rows.

It copies every setting from shared/config.lua into that table. The server console shows a configSeeded line when it does.

After the First Start

On every start after the first one, oxide-phone reads its settings from the database. The config file is only used in these cases:

  • A setting missing from the database is copied in from shared/config.lua. This happens when a resource update adds a brand-new setting, or when you delete a setting's row from the database.
  • A new option inside an existing group is filled in from shared/config.lua. For example, if an update adds a new option under Config.Battery, that one option is added and your other battery settings stay as they are.
  • Lists are never merged. Lists such as Config.Items.phones, Config.Numbers.prefixes, Config.Evidence.jobs, Config.Evidence.stations, Config.Emergency.numbers, Config.DeadZones, Config.Store.preinstalled, Config.Home.wallpapers and Config.ModelSwaps are saved as a whole. After the first start, the whole list comes from the database.
  • Reset to default in the menu puts a setting back to the value in shared/config.lua (see below).

When you update oxide-phone and the update replaces shared/config.lua, you lose nothing: your saved settings stay in the database.

Changing Settings in Game

Join your server with an admin account. See Admin for who counts as an admin.

Type /phone settings in chat and press Enter. The Phone Settings window opens. If your own phone was open, it is put away first.

Pick a section in the left sidebar. Sections are grouped under Device, Police, World, Screen and Advanced.

Use the Basic and Advanced tabs at the top. Most settings are on Basic. Advanced has the app start timeout, the timers and debug mode.

Use the search box to find a setting by name.

Change a value. A changed badge appears next to it, and the bar at the bottom counts your unsaved changes.

Press Save Changes. A message confirms the save. If a value is not allowed, that setting shows the reason and your other changes are still saved.

Close the window with Close or ESC. Closing throws away changes you have not saved.

Reset to default next to a setting puts it back to the value shared/config.lua had the last time the phone started. The reset is saved immediately. For settings that hold several options (such as Battery), the reset puts back all of them together.

Positions in the world (Forensics stations and charging stations) have two small buttons: the crosshair (Place in world) hides the menu so you can pick the spot in the world, and Teleport here takes you to a saved spot. A charging station is placed as a see-through copy of its model that you turn and put down.

Using the Config File After the First Start

If you prefer editing shared/config.lua, you need one extra step to push your change into the database:

Open shared/config.lua, change the value, and save the file.

Restart your server (or type restart oxide-phone in the server console).

Join as an admin and type /phone settings.

Find the setting and press Reset to default. The value from the file is now saved in the database.

When Changes Take Effect

Almost every setting applies as soon as you press Save Changes, for every player, with no restart. The exceptions:

SettingWhen it applies
Config.OpenKey, Config.Calls.answerKey, Config.Calls.declineKeyOnly for players who have never joined your server. Everyone else keeps their own key binding
Config.NumbersOnly for new numbers. Existing numbers never change
Config.Home.wallpapers rows pointing at a new file in wallpapers/After the new file is served: restart oxide-phone once after copying the file
Config.PropThe next time a phone is opened
Server convars (keys in server.cfg)After a restart. See Installation → Server Convars

Where Each Setting Is in the Menu

SidebarSectionSettings
DeviceGeneralConfig.OpenKey, Map mode (see below)
DeviceItemsConfig.Items
DeviceNumbers & SIMsConfig.Numbers, Config.Sim
DeviceSecurityConfig.Lock
DeviceCalls & MessagesConfig.Calls, Config.Messages, Config.Contacts, Config.Mail
DeviceMediaConfig.Media, Config.Camera, Config.Streams
PoliceEvidenceConfig.Evidence
PoliceEmergencyConfig.Emergency
WorldBatteryConfig.Battery, Config.Chargers
WorldSignalConfig.Signal, Config.DeadZones
ScreenHome & AppsConfig.Store, Config.Appearance, Config.Home, Config.AppReadyTimeout (Advanced tab)
ScreenAppsConfig.Apps
ScreenNotificationsConfig.Notifications
ScreenAppearanceConfig.Prop
AdvancedCompatibilityConfig.ModelSwaps
AdvancedAdvancedConfig.Session, Config.Debug (Advanced tab)
Not in the menuConfig.SettingsCommand, Config.ModelHints

Config File: shared/config.lua

General

SettingTypeDefaultDescription
Config.DebugbooleanfalsePrints extra detail to the server console and the F8 console, and offers a Demo app in the Store (and on oxide-tablet, when it runs) for testing apps from other resources. Leave off on a live server
Config.SettingsCommandstring'/phone settings'The command named in model warnings as the place to set a replacement model. Not in the settings menu
Config.OpenKeystring'F1'The default key that opens the phone the player carries. Players change it in Esc → Settings → Key Bindings → FiveM → Open phone. A new default only reaches players who have never joined
Config.Debug = false
Config.SettingsCommand = '/phone settings' -- named in warnings
Config.OpenKey = 'F1'

Menu: Device → General (OpenKey, up to 20 characters) and Advanced → Advanced on the Advanced tab (Debug, shown as Debug mode). Config.SettingsCommand has no place in the menu; leave it as it is.

Items

The inventory item names the phone reacts to. Each item must exist in your inventory (see Installation → Framework Setup).

SettingTypeDefaultDescription
Config.Items.phonestable (list of strings){ 'phone' }Every item listed opens as a phone. Each phone item is its own device with its own data
Config.Items.simstring'sim_card'The registered SIM card. The carrier records the character it was issued to
Config.Items.burnerSimstring'burner_sim'The unregistered SIM card. '' turns burners off
Config.Items.powerbankstring'powerbank'A one-shot charge for the phone the player holds. '' turns it off
Config.Items.wiperstring'phone_wiper'Carrying one adds Secure wipe to the phone's Settings app; wiping uses it up. '' turns secure wipe off
Config.Items = {
    phones = { 'phone' },     -- every item listed opens as a phone
    sim = 'sim_card',         -- registered SIM
    burnerSim = 'burner_sim', -- unregistered SIM; '' disables burners
    powerbank = 'powerbank',  -- one-shot charge; '' disables the item
    wiper = 'phone_wiper',    -- secure wipe; '' disables it
}

Menu: Device → Items. Item names can be up to 60 characters. A name you add is ready to use as soon as you save.

Phone Numbers

SettingTypeDefaultDescription
Config.Numbers.formatstring'@-###-####'How new numbers look. Each # becomes a random digit and each @ one of the prefixes. May only contain #, @, digits and -, and needs at least one #; anything else falls back to the default. The default gives numbers like 213-555-0142
Config.Numbers.prefixestable (list of strings)ten Southern California area codes (below)The area codes used in place of @. Digits only, all the same length
Config.Numbers = {
    format = '@-###-####',
    prefixes = { '213', '310', '323', '424', '562', '626', '714', '818', '909', '949' },
}

Menu: Device → Numbers & SIMs → Phone numbers. Existing numbers never change. Players can type a number with or without dashes; the phone lays it out in your format.

SIM Cards

SettingTypeDefaultDescription
Config.Sim.autoIssuebooleantrueA phone used for the first time without a SIM gets a SIM registered to that character, so it has a number straight away. Turn off to make players buy or find SIM cards
Config.Sim.replacementCostnumber0What a player pays for a replacement SIM after reporting theirs lost or stolen. 0 makes it free
Config.Sim.replacementAccountstring'bank'Where the replacement is paid from: 'bank' or 'cash'
Config.Sim = {
    autoIssue = true,
    replacementCost = 0,
    replacementAccount = 'bank',
}

Menu: Device → Numbers & SIMs → SIM cards (Free SIM with a new phone, Replacement SIM price, Paid from).

Screen Lock

SettingTypeDefaultMenu limitsDescription
Config.Lock.minLengthnumber44 to 8Shortest passcode, in digits
Config.Lock.maxLengthnumber64 to 8Longest passcode, in digits
Config.Lock.maxAttemptsnumber51 to 20Wrong passcodes in a row before the phone locks itself out
Config.Lock.lockoutSecondsnumber30010 to 86400How long a lockout lasts, in seconds
Config.Lock = {
    minLength = 4,
    maxLength = 6,
    maxAttempts = 5,        -- wrong passcodes in a row before a lockout
    lockoutSeconds = 300,   -- 5 minutes
}

Menu: Device → Security → Screen lock. Passcodes are stored scrambled (hashed), so nobody can read them back. Admins remove a forgotten one with /phone resetpin.

Battery

Batteries are off by default: phones never run flat.

SettingTypeDefaultMenu limitsDescription
Config.Battery.enabledbooleanfalseTurns battery drain on. When off, phones never run flat and the powerbank says so
Config.Battery.drainPerMinutenumber0.20 to 10Percent lost per minute while the phone is switched on, even in a pocket. 0.2 lasts about 8 hours
Config.Battery.inUsePerMinutenumber0.60 to 10Extra percent lost per minute while the screen is open
Config.Battery.torchPerMinutenumber0.40 to 10Extra percent lost per minute while the phone's torch shines
Config.Battery.lowPowerFactornumber0.60.1 to 1Low Power multiplies every drain by this (0.6 drains 40% slower)
Config.Battery.vehiclePerMinutenumber3.00 to 50Percent gained per minute while the holder sits in a vehicle. 0 turns car charging off
Config.Battery.powerbankChargenumber501 to 100Percent one powerbank adds
Config.Battery = {
    enabled = false,          -- off: phones never run flat
    drainPerMinute = 0.2,     -- while switched on; 0.2 lasts about 8 hours
    inUsePerMinute = 0.6,     -- extra while the screen is open
    torchPerMinute = 0.4,     -- extra while the torch is on
    lowPowerFactor = 0.6,     -- Low Power multiplies every drain by this
    vehiclePerMinute = 3.0,   -- charge gained while sitting in a vehicle
    powerbankCharge = 50,     -- percent a powerbank adds
}

Menu: World → Battery. A flat or switched-off phone gets no calls, texts or mail (texts and mail wait) and cannot be traced.

Charging Stations

Kiosks where players charge their phones: the phone's oxide_phone_charger model. They only do something while batteries are on (Config.Battery.enabled). How players use them is in Features → Charging Stations.

SettingTypeDefaultMenu limitsDescription
Config.Chargers.nearbybooleantruePhones a player carries charge while they stand near a station
Config.Chargers.nearbyRadiusnumber3.01 to 15How close to a station's shelf counts as near, in metres
Config.Chargers.nearbyPerMinutenumber2.00.1 to 50Percent gained per minute near a station
Config.Chargers.dockingbooleantruePlayers can leave a phone on one of a station's three pads. Phones already on a pad can always be taken back, even when this is off
Config.Chargers.dockPerMinutenumber5.00.1 to 50Percent gained per minute on a pad. 5 charges a flat phone in 20 minutes
Config.Chargers.takeBackstring'anyone'Who can take a phone off a pad: 'anyone', or 'owner' (the player who left it there, or the phone's registered owner)
Config.Chargers.policeCanTakebooleantrueWith 'owner', police on duty (the jobs in Evidence) can still take any phone off a pad
Config.Chargers.stationstable (rows){}50 rowsThe stations. Each row is { label = 'Name', coords = vector4(x, y, z, heading) }. The phone puts the station model at each one, unless your map already has one at that spot
Config.Chargers = {
    nearby = true,
    nearbyRadius = 3.0,
    nearbyPerMinute = 2.0,
    docking = true,
    dockPerMinute = 5.0,
    takeBack = 'anyone',      -- or 'owner'
    policeCanTake = true,
    stations = {},            -- { label = 'Name', coords = vector4(x, y, z, heading) }
}

Menu: World → Battery → Charging stations. Each option shows a short hint under its name. Changes, new stations included, take effect for everyone as soon as you save.

Place a station in game (this uses o-link's in-world placement):

Stand where the station should go, type /phone settings and open World → Battery.

Scroll to Charging stations → Stations and press Add.

Type a Name, for example the place it stands. Only you see it.

Press the crosshair button next to Spot. The menu hides and a see-through station follows your aim. The keys show on screen.

Scroll to turn it so its pads face where players will stand, then left-click to put it down. Right-click or Esc cancels.

The menu comes back with X, Y, Z and W (the way it faces) filled in. Press Save Changes. The station appears for every player.

The person button next to the crosshair takes you to a saved spot.

Use a station you placed with your own map tools: add a row the same way, and in step 4 aim at your station. The see-through station snaps onto it, so the spot matches it exactly. The phone then sees the model already there and doesn't spawn a second one. A station model on your map that isn't in this list charges nothing: the server only trusts its own list.

Move or remove a station: change its position or delete its row, then save. Phones lying on its pads go back to the players who left them, the next time they are online.

Calls

Calls need pma-voice. See Installation → Calls.

SettingTypeDefaultMenu limitsDescription
Config.Calls.ringSecondsnumber305 to 120An unanswered call ends after this many seconds and becomes a missed call
Config.Calls.ringRangenumber15.00 to 50Metres within which other players hear a phone ring. 0 means nobody hears it. A phone whose owner turned sound off or uses Do Not Disturb never rings out loud
Config.Calls.ringSound.namestring'Text_Arrive_Tone'The GTA sound played on the ringing phone
Config.Calls.ringSound.setstring'Phone_SoundSet_Default'The GTA sound set that sound is in
Config.Calls.ringSound.intervalnumber2500500 to 10000How often the sound repeats, in milliseconds
Config.Calls.voicemailSecondsnumber305 to 120Longest voicemail message, in seconds. Never longer than Config.Media.audio.maxSeconds. Voicemail needs photo storage
Config.Calls.voicemailDaysnumber301 to 365Voicemail is deleted after this many days. Police can still recover it for the recovery window
Config.Calls.answerKeystring'RETURN'Default key that answers a call with the phone put away. Only for players who have never joined; everyone else rebinds it in FiveM's key bindings
Config.Calls.declineKeystring'BACK'Default key that declines a call with the phone put away. Same rule as answerKey
Config.Calls = {
    ringSeconds = 30,   -- an unanswered call ends after this
    ringRange = 15.0,   -- metres within which other players hear a phone ring
    ringSound = { name = 'Text_Arrive_Tone', set = 'Phone_SoundSet_Default', interval = 2500 },
    voicemailSeconds = 30,
    voicemailDays = 30,
    answerKey = 'RETURN',
    declineKey = 'BACK',
}

Menu: Device → Calls & Messages → Calls.

Texts

SettingTypeDefaultMenu limitsDescription
Config.Messages.maxLengthnumber50020 to 2000Longest text, in characters
Config.Messages.groupSizenumber82 to 32People in one group text, the sender included
Config.Messages.perMinutenumber201 to 120Texts one player may send per minute
Config.Messages.queueDaysnumber71 to 60A text for a phone that stays off or out of signal is dropped after this many days
Config.Messages.voiceSecondsnumber605 to 300Longest voice message, in seconds. Never longer than the voice clip limit in Config.Media.audio
Config.Messages = {
    maxLength = 500,
    groupSize = 8,
    perMinute = 20,
    queueDays = 7,
    voiceSeconds = 60,
}

Menu: Device → Calls & Messages → Texts.

Contacts

SettingTypeDefaultMenu limitsDescription
Config.Contacts.maxnumber20010 to 1000Contacts one phone can hold
Config.Contacts.shareRangenumber3.01 to 10How close, in metres, two players must stand to share something nearby (a contact, photo, place, note or post)
Config.Contacts.shareSecondsnumber6010 to 300How long a nearby share waits to be accepted, in seconds
Config.Contacts = {
    max = 200,
    shareRange = 3.0,
    shareSeconds = 60,
}

Menu: Device → Calls & Messages → Contacts. Contacts are stored on the phone, not on the character.

Mail

SettingTypeDefaultMenu limitsDescription
Config.Mail.maxPerPhonenumber20020 to 2000Mail one phone keeps. The oldest is removed beyond this
Config.Mail.pendingDaysnumber301 to 365Mail for someone who has no phone is dropped after this many days
Config.Mail.domaintext'phone.mail'up to 40 charactersEvery SIM's address is its digits at this domain, and aliases end in it. Changing it changes every address
Config.Mail.perMinutenumber61 to 60Mail one phone may send per minute
Config.Mail.perHournumber401 to 500Mail one phone may send per hour
Config.Mail.transactionWordslistbank, shop, store, receipt, invoice, paymenteach word up to 24 charactersMail from a resource whose sender name has one of these words goes to Transactions; the rest goes to Updates. Mail between players goes to Primary
Config.Mail = {
    maxPerPhone = 200,
    pendingDays = 30,
    domain = 'phone.mail',
    perMinute = 6,
    perHour = 40,
    transactionWords = { 'bank', 'shop', 'store', 'receipt', 'invoice', 'payment' },
}

Menu: Device → Calls & Messages → Mail. Mail sent to a character without a phone waits and arrives on the next phone that holds one of their registered SIMs.

Photo Storage

The phone stores no photos itself. See Installation → Photos for setting up each service.

SettingTypeDefaultMenu limitsDescription
Config.Media.providerstring'none''none', 'fivemanage', 's3', 'custom'Where photos go. 'none' turns the camera off (it says photos are not set up). 'custom' means another resource hands out upload addresses
Config.Media.maxKBnumber204864 to 10240Largest photo, in kilobytes
Config.Media.perMinutenumber61 to 60Photos one player may upload per minute
Config.Media.keepPerPhonenumber50010 to 5000Photos, videos and audio clips one phone can hold. A full phone refuses new ones until some are deleted
Config.Media.video.maxSecondsnumber605 to 180Longest video, in seconds. Recording stops and saves at this length
Config.Media.video.fpsnumber2424 or 30Video frame rate
Config.Media.video.kbpsnumber1200500 to 3000Video bitrate. Higher looks sharper and makes bigger files (about 9 MB a minute at 1200)
Config.Media.video.maxMBnumber121 to 50Largest video, in megabytes
Config.Media.video.perMinutenumber31 to 20Videos one player may upload per minute
Config.Media.video.perPhoneMBnumber25010 to 5000All the videos on one phone together, in megabytes
Config.Media.audio.maxSecondsnumber1205 to 300Longest voicemail or voice message, in seconds
Config.Media.audio.maxKBnumber102464 to 10240Largest voicemail or voice message, in kilobytes
Config.Media.audio.perMinutenumber31 to 20Voice clips one player may upload per minute
Config.Media.hoststable (list of strings){}Extra web hosts photos may come from, like cdn.example.com (subdomains included). Needed for custom storage. Photos from anywhere else are never shown
Config.Media.fivemanage.endpointstring'https://api.fivemanage.com/api/v3/file/presigned-url'Fivemanage's upload address API. Must be on https://api.fivemanage.com/; anything else uses the default
Config.Media.s3.endpointstring''Your S3 or R2 endpoint, starting with https://
Config.Media.s3.regionstring'auto'The bucket's region. auto for R2
Config.Media.s3.bucketstring''The bucket name
Config.Media.s3.publicUrlstring''The https:// address the bucket is served from, like https://photos.example.com. Its host is automatically allowed
Config.Media.s3.prefixstring'phone'The folder inside the bucket photos go into
Config.Media = {
    provider = 'none',   -- 'none' | 'fivemanage' | 's3' | 'custom'
    maxKB = 2048,        -- largest photo
    perMinute = 6,       -- photos one player may upload per minute
    keepPerPhone = 500,  -- photos, videos and audio clips a phone can hold
    hosts = {},          -- extra hosts photos may come from (custom storage)
    video = {
        maxSeconds = 60,   -- longest clip (5-180)
        fps = 24,          -- 24 or 30
        kbps = 1200,       -- recording bitrate (500-3000)
        maxMB = 12,        -- largest clip
        perMinute = 3,     -- clips one player may upload per minute
        perPhoneMB = 250,  -- all the videos on one phone together
    },
    audio = { maxSeconds = 120, maxKB = 1024, perMinute = 3 },   -- voicemail and voice messages
    fivemanage = { endpoint = 'https://api.fivemanage.com/api/v3/file/presigned-url' },
    s3 = { endpoint = '', region = 'auto', bucket = '', publicUrl = '', prefix = 'phone' },
}

Menu: Device → Media → Photo storage (Video and Audio are inside it). The keys for Fivemanage and S3 go in server.cfg, never here. With Fivemanage, photos and videos are allowed from fivemanage.com and fmapi.net.

Camera

With the camera out on foot, W walks where the player and the camera face, and the mouse turns the player (the selfie camera too).

KeyTypeDefaultDescription
Config.Camera.sprintbooleanfalseOff, players cannot sprint with the camera out and move at their normal pace. On, they can sprint
Config.Camera.modeKeystring'F7'Initial key for changing camera mode. Players can rebind it in FiveM's key bindings. Restart the phone after changing this default
Config.Camera = { sprint = false, modeKey = 'F7' }

Menu: Device → Media → Camera.

Live Streams

Apps on the phone (such as Leakd and Glitch) can let players go live with the phone's camera. The video goes through your server to every viewer, so each viewer costs your server upload. A viewer counts as the video bitrate sent as base64 (4/3 of it) plus a tenth for sound and events: kbps × 4/3 × 1.1, about 1.47 times the bitrate. At the default 500 kbps that is about 0.73 Mbps a viewer, so 25 viewers count as about 18 Mbps. A stream that really sends more than that counts at what it sends.

KeyTypeDefaultRangeDescription
Config.Streams.enabledbooleantrueOff refuses every new stream
Config.Streams.maxViewersnumber251 to 200Viewers per stream. Anyone past this is told the stream is full
Config.Streams.maxStreamsnumber41 to 50Streams live at once on the server, every app together
Config.Streams.kbpsnumber500150 to 2000Video bitrate. Each viewer costs about 1.47 times this in upload
Config.Streams.fpsnumber2010 to 30Frames per second
Config.Streams.egressMbpsnumber405 to 1000Upload your server may spend on streams, in Mbps. A viewer who would pass it is told the server is busy
Config.Streams.maxMinutesnumber601 to 240Longest stream, in minutes
Config.Streams = { enabled = true, maxViewers = 25, maxStreams = 4, kbps = 500, fps = 20, egressMbps = 40, maxMinutes = 60 }

Menu: Device → Media → Live streams. Admins can list and end streams with /phone streams and /phone endstream (see Admin).

Evidence

Everything police do with phones. Every check runs on the server. See Features → Police and Evidence.

A job row is { job = 'name', rank = number }: that job at that grade or higher.

SettingTypeDefaultMenu limitsDescription
Config.Evidence.jobstable (job rows){ { job = 'police', rank = 0 } }up to 20 rowsWho counts as police. They see the Forensics app and open other people's phones in evidence mode
Config.Evidence.authorizerstable (job rows){ { job = 'police', rank = 3 } }up to 20 rowsWho may issue and revoke search authorizations (police command, or a judge job)
Config.Evidence.requireDutybooleantruePolice and authorizers must be on duty to use Forensics. Opening someone else's phone in evidence mode works on or off duty
Config.Evidence.authorizationstring'builtin''builtin', 'none', 'hook''builtin': an authorizer issues an authorization in Forensics. 'none': police need none. 'hook': another resource decides (see Evidence Bridge)
Config.Evidence.maxAuthorizationHoursnumber721 to 720The longest an authorization can last, in hours
Config.Evidence.extractionSecondsnumber605 to 600How long an extraction takes, in seconds
Config.Evidence.requireStationbooleanfalseWhen on, extraction only works while standing at a forensics station. When off, police can also extract from the Forensics app anywhere
Config.Evidence.stationstable (rows){}up to 30 rowsForensics stations. Each row is { label, coords = vector3(x, y, z), radius }. radius is how close police must stand, in metres (0.5 to 10)
Config.Evidence.recoveryDaysnumber70 to 90Deleted texts, contacts, calls, mail, photos and notes an extraction still finds, for this many days after deletion. It is also how long Recently Deleted in Photos and Messages keeps items. A secure wipe defeats it. 0 recovers nothing deleted
Config.Evidence.carrierDaysnumber301 to 365How long carrier records (calls and texts per number) are kept, in days. They survive a wiped or destroyed phone
Config.Evidence.traceCooldownnumber1200 to 3600Seconds before the same officer can trace the same number again
Config.Evidence.traceRadiusnumber150.025 to 1000Radius, in metres, of the area a trace shows around the phone
Config.Evidence.backendstable (rows){ { name = 'oxide-police', enabled = true } }up to 10 rowsResources that also receive every extraction report (an MDT). Each row is { name = 'resource-name', enabled = true }. Reports are always kept in Forensics too
Config.Evidence.darkChatRecoverynumber00 to 100The chance, in percent, that an extraction recovers each Dark Chat message sent from the phone. 0 keeps Dark Chat out of reports
Config.Evidence = {
    jobs = { { job = 'police', rank = 0 } },        -- who is police here
    authorizers = { { job = 'police', rank = 3 } }, -- who may issue search authorizations
    requireDuty = true,
    authorization = 'builtin',      -- 'builtin' | 'none' | 'hook'
    maxAuthorizationHours = 72,
    extractionSeconds = 60,
    requireStation = false,
    stations = {},                  -- { label, coords = vector3, radius }
    recoveryDays = 7,
    carrierDays = 30,
    traceCooldown = 120,
    traceRadius = 150.0,
    backends = { { name = 'oxide-police', enabled = true } },
    darkChatRecovery = 0,
}

A station written in the file looks like this:

stations = {
    { label = 'Mission Row Lab', coords = vector3(0.0, 0.0, 0.0), radius = 1.5 },   -- use your own position
},

Menu: Police → Evidence. Use the job names exactly as your framework spells them. Always give a station a Reach (radius).

Apps

The phone's own apps.

SettingTypeDefaultMenu limitsDescription
Config.Apps.notes.maxnumber10010 to 1000Notes one phone can hold. Deleted notes still inside the evidence recovery window count toward a second limit of three times this
Config.Apps.maps.maxPlacesnumber505 to 200Saved favourites one phone can hold (Home, Work and the parked car come on top). Deleted favourites and replaced Homes, Works and parked cars still inside the evidence recovery window count toward a second limit of three times this, per kind
Config.Apps.darkchat.enabledbooleantrueTurns Dark Chat on or off. When off, it disappears from every phone
Config.Apps.darkchat.perMinutenumber151 to 60Dark Chat messages one player may send per minute
Config.Apps.darkchat.maxRoomsnumber201 to 100Dark Chat rooms one SIM card can be in
Config.Apps.feed.enabledbooleantrueTurns Feed on or off
Config.Apps.feed.perMinutenumber31 to 20Feed posts one player may make per minute
Config.Apps.feed.maxLengthnumber28020 to 600Longest Feed post, in characters
Config.Apps.feed.postsPerHournumber301 to 500Feed posts one SIM may make in an hour
Config.Apps.feed.editMinutesnumber150 to 60How long a Feed post can be edited. Every earlier version is kept as evidence. 0 turns editing off
Config.Apps.feed.trendHoursnumber241 to 168The hours trending hashtags are counted over
Config.Apps.bank.enabledbooleantrueTurns the Wallet app on or off
Config.Apps.bank.maxTransfernumber500001 to 10000000Largest single transfer
Config.Apps.bank.dailyLimitnumber1000001 to 100000000The most one character can send in 24 hours
Config.Apps.bank.perMinutenumber31 to 20Transfers one player may make per minute
Config.Apps.bank.requestsPerDaynumber301 to 200Payment requests one character can send in 24 hours
Config.Apps.bank.requestHoursnumber241 to 168How long a payment request can be paid
Config.Apps.gigs.enabledbooleantrueTurns the Gigs app on or off. It shows only while an Oxide gig job runs. When off, the gig jobs send their shift updates as texts
Config.Apps = {
    notes = { max = 100 },
    maps = { maxPlaces = 50 }, -- saved places (Home, Work, favourites, parked car) per phone
    darkchat = { enabled = true, perMinute = 15, maxRooms = 20 },
    feed = {
        enabled = true,
        perMinute = 3,
        maxLength = 280,
        postsPerHour = 30,   -- posts one number may make in an hour
        editMinutes = 15,    -- how long a post can be edited (0 turns editing off)
        trendHours = 24,     -- the hours trending hashtags are counted over
    },
    bank = {
        enabled = true,
        maxTransfer = 50000,        -- largest single transfer
        dailyLimit = 100000,        -- most one character sends in 24 hours
        perMinute = 3,
        requestsPerDay = 30,        -- payment requests one character may send in 24 hours
        requestHours = 24,          -- how long a payment request can be paid
    },
    gigs = { enabled = true }, -- the Oxide gig jobs that run here; off keeps their updates as texts
}

Menu: Screen → Apps.

Emergency Numbers

SettingTypeDefaultDescription
Config.Emergency.enabledbooleantrueTurns emergency numbers on or off. When off, the lock screen has no Emergency call button and 911/311 are treated as normal numbers
Config.Emergency.numberstable (rows)911 and 311 (below)Each row: number (up to 6 characters), channel ('911' emergency or '311' non-emergency) and jobs (the jobs alerted when no dispatch resource runs; police when empty)
Config.Emergency = {
    enabled = true,
    numbers = {
        { number = '911', channel = '911', jobs = { 'police', 'ambulance' } },
        { number = '311', channel = '311', jobs = { 'police' } },
    },
}

Menu: Police → Emergency. Up to 10 numbers. See Features → Emergency Numbers for where a call goes.

Signal

SettingTypeDefaultDescription
Config.Signal.indoorsNoSignalbooleanfalseWhen on, a player inside any interior has no signal on their own phone: they cannot call, text, post or send an emergency call from inside. Calls and texts to them still arrive
Config.Signal = {
    indoorsNoSignal = false,
}

Menu: World → Signal → Signal (No signal indoors).

No-Signal Areas

SettingTypeDefaultDescription
Config.DeadZonestable (list of areas){}Areas with no signal, such as tunnels and basements. Inside one, a phone cannot call or text, gets no calls or texts (texts wait), and an active call drops
Config.DeadZones = {}

Menu: World → Signal → No-signal areas. Draw each area in the world:

Press Draw a zone. The menu hides and o-link's zone builder starts: place the corners of the area in the world.

Finish the shape. The menu comes back and the area appears in the list with its number of points.

Give it a Zone name if you like, then press Save Changes.

Redraw in the world reshapes an existing area. Each area needs 3 to 64 points, and you can have up to 100 areas. Drawing needs an o-link with in-world placement; with an older one the menu says so.

Store

SettingTypeDefaultDescription
Config.Store.enabledbooleantruePlayers install apps on each phone from the Store. When off, the Store disappears and every app a player may use is on every phone
Config.Store.preinstalledtable (list of app IDs){}Apps on every phone that players cannot remove. Use app IDs from the App ID Reference or from the resource that adds the app
Config.Store.simulateInstallsbooleantrueGetting an app downloads and installs it over a few seconds, as on a real phone. When off, apps install at once
Config.Store.installSpeednumber (0.1 to 20)1Download speed multiplier. At 1 a download runs at about 6 MB a second on full signal; 2 halves the wait
Config.Store.defaultAppSizenumber, MB (1 to 4000)50The size of apps that do not declare one. At 1, a 50 MB app takes about 11 seconds
Config.Store = {
    enabled = true,
    preinstalled = {}, -- e.g. { 'phone_darkchat', 'phone_feed' }
    simulateInstalls = true,
    installSpeed = 1,
    defaultAppSize = 50,
}

Menu: Screen → Home & Apps → Store.

How a download behaves. Tapping Get turns the button into a ring (tap it to cancel) and puts the app's icon on the next free spot of the home screen, dimmed, with a progress pie. Its label reads Waiting…, Loading…, then Installing…; then the icon brightens. Tapping the icon pauses or resumes the download (Paused); holding it offers Cancel Download. The app cannot open, notify or show widgets until it is installed.

  • Time: the app's size divided by the download speed, with a little random variation, plus about a second before it starts and one to four seconds to install. Most apps take 5 to 20 seconds.
  • Signal: weak signal slows the download. No signal, Airplane Mode or a phone that is off or flat pauses it on Waiting… until the signal returns.
  • Kept by the server: closing the phone, logging out or restarting the resource never loses a download. A phone nobody is holding finishes on time in the background, and the app is there the next time it is opened.
  • Not for every app: built-in apps and preinstalled apps are always there and never download. Removing an app is still instant.

Default Look

How every phone looks until its owner picks something else in Settings → Appearance on the phone. A player's own choice always wins. A player who taps Use server default goes back to these values.

SettingTypeDefaultMenu limitsDescription
Config.Appearance.modestring'dark''dark', 'light', 'auto'Dark or light screens. 'auto' is dark from 20:00 to 06:00 game time and light the rest of the day
Config.Appearance.accentstring'blue''blue', 'red', 'green', 'orange', 'purple', 'pink', 'graphite'The colour of buttons, links and switches
Config.Appearance.glassnumber0.50 to 1How see-through the glass panels are (dock, folders, sheets). 0 is clearer, 1 is more tinted
Config.Appearance = {
    mode = 'dark',
    accent = 'blue',
    glass = 0.5,
}

Menu: Screen → Home & Apps → Default Look. A change reaches each phone the next time it is opened.

With Oxide HUD running, the card that rises while the phone is put away keeps the phone's own colours: there is no setting to give it Oxide HUD's accent colour. See Features → With Oxide HUD.

Home Screen

SettingTypeDefaultMenu limitsDescription
Config.Home.dockSizenumber40 to 4Apps in the dock at the bottom of the home screen
Config.Home.maxPagesnumber41 to 6Home screen pages
Config.Home.wallpaperstable (rows){}up to 30 rowsExtra wallpapers besides the five built-in ones. Each row is { id, label, url }. The url is an https:// address or the name of a .png, .jpg, .jpeg or .webp file in the wallpapers/ folder
Config.Home.wallpaperLinkstable (list){}up to 100 entriesSites players may set a wallpaper from by pasting an image link. An entry is a site (images.example.com, which covers its subdomains too) or an https:// address links must start with (https://cdn.example.com/wallpapers/). Empty: players cannot use links
Config.Home = {
    dockSize = 4,
    maxPages = 4,
    wallpapers = {}, -- { id = 'skyline', label = 'Skyline', url = 'skyline.jpg' }
    wallpaperLinks = {}, -- e.g. { 'images.example.com', 'https://cdn.example.com/wallpapers/' }
}

A link is accepted only when it is an https:// address ending in .png, .jpg, .jpeg or .webp, with nothing after it (no ? or #), at most 512 characters, on an approved site. The phone checks this when the player adds the link and the server checks it again on every save; a site you later remove sends those phones back to the default wallpaper. The image loads from that site in the player's game, so approve only sites you trust.

Menu: Screen → Home & Apps → Home screen. Lowering a limit trims existing home screens to fit. See Installation → Custom Wallpapers.

Notifications

SettingTypeDefaultMenu limitsDescription
Config.Notifications.bannerDurationnumber40001000 to 15000How long a banner stays on screen, in milliseconds
Config.Notifications.sound.enabledbooleantrueTurns the notification sound on or off for everyone
Config.Notifications.sound.volumenumber0.50 to 1Loudness of the notification sound. Each player's own volume setting is applied on top
Config.Notifications.storednumber10010 to 500Notifications a phone keeps until the player clears them. The oldest go first
Config.Notifications = {
    bannerDuration = 4000, -- ms a banner stays on screen
    sound = { enabled = true, volume = 0.5 },
    stored = 100,          -- notifications kept per phone
}

Menu: Screen → Notifications. Players can also mute apps, turn banners or sound off, or use Do Not Disturb in their phone's Settings app.

App Start Timeout

SettingTypeDefaultMenu limitsDescription
Config.AppReadyTimeoutnumber80002000 to 60000How long, in milliseconds, an app from another resource may take to load before the phone shows an error with a Try again button
Config.AppReadyTimeout = 8000

Menu: Screen → Home & Apps, on the Advanced tab (App start timeout).

Held Phone

The phone in the character's hand while the phone is open. The phone ships its own model in four colours (see Assets → Phone Models). The colour belongs to the phone, not the player: a phone keeps its colour for good, and everyone nearby sees it.

SettingTypeDefaultDescription
Config.Prop.colourstring'random''black', 'silver', 'burgundy' or 'glacier' gives every phone that colour. 'random' gives each phone its own colour the first time it is opened, and it keeps it
Config.Prop.itemColourstable (rows){}A colour per phone item, for selling phones in colours. Each row is { item = 'item name', colour = 'colour' }. A row wins over colour
Config.Prop.customModelstring''Another model for every phone instead of the colours, for example 'prop_npc_phone_02'. Leave it empty for the colours
Config.Prop.bonenumber28422The hand bone it is attached to
Config.Prop.offsetvector3vector3(0.0, 0.0, 0.0)Moves the model from the bone, in metres
Config.Prop.rotationvector3vector3(0.0, 0.0, 0.0)Turns the model, in degrees
Config.Prop = {
    colour = 'random',
    itemColours = {},
    customModel = '',
    bone = 28422,
    offset = vector3(0.0, 0.0, 0.0),
    rotation = vector3(0.0, 0.0, 0.0),
}

Menu: Screen → Appearance (Held phone). Colour per phone item is a list: press Add for each row.

The bundled phone sits in the hand with no offset and no rotation, in every pose. Leave Offset and Rotation at zero unless you set Other model to a model that needs them.

Sell phones in colours (optional):

Register one extra phone item per colour in your inventory, for example phone_silver, the same way as your phone item.

In /phone settings → Items, add each item to Phone items, so it opens as a phone.

In Appearance → Held phone → Colour per phone item, add a row for each item with its colour.

Press Save Changes. Each phone made from those items now shows its colour the next time it is opened.

Phones made from items with no row use Colour.

Config.ModelHints lists the models the phone streams itself, so a warning about one of them says the install is incomplete. It is not in the menu; leave it as it is.

Model Replacements

SettingTypeDefaultDescription
Config.ModelSwapstable (rows){}Replace a model your game build lacks. Each row is { from = 'shipped model', to = 'your model' }
Config.ModelSwaps = {} -- { { from = 'oxide_phone_black', to = 'your_model' } }

Menu: Advanced → Compatibility → Model replacements. When a model can't load, the phone warns in the console, tells online admins, and skips it. Add a row using the model name exactly as the warning shows it.

Timers

How often the server checks phones.

SettingTypeDefaultMenu limitsDescription
Config.Session.watchdogSecondsnumber51 to 30How often an open phone is checked. It closes when it leaves the inventory, goes flat or is switched off
Config.Session.scanSecondsnumber155 to 120How often carried phones are looked up. Car charging and finding who holds a number use this scan
Config.Session = {
    watchdogSeconds = 5,
    scanSeconds = 15,
}

Menu: Advanced → Advanced, on the Advanced tab (Timers).

o-link adds one setting of its own to the phone's menu, for the Maps app. It is not in shared/config.lua.

SettingTypeDefaultDescription
Config.MapModestring'inherit'How Maps draws the islands. 'inherit' uses the o-link default, 'combined' shows both islands on one map, 'separate' shows separate island views, 'disabled' hides Cayo Perico

Menu: Device → General (Map mode). Admins can also set it with oxide-phone:mapmode (see Admin).

App ID Reference

Use these IDs in Config.Store.preinstalled.

AppIDNotes
Phonephone_callsAlways on every phone
Messagesphone_messagesAlways on every phone
Mailphone_mailAlways on every phone
Cameraphone_cameraAlways on every phone
Photosphone_galleryAlways on every phone
Notesphone_notesAlways on every phone
Calculatorphone_calculatorAlways on every phone
Clockphone_clockAlways on every phone
Mapsphone_mapsAlways on every phone
Walletphone_bankAlways on every phone, beside any bank app, unless turned off
Gigsphone_gigsOn every phone while at least one Oxide gig job runs, unless turned off
Settingsphone_settingsAlways on every phone
Storephone_storeWhile Config.Store.enabled is on
Forensicsphone_forensicsOnly for the jobs in Config.Evidence
Dark Chatphone_darkchatFrom the Store
Feedphone_feedFrom the Store
Demophone_demoFrom the Store, only while Config.Debug is on

Apps from other resources have their own IDs; oxide-banking's app is banking.

Next Steps