2.4 Native Installation on Linux
2.4.1 Backend Services
Install Python 3.12 or later with virtual environment support.
Create a virtual environment per service and install each service dependency set.
Copy the configuration templates to their working filenames and populate them — database connection, identity provider details, logging destination, and the credential encryption key.
Verify a reachable MongoDB and Keycloak before starting either service. Both services fail fast on a missing dependency, which is correct but produces a terse message.
Start the services. The repository ships start and stop helpers that can bring up all services or a named service individually.
2.4.2 Frontend
Install Node.js 22 or later.
Install dependencies and build the production bundle.
Serve the built assets from a web server, and configure that server to proxy the API paths to CBOM-Server and the ingestion path to Collector-Services.
For development only, the frontend dev server may be run directly with hot reload.
2.4.3 Service Start, Stop and Status
The repository ships helper scripts that start or stop the whole stack, or a single named service.
For production, wrap each service in a supervised unit so that it restarts on failure and starts at boot.
A configuration file watcher restarts the service automatically when its configuration changes on disk. Operators should know this, because it means an edit takes effect without an explicit restart — convenient, but surprising if unexpected, and it means a partially-saved configuration file can trigger a restart.
2.4.4 Configuration File Layout
CBOM Secure loads two configuration files at startup and merges them in order. Which setting belongs in which file matters, because a setting placed in the wrong file is silently ignored.
-
Root configuration: settings shared across all services: database connection, identity server, and shared interface configuration.
-
Service configuration: settings specific to one service: its own bind address and port, its deployment settings, and its logging configuration.
Both files are excluded from version control because they contain secrets. Templates are provided and are the correct starting point.
In a container deployment both files are generated at container start from the environment file, so the environment file is the single source of truth and the generated files should never be edited in place.
2.4.5 Worked Installation
The sections above set out what a native installation consists of. This is the same installation as a sequence of commands, for a current 64-bit Linux.
Packages
sudo apt update
sudo apt install -y python3.12 python3.12-venv python3-pip \
git curl build-essential nginx
Python 3.12 or later is required — the codebase uses syntax earlier versions cannot parse, so an older interpreter fails at import with a syntax error rather than with a version message.
Node.js 22 or later is needed for the console. Install it from your distribution's current repository or from the upstream packages; the version shipped in a long-term-support distribution is usually too old.
The repository
git clone --recurse-submodules <repository-url> /opt/cbom
cd /opt/cbom
--recurse-submodules matters. The sensors are a submodule, and a clone without it leaves the discovery service with nothing to run — the service starts and every scan finds nothing, which is a confusing failure. If you have already cloned:
git submodule update --init --recursive
Python environments
Each service gets its own virtual environment, so a dependency change in one cannot break another:
cd /opt/cbom/CBOM-Server
python3.12 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
deactivate
cd /opt/cbom/Collector-services
python3.12 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
deactivate
The repository ships a helper that does this for every service in one pass, which is the better choice when installing all of them.
Configuration
Copy each template to its working filename and fill it in:
cd /opt/cbom
cp conf/master-server.yaml.tmpl conf/master-server.yaml
cp CBOM-Server/conf/server.yaml.tmpl CBOM-Server/conf/server.yaml
cp Collector-services/conf/server.yaml.tmpl Collector-services/conf/server.yaml
What has to be set before anything will start:
| Setting | In |
|---|---|
| Database connection | Root configuration |
| Identity provider URL, realm, client id and secret | Root configuration |
| Credential encryption key — a valid Fernet key | Service configuration |
| Flask secret key | Service configuration |
| The platform's own public URL | Service configuration |
| The collector URL agents will submit to | Service configuration |
# A valid Fernet key for the credential encryption setting
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
! The two agent-facing addresses must not be left as loopback. They are resolved on the target host, not on the platform, so a loopback value names the agent rather than CBOM — the deployment reports success, the scan runs, and the results go nowhere. The server warns at startup when either resolves to loopback. Read that warning.
The configuration files are git-ignored because they hold secrets. Keep them out of any repository and back them up separately.
Dependencies must be reachable first
# MongoDB
mongosh "<connection string>" --eval "db.adminCommand('ping')"
# Identity provider
curl -fsSk https://keycloak.example.com:8443/auth/realms/<realm>/.well-known/openid-configuration
Both services fail fast on a missing dependency, which is correct behaviour and produces a terse message. Checking first turns a puzzling exit into a known cause. The start helper runs these checks for you before starting anything.
Seed the database
A fresh database needs its initial data — the configuration schema, the dashboard widgets, the standard policies, the menu structure and the algorithm rankings. The repository ships a seeding tool that loads them from the initial-data directory.
This is a first-boot operation. It writes only what is not already there, so it is safe to re-run and will not overwrite a configuration you have since changed.
Start
cd /opt/cbom
./start.sh # everything
./start.sh cbom # or one service at a time
Confirm the backend is serving, rather than merely running:
curl -fsSk https://localhost:5000/cbomsrv/api/v1/version
The console
cd /opt/cbom/cbom-frontend-vite
npm ci
npm run build
The build produces a static bundle to be served by a web server. The backend URL is compiled in, so it must be correct before the build — changing it later means building again, not editing a file.
The dev server with hot reload is for development only. It is not a production server and should not be exposed.
2.4.6 Running as Supervised Units
For production, wrap each service so it restarts on failure and starts at boot. A unit per service, for example:
[Unit]
Description=CBOM Secure backend API
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=cbom
Group=cbom
WorkingDirectory=/opt/cbom/CBOM-Server
ExecStart=/opt/cbom/CBOM-Server/venv/bin/python app.py
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now cbom-server
sudo systemctl status cbom-server
Use either the units or the shipped scripts, not both. They will fight over the same process: the script starts one the unit does not know about, and the unit restarts one the script has just stopped.
Run the services as a dedicated unprivileged account that owns the installation directory and the log directory, and nothing else.
2.4.7 The Reverse Proxy
A native installation needs the proxy configured by hand — in a container deployment it is shipped configured. The routing table, the body-size limits, the prefix-stripping rules and the WebSocket route are all on the Reverse Proxy page, and getting them wrong produces failures that do not look like proxy failures.
The three that cost the most time:
Body size on the API and collector routes. The default of 1 MB accepts small scans and rejects large ones.
Do not strip the prefix from the identity provider, dashboard or broker portal routes. Stripping it gives a page that loads with every asset returning a 404.
Forward the protocol header. Without it the backend builds redirect URLs as plaintext and sign-in downgrades.
2.4.8 The Configuration File Watcher
A file watcher restarts a service when its configuration changes on disk. This is convenient and occasionally surprising: an edit takes effect without an explicit restart, and a partially saved file can trigger a restart against incomplete configuration.
Write configuration changes atomically — edit a copy and move it into place — rather than editing the live file in an editor that saves incrementally.
The same applies to the relationship between the files and the database: configuration is generated from the database on every save, activation and startup, and the regeneration is wholesale. A section hand-edited into a file is removed the next time it is written, with nothing logged. Change settings in System Configuration.
2.4.9 After Installation
| Step | Where |
|---|---|
| Create the first administrator | The repository's administrator creation tool |
| Install a real TLS certificate | Certificates |
| Review the open ports | Ports and Firewall |
| Set up SSO | Authentication Methods |
| Configure backups of both databases | Backup and Recovery, Database Administration |
| Run one small discovery task end to end | The only check that exercises the whole path |