# How to use the dedicated server

## Recommended Hardware

We recommend running the Bedrock Minecraft Server on 64-bit Intel or AMD processor machines with at least 2 cores and 1 Gb RAM.

## Platforms

### Linux

The Linux version of the Bedrock Server requires Ubuntu 18 or later. Other distributions are not supported. Unzip the container file into an empty folder. Start the server with the following command:

> LD_LIBRARY_PATH=. ./bedrock_server

### Windows

The Windows version of the Bedrock Server requires either:

- Windows 10 version 1703 or later
- Windows Server 2016 or later

Unzip the container file into an empty folder. Start the server by executing the `bedrock_server.exe` file.

## Configuration

The server will try to read a file named `server.properties`. Some of these options are only read when a new world is created, while some others are read every startup. The file should contain a list with keys and values separated with an equal sign, one per line.

The following options are available. If a value as a number in parenthesis, that number can be used instead of the text value.

Option name | Possible values | Default value | When is it used | Notes
--- | --- | --- | --- | ---
server-name | Any string (no semicolon allowed) | Dedicated Server | Always | This is the server name shown in the in-game server list.
gamemode | survival, creative, adventure | survival | Always or only for new players |
force-gamemode | true, false | false | Always | force-gamemode=false(or force-gamemode is not defined in the server.properties file) prevents the server from sending to the client gamemode values other than the gamemode value saved by the server during world creation even if those values are set in server.properties file after world creation. force-gamemode=true forces the server to send to the client gamemode values other than the gamemode value saved by the server during world creation if those values are set in server.properties file after world creation.
difficulty | peaceful, easy, normal, hard | easy | Always |
allow-cheats | true, false | false | Always | If true then cheats like commands can be used.
max-players | Any integer | 10 | Always | The maximum numbers of players that should be able to play on the server. Higher values have performance impact.
server-port | Integer between 1024 and 65535 | 19132 | Always | Values below 1024 may be used, but are generally reserved for well known applications
server-portv6 | Integer between 1024 and 65535 | 19133 | Always | Values below 1024 may be used, but are generally reserved for well known applications. This property is ignored when `transport=nethernet`; in that mode a single dual-stack socket is opened on `server-port` instead.
transport | raknet, nethernet | raknet | Always | Selects the network transport used to accept client connections. See the Transport section below for details on the differences between the two modes and for the additional options that apply when `transport=nethernet`.
server-ip | IPv4 or IPv6 literal, or empty | (empty) | When `transport=nethernet` | The local address the server should bind its listening socket to. Leave empty to bind to all interfaces (the default). Ignored when `transport=raknet`.
server-udp-ports | See notes | (empty) | When `transport=nethernet` | Configures the UDP ports used for client peer-to-peer transport when running on NetherNet. See the UDP port configuration section below. Ignored when `transport=raknet`.
enable-lan-visibility | true, false | true | Always | Listen and respond to clients that are looking for servers on the LAN. When `transport=raknet` this will cause the server to bind to the default ports (19132, 19133) even when 'server-port' and 'server-portv6' have non-default values. Consider turning this off if LAN discovery is not desirable, or when running multiple servers on the same host may lead to port conflicts.
level-name | Any string | Bedrock level | Always | The name of level to be used/generated. Each level has its own folder in `/worlds`.
level-seed | Any string |  | World creation | The seed to be used for randomizing the world. If left empty a seed will be chosen at random.
online-mode | true, false | true | Always | If true, all connected players must be authenticated with Xbox Live. Clients connecting to remote (non-LAN) servers will always require Xbox Live authentication regardless of this setting. If the server accepts connections from the Internet, then it is highly recommended to enable online-mode.
allow-list | true, false | true | Always | If true then all connected players must be listed in the separate `allowlist.json` file. See the Allowlist section.
enable-packet-rate-limiter | true, false | false | Always | If true, the packet rate limiter will be enabled with the configuration provided by the `packetlimitconfig.json` file. See the Packet Rate Limit Config section.
view-distance | Any integer greater than 5 | 32 | Always | The maximum allowed view distance. Higher values have performance impact.
player-idle-timeout | Any positive integer, including 0 | 30 | Always | After a player has idled for this many minutes they will be kicked. If set to 0 then players can idle indefinitely.
max-threads | Any integer | 8 | Always | Maximum number of threads the server will try to use. If set to 0 or removed then it will use as many as possible.
tick-distance | An integer in the range [4, 12] | 4 | Always | The world will be ticked this many chunks away from any player. Higher values have performance impact.
default-player-permission-level | visitor, member, operator | member | Always | Which permission level new players will have when they join for the first time.
texturepack-required | true, false | false | Always | If the world uses any specific texture packs then this setting will force the client to use it.
content-log-file-enabled | true, false | false | Always | Enables logging content errors to a file.
compression-threshold | An integer in the range [0-65535] | 1 | Always | Determines the smallest size of raw network payload to compress. Can be used to experiment with CPU-bandwidth tradeoffs.
compression-algorithm | zlib, snappy | zlib | Always | Determines the compression algorithm to use for networking.
server-authoritative-movement-strict | true, false | false | Always | If true, will be more strict toward the Player position and be less permissive in accepting the client info. This will impact Player around moving block if there is high latency.
server-authoritative-dismount-strict | true, false | false | Always | If true, will be more strict toward the Player dismount position. This means clients will receive a correction on their dismount position in higher latency situation.
server-authoritative-entity-interactions-strict | true, false | false | Always | If true, will be more strict toward the Entity interactions. This will impact Players interacting with each other in higher latency situations.
player-position-acceptance-threshold | Any positive float | 0.5 | Always | This is the tolerance of discrepancies between the Client and Server Player position. This helps in problematic scenarios. The higher the number, the more tolerant the server will be before asking for a correction. Passed value of 1.0, the chance of missing cheating increases.
player-movement-action-direction-threshold | Any positive float in the range of [-1.00, 1.00] | 0.85 | Always | The amount that the direction the player is attacking can differ from the direction the player is looking as cos(x) where x is the angle between the two vectors. A value of 1 means the two vectors must be parallel, 0 means anything in front of the player, and -1 means any vector.
server-authoritative-block-breaking | true, false | false | Not when client-auth | If true, the server will compute block mining operations in sync with the client so it can verify that the client should be able to break blocks when it thinks it can. This setting cannot be combined with client authoritative movement and will be disabled if that setting is enabled.
server-authoritative-block-breaking-pick-range-scalar | Any float above 1.0 | 1.5 | When server-authoritative-block-breaking is true | This increase the range of block breaking. This is squared and multiplied with the default range.
chat-restriction | None, Dropped, Disabled | None | Always | This represents the level of restriction applied to the chat for each player that joins the server. "None" is the default and represents regular free chat. "Dropped" means the chat messages are dropped and never sent to any client. Players receive a message to let them know the feature is disabled. "Disabled" means that unless the player is an operator, the chat UI does not even appear. No information is displayed to the player.
disable-player-interaction | true, false | false | Always | If true, the server will inform clients that they should ignore other players when interacting with the world. This is not server authoritative.
| client-side-chunk-generation-enabled | true, false | true | Always | If true, the server will inform clients that they have the ability to generate visual level chunks outside of player interaction distances.
block-network-ids-are-hashes | true, false | true | Always | If true, the server will send hashed block network ID's instead of id's that start from 0 and go up. These id's are stable and won't change regardless of other block changes.
disable-persona | true, false | false | Internal Use Only |
disable-custom-skins | true, false | false | Always | If true, disable players customized skins that were customized outside of the Minecraft store assets or in game assets. This is used to disable possibly offensive custom skins players make.
| server-build-radius-ratio | Disabled, 0.0-1.0 | Disabled | Always | If "Disabled" the server will dynamically calculate how much of the player's view it will generate, assigning the rest to the client to build. Otherwise from the overridden ratio tell the server how much of the player's view to generate, disregarding client hardware capability. Only valid if client-side-chunk-generation-enabled is enabled.

