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 like26.3.4: the Minecraft version, then a counter. - Nightly. A single prerelease called
nightlythat 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:
sha256sum --check --ignore-missing SHA256SUMSOn Linux, macOS, FreeBSD and Android, make the file executable:
chmod +x BasaltProxy-26.3.4-Linux-x64First 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.
mkdir basalt-proxy && cd basalt-proxy
./BasaltProxy-26.3.4-Linux-x64On 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:
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:
[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.targetSIGHUP 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:
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:
services:
proxy:
build: .
ports:
- "25565:25565"
volumes:
- ./data:/data
stdin_open: true
tty: true
restart: unless-stoppedstdin_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:
git clone --recurse-submodules https://github.com/BasaltProject/Proxy.git
cd Proxy
cmake --preset release
cmake --build build/releaseThe 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:
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#
- Download the new executable and verify its checksum.
- Stop the proxy (
stop). Players are disconnected. - 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.