Several setup variants are presented here. You can pick the one best suited to your needs, and modify it at will.
The
setup via docker compose
is probably the easiest, and directly exposes your server to the internet. Choose this method if you have a dedicated system and IP just for BOMnipotent Server.
The
setup including a proxy
is very similar, but also sets up a reverse proxy. Choose this method if you potentially want to offer more than one service from the same system and IP.
The
standalone setup
avoids the overhead of containerisation, at the cost of, well, containerisation. Choose this method if you are experienced in more classical server setups.
After following the steps of one of the variants, your server has a default configuration and should be reachable from the internet. After that, you should
create an admin user account
.
Subsections of Starting the Server
Docker Compose
The recommended and easiest setup for BOMnipotent Server uses
docker compose
. This variant of the setup will make BOMnipotent Server directly reachable from the internet. If you want to handle traffic through a reverse proxy, check out
another setup
instead.
Suggested File Structure
The suggested file structure in the favourite directory of your server looks like this:
This tutorial will walk through the files and explain them one by one.
.env
BOMnipotent server communicates with a database. Currently, only
PostgreSQL
is supported as a backend. The database is protected by a password. It is best practice to store the password inside a separate .env file instead of directly in the compose.yaml.
The name of the file must be “.env”, otherwise docker will not recognise it.
If you are using a versioning system to store your setup, do not forget to add “.env” to your .gitignore or analogous ignore file!
config.toml
BOMnipotent Server needs a configuration file, which is explained in more detail in
another section
.
The name of the file is arbitrary in principle, but the ready-to-deploy BOMnipotent Server docker container is set up to look for “config.toml”.
A minimal configuration looks like this:
# The db_url has the structure [db_client]://[user]:[password]@[container]:[port]/[db]# Note that ${BOMNIPOTENT_DB_PW} references an environment variable.db_url = "postgres://bomnipotent_user:${BOMNIPOTENT_DB_PW}@bomnipotent_db:5432/bomnipotent_db"# Domain behind which bomnipotent server will be hosteddomain = "https://bomnipotent.<your-domain>.<top-level>"[tls]
# The path to your full TLS certificate chaincertificate_chain_path = "/etc/ssl/certs/<your-TLS-certificate-chain.crt>"# The path to your secret TLS keysecret_key_path = "/etc/ssl/private/<your-secret-TLS-key>"[smtp]
# The username for your mail provider, typically your mail addressuser = "<you@yourdomain.com>"# The smtp endpoint of your mail providerendpoint = "<your.smtp.host>"# The secret to authenticate against the mail provider, typically your passwordsecret = "${SMTP_SECRET}"# Publisher data according to the CSAF Standard linked below[provider_metadata.publisher]
name = "<Provide the name of your organsiation>"# Namespace of your organisation, in form of a complete URLnamespace = "https://<your-domain>.<top-level>"# This is most likely the enum variant you wantcategory = "vendor"# Contact details are optional and in free formcontact_details = "<For security inquiries, please contact us at...>"
It is recommended to store your config.toml file inside a dedicated directory, “bomnipotent_config” in this example. The docker compose file will grant read access to this folder. This setup has two advantages:
In the unlikely case of a security breach of the BOMnipotent Server container, an attacker would only have access to you config directory, and nothing else on your server.
BOMnipotent Server will watch the directory for changes and will try to reload the configuration file if it has changed. This does not work when exposing only a single file to the docker container.
Many configuration values support hot reloading, meaning they can be modified without restarting the server.
After having set up your config.toml, you may want to copy it as for example config.toml.default, to be able to quickly restore your initial configuration. This is entirely optional, though.
compose.yaml
The compose file is where you specify the container setup. Once it is running smoothly, it does not need to be modified very often, but initially understanding it can take some time if you are new to docker.
The file needs to be called “compose.yaml”, docker can be a bit pecky otherwise.
A completely ready to deploy compose file looks like this:
# Giving the setup a name is optional, it will be derived by docker otherwise.name: bomnipotent_server_containers# The docker containers need to communicate, and they need a network for that.networks:
# This network needs a referencebomnipotent_network:
# Since the containers are on the same docker host, "bridge" is a reasonable driver choice.driver: bridge# Giving the network the same name as the reference is ok.name: bomnipotent_networkvolumes:
# Define the volume for persistent storage of the databasebomnipotent_data:
driver: local# The server itself also needs persistence if you do not want to activate the subscription after every rebootbomnipotent_subscription:
driver: localservices:
bomnipotent_db:
# Name of the database containercontainer_name: bomnipotent_dbdeploy:
resources:
limits:
# Limit the CPU usage to 0.5 corescpus: "0.5"# Limit the memory usage to 512MBmemory: "512M"environment:
# Set the database namePOSTGRES_DB: bomnipotent_db# Set the database userPOSTGRES_USER: bomnipotent_user# Set the database password from the .env file variablePOSTGRES_PASSWORD: ${BOMNIPOTENT_DB_PW}healthcheck:
# Check if the database is readytest: ["CMD-SHELL", "pg_isready -U bomnipotent_user -d bomnipotent_db"]
# Interval between health checksinterval: 60s# Timeout for each health checktimeout: 10s# Number of retries before considering the container unhealthyretries: 5# Start period before the first health checkstart_period: 10s# Use the specified PostgreSQL image# You may ddjust the container tag at willimage: postgres:17logging:
# Use the local logging driverdriver: localoptions:
# Limit the log size to 10MBmax-size: "10m"# Keep a maximum of 3 log filesmax-file: "3"networks:
# Connect to the specified network - bomnipotent_network# Restart the container if it has stopped for some reason other than a user commandrestart: alwaysvolumes:
# Mount the volume for persistent data storage - bomnipotent_data:/var/lib/postgresql/databomnipotent_server:
# Name of the server containercontainer_name: bomnipotent_serverdepends_on:
# Ensure the database service is healthy before starting the serverbomnipotent_db:
condition: service_healthydeploy:
resources:
limits:
# Limit the CPU usage to 0.5 corescpus: "0.5"# Limit the memory usage to 512MBmemory: "512M"environment:
# Pass the database password on to the server.BOMNIPOTENT_DB_PW: ${BOMNIPOTENT_DB_PW}# Pass the SMTP secret on to the server.SMTP_SECRET: ${SMTP_SECRET}healthcheck:
# Check if the server is healthy# Your TLS certificate is most likely not valid for "localhost"# Hence the --insecure flagtest: ["CMD-SHELL", "curl --fail --insecure https://localhost:8443/health || exit 1"]
# Interval between health checksinterval: 60s# Timeout for each health checktimeout: 10s# Number of retries before considering the container unhealthyretries: 5# Start period before the first health checkstart_period: 10s# This is the official docker image running a BOMnipotent Server instance.image: wwhsoft/bomnipotent_server:latestlogging:
# Use the local logging driverdriver: localoptions:
# Limit the log size to 10MBmax-size: "10m"# Keep a maximum of 3 log filesmax-file: "3"networks:
# Connect to the specified network - bomnipotent_networkports:
# Map port 443 on the host to port 8443 on the container# This allows to connect to it via encrypted communication from the internet - target: 8443published: 443# Restart the container if it has stopped for some reason other than a user commandrestart: alwaysvolumes:
# Bind mount the config folder on the host - type: bindsource: ./bomnipotent_configtarget: /etc/bomnipotent_server/configs/read_only: true# Bind mount the SSL directory, so that BOMnipotent can find the TLS certificate and key - type: bindsource: /etc/ssltarget: /etc/sslread_only: true# The subscription can be stored inside the container - bomnipotent_subscription:/root/.config/bomnipotent
This tutorial will walk through the files and explain them one by one.
proxy_config/conf.d/default.conf
The use of nginx as the reverse proxy is merely a suggestion. You can substitute it with any other server software you prefer.
In very crude terms, the reverse proxy serves as a gateway to your server: It allows you to host several services (BOMnipotent Server, a website, etc.) behind the same IP address. Any request to one of your URLs will end up at the reverse proxy, which then passes them on to the correct service. This is how you land on a different website when you visit doc.bomnipotent.de
than when you visit www.bomnipotent.de
, although they are hosted behind the same IP address.
Nginx looks up its configuration in various locations. Later on in the
compose.yaml
we will use mount binding to sneakily inject our configuration into the nginx docker container.
You can use the following as the starting point for your default.conf:
# Rate limiting: Allows up to 5 requests per second per IP address, stored in a memory zone of 10 MB.
limit_req_zone $binary_remote_addr zone=api_limit:10mrate=5r/s;
# BOMnipotent Server
server {
# This makes the server listen on port 443, which is typically used for HTTPS.
listen443sslhttp2;
# Replace this with the actual domain of your BOMnipotent Server.
server_namebomnipotent.your-domain.com;
# Replace this with the actual certificate for your domain.
ssl_certificate/etc/ssl/certs/your-domain-fullchain.crt;
# Replace this with the actual private key for your certificate.
ssl_certificate_key/etc/ssl/private/your-domain_private_key.key;
ssl_protocolsTLSv1.2TLSv1.3;
ssl_prefer_server_cipherson;
ssl_ciphers"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384";
location/ {
# Apply rate limiting
limit_reqzone=api_limitburst=10nodelay;
# This tells nginx to pass on requests to port 8080 of the docker container.
proxy_passhttp://bomnipotent_server:8080;
proxy_set_headerHost $host;
# The following lines assure that the BOMnipotent logs contain the IP of the sender,
# instead of the local IP of the reverse proxy.
proxy_set_headerX-Real-IP $remote_addr;
proxy_set_headerX-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_headerX-Forwarded-Proto $scheme;
}
}
You probably want to add more “server” blocks – why else would you decide to set up a reverse proxy?
.env
BOMnipotent server communicates with a database. Currently, only
PostgreSQL
is supported as a backend. The database is protected by a password. It is best practice to store the password inside a separate .env file instead of directly in the compose.yaml.
The name of the file must be “.env”, otherwise docker will not recognise it.
If you are using a versioning system to store your setup, do not forget to add “.env” to your .gitignore or analogous ignore file!
config.toml
BOMnipotent Server needs a configuration file, which is explained in more detail in
another section
.
The name of the file is arbitrary in principle, but the ready-to-deploy BOMnipotent Server docker container is set up to look for “config.toml”.
A minimal configuration for a BOMnipotent Server behind a reverse proxy looks like this:
# The db_url has the structure [db_client]://[user]:[password]@[container]:[port]/[db]# Note that ${BOMNIPOTENT_DB_PW} references an environment variable.db_url = "postgres://bomnipotent_user:${BOMNIPOTENT_DB_PW}@bomnipotent_db:5432/bomnipotent_db"# Domain behind which bomnipotent server will be hosteddomain = "https://bomnipotent.<your-domain>.<top-level>"[tls]
# TLS encryption is handled by the reverse proxy,# BOMnipotent Server is not directly reachable from the internet.allow_http = true[smtp]
# The username for your mail provider, typically your mail addressuser = "<you@yourdomain.com>"# The smtp endpoint of your mail providerendpoint = "<your.smtp.host>"# The secret to authenticate against the mail provider, typically your passwordsecret = "${SMTP_SECRET}"# Publisher data according to the CSAF Standard linked below[provider_metadata.publisher]
name = "<Provide the name of your organsiation>"# Namespace of your organisation, in form of a complete URLnamespace = "https://<your-domain>.<top-level>"# This is most likely the enum variant you wantcategory = "vendor"# Contact details are optional and in free formcontact_details = "<For security inquiries, please contact us at...>"
Fill in the braces with your data.
If you prefer using a local smtp releay station, have a look at the
necessary adjustments
to the compose file.
It is recommended to store your config.toml file inside a dedicated directory, “bomnipotent_config” in this example. The docker compose file will grant read access to this folder. This setup has two advantages:
In the unlikely case of a security breach of the BOMnipotent Server container, an attacker would only have access to you config directory, and nothing else on your server.
BOMnipotent Server will watch the directory for changes and will try to reload the configuration file if it has changed. This does not work when exposing only a single file to the docker container.
Many configuration values support hot reloading, meaning they can be modified without restarting the server.
After having set up your config.toml, you may want to copy it as for example config.toml.default, to be able to quickly restore your initial configuration. This is entirely optional, though.
compose.yaml
The compose file is where you specify the container setup. Once it is running smoothly, it does not need to be modified very often, but initially understanding it can take some time if you are new to docker.
The file needs to be called “compose.yaml”, docker can be a bit pecky otherwise.
A completely ready to deploy compose file looks like this:
# Giving the setup a name is optional, it will be derived by docker otherwise.name: bomnipotent_server_containers# The docker containers need to communicate, and they need a network for that.networks:
# This network needs a referencebomnipotent_network:
# Since the containers are on the same docker host, "bridge" is a reasonable driver choice.driver: bridge# Giving the network the same name as the reference is ok.name: bomnipotent_network# The reverse proxy needs to communicate with BOMnipotent Server, but not with the database.proxy_network:
driver: bridgename: proxy_networkvolumes:
# Define the volume for persistent storage of the databasebomnipotent_data:
driver: local# The server itself also needs persistence if you do not want to activate the subscription after every rebootbomnipotent_subscription:
driver: localservices:
reverse_proxy:
# Name of the reverse proxy containercontainer_name: reverse_proxydeploy:
resources:
limits:
# Limit the CPU usage to 0.5 corescpus: "0.5"# Limit the memory usage to 512MBmemory: "512M"healthcheck:
# Check if nginx is running and could parse the config.test: ["CMD-SHELL", "nginx -t || exit 1"]
# Interval between health checksinterval: 60s# Timeout for each health checktimeout: 10s# Number of retries before considering the container unhealthyretries: 3# Start period before the first health checkstart_period: 60simage: nginx:latestlogging:
# Use the local logging driverdriver: localoptions:
# Limit the log size to 10MBmax-size: "10m"# Keep a maximum of 3 log filesmax-file: "3"networks:
# Connect to the specified network - proxy_networkports:
# Expose port 443 of the container# This allows to connect to it via encrypted communication from the internet - "443:443"# Restart the container if it has stopped for some reason other than a user commandrestart: on-failurevolumes:
# Bind mount the SSL directory, so that nginx can find the TLS certificate and key - type: bindsource: /etc/ssltarget: /etc/sslread_only: true# Bind mount the config folder on the host - type: bindsource: ./proxy_config/conf.dtarget: /etc/nginx/conf.dread_only: truebomnipotent_db:
# Name of the database containercontainer_name: bomnipotent_dbdeploy:
resources:
limits:
# Limit the CPU usage to 0.5 corescpus: "0.5"# Limit the memory usage to 512MBmemory: "512M"environment:
# Set the database namePOSTGRES_DB: bomnipotent_db# Set the database userPOSTGRES_USER: bomnipotent_user# Set the database password from the .env file variablePOSTGRES_PASSWORD: ${BOMNIPOTENT_DB_PW}healthcheck:
# Check if the database is readytest: ["CMD-SHELL", "pg_isready -U bomnipotent_user -d bomnipotent_db"]
# Interval between health checksinterval: 60s# Timeout for each health checktimeout: 10s# Number of retries before considering the container unhealthyretries: 5# Start period before the first health checkstart_period: 10s# Use the specified PostgreSQL image# You may ddjust the container tag at willimage: postgres:17logging:
# Use the local logging driverdriver: localoptions:
# Limit the log size to 10MBmax-size: "10m"# Keep a maximum of 3 log filesmax-file: "3"networks:
# Connect to the specified network - bomnipotent_network# Restart the container if it has stopped for some reason other than a user commandrestart: alwaysvolumes:
# Mount the volume for persistent data storage - bomnipotent_data:/var/lib/postgresql/databomnipotent_server:
# Name of the server containercontainer_name: bomnipotent_serverdepends_on:
# Ensure the database service is healthy before starting the serverbomnipotent_db:
condition: service_healthydeploy:
resources:
limits:
# Limit the CPU usage to 0.5 corescpus: "0.5"# Limit the memory usage to 512MBmemory: "512M"environment:
# Pass the database password on to the server.BOMNIPOTENT_DB_PW: ${BOMNIPOTENT_DB_PW}# Pass the SMTP secret on to the server.SMTP_SECRET: ${SMTP_SECRET}healthcheck:
# Check if the server is healthytest: ["CMD-SHELL", "curl --fail http://localhost:8080/health || exit 1"]
# Interval between health checksinterval: 60s# Timeout for each health checktimeout: 10s# Number of retries before considering the container unhealthyretries: 5# Start period before the first health checkstart_period: 10s# This is the official docker image running a BOMnipotent Server instance.image: wwhsoft/bomnipotent_server:latestlogging:
# Use the local logging driverdriver: localoptions:
# Limit the log size to 10MBmax-size: "10m"# Keep a maximum of 3 log filesmax-file: "3"networks:
# Connect the server to the reverse proxy - proxy_network# Connect the server to the database - bomnipotent_network# Restart the container if it has stopped for some reason other than a user commandrestart: alwaysvolumes:
# Bind mount the config folder on the host - type: bindsource: ./bomnipotent_configtarget: /etc/bomnipotent_server/configs/read_only: true# The subscription can be stored inside the container - bomnipotent_subscription:/root/.config/bomnipotent
You are not required to run the official BOMnipotent Server
docker container
. Instead, you can download and directly run the BOMnipotent Server binary as a standalone application.
This setup only really makes sense for version 0.4.2 onwards, because the server did not offer port adjustments and logging to files before that.
Prerequisite: PostgreSQL
BOMnipotent Server requires a PostgreSQL database for storing its data. The setup depends on your server operating system.
On the most common distributions, PostgreSQL is offered as a package. You can install it via for example apt/apt-get/aptitude:
This creates a container named “bomnipotent_db”, with a database also called “bomnipotent_db”, a user called “bomnipotent_user”, and a password that you need to set. It exposes port 5432 of the container, persists the data in a docker volume, and spins up the “postgres:latest” image in detached mode.
You could use different names for the user and database, but would need to adjust the “db_url” entry of your
config file
accordingly.
Suggested File Structure
The suggested file structure in the favourite directory of your server looks like this:
This tutorial will walk through the files and explain them one by one.
.env
BOMnipotent server communicates with a database. Currently, only
PostgreSQL
is supported as a backend. The database is protected by a password. It is best practice to store the password inside a separate .env file instead of directly in the compose.yaml.
The name of the file must be “.env”, otherwise BOMnipotent Server will not recognise it.
If you are using a versioning system to store your setup, do not forget to add “.env” to your .gitignore or analogous ignore file!
config.toml
BOMnipotent Server needs a configuration file, which is explained in more detail in
another section
.
The name of the file is arbitrary.
A minimal configuration looks like this:
# The db_url has the structure [db_client]://[user]:[password]@[address]:[port]/[db]# Note that ${BOMNIPOTENT_DB_PW} references an environment variable.db_url = "postgres://bomnipotent_user:${BOMNIPOTENT_DB_PW}@localhost:5432/bomnipotent_db"# Domain behind which bomnipotent server will be hosteddomain = "https://bomnipotent.<your-domain>.<top-level>"# Bind to the typical port used for HTTPShttps_port = 443[log]
# Tell the server to log to a file instead of to stdoutfile = "/var/log/bomnipotent.log"[tls]
# The path to your full TLS certificate chaincertificate_chain_path = "/etc/ssl/certs/<your-TLS-certificate-chain.crt>"# The path to your secret TLS keysecret_key_path = "/etc/ssl/private/<your-secret-TLS-key>"[smtp]
# The username for your mail provider, typically your mail addressuser = "<you@yourdomain.com>"# The smtp endpoint of your mail providerendpoint = "<your.smtp.host>"# The secret to authenticate against the mail provider, typically your passwordsecret = "${SMTP_SECRET}"# Publisher data according to the CSAF Standard linked below[provider_metadata.publisher]
name = "<Provide the name of your organsiation>"# Namespace of your organisation, in form of a complete URLnamespace = "https://<your-domain>.<top-level>"# This is most likely the enum variant you wantcategory = "vendor"# Contact details are optional and in free formcontact_details = "<For security inquiries, please contact us at...>"
It is recommended to store your config.toml file inside a dedicated directory, “bomnipotent_config” in this example. BOMnipotent Server will watch the directory for any changes, meaning that it has less to watch the less files are in the folder. The server will try to reload the configuration file and the .env file if either have changed.
Many configuration values support hot reloading, meaning they can be modified without restarting the server.
After having set up your config.toml, you may want to copy it as for example config.toml.default, to be able to quickly restore your initial configuration. This is entirely optional, though.
bomnipotent_server
This is the binary that runs BOMnipotent Server. You can download any version for your server platform from
www.bomnipotent.de
.
In principle, all BOMnipotent Server needs to run is to know the path to its config file. If you run the binary and provide the path as the first argument, you have created a working server instance. However, your terminal is now eternally blocked, and the service will not restart if you reboot your system. The rest of this section only serves to ensure that the operating system properly supports the server.
Unlike BOMnipotent Client, which runs under all major operating systems, BOMnipotent Server is currently only supported under Linux and Windows. If you want to host it on a server running MacOS, please
create an issue
.
This setup requires your distribution to incorporate systemd.
If you’re not sure if it does, it probably does.
If you’re sure that it does not, you probably don’t need these instructions.
Create the file “/etc/systemd/system/bomnipotent.service” with the following content: