> ## Documentation Index
> Fetch the complete documentation index at: https://docs.digitalfyre.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Install Beszel

[Beszel](https://beszel.dev) 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](/guides/scripts/docker-install)
* 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:

```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
mkdir -p /opt/beszel && cd /opt/beszel
```

```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
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:

```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
docker compose up -d
```

The hub is now running on `127.0.0.1:8090`.

## Step 2: Install Nginx

<Tabs>
  <Tab title="Debian / Ubuntu" value="debian">
    ```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
    apt update && apt install -y nginx
    systemctl enable nginx
    ```
  </Tab>

  <Tab title="RHEL / AlmaLinux / Rocky" value="rhel">
    ```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
    dnf install -y nginx
    systemctl enable nginx
    systemctl start nginx
    ```
  </Tab>
</Tabs>

## Step 3: Configure Nginx Reverse Proxy

Replace `monitor.example.com` with your actual domain:

```bash expandable lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
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:

```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
ln -sf /etc/nginx/sites-available/beszel /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl reload nginx
```

<Card title="RHEL-Based Systems" type="warning" horizontal>
  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.
</Card>

## Step 4: Install SSL with Certbot

<Tabs>
  <Tab title="Debian / Ubuntu" value="debian-cert">
    ```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
    apt install -y certbot python3-certbot-nginx
    ```
  </Tab>

  <Tab title="RHEL / AlmaLinux / Rocky" value="rhel-cert">
    ```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
    dnf install -y epel-release
    dnf install -y certbot python3-certbot-nginx
    ```
  </Tab>
</Tabs>

Obtain and install the certificate:

```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
certbot --nginx -d monitor.example.com
```

Verify automatic renewal:

```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
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:

<Tabs>
  <Tab title="Linux (any distro)" value="agent-linux">
    ```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
    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`)
  </Tab>

  <Tab title="Docker" value="agent-docker">
    ```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
    docker run -d \
      --name beszel-agent \
      --restart unless-stopped \
      --network host \
      -v /var/run/docker.sock:/var/run/docker.sock:ro \
      -e PORT=45876 \
      -e KEY="PASTE_HUB_PUBLIC_KEY_HERE" \
      henrygd/beszel-agent:latest
    ```
  </Tab>
</Tabs>

### Open the Agent Port

On the monitored server, allow the agent port in the firewall:

<Tabs>
  <Tab title="UFW" value="ufw-agent">
    ```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
    # Allow only the hub server to reach the agent
    ufw allow from HUB_SERVER_IP to any port 45876/tcp comment "Beszel Agent"
    ```
  </Tab>

  <Tab title="firewalld" value="firewalld-agent">
    ```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
    firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=HUB_SERVER_IP port port=45876 protocol=tcp accept'
    firewall-cmd --reload
    ```
  </Tab>
</Tabs>

<Tip>
  Restrict agent access to the hub server's IP only. There is no reason for other hosts to reach the agent port.
</Tip>

## Updating

### Hub

```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
cd /opt/beszel
docker compose pull
docker compose up -d
```

### Agent (systemd)

```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
curl -sL https://raw.githubusercontent.com/henrygd/beszel/main/supplemental/scripts/install-agent.sh | bash
```

### Agent (Docker)

```bash lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
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:

```bash install-beszel.sh expandable lines theme={"theme":{"light":"light-plus","dark":"ayu-dark"}}
#!/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/_/"
```
