Skip to content

Frequently Asked Questions

Quick answers to common questions about Bifrost Proxy.


Bifrost Proxy is a Go-based proxy system with client-server architecture that supports:

  • HTTP and SOCKS5 proxy protocols
  • WireGuard and OpenVPN tunnel backends
  • Domain-based routing
  • Multiple authentication modes
  • VPN mode with split tunneling
  • P2P mesh networking
Platform Server Client
Linux (x64, ARM64) Yes Yes
macOS (Intel, Apple Silicon) Yes Yes
Windows (x64) Yes Yes
FreeBSD Yes Yes
OpenWrt Limited Yes

What’s the difference between server and client?

Section titled “What’s the difference between server and client?”
  • Server: Central proxy that handles routing, backends (WireGuard, OpenVPN), and caching
  • Client: Local proxy with traffic debugging, VPN mode, and connects to servers

Terminal window
# Using Go
go install github.com/rennerdo30/bifrost-proxy/cmd/bifrost-server@latest
go install github.com/rennerdo30/bifrost-proxy/cmd/bifrost-client@latest
# Using Docker
docker pull ghcr.io/rennerdo30/bifrost-proxy:latest
# Binary releases
# Download from GitHub releases page
Resource Minimum Recommended
CPU 1 core 2+ cores
RAM 128 MB 512+ MB
Disk 50 MB 1+ GB (with caching)
Terminal window
# Check version
bifrost-server version
# Validate configuration
bifrost-server validate -c config.yaml
# Test startup
bifrost-server -c config.yaml --log-level debug

Default locations checked:

  1. Path specified with -c flag
  2. ./config.yaml
  3. /etc/bifrost/config.yaml
  4. ~/.config/bifrost/config.yaml

How do I use environment variables in config?

Section titled “How do I use environment variables in config?”

Use the ${VAR_NAME} syntax:

auth:
providers:
- name: native
type: native
enabled: true
priority: 1
config:
users:
- username: admin
password_hash: "${ADMIN_PASSWORD_HASH}"

${VAR_NAME:-fallback} supplies a default when the variable is unset or empty, and $$ writes a literal $. A bare $VAR_NAME is not expanded, and any other $ is literal — so a password or bcrypt hash containing $ is loaded exactly as written. Details in Configuration.

Why does Bifrost refuse to start with “unknown key”?

Section titled “Why does Bifrost refuse to start with “unknown key”?”

Because that key does nothing. A misspelled or obsolete key used to be ignored in silence, which is indistinguishable from a setting that has no effect. The error names every offending key, its line and its config block; correct or remove them.

If a deployment has to come up first, start it with BIFROST_CONFIG_ALLOW_UNKNOWN_KEYS=1, which logs the keys as warnings and ignores them, then fix the file. See Configuration.

Hot-reloadable (no restart):

  • Routes
  • Rate limits
  • Access control lists
  • Cache settings

Require restart:

  • Listener addresses (ports)
  • TLS configuration
  • Authentication mode
  • Backend type changes

Reload without restart:

Terminal window
# Via signal
kill -HUP $(pgrep bifrost-server)
# Via API
curl -X POST http://localhost:7082/api/v1/config/reload
Terminal window
# htpasswd (bcrypt)
htpasswd -nbBC 12 "" "mypassword" | cut -d: -f2
# Python
python3 -c "import bcrypt; print(bcrypt.hashpw(b'mypassword', bcrypt.gensalt(12)).decode())"
# Go tool
go run github.com/rennerdo30/bifrost-proxy/tools/hashpw mypassword

Terminal window
# HTTP proxy
curl -x http://localhost:7080 https://httpbin.org/ip
# SOCKS5 proxy
curl --socks5 localhost:7180 https://httpbin.org/ip
# With authentication
curl -x http://user:pass@localhost:7080 https://httpbin.org/ip

Why am I getting “Connection refused”?

Section titled “Why am I getting “Connection refused”?”

Common causes:

  1. Service not running: systemctl status bifrost-server
  2. Wrong port: Check listen in config
  3. Firewall blocking: sudo ufw status
  4. Bound to localhost only: Use :7080 instead of 127.0.0.1:7080

The proxy requires authentication. Provide credentials:

Terminal window
curl -x http://username:password@localhost:7080 https://example.com

If credentials are correct, verify the password hash in your config.

How do I configure my browser to use the proxy?

Section titled “How do I configure my browser to use the proxy?”

Firefox:

  1. Settings → Network Settings → Manual proxy configuration
  2. HTTP Proxy: localhost, Port: 7080
  3. Check “Use this proxy server for all protocols”

Chrome: Uses system proxy settings, or use an extension like SwitchyOmega.

System-wide (environment variables):

Terminal window
export http_proxy="http://localhost:7080"
export https_proxy="http://localhost:7080"

How do I route specific domains through different backends?

Section titled “How do I route specific domains through different backends?”
routes:
- domains:
- "*.company.com"
- "internal.corp"
backends:
- corporate-vpn
- domains:
- "*.streaming.com"
backends:
- fast-direct
- domains:
- "*" # Default/catch-all
backends:
- default-backend
routes:
- domains: ["*"]
backends:
- backend1
- backend2
- backend3
load_balance: round_robin # or: least_conn, ip_hash

Why is my WireGuard backend showing unhealthy?

