Skip to content

gtmills/bmcweb-ng

Repository files navigation

bmcweb-ng

Next-generation BMC webserver for OpenBMC, written in Rust

License Rust

Overview

bmcweb-ng is a modern rewrite of bmcweb, the embedded webserver for OpenBMC. Built from the ground up in Rust, it provides a high-performance, memory-safe implementation of the Redfish API and other BMC management interfaces.

Why a Rewrite?

The original bmcweb is a mature, production-ready C++ application. This rewrite aims to:

  • Improve Maintainability - Simpler architecture, less template metaprogramming
  • Enhance Safety - Memory safety guarantees from Rust
  • Better Testing - Mockable interfaces, comprehensive test coverage
  • Developer Experience - Faster compile times, better tooling, clearer error messages
  • Modern Async - Clean async/await syntax instead of callback chains

Key Features

  • βœ… Redfish API - Broad Redfish coverage from ServiceRoot through TelemetryService, plus OData, Fabrics, and Virtual Media routes
  • βœ… Multiple Protocols - HTTP/1.1, HTTP/2, HTTPS with TLS 1.3
  • βœ… Authentication - Basic auth with PAM, Session management, Token-based auth
  • βœ… Event Service - Event subscriptions, async notifications, SSE endpoint, and PATCH-configurable retry settings
  • βœ… Task Service - Long-running operation tracking and management
  • βœ… Update Service - Firmware update management and live DBus inventory
  • βœ… DBus Integration - Comprehensive async DBus wiring to OpenBMC services
  • βœ… WebSocket Support - Serial console, KVM proxy, and Virtual Media/NBD UNIX-socket proxies
  • βœ… Performance - ~5MB binary, <10MB memory (idle), fast request latency on QEMU and real hardware
  • βœ… Observability - Structured logging, Prometheus metrics support

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   API Layer (Redfish/REST/WS)       β”‚  ← HTTP handlers, routing
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Business Logic (Resources)        β”‚  ← Redfish resource handlers
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Service Layer (DBus)              β”‚  ← DBus abstraction, caching
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Protocol Layer (HTTP/WS/TLS)      β”‚  ← axum, hyper, tokio-tungstenite
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Runtime (Async I/O)               β”‚  ← tokio runtime
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Design Principles

  1. Layered Architecture - Clear separation of concerns
  2. Dependency Injection - Testable components via traits
  3. Schema-Driven - Generate types from Redfish schemas
  4. Configuration as Code - Runtime TOML configuration
  5. Fail Fast - Validate at startup, not at runtime
  6. Observability First - Logging, metrics, and tracing built-in

Getting Started

Prerequisites

  • Rust 1.96.1 or later
  • OpenBMC development environment (for DBus integration)
  • OpenSSL 3.0+ (for TLS support)

Building

# Clone the repository
git clone https://github.com/gtmills/bmcweb-ng.git
cd bmcweb-ng

# Build in debug mode
cargo build

# Build optimized release
cargo build --release

# Run tests
cargo test

# Run with logging
RUST_LOG=info cargo run

Configuration

Create a config.toml file:

[server]
bind_address = "0.0.0.0"
port = 443
tls_cert = "/etc/bmcweb/cert.pem"
tls_key = "/etc/bmcweb/key.pem"
max_connections = 100

[auth]
session_timeout_seconds = 3600
max_sessions = 64

[logging]
level = "info"

[metrics]
enabled = true
port = 9090

Running

# Run with default config
cargo run --release

# Run with custom config
cargo run --release -- --config /path/to/config.toml

# Run in development mode with hot reload
cargo watch -x run

Project Structure

