Build From Source

View as Markdown

NVIDIA HeavyAI Open Source Build

This document outlines the steps to download, build, and deploy the open source edition of NVIDIA HeavyAI.

Prerequisites

Confirm the following are in place before starting:

  • gh CLI installed and authenticated — run gh auth login if you haven’t already
  • A GitHub token with read:packages + repo scopes — your gh auth token output typically satisfies this
  • Docker Engine, NVIDIA drivers, and nvidia-container-toolkit installed on the build host (see Step 1)

1. Prepare the build environment

The HeavyAI build process requires a Linux host running Docker Engine with NVIDIA drivers and nvidia-container-toolkit installed. The build environment can be the same machine that will run HeavyAI in production, or any separate system that meets these requirements — including a dedicated build server or a cloud VM.—

Pre-open source release: use heavyai/heavydb-internal instead of heavyai/heavydb wherever the repository name appears in this guide.

Install the following on your Linux build host using the official documentation for each:

Additionally, if this is the first time you’re installing NVIDIA HeavyAI on the machine, please install the following Docker configuration, by writing the following into /etc/docker/daemon.json

{
"default-runtime": "nvidia",
"exec-opts": ["native.cgroupdriver=cgroupfs"],
"runtimes": {
"nvidia": {
"args": [],
"path": "nvidia-container-runtime"
}
}
}

After installing this configuration, restart Docker with this command:
sudo systemctl restart docker

Verification
Once all three are installed, confirm the GPU passthrough is working: docker run --rm nvidia/cuda:12.0-base nvidia-smi. If it prints your GPU details, the environment is ready.


2. Clone the repository

Clone heavyai/heavydb to your build machine and enter the project directory:

gh repo clone heavyai/heavydb
cd heavydb

Note: This repository requires a GitHub account with access to the HeavyAI organization. Ensure gh auth login has been run and your token has read:packages + repo scopes.


3. Pull the build container

The HeavyAI build system compiles all components inside a deps container, ensuring a consistent toolchain regardless of what is installed on the host. Pull the deps image for your target distribution before building, executing the below in your heavydb (or heavydb-internal) cloned repository folder:

# Ubuntu 22.04 (default and recommended)
dev-tools/dev.sh build deps --distro=ubuntu22.04

Other supported distributions:

# Rocky Linux 8
dev-tools/dev.sh build deps --distro=rockylinux8

Note: Pulling the deps image is a one-time operation per distro. Building the deps image from scratch (if no pre-built image is available) is a multi-hour process; pulling a pre-built image from GHCR is the expected workflow. The build system auto-detects the local deps image on subsequent runs and prefers Ubuntu over Rocky when multiple images are present. Override with --deps-image=<image> if needed.


4. Obtain API keys

Immerse requires two API keys for map chart functionality. These are passed as environment variables at build time — they are baked into the Immerse artifact during compilation and never written to a config file on disk.

  • Mapbox — basemap tiles for pointmap, choropleth, linemap, and other geo charts
  • Google Maps Geocoding — powers the zoom-to address search box on map charts

4a. Create a Mapbox access token

  1. Sign in at account.mapbox.com.
  2. Open Tokens → Create a token and give it a descriptive name.
  3. Use a public token (begins with pk.). Do not use a secret sk. token — Immerse runs in the browser.
  4. Enable at minimum these scopes: STYLES:READ, STYLES:TILES, FONTS:READ, DATASETS:READ. DATASETS:READ is only required if you use custom Mapbox Studio styles.
  5. Optionally add URL restrictions to limit where the token can be used:
http://YOUR_HEAVYAI_HOST:6273/* https://YOUR_HEAVYAI_HOST/*
  1. Copy the token — you will need it in Step 5.

Warning: Mapbox charges per map load and tile request beyond the free tier. URL restrictions and your own token are strongly recommended over any shared or vendor-supplied default.