## Transport

The `transport` property selects which network protocol the server uses to accept client connections. Two values are supported:

- raknet (default) — The traditional Bedrock UDP transport. The server listens directly on `server-port` (IPv4) and `server-portv6` (IPv6), and clients connect to that address and port. This is the mode used by all previous releases.
- nethernet — A WebRTC-based transport. The server listens on a single dual-stack TCP socket on `server-port` for an HTTP-based signaling handshake, then negotiates a UDP connection with each client that carries the gameplay traffic.

  When `transport=nethernet`, the following additional properties apply:

  - `server-ip` — The local address to bind the listening socket to. Leave empty to bind to all interfaces. Accepts either an IPv4 or IPv6 literal. When empty, the server prefers a dual-stack IPv6 socket so that one listener serves both IPv4 and IPv6 clients, and falls back to IPv4-only if dual-stack is unavailable.
  - `server-udp-ports` — Constrains the local UDP port range and optionally publishes an external NAT/port-forwarding mapping for clients. See the UDP port configuration for NetherNet section below.

  Tip for servers open to the Internet: Because the NetherNet handshake on `server-port` speaks HTTP/TCP, it is recommended to put a reverse proxy (for example nginx, HAProxy, or a managed edge service) in front of `server-port` to terminate connections, enforce request and rate limits, and absorb abusive traffic before it ever reaches the server. Only the signaling traffic on `server-port` needs to be forwarded through the proxy — the gameplay traffic flows directly between the client and the server over the negotiated UDP connection.

