Product page: <www.omnect.io>
This module implements a web frontend and backend to provide omnect specific features in a local environment, where the device might not be connected to the azure cloud. In that case the device cannot be remotely controlled by omnect-portal and omnect UI might be the alternative.
omnect UI provides the following main features:
- Device Status Monitoring: Real-time visualization of device health, system information, and connectivity status.
- Network Management: Configuration of network adapters with support for DHCP and Static IP.
- Automatic Network Rollback: Safety mechanism that reverts failed network configurations to prevent device isolation.
- Firmware Updates: Local trigger and monitoring of atomic A/B partition updates.
- Device Control: Administrative actions like rebooting or factory resetting the device.
- Secure Access: Integrated user authentication to protect device settings.
omnect UI follows a full-stack Single Page Application (SPA) architecture:
- Backend: Rust-based web service (Actix-web) providing API endpoints and WebSocket support
- Crux Core: Platform-agnostic business logic compiled to WebAssembly
- Frontend: Vue 3 TypeScript SPA serving as the shell for the Crux Core
- Shared Types: TypeScript bindings auto-generated from Rust types
All external communication uses encrypted transports. Internal service communication uses Unix domain sockets (not network-exposed).
| Connection | Direction | Protocol | Port | Security | Purpose |
|---|---|---|---|---|---|
| Browser ↔ Backend | bidirectional | HTTPS / WSS | 1977 (configurable) | TLS via rustls, self-signed certificate | UI serving and real-time WebSocket updates |
| Backend → omnect-device-service | outbound | Unix domain socket | — | OS filesystem permissions | Device control: reboot, factory reset, network config, firmware update |
| Backend → WiFi commissioning service | outbound | Unix domain socket | — | OS filesystem permissions | WiFi scan, connect, disconnect, forget |
| Backend → Keycloak (optional) | outbound | HTTPS | configured via KEYCLOAK_URL |
TLS + RS256 JWT signature verification | Portal SSO token validation |
| Internal publish endpoint | localhost only | HTTP | 8000 (configurable) | X-API-Key header (UUID, generated per instance) |
Receives event publications from omnect-device-service |
- The backend serves HTTPS using rustls (memory-safe TLS library). TLS 1.2+ is enforced; no client certificate is required.
- The WebSocket endpoint (
/ws) runs over the same TLS connection as the UI (WSS). - The TLS certificate is issued by
aziot-edgedand written to/cert/cert.pem//cert/key.pem. The certificate CN is set to the device's first detected IPv4 address and is regenerated when the address changes. See HTTPS & Certificate Validation for browser trust requirements. - The internal publish endpoint (port 8000) is plain HTTP and must not be exposed outside the device network namespace. It is protected by a per-instance UUID API key passed as
X-API-Key.
- On first access the UI shows a Set Password page — no prior credential exists.
- The user sets a password (no username). The password is hashed with Argon2id and stored atomically at
/data/config/password. - On subsequent logins the password is validated against the stored hash and a session cookie is issued.
- API clients may alternatively pass
Authorization: Bearer <token>or HTTP Basic Auth (:<password>).
When configured, Keycloak-based OIDC authentication gates the initial Set Password step:
- The frontend initiates an OIDC flow and obtains a token from Keycloak (RS256-signed JWT).
- The token is submitted to
POST /token/validate. The backend fetches Keycloak's realm public key and verifies the RS256 signature. - If valid, the backend records a
portal_validatedflag in the session, allowing the user to callPOST /set-password. - From that point on the local password flow applies.
Session cookie:
| Attribute | Value | Purpose |
|---|---|---|
| Name | omnect-ui-session |
|
HttpOnly |
true | Prevents JavaScript access (XSS mitigation) |
Secure |
true | Transmitted over HTTPS only |
SameSite |
Strict | CSRF mitigation |
| Encryption | AES-GCM (private cookie) | Cookie value is authenticated and encrypted |
| Lifetime | Browser session | Destroyed when the browser is closed |
Session JWT (stored inside the cookie):
| Property | Value |
|---|---|
| Algorithm | HS256 |
| Expiry | 2 hours |
| Clock-skew leeway | 15 minutes |
| Signing key | 64-byte key from OsRng, stored at /data/session.key |
Authorization applies in Portal SSO mode when validating Keycloak tokens:
| Role | Access |
|---|---|
FleetAdministrator |
Full access — no fleet restriction |
FleetOperator |
Access only if the device's fleet_id is in the user's fleet_list claim |
| Other / missing | Access denied |
Additionally, the user's tenant_list claim must contain the configured tenant (default: cp).
| Secret | Path | Protection |
|---|---|---|
| Password hash | /data/config/password |
Argon2id; written via atomic rename + post-write verification |
| Session signing key | /data/session.key |
64 bytes from OsRng; generated once and persisted for restart continuity |
Both paths are under /data, which is the persistent, writable partition on omnect Secure OS.
No authentication required:
GET /— serves the SPAGET /config.js— Keycloak/SSO configuration for the frontendGET /version— backend version stringGET /healthcheck— health probe (CORS enabled for external monitors)GET /require-set-password— indicates whether a password has been setPOST /set-password— set initial password (requires portal session if SSO is configured)POST /token/validate— validate a Keycloak OIDC tokenGET /api/settings— read timeout settings
Authentication required (session cookie, Bearer token, or Basic Auth):
GET /ws— WebSocketPOST /token/login,GET /token/refresh— issue / refresh session tokenPOST /update/file,/update/load,/update/run— firmware updatePOST /factory-reset,POST /reboot— device controlPOST /network— network configurationPOST /ack-rollback,/ack-factory-reset-result,/ack-update-validation— acknowledge operationsPOST /republish— republish device statePOST /api/settings— write timeout settingsPOST /update-password— change the current password/wifi/*— all WiFi management endpoints
- Self-signed certificate: The device certificate is not issued by a public CA. Browsers will show a security warning unless the device root certificate is imported into the browser's trust store. See HTTPS & Certificate Validation.
- Internal HTTP endpoint: Port 8000 is plain HTTP and relies solely on the API key for protection. It must not be reachable from outside the device's loopback or container network.
- Session key persistence:
/data/session.keyis intentionally kept across restarts so that existing session cookies remain valid after a service restart. Delete this file to invalidate all active sessions (the service will generate a new key on the next start). - Password recovery: There is no password-reset mechanism without authentication. If the password is lost, a factory reset is required.
Since omnect secure OS is designed as generic OS, all specific or optional applications must be provided as docker images via azure iotedge deployment:
- deployment of omnect UI docker image via omnect-portal to a device in field
- device must be online (at least once) in order to receive the deployment and to set initial password
- after a factory reset omnect UI must be deployed again what requires a connection to azure cloud
omnect UI can be reached at https://DeviceIp:1977
omnect-ui uses HTTPS to secure communication. However, due to technical constraints, full certificate validation is only possible for the first IPv4 address of the first online network interface detected by systemd-networkd.
To access the UI without security warnings, you must import the device's root certificate into your browser's trust store.
Why can't all IPs and hostnames be automatically secured?
-
Certificate Generation Limitations: The certificates are generated by the Azure IoT Edge security daemon (
aziot-edged). This service only supports defining a Common Name (CN) but does not support Subject Alternative Names (SANs). This means a single certificate cannot be valid for multiple IP addresses or hostnames simultaneously. -
SNI (Server Name Indication) Limitations: While SNI allows a server to present different certificates based on the hostname requested by the client, it relies on the client sending the hostname during the TLS handshake.
- Direct IP Access: Browsers do not send SNI when accessing a site via IP address (e.g.,
https://192.168.1.100). - Docker Bridge Mode: In bridge mode, the container binds to
0.0.0.0and cannot easily distinguish which host interface the traffic arrived on to serve a specific certificate.
- Direct IP Access: Browsers do not send SNI when accessing a site via IP address (e.g.,
-
Network Mode Constraints:
- Host Network Mode: While using
network_mode: hostwould allow binding to specific interfaces, it exposes all container ports to the host network interface directly. This would require opening the device firewall to allow traffic, which is security restrictive. - Bridge Mode (Required): We use Docker bridge mode to maintain isolation and control over exposed ports, but this necessitates the certificate limitations described above.
- Host Network Mode: While using
The device overview page displays a real-time snapshot of the device's health and identity. All data is pushed via WebSocket (healthcheck channel) so the UI updates automatically without polling.
Information displayed:
- Cloud Connectivity: Whether the device is connected to the omnect Azure IoT Hub
- Hostname: Device hostname
- OS Variant & Version: omnect Secure OS build name and version string
- Boot Time: Timestamp of the last system boot
- Wait-Online Timeout: Configured network wait timeout (seconds)
- Service Versions: omnect-device-service, Azure SDK, and WiFi commissioning service versions (the WiFi entry also shows the minimum required version when the installed version is too old)
omnect UI supports uploading and applying firmware update packages directly from the browser.
- Navigate to the Update section
- Drag-and-drop or click to select a
.tarupdate archive - Upload progress is shown as a percentage
- Once uploaded, the manifest is parsed and displayed in three columns:
- Version Info: Current device version, update version, OS variant
- Provider Info: Update provider name, creation date and time
- Compatibility: Manufacturer, model, compatibility ID
- Optionally enable "Enforce cloud connection" — requires the device to successfully reconnect to Azure IoT Hub after the update before declaring success
- Click Install Update
- The UI polls for update completion (default timeout: 900 s, configurable in Settings)
- On success the device reports the new version; on failure it reports a rollback
The device overview page provides two administrative operations, each guarded by a confirmation dialog.
- Click Restart and confirm the dialog
- The reboot command is sent to omnect-device-service
- An overlay with a countdown timer appears while the UI polls for the device to come back online (5 s interval, default timeout: 300 s)
- Once the device responds the overlay clears and the page resumes normally
- Click Factory Reset and confirm the dialog
- Optionally select items to preserve (e.g., network configuration, certificates) — available options are reported by the device
- The reset command is sent; an overlay with a countdown timer appears
- The UI polls for reconnection (5 s interval, default timeout: 600 s)
- Once the device responds the overlay clears
omnect UI protects device settings with authentication.
Password login (default):
- Enter the password on the login page — no username is required
- On first use, a guided Set Password page is shown before the login form is accessible
- Passwords are hashed and stored on the device; the session is managed via JWT
Portal SSO (optional):
- If the device is configured for OIDC-based portal authentication, the UI detects this automatically and redirects to the identity provider
- When the portal session expires the UI clears the stale token and re-initiates the login flow
The Settings page exposes configurable timeout durations (in seconds) for long-running operations. All values are persisted on the device and applied on the next operation.
| Setting | Default | Description |
|---|---|---|
| Network rollback | 90 s | How long to wait at the new address before reverting a failed network change |
| Reboot reconnect | 300 s | Maximum time to wait for the device to come back online after a reboot |
| Factory reset reconnect | 600 s | Maximum time to wait for the device to come back online after a factory reset |
| Firmware update | 900 s | Maximum time to wait for an update to complete |
All timeouts accept values between 30 s and 3600 s. A Reset to Defaults button restores all four values at once.
omnect UI can discover and manage WiFi networks when the WiFi commissioning service is installed on the device and meets the minimum required version.
- Navigate to the Network section and open the WiFi panel
- Click Scan to discover nearby networks; each result shows the SSID and signal strength (1–4 bars based on RSSI)
- Click a network to open the Connect dialog, enter the password, and press Connect
- Connection status (Idle / Connecting / Connected / Failed) is shown in real time
- Previously connected networks appear in the Saved Networks list with a CURRENT badge on the active connection
- Click the delete icon next to a saved network to forget its credentials
- Use the Disconnect button to drop the current WiFi connection without forgetting it
omnect UI allows you to configure network settings for your device's network adapters. This feature is particularly useful when you need to change IP addresses or switch between DHCP and static IP configuration.
- Navigate to the Network section in the UI
- Select the network adapter you want to configure
- Choose between DHCP or Static IP assignment
- For static IP, configure:
- IP address and subnet mask
- Gateway addresses
- DNS servers
- Click "Save" to apply the configuration
When changing network settings that affect your current connection, omnect UI provides an optional automatic rollback feature to prevent losing access to your device:
When does this apply:
The confirmation dialog appears when you:
- Change the static IP address of the adapter you're currently connected to, OR
- Switch from static IP to DHCP on the adapter you're currently connected to
How it works:
- When you attempt a change that affects your connection, a confirmation dialog appears
- You can choose to enable automatic rollback protection (enabled by default and recommended)
- If enabled:
- For static IP changes: You have 90 seconds to access the device at the new IP address. An overlay with a countdown timer will guide you to the new address. You must log in at the new IP address to confirm the change works.
- For DHCP changes: You have 90 seconds to find and access the new DHCP-assigned IP (check your DHCP server or device console). The overlay will show a countdown.
- If you don't access the new address and log in within 90 seconds, the device automatically restores the previous network configuration. The browser will attempt to reconnect to the original address.
- If disabled:
- Changes are applied immediately without automatic rollback protection
- For static IP changes: An overlay appears with a button to navigate to the new IP address
- For DHCP changes: An overlay informs you to use your DHCP server or console to find the new IP
- You're responsible for manually accessing the new address
- If the new configuration doesn't work, you may lose network access to the device
Important notes:
- Automatic rollback only applies when changing settings on the adapter you're currently connected through
- Changes to other network adapters don't trigger the rollback mechanism
- When switching to DHCP, the new IP address cannot be known in advance - you must check your DHCP server or device console
- The rollback feature requires physical or console access to recover if network access is lost and rollback fails
- Rust toolchain (1.91+)
- Bun for frontend development
- wasm-pack for WASM builds
- Docker with buildx support
tomlCLI tool (for version extraction)- Running instance of omnect-device-service
# Run development setup (builds frontend once)
./scripts/build-frontend.sh
# Run backend with mock features
cargo run --bin omnect-ui --features=mock
# Or use VSCode debugger (F5) - pre-launch task is configured# Build frontend (WASM + TypeScript types + UI)
./scripts/build-frontend.sh
# Build backend
cargo build -p omnect-ui --releaseFor hot-reload during frontend development:
cd src/ui
bun run dev # Starts Vite dev server with HMRUse the build-and-deploy-image.sh script for building and optionally deploying a Docker image to device (there must be an existing deployment and the restart policy of omnect-ui must be set to never).
# Build ARM64 image (default)
./scripts/build-and-deploy-image.sh
# Build for different architecture
./scripts/build-and-deploy-image.sh --arch amd64
# Build with custom tag
./scripts/build-and-deploy-image.sh --tag v1.2.0
# Build and push to registry
./scripts/build-and-deploy-image.sh --push
# Build and deploy to device
./scripts/build-and-deploy-image.sh --deploy
# Full example with all options
./scripts/build-and-deploy-image.sh --arch arm64 --tag my-feature --push --deploy --host 192.168.1.100 --port 1977Run ./scripts/build-and-deploy-image.sh --help for all available options.
# Run all unit tests (backend + core)
cargo test --features mock
# Run E2E tests (automated setup - starts Mock WebSocket server + frontend dev server)
./scripts/run-e2e-tests.sh
# Run E2E tests in Docker container (isolated environment)
./scripts/test-e2e-in-container.sh
# Lint all code
cargo clippy --all-targets --features mockIf you encounter permission errors when running E2E tests (typically after running Docker-based tests), clean up files created by root:
# Clean all E2E test artifacts with permission issues
sudo rm -rf temp/certs src/ui/dist src/ui/test-results src/ui/playwright-reportThe project includes VSCode launch configurations optimized for development:
check_odstask: Verifies omnect-device-service is running
Prerequisites before launching the debugger:
- Ensure omnect-device-service is running (
/tmp/api.sockmust exist) - Build frontend if you made changes:
./scripts/build-frontend.sh
Licensed under either of
- Apache License, Version 2.0, (./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (./LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
copyright (c) 2024 conplement AG
Content published under the Apache License Version 2.0 or MIT license, are marked as such. They may be used in accordance with the stated license conditions.