Velox builds a custom RoadRunner binary from the plugin list in velox.toml. It downloads the RoadRunner source for the requested ref, renders container/plugins.go, applies the requested plugin versions plus any replace and exclude directives through go mod edit, runs go mod tidy, and compiles the binary with go build.
Documentation: docs.roadrunner.dev/customization/build.
go install github.com/roadrunner-server/velox/v3/cmd/vx@v3.0.0-beta.1Install the exact tag. The /v3 module line has only pre-release tags for now, so @latest has no stable release to resolve to.
Migration: releases before v3 install from github.com/roadrunner-server/velox/v2025/cmd/vx.
docker pull ghcr.io/roadrunner-server/velox:3.0.0-beta.1Images are published to ghcr.io/roadrunner-server/velox and spiralscout/velox; the image tag is the release tag without the leading v. The entrypoint is vx, and the image ships the sample config at /etc/velox.toml.
docker run --rm \
-e GITHUB_TOKEN \
-v "$PWD/velox.toml:/etc/velox.toml" \
-v "$PWD:/output" \
ghcr.io/roadrunner-server/velox:3.0.0-beta.1 build -c /etc/velox.toml -o /outputThe docker-compose.yml in this repository builds the image from source and runs build -c=/etc/velox.toml -o=/tmp/; uncomment the volume mapping there to copy the produced binary to the host.
vx build -c velox.toml -o .-c,--config: path to the configuration file, defaultvelox.toml.-o,--out: output directory for the producedrrbinary, default the current directory.--version: velox version and build time.
Both flags are persistent, so vx -c velox.toml build -o . works as well. The build downloads the RoadRunner source into a temporary directory that is removed when the command returns.
[roadrunner]
ref = "master"
[github.token]
token = "${GITHUB_TOKEN}"
[log]
level = "debug"
mode = "production"
[plugins.logger]
tag = "latest"
module_name = "github.com/roadrunner-server/logger/v6"
[plugins.server]
tag = "latest"
module_name = "github.com/roadrunner-server/server/v6"
[plugins.rpc]
tag = "latest"
module_name = "github.com/roadrunner-server/rpc/v6"
[plugins.http]
tag = "latest"
module_name = "github.com/roadrunner-server/http/v6"The velox.toml shipped in this repository is the full sample: it lists every plugin that RoadRunner master registers.
ref: tag, branch, or 40-character commit SHA ofroadrunner-server/roadrunner. Defaultmaster. A valid semver value (v2025.1.7) downloadsrefs/tags, a 40-character hex value downloads that commit, anything else downloadsrefs/heads.
base_url: GitHub host, defaulthttps://github.com. Set it to a GitHub Enterprise host (https://ghe.example.com) to download the source from a private installation; the archive paths and theAuthorizationheader are the same as on github.com. Only the host is configurable: the mirror must live at<base_url>/roadrunner-server/roadrunner.token: personal access token used for the download.${ENV_VAR}is expanded from the environment. It is sent as a bearerAuthorizationheader and dropped on a redirect to another host.
os: targetGOOS, default the hostGOOS.windowsis rejected.arch: targetGOARCH, default the hostGOARCH.
Either key may be omitted on its own; the host value fills it. Every build reuses the caller module and build caches (Go keys build cache entries by target). A cross build skips the rr --version smoke test.
level:debug,info,warn, orerror.mode:production,development,raw, ornone(offis an alias). Default when the section is absent: leveldebug, modedevelopment.
enabled: compiles with-gcflags "all=-N -l" -tags debugand keeps the symbol table for a debugger.race: compiles with-race(setsCGO_ENABLED=1). Requires a C toolchain for the target platform. The Docker image includes GCC and musl development headers for native Linux builds.
module_name: full Go module path of the plugin, including the major-version suffix; each module may be listed once.tag: semver version to require, or a non-semver ref (latest, a branch, a commit) that skips the post-tidy version check.
informer and resetter are compiled in from the versions the downloaded RoadRunner requires. Listing either of them here is skipped with a warning, because a user entry would register the plugin twice.
Maps to a go.mod replace directive applied before go mod tidy.
[[replaces]]
new = "../local-fork"
old = "github.com/foo/bar"
[[replaces]]
new = "github.com/me/bar-fork@v1.2.3-patched"
old = "github.com/foo/bar@v1.2.3"- Both fields are single strings; embed the version inline with
@. - A local path in
new(.,..,./,../, or absolute) must not carry an@version. An@inside a directory name is fine: only a trailing@<semver>counts as a version. - Neither field may contain
=. oldmust be unique across the list.- A relative local path in
newresolves against the working directory ofvx, not against the downloaded source tree.
Maps to a go.mod exclude directive applied before go mod tidy.
[[excludes]]
module = "github.com/redis/go-redis/v9"
version = "v9.15.0"versionmust be a canonical semver version (v9.15.0, notv9.15) whose major matches the module path (/v9needsv9.x.y).
- Supported: RoadRunner
master(thev2025module line) with the/v6beta plugins. RoadRunnerv2025.xreleases pair with the/v5plugins. - All plugins in one build must share the same major version:
http/v6withlogger/v6, neverhttp/v6withlogger/v5. - Do not point plugins at a
masterbranch.
- Windows build targets are not supported in velox v3.
- Pin plugin tags for reproducible builds. A tag that is not a semver version (
latest, a branch, a commit) skips the post-tidy version check, so the resolved version depends on when the build runs. - Plugins are registered in module-path order, so the same plugin set renders the same
container/plugins.go. - Each build compiles the binary in a unique temporary directory inside the output directory. The binary is renamed to
rrafterrr --versionprints the requested ref; a cross build skips that check. -trimpathis always set, andSOURCE_DATE_EPOCHis honored for the injected build timestamp.