### UDP port configuration for NetherNet

By default, the NetherNet transport allocates UDP ports for client connections from the operating system's ephemeral range, which is fine for most LAN and outbound-friendly deployments but is not always suitable for servers that sit behind a firewall or NAT. `server-udp-ports` lets you pin the local port range the server uses, and/or describe a port mapping that clients should connect to.

Each entry takes one of the following forms:

- `internal` or `start-end` — restricts the UDP port allocation window to the given port or inclusive range. Use this to confine the server to a specific set of local ports (for example, a firewall-opened range).
- `[ip:]external[-external]:internal[-internal]` — publishes a NAT or port-forwarding mapping that the server advertises to clients. Use this when the address or port the server binds locally differs from the address or port clients must connect to (for example, when the server sits behind a 1:1 NAT or a router-level port-forwarding rule).
  - `internal` is the local UDP port the server actually binds to.
  - `external` is the port clients reach from outside — the port the NAT or router translates to `internal`. The optional `ip:` prefix is the public address those clients see (IPv6 literals must be enclosed in square brackets); omit it to advertise the host's own addresses.
  - Either side may be a single port or a `start-end` range. If both are ranges they must be the same length, and each external port is paired with the internal port at the same offset.

Multiple entries can be supplied on a single line separated by commas, and the property may also appear on more than one line to accumulate entries. Some examples:

    # Restrict local UDP allocation to the specified range
    server-udp-ports=49152-49200

    # Bind locally to ports 32000-32100 and advertise them to clients as external ports 19132-19232
    server-udp-ports=19132-19232:32000-32100

    # Same, but advertised on a specific public IPv4 address
    server-udp-ports=203.0.113.10:19132-19232:32000-32100

    # Same, but advertised on a specific public IPv6 address
    server-udp-ports=[2001:db8::1]:19132-19232:32000-32100

## Folders

When unpacking you will see a few folders and the binary executable. When starting the server for the first time a bunch of new (empty) folders will be created. The folders you should care about are the following:

