Beszel

A lightweight server monitor with Docker stats, historical data, and alerts.

Overview

Overview

What is Beszel?

GitHub-logo.png logo.png

2025-02-01 23_19_45-Beszel _ Simple, lightweight server monitoring - Brave.png

Introduction

Beszel is a lightweight server monitoring platform that provides a friendly, configurable interface for tracking system health and Docker statistics. It supports historical data storage, alerting, and simple setup processes. It offers multi-user support, OAuth / OIDC authentication, automatic backups, and more—making it ready to use out of the box.


Architecture

Beszel consists of two main components: the hub and the agent.


Features


Supported Metrics


Screenshots

dashboard.png

Metrics:

system-full.png

Settings:

settings-notifications.png

Getting Started

Getting Started

Quickstart Guide

GitHub-logo.png logo.png

2025-02-01 23_19_45-Beszel _ Simple, lightweight server monitoring - Brave.png

Introduction

Architecture

Beszel consists of two main components:


Step 1: Create the Necessary Folders

If you have multiple nodes and a Docker Swarm environment, you can reference the GlusterFS guide for distributing folders across nodes. The Folders needs to be Accasable from every Node and be updated in realtime.

mkdir -p /mnt/glustermount/data/beszel_data


Step 2: Docker Compose or Portainer for Initial Setup

You can either create a docker-compose.yaml file manually or use Portainer to set up Beszel. Below is an example configuration that should work out of the box for a standalone Docker setup.

IMPORTANT: After you add a new system in the Beszel web UI, you must update the KEY value with your public key (provided by the hub) and then restart the agent service. Also, use host.docker.internal as the Host/IP when prompted, instead of localhost or 127.0.0.1.

Always make sure your beszel-hub starts first. So on the Agent you add the Option: ""depends_on:"

Docker Standalone Example
services:
  beszel:
    image: henrygd/beszel:latest
    container_name: beszel
    restart: unless-stopped
    extra_hosts:
      - host.docker.internal:host-gateway
    ports:
      - 8090:8090
    volumes:
      - /mnt/glustermount/data/beszel_data:/beszel_data

  beszel-agent:
    image: henrygd/beszel-agent:latest
    container_name: beszel-agent
    restart: unless-stopped
    network_mode: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      PORT: 45876
      # Do not remove quotes around the key
      KEY: 'UPDATE WITH YOUR PUBLIC KEY (copy from "Add system" dialog)'
Docker Swarm + Traefik Example
version: "3.7"

services:
  beszel:
    image: henrygd/beszel:latest
    container_name: beszel
    restart: unless-stopped
    networks:
      - management_net
    extra_hosts:
      - host.docker.internal:host-gateway
    ports:
      - 8090:8090
    volumes:
      - /mnt/glustermount/data/beszel_data:/beszel_data
    deploy:
      mode: replicated
      replicas: 1
      labels:
        - "traefik.enable=true"
        - "traefik.http.services.beszel-agent.loadbalancer.server.port=8090"

  beszel-agent:
    image: henrygd/beszel-agent:latest
    container_name: beszel-agent
    restart: unless-stopped
    network_mode: host
    depends_on:
      - beszel_beszel
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      PORT: 45876
      # Do not remove quotes around the key
      KEY: 'UPDATE WITH YOUR PUBLIC KEY (copy from "Add system" dialog)'
    deploy:
      mode: replicated
      replicas: 1
      labels:
        - "traefik.enable=true"
        - "traefik.http.services.beszel-agent.loadbalancer.server.port=45876"

networks:
  management_net:
    external: true

In Docker Swarm the Name-Conventions might be a little different, thats why the Depends_on Option uses beszel_beszel and not only beszel. because the first beszel stands for the stackname and the second beszel for the service name defined in the docker-compose

Why network_mode: host?
The agent must use host network mode to access network interface metrics, which automatically exposes the port. If you do not need network statistics, you can remove network_mode: host and map the port manually in the Compose file.


Step 3: Start the Containers

Once you've created your Compose file, you can deploy the services. The process differs slightly depending on your setup:


Step 4: Create an Admin User

Open http://localhost:8090 (or your chosen URL/port) in your browser and follow the prompts to create an admin user.


Step 5: Adding Systems / Nodes

When you add a new system from the Beszel hub's web UI, you'll be given a snippet for the beszel-agent configuration (Docker Compose or a binary install command). Copy the public key from the "Add system" dialog and place it in the KEY variable of your agent container or service.

add-system-2.png

Different Agents on Different Nodes:

If you plan to monitor multiple nodes with Docker Swarm, you can create separate agent services, each running on a different node with constraints to ensure proper placement.

Make sure to give each Agent an unique Servicename.
Make sure to give each Agent an unique Port and also change that Port in the Web-UI when adding a new System.

beszel-agent1:
  image: henrygd/beszel-agent:latest
  restart: unless-stopped
  network_mode: host
  depends_on:
    - beszel_beszel
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
  ports:
    - 45876:45876
  environment:
    PORT: 45876
    KEY: 'YOUR_PUBLIC_KEY_FROM_HUB'
  deploy:
    mode: replicated
    replicas: 1
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.beszel-agent1.loadbalancer.server.port=45876"
    placement:
      constraints:
        - node.hostname == swarmpi1  # Only deploy on node 'swarmpi1'

beszel-agent2:
  image: henrygd/beszel-agent:latest
  restart: unless-stopped
  network_mode: host
  depends_on:
    - beszel_beszel
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
  ports:
    - 45877:45877
  environment:
    PORT: 45877
    KEY: 'YOUR_PUBLIC_KEY_FROM_HUB'
  deploy:
    mode: replicated
    replicas: 1
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.beszel-agent2.loadbalancer.server.port=45877"
    placement:
      constraints:
        - node.hostname == swarmpi2  # Only deploy on node 'swarmpi2'

beszel-agent3:
  image: henrygd/beszel-agent:latest
  restart: unless-stopped
  network_mode: host
  depends_on:
    - beszel_beszel
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
  ports:
    - 45878:45878
  environment:
    PORT: 45878
    KEY: 'YOUR_PUBLIC_KEY_FROM_HUB'
  deploy:
    mode: replicated
    replicas: 1
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.beszel-agent2.loadbalancer.server.port=45878"
    placement:
      constraints:
        - node.hostname == swarmpi3  # Only deploy on node 'swarmpi3'

Each agent service can then monitor the node on which it is running, allowing you to collect and consolidate metrics across your entire cluster.

Troubbleshooting

If you have Problems with this Quicksetup Guide or its just not running, go visit my Troubbleshooting-Section.

Advanced Configurations

Advanced Configurations

Enviroment Variables

GitHub-logo.png Docker-logo.png

Beszel Homepage

Beszel Environment Variables

Below is a comprehensive list of environment variables for both the Beszel Hub and the Agent. These variables control functionality such as content security policies, OAuth/OIDC behavior, filesystem monitoring, and more. For additional details, refer to the official Beszel Environment Variables Guide.


Hub

Name Default Description
CSP unset Adds a Content-Security-Policy header with this value.
DISABLE_PASSWORD_AUTH false Disables password authentication.
USER_CREATION false Enables automatic user creation for OAuth2 / OIDC.

Agent

Name Default Description
DOCKER_HOST unset Overrides the docker host (docker.sock) if using a proxy. Relevant when using linuxserver/docker-socket-proxy or similar.
EXTRA_FILESYSTEMS unset Monitor extra disks if using the binary agent. See Additional Disks .
FILESYSTEM unset Device, partition, or mount point to use for root disk stats.
KEY unset Public SSH key to use for authentication (provided by the Hub).
LOG_LEVEL info Logging level. Valid values:
Advanced Configurations

GPU Monitoring

GitHub-logo.png Docker-logo.png

Beszel Homepage

GPU Monitoring

Beszel can monitor GPU usage, temperature, and power draw for select devices. This feature is currently only available in the binary agent, not in the Docker agent.


Binary Agent Only