4b. Create a Google Maps Geocoding API key

  1. Open Google Cloud Console and create or select a project.
  2. Go to APIs & Services → Library, search for Geocoding API, and enable it.
  3. Go to APIs & Services → Credentials → Create credentials → API key.
  4. Copy the key.
  5. Apply key restrictions if desired or required by your IT policy. Note that because this key is used directly within the end user’s browser, any IP-based restrictions must account for the full range of your users’ client IP addresses rather than server IPs.
    • Under Application restrictions, HTTP referrer restrictions are generally preferable to IP restrictions for browser-side keys:
http://YOUR_HEAVYAI_HOST:6273/* https://YOUR_HEAVYAI_HOST/*
  • Under API restrictions, limit to Geocoding API only.
  1. Ensure billing is enabled on the project. Google requires this even when usage stays within the free credit tier.

5. Build the Docker image

With both keys ready, run the full build from inside the heavydb directory. Pass the API keys as environment variables alongside your GitHub token — this keeps credentials out of any config file on disk.

MAPBOX_TOKEN=pk.xxx \
GOOGLE_API_KEY=your-google-key \
PRIVATE_PACKAGES_TOKEN=$(gh auth token) \
dev-tools/dev.sh build all --docker

Pre-open source release: PRIVATE_PACKAGES_TOKEN=$(gh auth token) is required to access private npm packages used during the Immerse build. This token requirement will be removed once the repository is public.

Replace pk.xxx with your Mapbox public token and your-google-key with your Google Geocoding API key from Step 4.

This builds all components and packages them into a single Docker image:

ComponentDescription
ImmerseFrontend map and chart UI
WebServerHeavyAI web server
HeavyIQAI query assistant
GEOS DSOsGeometry shared libraries
HeavyDBCore database engine
Docker imageFinal packaged container image

Build output is written to build/ubuntu22.04/logs/. If a step fails, the last 50 lines of the relevant log are printed automatically. You can also tail a log directly:

# Watch the heavydb build log in real time
tail -f build/ubuntu22.04/logs/heavydb.log

6. Confirm the image

Once the build completes, confirm that the new HeavyAI product image was created:

docker image ls

You should see two new images. For example:

REPOSITORY TAG IMAGE ID CREATED SIZE
heavyai-ubuntu22.04-cuda-render-x86_64 10.0.0 3f9a1c2d8e4b 2 minutes ago 18.3GB
ghcr.io/heavyai/heavydb/core-build-... latest 7a2b4d6e8f1c 3 days ago 12.1GB

Warning: The image whose name begins with core-build- is the build container used to compile HeavyAI — it does not run HeavyAI. Only the product image (e.g. heavyai-ubuntu22.04-cuda-render-x86_64:10.0.0) should be deployed to your production environment.

Note the full product image name and tag from your output — you will need it in Step 7.


7. Deploy to your production environment

Update your existing docker-compose.yml with the new image name, then start the service. If you built on a separate machine from where HeavyAI will run, you’ll also need to export and transfer the image first.

Update docker-compose.yml

Open your existing docker-compose.yml and update the image: field for the HeavyAI service to match the product image name from Step 6:

services:
heavyai:
image: heavyai-ubuntu22.04-cuda-render-x86_64:10.0.0
devices:
- nvidia.com/gpu=all
# ... rest of your existing service configuration
services:
heavyai:
image: heavyai-ubuntu22.04-cuda-render-x86_64:10.0.0
# ... rest of your existing service configuration

Note: Only the image: value needs to change — all other settings in your docker-compose.yml (volumes, ports, environment, restart policy) can remain as-is.

If you built on the same machine where HeavyAI runs, apply the updated compose file and start the service now:

docker compose up -d

Export and transfer to production

Skip this section if the build machine is the same as the production host. Otherwise, save the image to a compressed archive and transfer it along with the updated docker-compose.yml using rsync.

On the build machine:

