BuildBuddy on Ubuntu 24.04 on Azure User Guide
Overview
This image runs BuildBuddy v2.287.0, the open source Bazel build acceleration platform from buildbuddy-io, on Ubuntu 24.04 LTS. BuildBuddy combines a remote content-addressable cache, a Build Event Protocol (BES) results store, and a web dashboard, so your team stops rebuilding what has already been built and gets a shareable, drillable view of every Bazel invocation. Point Bazel at the appliance and action results are cached centrally: the first machine to build a target populates the cache, and everyone else, including CI, downloads the result instead of recompiling.
The appliance ships the official open source on-prem image (gcr.io/flame-public/buildbuddy-app-onprem, pinned by digest), run as a systemd-managed container. It is self-contained on SQLite plus a local disk cache - there is no external database to run. The dashboard is served on port 8080, fronted by an nginx reverse proxy with HTTP Basic Auth, and the gRPC BES + remote cache endpoint is served on port 1985.
Genuinely open source. BuildBuddy's core is MIT licensed. The project's
enterprise/code is under a separate commercial license and is not part of this image - this appliance ships only the open source on-prem build.
What is included:
- BuildBuddy v2.287.0 (official open source
buildbuddy-app-onpremimage, pinned by digest), run by systemd - The BuildBuddy dashboard on
:8080, behind an nginx HTTP Basic Auth reverse proxy - The gRPC BES + remote cache endpoint on
:1985for Bazel clients - A per-VM dashboard administrator password generated on first boot and recorded in a root-only file
- Self-contained storage: SQLite plus a local disk cache under
/var/lib/buildbuddy, no external datastore - A pre-installed
bazeliskand a self-test workspace at/opt/buildbuddy-selftestso you can prove the cache from the box docker.service,nginx.serviceandbuildbuddy.serviceas systemd units, enabled and active- No default login surviving into the image
- 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point; size up and grow the OS disk for a larger shared cache. NSG inbound: allow 22/tcp from your management network, 8080/tcp for the dashboard, and 1985/tcp for Bazel clients. The gRPC endpoint on port 1985 has no built-in authentication in the open source edition - restrict 1985/tcp to your trusted build hosts / CI in the NSG. BuildBuddy serves plain HTTP; for production, front it with your own domain and TLS.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for BuildBuddy by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22), 8080 and 1985. Then Review + create then Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name buildbuddy \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name buildbuddy --port 8080 --priority 1010
az vm open-port --resource-group <your-rg> --name buildbuddy --port 1985 --priority 1020
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
BuildBuddy runs as the buildbuddy systemd service (the official buildbuddy-app-onprem container), with nginx providing the Basic Auth reverse proxy and docker the runtime. Confirm all three are active, and that the dashboard (8080) and gRPC cache (1985) ports are listening:
systemctl is-active docker nginx buildbuddy
sudo ss -tlnp | grep -E ':8080|:1985|:8081|:9090' | awk '{print $4}' | sort -u
Expected output:
active
active
active
0.0.0.0:1985
0.0.0.0:8080
127.0.0.1:8081
127.0.0.1:9090
Port 8080 is the public nginx Basic Auth proxy; 1985 is the gRPC BES + remote cache endpoint for Bazel; 8081 (BuildBuddy's own web port) and 9090 (Prometheus metrics) are bound to loopback and reached only through the proxy.

Step 5 - Retrieve your per-VM credentials
On the first boot of every VM, buildbuddy-firstboot.service generates a unique dashboard administrator password, writes it to the nginx Basic Auth file, and records the access URLs and the credential in a root-only file. Read it with:
sudo cat /root/buildbuddy-credentials.txt
Expected output (your password and IP will differ):
BUILDBUDDY_URL=http://<vm-public-ip>:8080
BUILDBUDDY_ADMIN_USER=admin
BUILDBUDDY_ADMIN_PASSWORD=<unique-per-VM-password>
BUILDBUDDY_GRPC_URL=grpc://<vm-public-ip>:1985
There is no default or shared credential in the image: the password is unique to this VM. buildbuddy-configure.service sets the URLs to this VM's detected public IP on every boot, so the links work over the Azure public IP out of the box.

Step 6 - Confirm the dashboard is secured
The dashboard is fronted by nginx with HTTP Basic Auth. Confirm an unauthenticated request is rejected (401), a wrong password is rejected (401), and the per-VM administrator credential is accepted (200):
U=$(sudo grep '^BUILDBUDDY_ADMIN_USER=' /root/buildbuddy-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^BUILDBUDDY_ADMIN_PASSWORD=' /root/buildbuddy-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'no auth: %{http_code}\n' http://127.0.0.1:8080/
curl -s -o /dev/null -w 'wrong pass: %{http_code}\n' -u "$U:wrong" http://127.0.0.1:8080/
curl -s -o /dev/null -w 'admin: %{http_code}\n' -u "$U:$P" http://127.0.0.1:8080/
Expected output:
no auth: 401
wrong pass: 401
admin: 200

Step 7 - Accelerate a real Bazel build (self-test)
The image ships bazelisk and a minimal Bazel workspace at /opt/buildbuddy-selftest so you can prove the remote cache straight from the box. Copy it to a writable directory, then build it twice: the first build populates the cache; the second, after a clean, is served from the cache (remote cache hit).
cp -r /opt/buildbuddy-selftest ~/bb-selftest && cd ~/bb-selftest
bazel build //:hello \
--bes_backend=grpc://127.0.0.1:1985 \
--bes_results_url=http://127.0.0.1:8080/invocation/ \
--remote_cache=grpc://127.0.0.1:1985
bazel clean
bazel build //:hello \
--bes_backend=grpc://127.0.0.1:1985 \
--bes_results_url=http://127.0.0.1:8080/invocation/ \
--remote_cache=grpc://127.0.0.1:1985
The second build reports a remote cache hit, and each build prints a Streaming build results to: link to its invocation in the dashboard:
INFO: 2 processes: 1 remote cache hit, 1 internal.
INFO: Build completed successfully, 2 total actions
INFO: Streaming build results to: http://<vm-public-ip>:8080/invocation/<invocation-id>
The first bazelisk run downloads the pinned Bazel version, so it takes a little longer. On your own machines, point any Bazel build at this appliance with the same --bes_backend / --remote_cache flags (using grpc://<vm-public-ip>:1985), or add them to a .bazelrc.

Step 8 - Open the dashboard
Browse to http://<vm-public-ip>:8080/ and sign in with admin and the password from your credentials file. The landing page is a Quickstart that shows the exact .bazelrc configuration for this appliance - the --bes_results_url and --bes_backend lines are prefilled with this VM's own address, ready to copy into any Bazel project.

Step 9 - Inspect an invocation
Open the invocation link that Bazel printed in Step 7 (Streaming build results to: http://.../invocation/<id>) to reach its detail page. BuildBuddy shows the build succeeded, the targets built, the command line, timing and critical path, and per-invocation cache statistics - the shareable, drillable view that makes a failing or slow build easy to diagnose.

Step 10 - Review the cache performance
Open the invocation's Cache tab (or the second cached build's invocation) to see cache requests, hits and bytes transferred - the proof that the remote cache served artifacts instead of rebuilding them. This is where you confirm the acceleration your team is getting across builds and CI.

Step 11 - Production hardening
The image ships the fully functional cache, results store and dashboard. For production:
- Restrict the gRPC endpoint: open source BuildBuddy does not authenticate the gRPC cache/BES endpoint on
1985, so anyone who can reach it can read and write the cache. Restrict1985/tcpto your trusted build hosts and CI runners in your NSG. - TLS and DNS: front the dashboard with your own domain and a TLS-terminating reverse proxy or Azure Application Gateway. BuildBuddy generates invocation links from
app.build_buddy_urlin/etc/buildbuddy/config.yaml; set it to yourhttps://address andsudo systemctl restart buildbuddyif you front it yourself. - Rotate the dashboard password: replace the Basic Auth credential with
sudo htpasswd -B /etc/buildbuddy/htpasswd adminandsudo systemctl reload nginx. - Remote build execution (RBE): this single-VM appliance provides the remote cache and results store, which accelerate the majority of Bazel builds. Full RBE (running actions on remote executors) is out of scope for a single VM; run BuildBuddy executors separately if you need it.
Maintenance
- Back up your data: the invocation history (SQLite) and cache live under
/var/lib/buildbuddyon the OS disk. Snapshot the OS disk to back them up; the cache is safe to discard and will refill. - Public URL:
app.build_buddy_urlis set to the detected public IP on each boot. For a stable hostname or HTTPS, set it in/etc/buildbuddy/config.yamlandsudo systemctl restart buildbuddy. - Security updates: unattended security upgrades are enabled, so the OS keeps itself patched. Reboot when a new kernel is installed.
- Upgrades: the BuildBuddy image is pinned for reproducibility; pull a newer
buildbuddy-app-onpremtag and update it in/etc/systemd/system/buildbuddy.servicewhen you choose to upgrade.
Support
cloudimg provides 24/7/365 expert technical support for this image. Contact support@cloudimg.co.uk. BuildBuddy's open source core is licensed under the MIT License. This image is provided by cloudimg; additional charges apply for build, maintenance and 24/7 support.