The Docker agent does not support GPU monitoring. You must use the binary agent if you need GPU metrics. For installation and usage details, refer to the official Beszel documentation on installing the binary agent.


AMD GPUs

Beszel uses rocm-smi to monitor AMD GPUs. Ensure rocm-smi is installed on the system running the agent.


Nvidia GPUs

Beszel uses nvidia-smi to monitor Nvidia GPUs. This must be installed on the system.


Intel GPUs

Intel GPUs are not currently supported due to:

  1. No test hardware is available to the developer.
  2. There is no straightforward utility akin to nvidia-smi for real-time Intel GPU metrics (utilization, memory usage).

Please see issue #262 for more information or to track progress on Intel GPU support.

Advanced Configurations

User Accounts

GitHub-logo.png Docker-logo.png

Beszel Homepage

 

User Accounts

This section covers the various user roles in Beszel, their permissions, and how to reset or change passwords. Note that Beszel user roles operate on top of a PocketBase back-end, and some features (like superuser creation) are handled through PocketBase directly.


User Roles

Beszel defines three main user roles:

Important: PocketBase superusers are separate from Beszel user roles. Promoting a Beszel user to Admin role does not create a PocketBase superuser account. If you want them to have access to the PocketBase admin panel (/_/#/ in the browser), you must create a new superuser for them manually via the PocketBase CLI or the Beszel superuser command.


Reset Password

To reset your password, you can use the built-in superuser command in Beszel. The upsert subcommand will reset the password if a superuser already exists for the specified email, or it will create a new superuser if one does not exist.

Once you have a PocketBase superuser account, you can change any user's password via the PocketBase admin interface under the users table.

Docker

docker exec beszel /beszel superuser upsert name@example.com password

This command will reset (or create) a PocketBase superuser with the specified email (name@example.com) and password (password).

To see all superuser options:

docker exec beszel /beszel superuser --help

Binary

./beszel superuser upsert name@example.com password

And to list all superuser options:

./beszel superuser --help

Troubbleshooting

Troubbleshooting

Most common Problems

GitHub-logo.png logo.png

Beszel Logo

 

Beszel Troubleshooting Guide

Below are common issues that you may encounter when setting up or running Beszel, along with suggested steps to diagnose and resolve them. Refer to the official Common Issues guide on the Beszel website for additional details.

First of all set your Agent/s to LogMode "debug" if you havent already.


Agent is not connecting

First, check the logs page in PocketBase at /_/#/logs to see if there's an identifiable error. The most common cause is a firewall blocking the connection request. You have two options to resolve this:

Another possibility is that you forgot to expose the container ports in your Docker configuration. Make sure the port is mapped and accessible.

To test connectivity, run:

telnet <agent-ip> <port>

If the connection is refused or times out, it indicates a networking or firewall problem.


Connecting hub and agent on the same system using Docker

If the hub runs in a normal bridged network mode, but the agent is using host network mode, add the system using host.docker.internal as the hostname, which resolves to the special IP used by the host system. (See the Getting Started guide for a complete docker-compose.yml example.)


Finding the correct filesystem

By default, the agent tries to detect and monitor the root filesystem for disk stats. In a container, this may not work reliably, so it’s recommended to specify the filesystem via the FILESYSTEM environment variable. To locate the correct filesystem:


Docker container charts are empty or missing

If the container charts in Beszel are empty or don’t appear, you may need to enable cgroup memory accounting. To verify this, run docker stats. If you see zero memory usage, follow the guide here:

Enabling memory stats in Docker

This issue is common on certain Raspberry Pi or other ARM-based systems, but can also affect other environments where cgroup memory accounting is disabled by default.


Docker containers are not populating reliably

Upgrade to the latest Docker version if possible. There is a known bug in Docker 24 (and possibly earlier versions) that affects container stats. Although the agent includes a workaround, it may not completely resolve the issue.


Month / week records are not populating reliably

Beszel aggregates longer time periods (week/month) from shorter interval data. The agent must run uninterrupted for the entire interval to properly generate these records. If you pause/unpause the agent for more than a minute, you’ll lose continuity for that interval, causing incomplete data.