Folder name | Purpose
--- | ---
behavior_packs | This is where new behavior packs can be installed. At the moment there's no way of activating them in a level.
resource_packs | This is where new resource packs can be installed. At the moment there's no way of activating them in a level.
worlds | This folder will be created at startup if it doesn't already exist. Every world created will have a folder named according to their `level-name` inside the `server.properties` file.
system_behavior_packs | This folder is not created automatically at server startup. It is used to store system administrator behavior packs that can be applied globally across all worlds. Additionally, the pack and it's module's `uuid` values are protected, and will result in other user packs failing to load if using the same ID.
system_resource_packs | This folder is not created automatically at server startup. It is used to store system administrator resource packs that can be applied globally across all worlds. Additionally, the pack and it's module's `uuid` values are protected, and will result in other user packs failing to load if using the same ID.

## Allowlist

If the `allow-list` property is enabled in `server.properties` then the server will only allow selected users to connect. To allow a user to connect you need to know their Xbox Live Gamertag. The easiest way to add a user to the allowlist is to use the command `allowlist add <Gamertag>` (eg: `allowlist add ExampleName`). Note: If there is a white-space in the Gamertag you need to enclose it with double quotes: `allowlist add "Example Name"`

If you later want to remove someone from the list you can use the command `allowlist remove <Gamertag>`.

The allowlist will be saved in a file called `allowlist.json`. If you want to automate the process of adding or removing players from it you can do so. After you've modified the file you need to run the command `allowlist reload` to make sure that the server knows about your new change.

NOTE: This file was previously named `whitelist.json`. For backwards compatability, if a `whitelist.json` file is also present, it will be used instead of `allowlist.json`. To migrate, delete the default `allowlist.json` file, rename `whitelist.json` to `allowlist.json`, then restart the server.

The file contains a JSON array with objects that contains the following key/values.

Key | Type | Value
--- | --- | ---
name | String | The gamertag of the user.
xuid | String | Optional. The XUID of the user. If it's not set then it will be populated when someone with a matching name connects.
ignoresPlayerLimit | Boolean | True if this user should not count towards the maximum player limit. Currently there's another soft limit of 30 (or 1 higher than the specified number of max players) connected players, even if players use this option. The intention for this is to have some players be able to join even if the server is full.

Example `allowlist.json` file:

    [
        {
            "ignoresPlayerLimit": false,
            "name": "MyPlayer"
        },
        {
            "ignoresPlayerLimit": false,
            "name": "AnotherPlayer",
            "xuid": "274817248"
        }
    ]

## Packet Rate Limit Config

If the `enable-packet-rate-limiter` property is enabled in `server.properties`, the server will use the packet rate limiter feature. Following the configuration described by the `packetlimitconfig.json` file, specific types of packets will be limited and rejected.

To reload the packet rate limiter configuration on the flight, use the server command `reloadpacketlimitconfig`. The server will reload the configuration from the `packetlimitconfig.json` file and update it for all of its clients.

The `packetlimitconfig.json` file contains a JSON array with a list of limit groups. Each group contains a list of packet ids and the corresponding packet rate limit algorithm that will be applied to them. Only `BucketPacketLimitAlgorithm` is currently supported. Additionally, the file can also use a default algorithm that will be applied to limit the rate for all packet types, on top of the ones specified by the limit groups.

`BucketPacketLimitAlgorithm` requires two parameters:

Key | Type | Value
--- | --- | ---
drainRatePerSec | float | The drain rate of the bucket per second. Value must be in the range [0.0f, 10000.0f]
maxBucketSize | uint32_t | The maximum size of the bucket. Value must be in the range [1, 10000]