Section titled “Why is my WireGuard backend showing unhealthy?”

Check:

  1. Keys match between client and server
  2. Endpoint is reachable: nc -u -zv endpoint 51820
  3. Firewall allows UDP: sudo ufw allow out 51820/udp
  4. DNS servers configured in backend config

Currently, Bifrost uses its own config format. Convert manually:

backends:
- name: wg-vpn
type: wireguard
config:
private_key: "YOUR_PRIVATE_KEY"
address: "10.0.0.2/24"
dns: ["1.1.1.1"]
peer:
public_key: "SERVER_PUBLIC_KEY"
endpoint: "vpn.example.com:51820"
allowed_ips: ["0.0.0.0/0"]

What authentication methods are supported?

Section titled “What authentication methods are supported?”
Method Use Case
none Development, trusted networks
native Simple username/password
ldap Enterprise (Active Directory)
system Linux/macOS users (PAM)
oauth SSO with OAuth/OIDC providers
jwt Token-based APIs
apikey Service-to-service
totp Time-based OTP
hotp Counter-based OTP
mtls Client certificates
kerberos Enterprise SSO
mfa_wrapper Two-factor (password + OTP)

System authentication uses PAM (Linux) or Directory Services (macOS). Windows is not supported. Use native, ldap, or oauth instead.

How do I set up two-factor authentication?

Section titled “How do I set up two-factor authentication?”
auth:
providers:
- name: mfa
type: mfa_wrapper
enabled: true
priority: 1
config:
primary:
mode: native
config:
users:
- username: admin
password_hash: "$2a$12$..."
secondary:
mode: totp
config:
secrets:
admin: "BASE32SECRET"
otp_separator: ":" # Use password:123456

  1. Enable caching:

    cache:
    enabled: true
    storage:
    type: memory
    memory:
    max_size: "256MB"
  2. Tune outbound connection reuse:

    network:
    keepalive: "30s"
    dial_timeout: "10s"

    Inbound connections are not reused — the HTTP listener serves one request per connection — so idle_timeout is not a connection-reuse knob. It bounds connections with nothing in flight; see Listener timeouts.

  3. Reduce logging:

    logging:
    level: warn
  4. Increase file descriptors:

    Terminal window
    ulimit -n 65536

Base memory: ~50-100 MB

Memory increases with:

  • Active connections
  • Cache size
  • Request logging
  • Number of routes

Check:

  1. Backend latency: curl -s http://localhost:7082/api/v1/backends | jq '.[] | .stats.avg_latency_ms'
  2. DNS resolution time
  3. TLS handshake overhead
  4. Connection ceilings being hit (server.http.max_connections, network.max_connections)

What’s the difference between VPN mode and proxy mode?

Section titled “What’s the difference between VPN mode and proxy mode?”
Feature Proxy Mode VPN Mode
Traffic capture Apps configured to use proxy All system traffic
Protocol HTTP/SOCKS5 TUN (IP-level)
Split tunneling Per-route Per-app, domain, IP
Setup complexity Low Medium
Permissions User-level Root/admin

Creating TUN/TAP devices requires elevated privileges. On Linux:

Terminal window
# Grant capabilities instead of root
sudo setcap cap_net_admin+ep ./bifrost-client
vpn:
enabled: true
split_tunnel:
mode: exclude
apps:
- name: "Slack"
- name: "Zoom"

A Hamachi-like feature that creates virtual LANs between peers using:

  • Automatic NAT traversal (STUN/TURN/ICE)
  • End-to-end encryption
  • Direct P2P connections when possible
  1. Symmetric NAT: Both peers behind symmetric NAT need TURN relay
  2. Firewall: Allow UDP on ephemeral ports
  3. STUN unreachable: Check STUN server connectivity

Only if both peers are behind symmetric NAT. Options:

  • Self-host using coturn
  • Use a commercial TURN service

Path Encryption
Client → Proxy (local) Optional TLS
Proxy → Backend (WireGuard) ChaCha20-Poly1305
Proxy → Backend (OpenVPN) Configurable (AES, etc.)
Proxy → Upstream (direct) End-to-end HTTPS
Mesh P2P ChaCha20-Poly1305
server:
http:
listen: ":7443"
tls:
enabled: true
cert_file: "/path/to/cert.pem"
key_file: "/path/to/key.pem"

No. The API should only be accessible from localhost or trusted networks:

api:
listen: "127.0.0.1:7082" # Localhost only

Use a reverse proxy with authentication if remote access is needed.


logging:
level: debug
format: text

Or: bifrost-server -c config.yaml --log-level debug

Deployment Location
Systemd journalctl -u bifrost-server
Docker docker logs bifrost-server
File Configured in logging.output
  1. Check existing issues on GitHub
  2. Gather: version, OS, config (sanitized), logs
  3. Open issue at: https://github.com/rennerdo30/bifrost-proxy/issues

Terminal window
# Go installation
go install github.com/rennerdo30/bifrost-proxy/cmd/bifrost-server@latest
# Docker
docker pull ghcr.io/rennerdo30/bifrost-proxy:latest
docker-compose up -d
# Binary
# Download new binary and replace, then restart

Are configuration files backward compatible?

Section titled “Are configuration files backward compatible?”

Generally yes. Check the CHANGELOG for breaking changes between versions.

Yes, restart is required after upgrading the binary. Your configuration will be preserved.