Install Beszel for Lightweight Server Monitoring With Docker Compose

Run Beszel when you want quick visibility into server health without committing to a full Prometheus stack, then keep the first deployment honest about the difference between the hub and the agent.

Beszel Docker Compose Monitoring
Illustrated guide cover for Install Beszel for Lightweight Server Monitoring With Docker Compose
Beszel • Docker Compose • Monitoring
What you learn

How to run the Beszel hub locally, register the first monitored machine, and add the agent without mixing up the install paths.

Best for

Small operators who want CPU, memory, disk, and container visibility with less setup weight than a traditional metrics stack.

Risk to watch

The most common early mistake is copying hub steps onto a remote node or pasting the wrong socket and key values into the agent config.

Before you begin

  • A Docker host with Compose v2.
  • A private admin path or reverse proxy plan for the Beszel hub UI.
  • One monitored machine to start with. It can be the same machine as the hub for a first test.
  • A decision to keep the first rollout simple instead of trying to cover every remote host on day one.

Beszel separates the monitoring UI and data store into the hub, then runs a small agent on each monitored machine. The current upstream docs still present those as separate installation paths. Treating them as different roles keeps the first setup much less confusing.

Expected outcome: you will finish with the Beszel hub running privately, one registered system reporting metrics, and a clean path for adding more agents later.

Step 1: Deploy the Beszel hub

Create the stack directory and save this as compose.yaml:

mkdir -p /opt/stacks/beszel
cd /opt/stacks/beszel
services:
  beszel:
    image: henrygd/beszel:latest
    container_name: beszel
    restart: unless-stopped
    environment:
      APP_URL: http://localhost:8090
    ports:
      - 127.0.0.1:8090:8090
    volumes:
      - ./beszel_data:/beszel_data
      - ./beszel_socket:/beszel_socket

  beszel-agent:
    image: henrygd/beszel-agent:latest
    container_name: beszel-agent
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./beszel_agent_data:/var/lib/beszel-agent
      - ./beszel_socket:/beszel_socket
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      LISTEN: /beszel_socket/beszel.sock
      HUB_URL: http://localhost:8090
      TOKEN: paste-a-token-from-settings-tokens
      KEY: paste-the-public-key-from-add-system

    

Binding the hub to 127.0.0.1 keeps the dashboard private by default. The agent uses host networking because that is the current upstream-recommended path for full host metrics, and the unix socket keeps the local agent-to-hub connection cleaner than trying to force localhost across container boundaries.

Start the hub:

docker compose up -d
docker compose ps
docker compose logs --tail 50 beszel

Step 2: Complete first-login setup

Reach the hub through SSH port forwarding or your private reverse proxy, then finish the first-login flow in the browser. Beszel's current docs still guide you through creating the initial admin account from the web UI.

After login, open Settings > Tokens and create a token for the agent. Then use Add System in the hub UI to get the public key for the monitored machine. Do not invent either value manually. Copy them from the UI so the registration key, token, and expected socket path stay in sync with the current Beszel flow.

Warning: the hub and the agent are not interchangeable. The hub stores the UI and data. The agent is what runs on each monitored machine and reports back.

Step 3: Add the first Beszel agent

For a simple same-host test, keep the bundled local-agent layout above and paste the exact token and public key values into the existing compose.yaml. Current Beszel docs recommend using the unix socket path when the hub and agent live on the same Docker host.

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

Back in the Beszel web UI, add the system and set Host / IP to /beszel_socket/beszel.sock. If you are monitoring a different machine, switch to Beszel's current remote-agent instructions instead of forcing the local-socket pattern onto a separate host.

Bring up the agent and watch the logs:

docker compose ps
docker compose logs -f beszel-agent

Step 4: Verify metrics and alerts

Back in the Beszel hub UI, confirm the system shows up as online and reports at least these basics:

  • CPU load and current utilization
  • Memory usage
  • Disk usage
  • Container status for the local Docker host

Set one low-stakes test alert, such as a high disk threshold, so you prove notification behavior before you depend on it during a real incident.

Step 5: Update and operate the stack

Routine checks:

docker compose ps
docker compose logs --tail 50 beszel
docker compose logs --tail 50 beszel-agent

When updating, change one layer at a time:

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

docker compose pull beszel-agent
docker compose up -d beszel-agent

Updating the hub and every agent in one blind wave is avoidable risk. Prove the hub still works, then move the agents.

Rollback notes

If an upgrade causes trouble, revert the image tag or restore the previous Compose file on the hub first. Because the hub stores the main data, protect the beszel_data volume before major changes.

For agent problems, it is usually safe to recreate the agent container after fixing the key, socket, or volume mapping because the agent does not hold the dashboard state itself.

Troubleshooting

The hub UI loads, but no systems appear online.
Check that the agent is using the registration key copied from the hub and that you did not mix local-socket instructions with a remote-host install.

The agent starts, then disconnects quickly.
Review the exact socket path, volume mappings, and whether the agent can read the Docker socket on that machine.

You can reach Beszel publicly without protection.
Change the bind address back to localhost or place it behind an authenticated private admin path immediately.

You want deep historical analytics across many hosts.
Beszel is intentionally lighter than a full metrics stack. That is a feature, not a bug. Move up to heavier tooling only if the lightweight path stops serving the job.

What to do next: continue with Monitor a VPS With Prometheus, Node Exporter, and Grafana if you later need deeper metrics retention, or Run Dozzle for Simple Docker Log Viewing for a complementary log-viewing surface.