Example of the `packetlimitconfig.json` file:

    {
        "limitGroups": [{
            "minecraftPacketIds": [193, 4],
            "algorithm": {
                "name": "BucketPacketLimitAlgorithm",
                "params": {
                    "drainRatePerSec": 0.0013,
                    "maxBucketSize": 1
                }
            }
        }, {
            "minecraftPacketIds": [9],
            "algorithm": {
                "name": "BucketPacketLimitAlgorithm",
                "params": {
                    "drainRatePerSec": 10,
                    "maxBucketSize": 50
                }
            }
        }],
        "defaultAlgorithm": {
            "name": "BucketPacketLimitAlgorithm",
            "params": {
                "drainRatePerSec": 0.0013,
                "maxBucketSize": 1
            }
        }
    }

## Permissions

You can adjust player specific permissions by assigning them roles in the `permissions.json` that is placed in the same directory as the server executable. The file contains a simple JSON object with XUIDs and permissions. Valid permissions are: `operator`, `member`, `visitor`. Every player that connects with these accounts will be treated according to the set premission. If you change this file while the server is running, then run the command `permission reload` to make sure that the server knows about your new change. You could also list the current permissions with `permission list`. Note that `online-mode` needs to be enabled for this feature to work since xuid requires online verification of the user account. If a new player that is not in this list connects, the `default-player-permission-level` option will apply.

Example `permissions.json` file:

    [
        {
            "permission": "operator",
            "xuid": "451298348"
        },
        {
            "permission": "member",
            "xuid": "52819329"
        },
        {
            "permission": "visitor",
            "xuid": "234114123"
        }
    ]

## Crash reporting

If the server crashes it will automatically send us various information that helps us solve it for the future.

## Commands

You can issue commands to the server by typing in the console. The following commands are available. < > means a parameter is required, [ ] means it's optional and | denotes different allowed values. Strings can be enclosed in double quotes, ", if they contain spaces.

Command syntax | Description
--- | ---
kick <player name or xuid> <reason> | Immediately kicks a player. The reason will be shown on the kicked players screen.
stop | Shuts down the server gracefully.
save <hold | resume | query> | Used to make atomic backups while the server is running. See the backup section for more information.
allowlist <on | off | list | reload> | `on` and `off` turns the allowlist on and off. Note that this does not change the value in the `server.properties` file! `list` prints the current allowlist used by the server `reload` makes the server reload the allowlist from the file. See the allowlist section for more information.
allowlist <add | remove> <name> | Adds or removes a player from the allowlist file. The name parameter should be the Xbox Gamertag of the player you want to add or remove. You don't need to specify a XUID here, it will be resolved the first time the player connects. See the Allowlist section for more information.
permission <list | reload> | `list` prints the current used operator list. `reload` makes the server reload the operator list from the ops file. See the Permissions section for more information.
op <player> | Promote a player to `operator`. This will also persist in `permissions.json` if the player is authenticated to XBL. If `permissions.json` is missing it will be created. If the player is not connected to XBL, the player is promoted for the current server session and it will not be persisted on disk. Defualt server permission level will be assigned to the player after a server restart.
deop <player> | Demote a player to `member`. This will also persist in `permissions.json` if the player is authenticated to XBL. If `permissions.json` is missing it will be created.
changesetting <setting> <value> | Changes a server setting without having to restart the server. Currently only two settings are supported to be changed, `allow-cheats` (true or false) and `difficulty` (0, `peaceful`, 1, `easy`, 2, `normal`, 3 or `hard`). They do not modify the value that's specified in `server.properties`.

## Backups

The server supports taking backups of the world files while the server is running. It's not particularly friendly for taking manual backups, but works better when automated. The backup (from the servers perspective) consists of three commands.

Command | Description
--- | ---
save hold | This will ask the server to prepare for a backup. It’s asynchronous and will return immediately.
save query | After calling `save hold` you should call this command repeatedly to see if the preparation has finished. When it returns a success it will return a file list (with lengths for each file) of the files you need to copy. The server will not pause while this is happening, so some files can be modified while the backup is taking place. As long as you only copy the files in the given file list and truncate the copied files to the specified lengths, then the backup should be valid.
save resume | When you’re finished with copying the files you should call this to tell the server that it’s okay to remove old files again.