Skip to content
Basalt Proxy

Installation

Download, run and update Basalt Proxy, with systemd and Docker setups.

Download#

Binaries are published on the Proxy releases page. Each file is a single executable named after its version, platform and architecture:

BasaltProxy-<version>-<Platform>-<arch>
Platform Architectures Platform in the name
Linux (glibc) x86-64, ARM64 Linux-x64, Linux-arm64
Linux musl (Alpine) x86-64, ARM64 Linux-musl-x64, Linux-musl-arm64
Windows x86-64, ARM64 Windows-x64, Windows-arm64
macOS 13+ Intel, Apple Silicon macOS-x64, macOS-arm64
Android 10+ (API 29) x86-64, ARM64 Android-x64, Android-arm64
FreeBSD 14.5+ x86-64, ARM64 FreeBSD-x64, FreeBSD-arm64

The musl downloads are fully static and require neither glibc nor additional C++ runtime packages. Android and FreeBSD downloads include the C++ runtime statically. Download the executable itself, not an archive or an installer.

Two kinds of build are published:

  • Releases. A tagged release (v<version>) is published every Monday at 09:00 in Madrid, when something changed since the previous one. Versions look like 26.3.4: the Minecraft version, then a counter.
  • Nightly. A single prerelease called nightly that is replaced by every push to the main branch. Its versions end in -n<k>. Use it to try a fix, not for a network you care about.

Every release carries a SHA256SUMS file. Verify the download before running it:

bash
sha256sum --check --ignore-missing SHA256SUMS

On Linux, macOS, FreeBSD and Android, make the file executable:

bash
chmod +x BasaltProxy-26.3.4-Linux-x64

First start#

Run the executable from the directory where you want its configuration and state to live. All relative paths (config/, .basalt/, plugins/) are resolved from the working directory.

bash
mkdir basalt-proxy && cd basalt-proxy
./BasaltProxy-26.3.4-Linux-x64

On the first start the proxy writes commented proxy.toml, backends.toml and plugins.toml into ./config/, then starts with them. Existing files are never overwritten. The default backends.toml defines a single backend, lobby, at 127.0.0.1:25566, so edit it before players join (see Backends and routing).

You can type console commands in the terminal while it runs. Stop it with stop, Ctrl+C or SIGTERM.

Android#

The Android download is a native NDK executable, not an APK or a Linux/glibc binary. It needs no Java runtime or libc++_shared.so alongside it.

Use a directory that allows execution, such as a compatible terminal's private home directory or /data/local/tmp through adb shell. Shared storage such as /sdcard does not allow execution.

For an ARM64 device, rename the downloaded Android-arm64 executable to basalt-proxy on your computer, then:

bash
adb push basalt-proxy /data/local/tmp/basalt-proxy
adb shell 'cd /data/local/tmp && chmod +x basalt-proxy && ./basalt-proxy'

No root access or APK is needed for this adb shell deployment. Keep the working directory consistent so the proxy finds its configuration and state. Android's battery and background-process restrictions still apply: the executable is not an Android foreground service and does not keep the device awake automatically.

Command line#

Option Meaning
--config <dir> Directory holding the configuration files. Default: ./config
-v, --version Print the version, Minecraft version and protocol number, then exit
-h, --help Print the usage and exit

--help and --version do not create any file. An unknown option, or --config without a directory, prints a message and exits with code 2. A configuration file that fails validation is named in the error and the process exits with code 1; a normal stop exits with 0.

Ports#

Port Protocol Setting Default
Java clients TCP [network] port 25565
Bedrock clients UDP [bedrock] port, only when [bedrock] enabled = true 19132

Open only these on the proxy's firewall. The backends' ports should accept connections from the proxy and nobody else.

Running as a service#

A systemd unit for Linux, assuming the binary is installed as /opt/basalt-proxy/basalt-proxy and runs as an unprivileged user:

ini
[Unit]
Description=Basalt Proxy
After=network-online.target
Wants=network-online.target

[Service]
User=basalt
WorkingDirectory=/opt/basalt-proxy
ExecStart=/opt/basalt-proxy/basalt-proxy
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
LimitNOFILE=65536
StandardInput=null

[Install]
WantedBy=multi-user.target

SIGHUP reloads backends.toml and the plugins, the same as the reload console command (see Hot reload). SIGTERM stops the proxy cleanly. With StandardInput=null the console reads nothing, which is harmless: the proxy keeps running.

Docker#

The proxy needs no runtime beyond the executable. A minimal image that downloads a release:

dockerfile
FROM ubuntu:24.04
ARG VERSION=26.3.4
ADD https://github.com/BasaltProject/Proxy/releases/download/v${VERSION}/BasaltProxy-${VERSION}-Linux-x64 /opt/basalt-proxy
RUN chmod +x /opt/basalt-proxy
WORKDIR /data
EXPOSE 25565/tcp
ENTRYPOINT ["/opt/basalt-proxy"]

And a compose file that keeps configuration, the forwarding key and logs in a volume:

yaml
services:
  proxy:
    build: .
    ports:
      - "25565:25565"
    volumes:
      - ./data:/data
    stdin_open: true
    tty: true
    restart: unless-stopped

stdin_open and tty let you reach the console with docker attach. Inside a container, localhost is the container itself, so backend hosts in backends.toml must be service names or addresses reachable from it. Add 19132:19132/udp to ports if you enable Bedrock.

Back up data/ before upgrading: it holds the forwarding key (.basalt/forwarding.key) that your backends trust.

Building from source#

You need CMake 3.28 or newer, Ninja and Clang. Clone with submodules, because the network library (Wire) is one:

bash
git clone --recurse-submodules https://github.com/BasaltProject/Proxy.git
cd Proxy
cmake --preset release
cmake --build build/release

The executable lands in build/release/bin/ with the same naming as the downloads.

Additional platform builds#

For Android, install NDK 29.0.14206865, set ANDROID_NDK_HOME to its directory and select an ABI:

bash
cmake --preset android-arm64
cmake --build --preset android-arm64
# Use android-x64 for x86-64 devices.

The Android presets target API 29 and statically link libc++.

On FreeBSD, use the freebsd configure and build presets with CMake, Ninja and Clang. On Alpine, use linux-musl with Clang and static libc++, libc++abi and libunwind libraries. The GitHub Actions workflow contains the complete toolchain and linker settings for both platforms. Each build writes only its executable to build/<preset>/bin/ for distribution.

Updating#

  1. Download the new executable and verify its checksum.
  2. Stop the proxy (stop). Players are disconnected.
  3. Replace the executable and start it again. Configuration and the forwarding key are read from the working directory and carry over.

Existing configuration files are not rewritten when the proxy is updated, so new keys do not appear in them; their defaults apply until you add them. Compare against Configuration after an upgrade. An unknown key is a startup error, so remove keys that a release no longer accepts.

Edit this page