bmcweb-ng/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.rs              # Application entry point
β”‚   β”œβ”€β”€ lib.rs               # Core library with AppState
β”‚   β”œβ”€β”€ persistent_data.rs   # UUID and session persistence
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   └── mod.rs           # Configuration management (TOML)
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”œβ”€β”€ mod.rs           # API layer
β”‚   β”‚   └── redfish/         # Redfish endpoints
β”‚   β”‚       β”œβ”€β”€ mod.rs                # Router + route table
β”‚   β”‚       β”œβ”€β”€ service_root.rs       # ServiceRoot
β”‚   β”‚       β”œβ”€β”€ systems.rs            # Systems + sub-resources
β”‚   β”‚       β”œβ”€β”€ chassis.rs            # Chassis + sub-resources
β”‚   β”‚       β”œβ”€β”€ managers.rs           # Managers + sub-resources
β”‚   β”‚       β”œβ”€β”€ sessions.rs           # SessionService + Sessions
β”‚   β”‚       β”œβ”€β”€ accounts.rs           # AccountService + Accounts + Roles
β”‚   β”‚       β”œβ”€β”€ event_service.rs      # EventService + Subscriptions
β”‚   β”‚       β”œβ”€β”€ task_service.rs       # TaskService + Tasks
β”‚   β”‚       β”œβ”€β”€ update_service.rs     # UpdateService + FirmwareInventory
β”‚   β”‚       β”œβ”€β”€ certificate_service.rs # CertificateService
β”‚   β”‚       └── telemetry_service.rs  # TelemetryService
β”‚   β”œβ”€β”€ auth/                # Authentication & authorization
β”‚   β”‚   β”œβ”€β”€ mod.rs           # Auth exports
β”‚   β”‚   β”œβ”€β”€ basic.rs         # Basic auth with PAM
β”‚   β”‚   β”œβ”€β”€ session.rs       # Session management
β”‚   β”‚   β”œβ”€β”€ middleware.rs    # Auth middleware
β”‚   β”‚   └── privilege.rs     # RBAC privilege checking
β”‚   β”œβ”€β”€ dbus/
β”‚   β”‚   └── mod.rs           # DbusClient trait + ZBusClient + MockDbusClient
β”‚   β”œβ”€β”€ services/            # Business logic services
β”‚   β”‚   β”œβ”€β”€ mod.rs
β”‚   β”‚   β”œβ”€β”€ event.rs         # Event Service
β”‚   β”‚   β”œβ”€β”€ task.rs          # Task Service
β”‚   β”‚   └── update.rs        # Update Service
β”‚   β”œβ”€β”€ protocol/            # Protocol layer
β”‚   β”‚   β”œβ”€β”€ mod.rs
β”‚   β”‚   └── http.rs          # HTTP/HTTPS server (axum + rustls)
β”‚   └── observability/       # Prometheus metrics
β”‚       β”œβ”€β”€ mod.rs
β”‚       └── metrics.rs
β”œβ”€β”€ Cargo.toml               # Rust dependencies
β”œβ”€β”€ config.toml              # Default configuration
β”œβ”€β”€ bmcweb-ng.service        # Systemd service file
β”œβ”€β”€ bmcweb-ng.socket         # Systemd socket activation
└── README.md                # This file

Development

Code Style

We follow the Rust standard style guide. Format your code before committing:

cargo fmt

Linting

Run clippy to catch common mistakes:

cargo clippy -- -D warnings

Testing

# Run all tests
cargo test

# Run specific test
cargo test test_name

# Run with output
cargo test -- --nocapture

# Run integration tests only
cargo test --test '*'

# Run benchmarks
cargo bench

Documentation

Generate and view documentation:

cargo doc --open

Performance Targets

Measured on OpenBMC qemuarm (Cortex-A15, 256 MB RAM, 4 cores) β€” July 2026.

Metric Target Current Notes
Binary Size <1MB 4.75 MB ARM dynamically-linked release build; musl static target would be smaller β€” see note below
Memory RSS (idle) <10MB 5.7 MB Measured via /proc/<pid>/status after cold start, no active requests
Startup Time <1s ~1.6s Cold start on emulated ARM; <200ms expected on real hardware
Request Latency (p99) <100ms <10ms p50=4ms p95=5ms p99=7ms β€” 30 sequential GETs to /redfish/v1 on QEMU
Concurrent Connections 100+ 20/20 βœ… 20 simultaneous GETs all succeeded; full 100+ load test pending on real hardware
Unit tests (v0.5.0) β€” 239 0 failures; covers all major handlers across systems/chassis/managers/accounts

Binary size note: The <1MB target assumed a musl static build. The current dynamically-linked ARM EABI release build is 4.75 MB stripped. This is because Tokio, hyper, rustls, zbus, and serde_json together contribute significant code. Switching to aarch64-unknown-linux-musl with LTO and opt-level = "z" (already set) typically yields 3–5 MB β€” still larger than the original target which was aspirational. The <10MB memory target is met at 5.7 MB RSS.

Startup time note: 1.6s is measured on QEMU's emulated Cortex-A15. On a real BMC SoC (e.g. AST2600 at 800 MHz) startup is expected to be under 500ms. The <1s target is realistic for production hardware.

Compatibility

API Compatibility

  • Redfish API: High parity with upstream bmcweb for the currently implemented route set
  • DBus Interface: Same DBus calls and object model intent as bmcweb for implemented resources
  • Configuration: New TOML format defined in config.toml

Migration from bmcweb

No standalone migration guide is checked into this repository yet. Use BUILDING.md, ARCHITECTURE.md, and DEVELOPMENT_STATUS.md for current setup and parity details.

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Development Setup

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests (cargo test)
  5. Format code (cargo fmt)
  6. Run linter (cargo clippy)
  7. Commit your changes (git commit -m 'Add amazing feature')
  8. Push to the branch (git push origin feature/amazing-feature)
  9. Open a Pull Request

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Acknowledgments

  • Original bmcweb project and contributors
  • OpenBMC community
  • DMTF for the Redfish specification
  • Rust community for excellent async ecosystem

Contact

Related Projects

  • bmcweb - Original C++ implementation
  • OpenBMC - Open source BMC firmware
  • Redfish - DMTF Redfish specification

About

A research project on a bmcweb RUST rewrite - for fun only

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages