Skip to main content
Beszel is a lightweight server monitoring hub with a web UI, historical data, Docker container stats, and alerting. It consists of a hub (central dashboard) and agents (installed on each monitored server). This guide deploys the hub with Docker, an Nginx reverse proxy, and a Let’s Encrypt SSL certificate, then covers agent installation.

Prerequisites

  • Docker and Docker Compose installed on the hub server — see Install Docker
  • A domain or subdomain pointed to the hub server (e.g., monitor.example.com)
  • Ports 80 and 443 are open in your firewall

Step 1: Deploy the Beszel Hub

Create a directory and Docker Compose file:
mkdir -p /opt/beszel && cd /opt/beszel
cat > docker-compose.yml << 'EOF'
services:
  beszel:
    image: henrygd/beszel:latest
    container_name: beszel
    restart: unless-stopped
    volumes:
      - ./data:/beszel_data
    ports:
      - "127.0.0.1:8090:8090"
EOF
Start the container:
docker compose up -d
The hub is now running on 127.0.0.1:8090.

Step 2: Install Nginx

apt update && apt install -y nginx
systemctl enable nginx

Step 3: Configure Nginx Reverse Proxy

Replace monitor.example.com with your actual domain:
cat > /etc/nginx/sites-available/beszel << 'CONF'
server {
    listen 80;
    listen [::]:80;
    server_name monitor.example.com;

    location / {
        proxy_pass http://127.0.0.1:8090;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
CONF
Enable the site and reload Nginx:
ln -sf /etc/nginx/sites-available/beszel /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl reload nginx

RHEL-Based Systems

RHEL, AlmaLinux, and Rocky do not use sites-available/sites-enabled by default. Place the configuration in /etc/nginx/conf.d/beszel.conf Instead, skip the symlink step.

Step 4: Install SSL with Certbot

apt install -y certbot python3-certbot-nginx
Obtain and install the certificate:
certbot --nginx -d monitor.example.com
Verify automatic renewal:
certbot renew --dry-run

Step 5: Access the Hub

Open https://monitor.example.com in your browser. On first visit, create your admin account at the /_/ admin path.

Installing the Agent

The Beszel agent runs on each server you want to monitor and reports back to the hub. It does not require Docker.

Add a System in the Hub

  1. Log in to the Beszel hub
  2. Click Add System
  3. Enter a name and the server’s IP/hostname
  4. The hub will generate a public key — copy it

Install the Agent

On the server you want to monitor, run:
curl -sL https://raw.githubusercontent.com/henrygd/beszel/main/supplemental/scripts/install-agent.sh -o install-agent.sh
chmod +x install-agent.sh
./install-agent.sh
The installer will prompt for:
  • The hub’s public key (paste the key from Step 1)
  • The port for the agent to listen on (default: 45876)

Open the Agent Port

On the monitored server, allow the agent port in the firewall:
# Allow only the hub server to reach the agent
ufw allow from HUB_SERVER_IP to any port 45876/tcp comment "Beszel Agent"
Restrict agent access to the hub server’s IP only. There is no reason for other hosts to reach the agent port.

Updating

Hub

cd /opt/beszel
docker compose pull
docker compose up -d

Agent (systemd)

curl -sL https://raw.githubusercontent.com/henrygd/beszel/main/supplemental/scripts/install-agent.sh | bash

Agent (Docker)

docker pull henrygd/beszel-agent:latest
docker stop beszel-agent && docker rm beszel-agent
# Re-run the docker run command from the installation step

All-in-One Hub Script

Edit the DOMAIN variable before running:
install-beszel.sh
#!/bin/bash
set -euo pipefail

# --- Configuration ---
DOMAIN="monitor.example.com"
# ---------------------

echo "=== Beszel Hub Setup ==="

. /etc/os-release
DISTRO="$ID"

if ! command -v docker &>/dev/null; then
    echo "Docker is not installed. Run the Docker install script first."
    exit 1
fi

# Deploy Beszel
echo "--- Deploying Beszel ---"
mkdir -p /opt/beszel && cd /opt/beszel
cat > docker-compose.yml << 'EOF'
services:
  beszel:
    image: henrygd/beszel:latest
    container_name: beszel
    restart: unless-stopped
    volumes:
      - ./data:/beszel_data
    ports:
      - "127.0.0.1:8090:8090"
EOF
docker compose up -d

# Install Nginx
echo "--- Installing Nginx ---"
case "$DISTRO" in
    debian|ubuntu)
        apt update -qq
        apt install -y nginx certbot python3-certbot-nginx
        ;;
    almalinux|rocky|centos|rhel|cloudlinux|fedora)
        dnf install -y nginx epel-release
        dnf install -y certbot python3-certbot-nginx
        systemctl start nginx
        ;;
esac
systemctl enable nginx

# Configure Nginx
echo "--- Configuring Nginx ---"
case "$DISTRO" in
    debian|ubuntu)
        NGINX_CONF="/etc/nginx/sites-available/beszel"
        cat > "$NGINX_CONF" << CONF
server {
    listen 80;
    listen [::]:80;
    server_name $DOMAIN;

    location / {
        proxy_pass http://127.0.0.1:8090;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
    }
}
CONF
        ln -sf "$NGINX_CONF" /etc/nginx/sites-enabled/
        rm -f /etc/nginx/sites-enabled/default
        ;;
    almalinux|rocky|centos|rhel|cloudlinux|fedora)
        cat > /etc/nginx/conf.d/beszel.conf << CONF
server {
    listen 80;
    listen [::]:80;
    server_name $DOMAIN;

    location / {
        proxy_pass http://127.0.0.1:8090;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
    }
}
CONF
        ;;
esac

nginx -t && systemctl reload nginx

# SSL
echo "--- Obtaining SSL Certificate ---"
certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos --register-unsafely-without-email --redirect

echo ""
echo "=== Setup Complete ==="
echo "Access Beszel at: https://$DOMAIN"
echo "Create your admin account at: https://$DOMAIN/_/"