Bifrost 2.3.1
Overview
Bifrost is an open source, high-performance LLM gateway from Maxim AI. It puts one OpenAI-compatible endpoint in front of the model providers you use, so existing application code usually needs only a base URL change. Supported providers include OpenAI, Anthropic, Google, Amazon Bedrock, Azure OpenAI, Vertex AI, Groq, Mistral, Ollama and more.
Behind that endpoint, Bifrost adds automatic failover between providers and keys, weighted load balancing, per-key budgets and rate limits, semantic caching and MCP tool routing. It also keeps a request log with cost and latency for every call.
Bifrost is a router, not a model host. It relays requests to providers using your own API keys, so it needs no GPU and runs on a small CPU instance. It is a single Go binary with the web dashboard compiled in, so this image needs no container runtime and no database server.
This guide covers launching and verifying Bifrost 2.3.1 on Ubuntu 24.04 from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud Hardened Ollama, LiteLLM & Self Hosted LLM Server AMIs listing on AWS Marketplace. You pick it as the software version when you subscribe and launch. The other LLM servers, gateways and chat interfaces in the listing are described on the listing's guide hub.
What you get:
- The official release binary. Bifrost 2.3.1 is the official upstream
linux/amd64release binary, pinned by sha256 and tied to upstream commitd3f707ed3669b71bd9052f9ce71ff63fa3e91f6c(tagtransports/v2.3.1).bifrost.serviceruns it as the unprivilegedbifrostuser. - Loopback-only Bifrost. Bifrost is bound to loopback only (
127.0.0.1:8080), with nginx as the only network-facing service. - HTTPS on port 443. The self-signed certificate is created on your instance's first boot, and port 80 redirects to HTTPS.
- A per-instance dashboard password and virtual key (
sk-bf-...). First boot generates both into a root-only file. The same password signs in to Bifrost's own dashboard. - Embedded SQLite stores. The configuration and log stores are in
/var/lib/bifrost/data(mode 0700), created on your instance's first boot. No provider is configured, so you add your own keys. - A hostname helper.
bifrost-set-hostnameserves Bifrost under your own DNS name and re-issues the certificate for it. - A dependency licence inventory at
/usr/share/bifrost/dependency-licences.txt, covering all 896 dependencies compiled into the binary. - 24/7 SecureAnyCloud support
Default user: ubuntu. Architecture: x86_64. Root volume: 8 GiB gp3.
Security advisories this version addresses
Bifrost 2.3.1 replaces the Bifrost 1.6.6 version of this listing. Two upstream advisories are fixed only from Bifrost 2.1.0:
- GHSA-86gf-xh3g-rvxq (critical): while Bifrost's dashboard authentication is off, anyone who reaches the management API can register an MCP client of type
stdio, which makes the gateway run a command of their choosing. - GHSA-2qp8-4xgm-fw6g (high):
POST /api/pluginswith anhttp(s)path makes the gateway download that URL as a plugin.
On this image, neither is reachable without the administrator credential. Three independent layers enforce this:
- Bifrost 2.3.1 refuses to register a
stdioMCP client for an unauthenticated caller and locks its management API while dashboard authentication is off. - Bifrost's own dashboard sign-in is on. First boot sets it up with this instance's username and password. The management API (
/api/...) needs that credential even on the loopback address, and Bifrost never accepts a virtual key there. - The nginx gate is scoped by path. The virtual key your applications use opens only the inference paths (
/v1/...,/openai/...,/anthropic/...,/genai/...,/bedrock/...,/cohere/...,/langchain/...,/litellm/...,/pydanticai/...,/cursor/...). The dashboard,/api/...,/metrics,/ws,/mcpand every other path accept only the dashboard credential or the browser's gate cookie.
The SecureAnyCloud build proves all three layers before the image is captured, and again on a fresh instance launched from it. Step 4 shows the same checks.
Security posture
- No default credential and no baked provider key. The dashboard password, the virtual key and the gate token are generated on each instance's first boot. None of them exists in the image, so no two instances share one, and no model provider key is ever shipped. Bifrost's configuration store is also created on first boot. The image carries none.
- Default-deny gate in front of every route. An LLM gateway spends your provider credit. nginx enforces a gate on every location. The inference paths need this instance's virtual key or dashboard credential, and everything else needs the dashboard credential. The only open location is nginx's own
/nginx-healthliteral, which never reaches Bifrost. - Fails closed. nginx will not start until first boot has proved three things against this instance's real gate configuration. An anonymous request gets
401. A one-character mutation of every credential is refused. The virtual key does not open the dashboard or the management API. Both units carry a preflight guard that refuses an empty or plaintext gate file, a missing virtual key, or Bifrost's dashboard sign-in being off. - Only nginx faces the network. It answers only for the configured hostname, and any other
Hostheader gets its connection closed. It uses TLS 1.2 or 1.3 and refuses cross-originPOSTrequests and WebSocket upgrades (403). It strips Bifrost's CORS headers, and it replaces any client-suppliedX-Forwarded-For,X-Real-IPorForwardedheader with the real peer address. - The hostname comes from configuration, never from a request. First boot reads it from EC2 instance metadata (IMDSv2) or from
/etc/sac/bifrost-hostname. - No instance metadata access for the gateway. An administrator can point a provider at any base URL, so systemd
IPAddressDenyblocksbifrost.servicefrom the instance metadata service (169.254.169.254 and fd00:ec2::254). Bifrost also refuses link-local base URLs itself, so a provider entry can never read the instance's role credentials. Amazon Time Sync (169.254.169.123) is unaffected. - IMDSv2 required. The AMI is registered with
ImdsSupport v2.0, so instances launched from it refuse token-less (IMDSv1) metadata requests. - Sandboxed service and per-instance identity.
bifrost.serviceruns withNoNewPrivileges,ProtectSystem=full,ProtectHomeandPrivateTmp. SSH host keys and the machine ID are generated fresh on every instance.
Prerequisites
- An AWS account and permission to launch EC2 instances
- An EC2 key pair in the Region you launch in
- An API key for at least one model provider (OpenAI, Anthropic, Bedrock and so on), or a self-hosted model server such as Ollama
Recommended instance type: m5.large. Bifrost is a gateway and holds no model, so its 2 vCPUs and 8 GiB of memory are ample. The model work happens at your providers.
Connecting to your instance
Version Operating system SSH user
Bifrost 2.3.1 on Ubuntu 24.04 Ubuntu 24.04 LTS ubuntu
Launch the instance
Option A: AWS Marketplace console
- Open the SecureAnyCloud Hardened Ollama, LiteLLM & Self Hosted LLM Server AMIs listing on AWS Marketplace. Choose View purchase options, then Subscribe. One subscription covers every version in the listing.
- When the subscription is active, choose Launch your software.
- Choose One-click launch from AWS Marketplace, or Launch from EC2 Console for the full launch wizard. In Version, choose Bifrost 2.3.1 on Ubuntu 24.04, then choose your Region.
- Pick an instance type and your key pair.
m5.largeis recommended, and the software charge is $0.04 per vCPU per hour. - Review the security group. The listing's default group opens SSH (22), HTTP (80) and HTTPS (443). Restrict SSH to your own IP address, and restrict ports 80 and 443 to the networks your applications and administrators use. This gateway spends your provider credit.
- Choose your VPC and subnet. Leave the metadata defaults, because the image already requires IMDSv2. Then choose Launch.
Option B: AWS CLI
Run this on your own workstation. It creates a security group that allows SSH from your management address and HTTPS from your application network, then launches the instance.
Replace the AMI ID with the one shown for your Region on the Marketplace launch page. Replace the VPC, subnet, key pair and CIDR ranges with your own:
SG=$(aws ec2 create-security-group --group-name bifrost-gateway \
--description "Bifrost gateway" --vpc-id vpc-0123456789abcdef0 \
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 443 --cidr 10.0.0.0/16
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 80 --cidr 10.0.0.0/16
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type m5.large \
--key-name my-key-pair \
--security-group-ids "$SG" \
--subnet-id subnet-0123456789abcdef0 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=bifrost-gateway}]'You do not need --metadata-options, because the AMI already requires IMDSv2.
Connect and find your credentials
Connect as ubuntu with the key pair you chose:
ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>First boot finishes within a minute of launch. It does the following:
- Sets the hostname Bifrost is served as, which is the instance's public DNS name when it has one, and creates the TLS certificate for it.
- Generates the dashboard password, the virtual key and the gate token.
- Sets up Bifrost's own dashboard sign-in with that password.
- Proves that the gate refuses anonymous and wrong credentials and keeps the virtual key out of the management API.
- Starts Bifrost and nginx.
- Writes
/root/bifrost-credentials.txt(mode 0600, root).
The following commands show the entries in that file. The secret values are not shown here:
sudo grep -E '^BIFROST_(URL|USERNAME)=' /root/bifrost-credentials.txt
sudo grep -oE '^[A-Z_]+=' /root/bifrost-credentials.txt
sudo stat -c '%a %U:%G' /root/bifrost-credentials.txtBIFROST_URL=https://ec2-54-209-70-122.compute-1.amazonaws.com/ BIFROST_USERNAME=bifrost BIFROST_URL= BIFROST_USERNAME= BIFROST_PASSWORD= <set-at-first-boot>= 600 root:rootValue What it is for
BIFROST_URL The dashboard and API address of this instance
BIFROST_USERNAME Dashboard username (always bifrost)
BIFROST_PASSWORD Dashboard password, generated on this instance: the browser prompt and Bifrost's sign-in page both use it
BIFROST_VIRTUAL_KEY The sk-bf-... virtual key your applications authenticate with on the inference paths
To read the password and key, run sudo cat /root/bifrost-credentials.txt in your own session. Store them in your secrets manager.
Confirm the gateway is running
Check that the first-boot unit, Bifrost and nginx are active, and that only sshd and nginx listen beyond loopback. Bifrost itself is on 127.0.0.1:8080, so the nginx gate is the only way in.
systemctl is-active bifrost-firstboot.service bifrost.service nginx.service
sudo ss -Htlnp | awk '{print $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort -u curl -sk https://127.0.0.1/nginx-healthactive active active 0.0.0.0:22 users:(("sshd"),("systemd")) 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) 127.0.0.1:8080 users:(("bifrost-http")) 127.0.0.53%lo:53 users:(("systemd-resolve")) 127.0.0.54:53 users:(("systemd-resolve")) [::]:22 users:(("sshd"),("systemd")) [::]:443 users:(("nginx"),("nginx"),("nginx")) [::]:80 users:(("nginx"),("nginx"),("nginx")) OK/nginx-health is answered by nginx itself and reveals nothing about your configuration, so it is safe to use as a load balancer health check.
Prove the gate
Anonymous requests to the inference endpoints, the metrics and the management API are all refused, and so is a virtual key that is wrong by one character. This instance's own key opens the inference paths, but it does not open the dashboard or the management API. That includes the two routes the advisories above concern:
for R in /v1/models /metrics /api/config /api/governance/virtual-keys /api/providers; do printf '%s -> %s\n' "$R" "$(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1$R)" done curl -sk -o /dev/null -w 'anonymous POST /v1/chat/completions -> %{http_code}\n' \
-X POST -H 'Content-Type: application/json' -d '{}' https://127.0.0.1/v1/chat/completions
K=$(sudo grep '^BIFROST_VIRTUAL_KEY=' /root/bifrost-credentials.txt | cut -d= -f2-)
curl -sk -o /dev/null -w 'wrong key on /v1/models -> %{http_code}\n' -K <(printf 'header = "Authorization: Bearer %sX"\n' "$K") https://127.0.0.1/v1/models
curl -sk -o /dev/null -w 'this instance key on /v1/models -> %{http_code}\n' -K <(printf 'header = "Authorization: Bearer %s"\n' "$K") https://127.0.0.1/v1/models for R in /api/mcp/client /api/plugins; do
curl -sk -o /dev/null -w "this instance key on POST $R -> %{http_code}\n" -K <(printf 'header = "Authorization: Bearer %s"\n' "$K") \
-X POST -H 'Content-Type: application/json' -d '{}' "https://127.0.0.1$R" done
curl -sk -o /dev/null -w 'this instance key on the dashboard -> %{http_code}\n' -K <(printf 'header = "Authorization: Bearer %s"\n' "$K") https://127.0.0.1//v1/models -> 401 /metrics -> 401 /api/config -> 401 /api/governance/virtual-keys -> 401 /api/providers -> 401 anonymous POST /v1/chat/completions -> 401 wrong key on /v1/models -> 401 this instance key on /v1/models -> 200 this instance key on POST /api/mcp/client -> 401 this instance key on POST /api/plugins -> 401 this instance key on the dashboard -> 401Bifrost enforces the same rule itself. Even on the loopback address, where nginx is not in the way, its management API refuses a request without the dashboard credential. It also refuses the virtual key:
K=$(sudo grep '^BIFROST_VIRTUAL_KEY=' /root/bifrost-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'loopback /api/mcp/clients, no credential -> %{http_code}\n' http://127.0.0.1:8080/api/mcp/clients
curl -s -o /dev/null -w 'loopback /api/mcp/clients, virtual key -> %{http_code}\n' -K <(printf 'header = "Authorization: Bearer %s"\n' "$K") http://127.0.0.1:8080/api/mcp/clients
curl -s http://127.0.0.1:8080/api/session/is-auth-enabled; echoloopback /api/mcp/clients, no credential -> 401 loopback /api/mcp/clients, virtual key -> 401 {"auth_type":"password","has_valid_token":false,"inference_auth_enforced":true,"is_auth_enabled":true,"setup_required":false,"setup_token_configured":false}The gate accepts the following proofs. All are compared exactly, and all are unique to this instance:
Proof Accepted on Who uses it
HTTP Basic with BIFROST_USERNAME / BIFROST_PASSWORD every path Your browser, and curl -u
A gate cookie issued after the browser signs in (Secure, HttpOnly, SameSite=Lax) every path Your browser, on every dashboard request
Authorization: Bearer <virtual key> inference paths only The OpenAI SDK, LiteLLM, LangChain
x-api-key: <virtual key> inference paths only The Anthropic SDK
x-goog-api-key: <virtual key> inference paths only The Google GenAI SDK
x-bf-vk: <virtual key> inference paths only Bifrost's native header
The last four are the header idioms that Bifrost itself uses for virtual keys. Your application sends one credential that satisfies both the gate and Bifrost's own governance check.
Open the dashboard
Browse to BIFROST_URL (https://<public-dns-name>/). The certificate is self-signed, so your browser warns once. Accept it for this host, or install your own certificate (see Step 8).
Signing in takes two steps, both with the same username and password:
- The browser asks for a username and password (the SecureAnyCloud gate). Use BIFROST_USERNAME and BIFROST_PASSWORD.
- Bifrost shows its own Sign in page. Enter the same
BIFROST_USERNAMEandBIFROST_PASSWORD.
The dashboard is the full Bifrost control plane: observability, model providers, governance, guardrails, the MCP gateway, routing rules and the prompt repository. Its setup checklist already shows dashboard authentication and authentication on inference as done:
On a new instance, Models > Model Providers is empty:
The checklist also suggests restricting CORS origins. nginx already strips every CORS header that Bifrost sends and refuses cross-origin writes. You can dismiss that item, or set your own origins under the dashboard's security settings.
Add your own model provider
The image ships with no provider configured, so no two customers ever share a key. Confirm this from the shell:
U=$(sudo grep '^BIFROST_USERNAME=' /root/bifrost-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^BIFROST_PASSWORD=' /root/bifrost-credentials.txt | cut -d= -f2-)
curl -sk -K <(printf 'user = "%s:%s"\n' "$U" "$P") https://127.0.0.1/api/providers; echo{"providers":[],"total":0}In the dashboard, go to Models > Model Providers > Add provider, choose your provider and paste your own API key. Changes take effect immediately. Provider keys are stored in the SQLite configuration store under /var/lib/bifrost/data, which only the bifrost user can read.
Add a self-hosted model server in your VPC the same way, with its base URL. An example is an Ollama instance from the same listing. Bifrost refuses link-local base URLs, and the instance metadata address is blocked for the gateway in any case.
Point your application at the gateway
Set your SDK's base URL to https://<BIFROST_HOST>/v1 and its API key to BIFROST_VIRTUAL_KEY. That single value authenticates through the gate on the inference paths and identifies the virtual key inside Bifrost.
Copy the instance's certificate (/etc/ssl/bifrost/bifrost.crt) to your client and trust it. Alternatively, put a certificate your clients already trust in front (Step 8).
With the OpenAI Python SDK, the only change to existing code is base_url and api_key:
from openai import OpenAI client = OpenAI( base_url="https://<BIFROST_HOST>/v1", api_key="<virtual key>", ) response = client.chat.completions.create( model="openai/gpt-4o-mini", messages=[{"role": "user", "content": "Hello!"}], ) print(response.choices[0].message.content)After you add a provider, a chat completion through the gateway looks like this:
curl --cacert bifrost.crt -X POST https://<BIFROST_HOST>/v1/chat/completions \
-H "Authorization: Bearer <virtual key>" -H "Content-Type: application/json" \
-d '{"model":"openai/gpt-4o-mini","messages":[{"role":"user","content":"Hello!"}]}'The model field is provider/model, so the same endpoint reaches every provider you configure. The provider-native routes (/openai/..., /anthropic/..., /genai/... and the others listed above) accept the same key.
Governance: budgets, rate limits and more keys
First boot creates one virtual key, the SecureAnyCloud appliance key, and enforces authentication on inference. Exactly one key exists on a new instance:
U=$(sudo grep '^BIFROST_USERNAME=' /root/bifrost-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^BIFROST_PASSWORD=' /root/bifrost-credentials.txt | cut -d= -f2-)
curl -sk -K <(printf 'user = "%s:%s"\n' "$U" "$P") https://127.0.0.1/api/governance/virtual-keys | jq -r '.virtual_keys[] | [.name, .is_active] | @tsv'
curl -sk -K <(printf 'user = "%s:%s"\n' "$U" "$P") https://127.0.0.1/api/config | jq '.client_config.enforce_auth_on_inference'sac appliance key true trueIn Governance > Virtual Keys, you can issue a key per team, application or customer. Each key can have a budget, a rate limit, an expiry and a restriction to specific providers or models. A new key starts with no provider allowed, so add the providers it may use.
Bifrost enforces the keys you issue in the dashboard. However, the nginx gate in front recognises only the appliance key and the dashboard credential, so a request that carries only a new key is refused at the gate with 401. To give each application its own key from outside the instance, put your own identity-aware proxy or API gateway in front of this instance. Have it forward the appliance key on the inference paths.
Serve Bifrost under your own DNS name
Port 80 redirects to HTTPS on the configured hostname. The certificate covers that name, the instance's public and private addresses, localhost and 127.0.0.1:
H=$(sudo grep '^BIFROST_URL=' /root/bifrost-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' "http://$H/v1/models" openssl x509 -in /etc/ssl/bifrost/bifrost.crt -noout -subject -enddate -ext subjectAltName301 https://ec2-54-209-70-122.compute-1.amazonaws.com/v1/models subject=CN = ec2-54-209-70-122.compute-1.amazonaws.com, O = sac notAfter=Jan 22 16:13:16 2029 GMT X509v3 Subject Alternative Name: DNS:ec2-54-209-70-122.compute-1.amazonaws.com, IP Address:54.209.70.122, IP Address:172.31.93.186, IP Address:127.0.0.1, DNS:localhostTo use your own name, point a DNS record at the instance. An Elastic IP keeps the address stable across stops. Then run the helper. It records the name in /etc/sac/bifrost-hostname, issues a new self-signed certificate for it, updates the allowed origins and the credentials file, and reloads nginx:
sudo bifrost-set-hostname <your-dns-name>For a publicly trusted certificate, put the instance behind an Application Load Balancer with an AWS Certificate Manager certificate. Alternatively, replace /etc/ssl/bifrost/bifrost.crt and bifrost.key with your own, then run sudo systemctl reload nginx.
Check the security controls
Three controls apply. Bifrost's service carries the metadata block. nginx refuses cross-origin writes and requests for any hostname it was not configured with. Bifrost itself refuses a provider pointed at the metadata address:
systemctl show -p IPAddressDeny bifrost.service
H=$(sudo grep '^BIFROST_URL=' /root/bifrost-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
U=$(sudo grep '^BIFROST_USERNAME=' /root/bifrost-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^BIFROST_PASSWORD=' /root/bifrost-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'cross-origin POST: %{http_code}\n' --cacert /etc/ssl/bifrost/bifrost.crt -K <(printf 'user = "%s:%s"\n' "$U" "$P") \
-X POST -H 'Origin: https://evil.example' -H 'Content-Type: application/json' -d '{}' "https://$H/api/governance/virtual-keys" code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Host: evil.example' http://127.0.0.1/ || true); echo "unknown Host: ${code} (connection closed by nginx)"
curl -s --cacert /etc/ssl/bifrost/bifrost.crt -K <(printf 'user = "%s:%s"\n' "$U" "$P") -H "Origin: https://$H" -H 'Content-Type: application/json' \
-X POST -d '{"provider":"openai","network_config":{"base_url":"http://169.254.169.254/latest/meta-data"}}' "https://$H/api/providers"; echoIPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32 cross-origin POST: 403 unknown Host: 000 (connection closed by nginx) {"is_bifrost_error":false,"status_code":400,"error":{"message":"Invalid base URL: link-local IP addresses are not allowed"},"extra_fields":{"routing_info":{}}}Before the image is captured, and again on a fresh instance, the SecureAnyCloud build also proves three things:
- A provider whose hostname is later re-pointed at 169.254.169.254 (DNS rebinding) is refused when Bifrost connects.
- A forged X-Forwarded-For never reaches Bifrost.
- A stdio MCP client or a plugin URL sent with the virtual key or with no credential is refused without running a command or fetching anything.
Where your data lives
/var/lib/bifrost/data holds the SQLite configuration store (your provider API keys) and the SQLite log store (the prompts and completions of every request). Only the bifrost user can read it:
sudo stat -c '%a %U:%G' /var/lib/bifrost/data700 bifrost:bifrostIf you do not want prompts and completions kept, turn content logging off or shorten the retention in Observability > Logs Settings:
To back up the gateway, stop it and copy the directory, or take an EBS snapshot of the instance:
sudo systemctl stop bifrost
sudo tar czf /root/bifrost-backup-$(date +%F).tar.gz -C /var/lib/bifrost data
sudo systemctl start bifrostWhat is in the image and under what licence
Every dependency compiled into the binary was enumerated and licence-checked at build time, and the inventory ships with the image. All of them are permissive (MIT, Apache-2.0, BSD, ISC, MPL-2.0). There is no AGPL, SSPL, Business Source, Elastic Licence, Commons Clause or non-commercial component.
The binary carries the upstream commit it was built from:
head -8 /usr/share/bifrost/dependency-licences.txt awk -F'\t' '$1=="go"||$1=="npm"{print $4}' /usr/share/bifrost/dependency-licences.txt | sort | uniq -c | sort -rn | head -6 LC_ALL=C grep -a -o 'vcs\.revision=[0-9a-f]\{40\}' /usr/local/bin/bifrost-http | head -1# Bifrost appliance — dependency licence inventory (sac)
#
# Every dependency compiled into /usr/local/bin/bifrost-http.
# Go modules : 232 (read from the shipped binary's build info) # npm packages: 664 (pinned ui/package-lock.json — the UI is # compiled into the same binary) # TOTAL : 896 # 657 MIT 108 Apache-2.0 37 BSD-3-Clause 28 ISC 26 MPL-2.0 16 Apache-2.0,BSD-3-Clause vcs.revision=d3f707ed3669b71bd9052f9ce71ff63fa3e91f6cMaintenance
- Logs. Run
sudo journalctl -u bifrost.service -ffor the gateway. HTTPS access logs are in/var/log/nginx/. - Restart. Run
sudo systemctl restart bifrost.service. - Operating system updates. Ubuntu's unattended security upgrades stay on, so nginx and the rest of the OS keep receiving patches. Apply the rest with
sudo apt update && sudo apt upgradein a maintenance window. - Upgrading Bifrost. Bifrost is a pinned binary. Upgrade deliberately by replacing
/usr/local/bin/bifrost-httpwith a newer official release, then restart the service. Keep the nginx gate as it is, because its path scoping keeps application keys out of the management API. - Changing the dashboard password. The gate and Bifrost's sign-in use the same password, so set the new one in both places. Run
sudo htpasswd -B /etc/nginx/bifrost.htpasswd bifrost, thensudo systemctl reload nginx. Then change it in Bifrost's dashboard security settings, and update/root/bifrost-credentials.txt. - Rotating the appliance key. Edit it in Governance > Virtual Keys. Put the new value in
/etc/nginx/conf.d/bifrost-gate-map.confand/root/bifrost-credentials.txt, then runsudo systemctl reload nginx.
Troubleshooting
The browser keeps asking for a password. Enter BIFROST_USERNAME and BIFROST_PASSWORD from /root/bifrost-credentials.txt exactly, over https://. The same pair works on Bifrost's sign-in page that follows.
An application gets 401 on a dashboard or /api/... URL with its virtual key. This is by design, because the virtual key opens only the inference paths. Administrative calls need BIFROST_USERNAME / BIFROST_PASSWORD (HTTP Basic).
nginx will not start. By design, the gate markers and a preflight guard hold it back. Check what it refused:
sudo /usr/local/sbin/bifrost-preflight.sh --nginx >/dev/null 2>&1; echo "exit=$?"exit=0First boot did not complete. Read its log with sudo journalctl -u bifrost-firstboot.service --no-pager | tail -20.
Requests return a provider error. Either no provider has been added yet (Step 6), or the virtual key you use is not allowed that provider (Governance > Virtual Keys).
Support
SecureAnyCloud provides 24/7 support for this image by email and live chat. Support covers launching and connecting, provider configuration, TLS and hostnames, governance and upgrades.
Trademarks
Bifrost is developed by Maxim AI. Ubuntu is a registered trademark of Canonical Ltd. All other product and company names are trademarks or registered trademarks of their respective holders. SecureAnyCloud is not affiliated with or endorsed by them.
Deploy on AWS
Launch Bifrost 2.3.1 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need help?
Our support team is available 24/7.
sales@secureanycloud.com