How to Install Heimdall Application Dashboard on Ubuntu 24.04 VPS
If you self-host a growing collection of services — Portainer, Sonarr, Radarr, Nextcloud, Grafana, a few internal tools — you quickly end up juggling a bookmarks folder full of http://192.168.x.x:port entries. A home dashboard solves that. Heimdall is one of the original, most recognisable names in the space: a clean PHP application that turns a single page into an organised grid of tiles for every service you run, with live stats pulled straight from supported apps.
This guide walks you through installing Heimdall on an Ubuntu 24.04 VPS using the official linuxserver/heimdall Docker image, wiring it up behind Nginx with TLS, and tuning it for day-to-day use. By the end, you will have a personal application launcher available at your own domain, ready to become the one browser tab you never close.
Looking for a lightweight VPS to host it? A small CloudCore Starter is more than enough for Heimdall plus a handful of companion services.
Table of Contents
What is Heimdall?
Heimdall is a self-hosted application dashboard, originally written by linuxserver.io developer Ryan as a Laravel (PHP) project. Its job is deliberately narrow: present a single, attractive home page listing all the services you run, with clickable tiles that open each app. Where it stands out from a plain bookmarks page is the concept of enhanced application types — for a growing list of popular self-hosted apps (Sonarr, Radarr, Lidarr, Bazarr, SABnzbd, NZBGet, Deluge, qBittorrent, Pi-hole, Portainer, Nextcloud, Plex, Jellyfin, Emby, UniFi, Proxmox, and many more), Heimdall can authenticate against the app's API and show live stats directly on the tile: queue sizes, download speeds, blocked DNS queries, server counts, and so on.
Under the hood Heimdall uses SQLite (a single app.sqlite file) for its configuration, stores backgrounds and app icons in the /config volume, and is shipped almost universally via the maintained linuxserver/docker-heimdall image. That image handles PHP-FPM, Nginx (internally), permissions via PUID/PGID, and automatic migrations on upgrade — all you need to supply is a persistent volume and a port.
A word of honesty: upstream Heimdall development has been paused for a while. The linuxserver.io team still publishes regular image rebuilds (security patches, base image refreshes), but new features from the original author have slowed significantly. That does not make Heimdall a bad choice — it means Heimdall today is what Heimdall will largely look like tomorrow. For many users that stability is a feature, not a bug. If you want an actively evolving dashboard, see the comparison section below.
Why Use Heimdall in 2026?
Despite newer alternatives, Heimdall continues to sit on the dashboard of tens of thousands of homelabs for good reasons:
- Battle-tested and boring in the best way — The core has barely changed in years, which means no surprise breaking upgrades and excellent documentation from years of community troubleshooting.
- Beautiful out of the box — The default dark theme and bundled background images look polished without any customisation.
- Live stats integration — Unlike pure bookmark dashboards, Heimdall speaks the APIs of many popular self-hosted apps and surfaces useful information (queue counts, download rates, container counts) directly on the tile.
- Per-user dashboards — Heimdall supports multiple users, each with their own tile layout, backgrounds, and search provider, controlled with a simple per-user PIN.
- Tiny resource footprint — The container uses roughly 50-100 MB of RAM and negligible CPU. It happily runs on a 2 GB VPS alongside other services.
- One image, one volume, one port — The LinuxServer image is the gold standard of "just works" containers. The entire state of your dashboard lives in a single
/configdirectory you can snapshot and restore.
Prerequisites
Before you begin, make sure you have:
- A VPS running Ubuntu 24.04 LTS with root or sudo access
- SSH access to your server
- A domain name (optional but strongly recommended) pointed at your VPS via an A record — for example,
dash.yourdomain.com - At least 1 GB of RAM free (Heimdall itself uses very little; this leaves room for the reverse proxy and OS)
- Docker and Docker Compose installed — covered in Step 2, or read our full How to Install Docker on Ubuntu 24.04 guide if you want a deeper walkthrough
Recommended Plan: CloudCore Starter>
Heimdall is a textbook lightweight service. Our CloudCore Starter plan is the sweet spot:>
- 2 vCPU cores
- 4 GB RAM
- 50 GB NVMe SSD
- Unmetered bandwidth>
You will have plenty of headroom to add Portainer, Uptime Kuma, and a handful of other small services on the same host.
Connect to your server via SSH:
ssh root@your-server-ipStep 1: Update System Packages
Start clean by refreshing the package index and upgrading installed packages:
sudo apt update && sudo apt upgrade -yIf the kernel was updated, reboot:
sudo rebootReconnect via SSH after a minute.
Step 2: Install Docker and Docker Compose
Heimdall is distributed as a container. If Docker is not already installed on your VPS, install the official Docker CE packages along with the Compose plugin:
sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpgecho \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu noble stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Verify:
docker --version
docker compose versionExpected output:
Docker version 27.x.x, build ...
Docker Compose version v2.x.xFor a more thorough setup (non-root user, log rotation, Docker networks), follow our Install Docker on Ubuntu 24.04 and Install Docker Compose guides.
Step 3: Create the Heimdall Directory
Create a tidy directory to hold the Compose file and Heimdall's persistent configuration:
sudo mkdir -p /opt/heimdall/config
cd /opt/heimdallThe config subdirectory is where Heimdall will write its SQLite database, uploaded icons, background images, and settings. Everything that makes your dashboard yours lives inside /opt/heimdall/config — remember this directory; it is all you need to back up.
Step 4: Write the docker-compose.yml File
Create the Compose file:
sudo nano /opt/heimdall/docker-compose.ymlPaste the following:
services:
heimdall:
image: lscr.io/linuxserver/heimdall:latest
container_name: heimdall
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Berlin
volumes:
- ./config:/config
ports:
- "8080:80"
- "8443:443"
restart: unless-stoppedA few notes:
PUID/PGID— These match the Unix user/group the container will use to read and write the./configvolume.1000:1000matches the default first non-root user created on Ubuntu. Check withid -uandid -g. Getting this wrong is the single most common source of permission errors — see Troubleshooting.TZ— Set to your timezone (e.g.Europe/Berlin,America/New_York,Asia/Jerusalem). This only affects log timestamps inside the container.- Ports
8080and8443— We map container ports80and443to8080/8443on the host, leaving the standard ports free for an Nginx reverse proxy in Step 9. If you do not plan to use a reverse proxy, change these to80:80and443:443. restart: unless-stopped— Ensures Heimdall comes back up after a reboot unless you explicitly stop it.
Ctrl+O, Enter, then Ctrl+X.Step 5: Start the Heimdall Container
From /opt/heimdall:
sudo docker compose up -dExpected output:
[+] Running 2/2
✔ Network heimdall_default Created
✔ Container heimdall StartedConfirm the container is healthy:
sudo docker compose psExpected output:
NAME IMAGE STATUS PORTS
heimdall lscr.io/linuxserver/heimdall:latest Up 15 seconds 0.0.0.0:8080->80/tcp, 0.0.0.0:8443->443/tcpTail the logs for a few seconds to make sure nothing is failing:
sudo docker compose logs -f heimdallYou should see the LinuxServer banner, permission setup, and finally [ls.io-init] done. followed by Nginx and PHP-FPM starting. Press Ctrl+C to exit the log stream.
Open http://your-server-ip:8080 in a browser — you should see the Heimdall landing page with a search bar and a dark default background. If so, the install is working.
Step 6: Complete the First-Run Wizard
Heimdall's first-run experience is minimal by design. On first load:
Heimdall does not force a login to view the dashboard by default (that is a deliberate design choice — the typical use case is a home page in your browser's new tab), but the admin account is required to add or edit tiles. You can enforce login for all users in Settings → System → Allow Registration and Require Login.
Step 7: Add Applications and Tiles
The real value of Heimdall is the application tile. To add your first one:
Sonarr. If the app is on Heimdall's list, selecting it will reveal extra fields: API URL, API Key, and so on. Filling these in enables live stats on the tile (episode queue, upcoming count, disk space, etc.).Sonarr).http://192.168.1.50:8989.Click Save. Back on the main screen, the new tile appears. For enhanced app types, within 30 seconds the tile should start displaying live stats pulled from the app's API.
Supported "Enhanced" Apps
The current enhanced list (apps with live-stats integration) includes: Sonarr, Radarr, Lidarr, Readarr, Bazarr, SABnzbd, NZBGet, Deluge, Transmission, qBittorrent, ruTorrent, Pi-hole (v5 and v6), AdGuard Home, Portainer, Nextcloud, Plex, Jellyfin, Emby, UniFi, Proxmox, OPNsense, pfSense, Uptime Kuma, Scrutiny, and a long tail of others. The full list lives in the Application Type dropdown.
For anything not on the list, choose None as the type — you still get a beautiful tile, just without live stats.
Organising Tiles with Tags
Once you have more than a dozen applications, flat lists become noisy. Use Tags:
Media, Admin, Monitoring.This is essential for heavy homelabs — a well-tagged Heimdall keeps the main view clean while still giving you one-click access to everything.
Step 8: Customise Backgrounds, Themes, and Search
Heimdall's look-and-feel options live under Settings.
Background Images
Under Settings → Background Image, upload one or more JPG/PNG files. Heimdall rotates between them on each page load when multiple are present. The /config/www/backgrounds directory is where they end up — you can drop files there directly if you prefer:
sudo cp my-wallpaper.jpg /opt/heimdall/config/www/backgrounds/
sudo chown 1000:1000 /opt/heimdall/config/www/backgrounds/my-wallpaper.jpgThemes
The bundled themes are limited (Dark, Light, Grey). Most users stick with Dark. Under Settings → Appearance, you can tweak:
- Tile opacity — Lower values let the background image show through.
- Window target —
_self,_blank, orframed(open apps in Heimdall's iframe layout). - Homepage search — Which search engine the central search bar uses.
Search Providers
Heimdall supports multiple search providers with shortcut keywords. Add them under Settings → SearchProviders:
- Name —
DuckDuckGo - URL —
https://duckduckgo.com/?q= - Tiles — Tiles this provider is associated with (leave blank for global).
g: keyword or ddg: keyword in the main search bar then routes to the relevant provider. Handy if you want the dashboard to double as your browser homepage.Users
Settings → Users → Add User creates a second user with their own dashboard view, wallpaper, and search provider. Users are switched with the four-digit PIN set at creation — useful for shared households (one view for work apps, one for media apps).
Step 9: Put Heimdall Behind an Nginx Reverse Proxy with TLS
Exposing port 8080 directly is fine for a private network but unsuitable for the public internet. For a proper deployment, put Heimdall behind Nginx on ports 80/443 with a real TLS certificate from Let's Encrypt. If you are not yet familiar with Nginx, our How to Install Nginx on Ubuntu 24.04 guide covers the basics.
Install Nginx and Certbot:
sudo apt install -y nginx certbot python3-certbot-nginxCreate the site config:
sudo nano /etc/nginx/sites-available/heimdallPaste:
server { listen 80; server_name dash.yourdomain.com;# Certbot will inject the TLS config below.
location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; 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; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
# Heimdall uploads (icons, backgrounds) can be a few MB. client_max_body_size 20m; } }
Replace dash.yourdomain.com with your domain. Enable the site and test the config:
sudo ln -s /etc/nginx/sites-available/heimdall /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxIssue a certificate with Certbot:
sudo certbot --nginx -d dash.yourdomain.comCertbot auto-edits your config to add the listen 443 ssl server block and a redirect from HTTP. Reload Nginx and browse to https://dash.yourdomain.com — you should see Heimdall over TLS.
Firewall
If you use UFW:
sudo ufw allow 'Nginx Full'
sudo ufw deny 8080
sudo ufw deny 8443
sudo ufw enableDenying 8080/8443 stops anyone from bypassing Nginx and hitting Heimdall directly.
Step 10: Back Up the /config Directory
Heimdall has no database server, no external state, and no secrets outside /opt/heimdall/config. Backups are therefore exceptionally simple:
sudo tar -czf heimdall-backup-$(date +%F).tar.gz -C /opt/heimdall configCopy the resulting .tar.gz to off-server storage (rsync to another VPS, upload to S3/Backblaze B2, pull via a backup tool like Restic or BorgBackup). To restore on a new host, install Docker, recreate /opt/heimdall/docker-compose.yml, extract the tarball into /opt/heimdall/, and run docker compose up -d. That is the entire disaster recovery plan.
Automate with Cron
sudo crontab -eAdd:
0 3 tar -czf /root/backups/heimdall-$(date +\%F).tar.gz -C /opt/heimdall config && find /root/backups -name 'heimdall-.tar.gz' -mtime +14 -deleteThis runs a nightly backup at 03:00 and prunes anything older than 14 days.
Upgrading Heimdall
LinuxServer publishes new image builds regularly. To upgrade:
cd /opt/heimdall
sudo docker compose pull
sudo docker compose up -dThe container is recreated with the new image, the /config volume is preserved, and any required SQLite migrations run automatically on first start. Take a fresh backup of /config immediately before pulling, just in case. Downgrading is as simple as pinning the image tag (e.g. lscr.io/linuxserver/heimdall:2.5.7) and running docker compose up -d.
Subscribe to the linuxserver/docker-heimdall releases feed if you want to know exactly what changed between rebuilds.
Heimdall vs Homepage, Homarr, and Dashy
Heimdall is no longer the only self-hosted dashboard in town. A quick honest comparison:
| Feature | Heimdall | Homepage | Homarr | Dashy |
|---|---|---|---|---|
| Active development | Paused (LSIO rebuilds) | Very active | Active | Active |
| Config style | GUI (click to add tiles) | YAML files | GUI | YAML files |
| Live app integrations | ~40 apps | 100+ apps | 30+ apps | Status checks only |
| Themes/customisation | Limited | Good | Excellent | Excellent |
| Multi-user | Yes (PIN-based) | No | Yes | Single-user |
| Resource usage | Very low (50-100 MB RAM) | Low | Moderate (~300 MB) | Low |
| Mobile-friendly | Decent | Excellent | Excellent | Excellent |
| Learning curve | Very low | Moderate (YAML) | Low | Moderate (YAML) |
Pick Homepage if you are comfortable editing YAML and want the broadest list of live integrations (Unraid, TrueNAS, Kubernetes, Proxmox with deep stats, etc.) with ongoing development.
Pick Homarr if you want a dashboard that doubles as a mini app launcher with widgets, drag-and-drop configuration, and a very modern UI.
Pick Dashy if you prefer fully version-controlled YAML configuration and a focus on status-checking dozens of services.
All four are excellent. Heimdall's niche in 2026 is "mature, calm, fire-and-forget." If that matches what you want, it remains a fantastic choice.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
Permission denied errors on /config/www/app.sqlite | PUID/PGID in Compose file do not match ownership of /opt/heimdall/config on the host | Run id -u and id -g for your host user, update the Compose file, then sudo chown -R 1000:1000 /opt/heimdall/config and docker compose up -d. |
database is locked on page load | SQLite database file is read-only or on a filesystem without proper locking (NFS, SMB) | Move /opt/heimdall/config to a local disk. Fix permissions: sudo chown -R 1000:1000 /opt/heimdall/config && sudo chmod 664 /opt/heimdall/config/www/app.sqlite. |
| 502 Bad Gateway from Nginx | Nginx is running before the container is ready, or container crashed | Check docker compose ps — container should be Up. Check docker compose logs heimdall for PHP-FPM errors. Reload Nginx: sudo systemctl reload nginx. |
| Tile shows "Could not connect" for an enhanced app | Heimdall cannot reach the app's API from inside the container | Use the container-routable hostname (e.g. the host's IP, not localhost). For apps on the same Docker network, use the container name. Check firewalls between Heimdall and the target. |
| Uploaded icon/background does not appear | File ownership mismatch | sudo chown -R 1000:1000 /opt/heimdall/config/www and reload the page. |
| Cannot log in / forgot admin password | Admin accounts cannot currently self-reset | Exec into the container and reset via Laravel's tinker: docker exec -it heimdall php /app/www/artisan tinker, then User::first()->update(['password' => Hash::make('newpass')]); |
| Changes do not persist after container restart | The ./config volume is not mounted correctly, Heimdall is writing to the ephemeral container filesystem | Re-check the volumes: section of docker-compose.yml. Run docker inspect heimdall and look for the Mounts entry pointing at /opt/heimdall/config. |
| Very slow page loads | Usually an enhanced-app tile with a broken/timing-out API URL | Open each enhanced tile's settings and verify its API URL responds fast. Remove or disable any tile whose backend is unreachable. |
Viewing Logs
Heimdall's container logs combine Nginx, PHP-FPM, and the LinuxServer init scripts:
sudo docker compose logs -f heimdallFor just the last 100 lines:
sudo docker compose logs --tail=100 heimdallFAQ
Is Heimdall still maintained in 2026?
Upstream feature development by the original author has been paused for some time. However, the linuxserver/docker-heimdall image is still rebuilt and published regularly with base-image security patches. For a dashboard that mostly sits there working, that is often enough. If you need new features or integrations regularly, consider Homepage or Homarr.
Can I run Heimdall without Docker?
Technically yes — it is a Laravel app and can be deployed on any PHP 8 + Nginx/Apache stack. In practice almost nobody does, because the LinuxServer Docker image handles PHP, extensions, migrations, and permissions perfectly. Stick with Docker unless you have a very specific reason not to.
Does Heimdall support authentication for the dashboard itself?
Yes. Heimdall supports multiple users, each with a four-digit PIN, and you can force login for all visitors under Settings → System. For stronger protection (especially on the public internet), add an Nginx auth_basic block or put Heimdall behind an SSO proxy like Authelia or Authentik. Never expose Heimdall to the internet without some form of authentication, because the app tiles frequently contain links to sensitive internal services.
Can Heimdall replace a bookmark manager?
For self-hosted services — yes, comfortably. For general web browsing bookmarks (news sites, forums, shopping), a bookmark manager like Linkwarden or Hoarder is a better fit. Heimdall's tiles are chunky and designed for "apps you use every day," not "the 500 articles I want to read later."
How much RAM does Heimdall actually use?
In normal operation, the container hovers around 50-100 MB of resident memory and near-zero CPU. Even on a 1 GB VPS you will barely notice it running. Adding many enhanced app tiles that poll APIs increases CPU slightly but is still negligible.
Can I theme Heimdall beyond the bundled themes?
Options are limited — the built-in themes, tile opacity, and your own background images cover most customisation. For pixel-perfect control you can inject custom CSS via /config/www/custom-css, but this is unofficial territory and may break across upgrades. If heavy theming matters to you, Homarr is a much better pick.
Next Steps
Now that Heimdall is running on your VPS, here are natural follow-up projects:
- Add Portainer to manage your containers — Pair Heimdall with Portainer for a full browser-based Docker admin experience, then add the Portainer tile to your dashboard.
- Monitor your stack with Uptime Kuma — Deploy Uptime Kuma to track the health of every service Heimdall links to, and pin the Uptime Kuma status page as a tile.
- Try Homepage side by side — Spin up Homepage on the same VPS (different port) for a week and see which dashboard feels right long-term.
- Harden the server — Walk through our How to Install Fail2ban on Ubuntu and CrowdSec guides to protect the Nginx front door.
- Read the source — The linuxserver/docker-heimdall GitHub repo documents every environment variable and mount, and the upstream project page at heimdall.site has the full list of supported enhanced apps.
Skip the Manual Setup — Launch a Ready-to-Host VPS>
Our CloudCore Starter plan gives you a fresh Ubuntu 24.04 VPS with root access, unmetered bandwidth, and enough resources to comfortably run Heimdall alongside Portainer, Uptime Kuma, and your favourite self-hosted apps — all on one box.>
- 2 vCPU, 4 GB RAM, 50 GB NVMe SSD
- Full root access, Docker-ready
- Deploy in under 60 seconds>
Launch Your CloudCore Starter VPS and turn your bookmarks folder into a real dashboard today.