Developer Tools Azure

BuildBuddy on Ubuntu 24.04 on Azure User Guide

| Product: BuildBuddy on Ubuntu 24.04 LTS on Azure

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-onprem image, 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 :1985 for 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 bazelisk and a self-test workspace at /opt/buildbuddy-selftest so you can prove the cache from the box
  • docker.service, nginx.service and buildbuddy.service as 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.

docker, nginx and buildbuddy services active, with the dashboard listening on 8080 and the gRPC cache on 1985

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.

The per-VM BuildBuddy credentials file with the dashboard URL, the gRPC URL and the administrator password (redacted)

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

An unauthenticated request and a wrong password rejected with 401, and the per-VM administrator credential accepted with 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.

A Bazel build against the appliance reporting a remote cache hit and streaming its results to the BuildBuddy dashboard

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.

The BuildBuddy dashboard Quickstart showing the appliance's own .bazelrc configuration

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.

A recorded Bazel invocation in BuildBuddy showing the build succeeded, its targets and timing

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.

The BuildBuddy cache statistics for an invocation showing cache requests and hits

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. Restrict 1985/tcp to 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_url in /etc/buildbuddy/config.yaml; set it to your https:// address and sudo systemctl restart buildbuddy if you front it yourself.
  • Rotate the dashboard password: replace the Basic Auth credential with sudo htpasswd -B /etc/buildbuddy/htpasswd admin and sudo 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/buildbuddy on 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_url is set to the detected public IP on each boot. For a stable hostname or HTTPS, set it in /etc/buildbuddy/config.yaml and sudo 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-onprem tag and update it in /etc/systemd/system/buildbuddy.service when 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.