Why Glance is a perfect fit for a VPS
What you get out of the box
- Built-in widgets: RSS feeds, Hacker News, Reddit, weather, bookmarks, world clock
- Live server metrics: CPU, RAM, disk, load average
- Docker container status (running / stopped / paused)
- Light/dark themes and custom colors via YAML
- No external dependencies: single static Go binary (~15 MB)
- Hot-reload configuration without restart
Glance vs alternatives: Heimdall, Homepage, Homarr
Self-hosted dashboard comparison
Scroll the table
| Tool | Language | Idle RAM | Config | Docker metrics | RSS/news widgets |
|---|---|---|---|---|---|
| **Glance** | Go | < 25 MB | Pure YAML | Yes (read-only) | Yes (native) |
| Homepage | Node/React | ~120 MB | YAML | Yes | Partial |
| Homarr | Node/React | ~150 MB | GUI + JSON | Yes | Via integration |
| Heimdall | PHP/Laravel | ~200 MB | GUI + MySQL | Not native | No |
Glance excels when lightness and speed matter more than a graphical configuration UI. For non-technical teams who prefer clicking over editing YAML, Homarr or Heimdall are valid alternatives.
Prerequisites
What you need before starting
- A ServOrbit VPS running Ubuntu 22.04 / Debian 12 (≥ 1 vCPU, 512 MB RAM is enough)
dockeranddocker composeinstalled (Docker Engine 24+, Compose v2)- SSH root or sudo access
- A subdomain pointed at your VPS (e.g.
glance.mydomain.tld) — optional but recommended for HTTPS
Deploy Glance on your ServOrbit VPS
Step-by-step installation
Create the working directory
SSH into your VPS and create the folder that will hold the Glance configuration:
mkdir -p /opt/glance && cd /opt/glanceWrite the `docker-compose.yml` file
Create the following file. The read-only mount of the Docker socket is mandatory (see Security section below):
services: glance: image: glanceapp/glance:latest restart: unless-stopped ports: - "8080:8080" volumes: - ./glance.yml:/app/glance.yml:ro - /var/run/docker.sock:/var/run/docker.sock:ro - /proc:/proc:ro environment: - TZ=UTCCreate the base configuration `glance.yml`
This YAML file defines your pages, columns and widgets:
server: port: 8080 pages: - name: Home columns: - size: small widgets: - type: clock hour-format: 24h - type: resource-usage - size: full widgets: - type: hacker-news - type: rss feeds: - url: https://blog.servOrbit.com/rss title: ServOrbit Blog - size: small widgets: - type: docker-containersStart the container
docker compose up -dCheck it's running:
docker compose ps— status should showUp.Open the firewall (if UFW is active)
ufw allow 8080/tcpOpen
http://<VPS-IP>:8080in your browser to confirm Glance responds.Set up an nginx reverse proxy with HTTPS
To serve Glance on
https://glance.mydomain.tld, create an nginx vhost:server { listen 443 ssl http2; server_name glance.mydomain.tld; ssl_certificate /etc/letsencrypt/live/glance.mydomain.tld/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/glance.mydomain.tld/privkey.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }Get the certificate via Certbot:
certbot --nginx -d glance.mydomain.tld.Enable HTTP basic authentication (recommended)
Glance has no built-in auth. Protect access via nginx:
htpasswd -c /etc/nginx/.htpasswd adminAdd to the
location /block in your vhost:auth_basic "Glance"; auth_basic_user_file /etc/nginx/.htpasswd;Reload nginx:
systemctl reload nginx.Verify system metrics
The
resource-usagewidget reads/proc— the:romount indocker-compose.ymlis therefore mandatory. If metrics don't appear, check:docker compose logs glance | grep -i proc.Reload config without restart
Any change to
glance.ymlis picked up by sendingSIGHUPto the container:docker kill --signal=SIGHUP glance_glance_1Alternatively:
docker compose restart glance(causes ~1 s of downtime).Enable automatic updates (optional)
Deploy [Watchtower](https://containrrr.dev/watchtower/) to keep the Glance image up to date automatically, or manage it manually:
docker compose pull && docker compose up -d
Advanced YAML configuration: widgets, themes and layout
Glance's power lies in its YAML file. Here are the most useful customizations.
Advanced configuration options
- Custom theme — add under
server::theme: { background-color: "240 21 15", primary-color: "217 92 83" }(HSL format withouthsl()) - Multiple pages — add as many
- name:blocks underpages:as you have contexts (e.g. "Dev", "Clients", "Personal") - Bookmarks widget —
type: bookmarkswith link groups to centralize quick access to internal tools - Monitor widget —
type: monitorwith a list of URLs: Glance performs HTTP checks and displays latency + status in real time - GitHub releases widget —
type: releaseswith a list of repos: ideal for tracking new versions of your tools - Refresh interval — each widget accepts
cache: 1h(or30m,5m) to control polling frequency
Security: the Docker socket in read-only mode
Mounting /var/run/docker.sock inside a container gives that container potentially full control over the host Docker daemon — equivalent to root. This is the most common privilege escalation vector in Docker environments.
Risks and mitigations
- Risk: a compromised container with
:rwsocket access can launch root containers, mount/, exfiltrate secrets - Mitigation 1 — Read-only mount: the
:roflag indocker-compose.ymlblocks all writes; Glance only needs to read container state - Mitigation 2 — Socket proxy: deploy [Docker Socket Proxy](https://github.com/Tecnativa/docker-socket-proxy) to expose only
GET /containersandGET /versionendpoints - Mitigation 3 — Network isolation: place Glance in a dedicated Docker network, isolated from your application services
- Verification:
docker inspect glance_glance_1 | grep -A5 Mounts— theModeline must showro, neverrw
If you don't need Docker metrics, simply remove the /var/run/docker.sock mount from docker-compose.yml and remove the docker-containers widget from glance.yml. Glance works perfectly without Docker daemon access.
Troubleshooting: common errors
Frequent issues and solutions
- Port 8080 already in use —
ss -tlnp | grep 8080to identify the process. Change the host port indocker-compose.yml:"8181:8080"(the container port stays 8080 on Glance's side). - Widget not loading / permanent spinner — check outbound network connectivity from the container:
docker exec glance_glance_1 curl -s https://news.ycombinator.com. If timeout, your VPS is behind a restrictive outbound firewall — open ports 80/443 outbound viaufw. - Docker socket refused (
permission denied) — the container runs under a non-root UID without access to thedockergroup. Fix: addgroup_add: ["docker"]or mount the socket with correct permissions. Check:ls -la /var/run/docker.sock(groupdocker, mode660). /procmetrics missing — the/proc:/proc:romount is missing fromdocker-compose.yml. Without it,resource-usageshows null values or an error. Add the volume and restart:docker compose up -d.
Real-world use cases for a web agency
An agency managing N client projects on separate VPSes can centralize monitoring in Glance with one page per client or environment.
How to structure Glance for an agency
- One page per client: each
pages[n]block corresponds to a project —monitorwidget with critical URLs (front, API, backoffice),docker-containerswidget if services run locally - "Global infra" page: the
monitorwidget can check healthcheck endpoints exposed on each machine (e.g./healthz) to aggregate multi-VPS status - Alert RSS feed: add the RSS feed from your monitoring tool (UptimeKuma, Gatus) to surface incidents without leaving Glance
- GitHub releases widget: track CMS/framework releases for your clients to anticipate critical updates
- Multi-team access: one Glance per environment (staging / prod), each protected by a separate HTTP auth via nginx, shareable by link with the relevant team
The official Glance documentation (github.com/glanceapp/glance) lists all available widgets and their options. The glance.yml reference section is the most up-to-date reference — options evolve with each minor release.