# Export the image to a compressed archive
docker save heavyai-ubuntu22.04-cuda-render-x86_64:10.0.0 \
| gzip > heavyai-ubuntu22.04-cuda-render-x86_64-10.0.0.tar.gz
# Transfer the image and updated compose file to the production host
rsync -avz --progress \
heavyai-ubuntu22.04-cuda-render-x86_64-10.0.0.tar.gz \
docker-compose.yml \
user@YOUR_HEAVYAI_HOST:/opt/heavyai/

On the production host:

# Load the image into Docker
docker load < /opt/heavyai/heavyai-ubuntu22.04-cuda-render-x86_64-10.0.0.tar.gz
# Start the service
cd /opt/heavyai
docker compose up -d

Note: A full HeavyAI image is typically 15–20 GB uncompressed. Ensure sufficient disk space on both machines before exporting. The --progress flag on rsync will show live transfer throughput.


8. Verify the installation

Open a browser and navigate to your HeavyAI host on port 6273:

http://YOUR_HEAVYAI_HOST:6273

Then perform the following checks to confirm maps and geocoding are working correctly:

  1. Log in and create a new dashboard.
  2. Add a new chart and select Choropleth as the chart type.
  3. Basemap tiles: the map background should render fully with no gray or blank tiles. Open browser DevTools → Network and confirm Mapbox tile requests return HTTP 200 with your access_token query parameter present. Any 401 responses indicate the MAPBOX_TOKEN was missing or invalid at build time.
  4. Geocoder: locate the zoom-to search box in the chart toolbar. Type a city name (e.g. Austin) and confirm the map pans and zooms to that location. In DevTools → Network, Geocoding API requests should return 200 with your key parameter present.
  5. Save the dashboard. Reload the page and confirm the choropleth and basemap render correctly on load.

Note: If the zoom-to search box is not visible, check that ui/disable_map_geocoder is not set to true in your feature_flags configuration.


9. Initial configuration (optional)

If you are configuring a fresh HeavyAI environment rather than upgrading an existing one, consider completing the following before going live. None of these are required for a functional installation, but all are strongly recommended for security and usability.

Change the admin password

Log in to Immerse as admin using the default password (HyperInteractive), then navigate to Admin Portal → Users → admin → Edit to set a new password. Alternatively, use heavysql directly:

docker compose exec heavyai \
/opt/heavyai/bin/heavysql \
-u admin -p HyperInteractive \
--db heavyai \
-c "ALTER USER admin (password='your-new-password');"

Configure servers.json

Immerse’s default connection behavior, feature flags, UI element visibility, and branding are all controlled through a servers.json file. This file must be referenced from heavy.conf and placed in your HEAVYAI_STORAGE directory.

Step 1: In the [web] section of heavy.conf, add:

[web]
servers-json = "/var/lib/heavyai/servers.json"

Step 2: Create servers.json in your storage directory. At minimum, set the default database connection. You can also pre-populate credentials to enable automatic login:

[
{
"database": "heavyai",
"host": "localhost",
"port": "6273",
"protocol": "http",
"username": "admin",
"password": "your-admin-password"
}
]

Warning: Storing a password in servers.json enables auto-login for all users arriving at the Immerse URL. Only do this in controlled environments where access to the URL is already restricted. Omit "password" to present the login form instead.

Feature flags

The feature_flags object inside servers.json controls global Immerse UI defaults. Common settings for a new deployment:

"feature_flags": {
"ui/default_theme": "dark",
"ui/dashboard_tabs": true,
"ui/enable_auto_dashboard_refresh": true,
"ui/enable_map_exports": true,
"ui/enable_joins": true
}

See the full feature flags reference for all available options.

Controlling UI visibility with immerse_ui_keys

Use immerse_ui_keys to show or hide parts of the Immerse interface. For example, to hide the help dropdown and data manager while keeping everything else visible:

"immerse_ui_keys": {
"default": "ALL",
"ui_off": ["help_dropdown", "data_manager"]
}

To start from a blank slate and only expose specific elements:

"immerse_ui_keys": {
"default": "NONE",
"ui_on": ["tabs", "sql_editor", "global_side_nav", "dashboards", "save", "refresh"]
}

See the full UI keys reference for all available key values.

Branding and custom styles

Use the customStyles object to add your own logo, login page text, browser tab title, and chart color palettes:

"customStyles": {
"logoURL": "https://YOUR_HEAVYAI_HOST/your-logo.png",
"darkThemeLogoURL": "https://YOUR_HEAVYAI_HOST/your-logo-dark.png",
"loginText": "Welcome to Your Organization",
"title": "Your Organization Analytics",
"disableHelpMenu": false
}

Logo URLs must be browser-accessible http(s) URLs — filesystem paths are not supported. See the full branding reference for color palette options (solid, ordinal, quantitative, custom).

Custom basemap styles

To use Mapbox Studio styles or third-party OGC-compliant raster tile sources as basemaps in geo charts, add the mapboxCustomStyles array:

"mapboxCustomStyles": [
{
"label": "My Mapbox Studio Style",
"value": "mapbox://styles/username/style-id",
"default": true
},
{
"label": "OpenStreetMap",
"value": {
"version": 8,
"sources": {
"osm": {
"type": "raster",
"tiles": ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
"tileSize": 256
}
},
"layers": [{"id": "osm", "type": "raster", "source": "osm"}]
}
}
]

Setting "default": true on a style makes it the initial basemap shown in new geo charts. See the full basemap styles reference for more detail.

After creating or modifying servers.json or heavy.conf, restart the service for changes to take effect:

docker compose restart heavyai

Enable TLS termination

If HeavyAI is exposed directly (not behind a TLS-terminating load balancer or reverse proxy), configure HTTPS in the [web] section of heavy.conf:

[web]
enable-https = true
https-cert = /var/lib/heavyai/certs/cert.pem
https-key = /var/lib/heavyai/certs/key.pem

Mount the certificate directory into the container via your docker-compose.yml:

services:
heavyai:
volumes:
- /path/to/certs:/var/lib/heavyai/certs:ro
# ... your other volume mounts

Note: If nginx, Traefik, or a cloud load balancer is already terminating TLS in front of HeavyAI, skip this step. Enabling TLS inside the container when it is already terminated upstream will cause connection errors.

Restart the service after any changes to heavy.conf:

docker compose restart heavyai

Troubleshooting

SymptomLikely cause
gh repo clone failsYour GitHub account doesn’t have access to heavyai/heavydb, or gh auth login hasn’t been run.
Deps container not foundThe build deps step in Step 3 may not have completed. Re-run dev-tools/dev.sh build deps --distro=ubuntu22.04, or use --deps-image=<image> to specify an image manually.
No product image after buildThe build may have failed silently. Check build/ubuntu22.04/logs/docker-build.log. Ensure --docker was included in the build command.
Deployed the wrong imageEnsure the image: in docker-compose.yml matches the product image (e.g. heavyai-ubuntu22.04-cuda-render-x86_64:10.0.0), not the core-build-* build container.
Blank or gray mapMAPBOX_TOKEN was missing or invalid at build time, token URL restrictions block the production host, or a Mapbox billing or scope issue.
Zoom-to does nothingGOOGLE_API_KEY was missing at build time, Geocoding API not enabled, referrer or IP restrictions too tight, or billing disabled on the Google project.
No zoom-to search boxui/disable_map_geocoder is set to true in feature_flags.
HTTPS connection errors after enabling TLSTLS may already be terminated upstream. Disable enable-https in heavy.conf if a proxy or load balancer handles SSL in front of HeavyAI.

Offline / no third-party API alternatives

  • No Mapbox: omit MAPBOX_TOKEN at build time and set "offline": true in servers.json to use built-in country-outline basemaps instead.
  • No Google geocoding: omit GOOGLE_API_KEY at build time and set "ui/enable_local_geocoder": true in feature_flags to use the HeavyAI /geocoder endpoint (requires server-side geocoder support).

References