A fast, private, self-hosted dashboard and startpage for your homelab — bookmarks, widgets, uptime monitoring, Docker and Proxmox, in a single binary. https://codigosh.com/projects/lastboard/
  • TypeScript 54%
  • Go 36.8%
  • CSS 7%
  • Shell 1.1%
  • HTML 1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
k4wit0 aa1bb57587
All checks were successful
CI / Check, test and build (push) Successful in 15m35s
Rebuild the website / Rebuild the website (push) Successful in 1m58s
docs: the pictures and the mockup show the tiles as they are in 1.10
2026-11-03 03:48:47 +01:00
.forgejo/workflows test: the tests of the outage list, the history and the hourly counts use far less data, so the API package fits in the time the race detector gives it on the CI runner; and the CI gives its Go tests twenty minutes instead of ten 2026-11-02 19:34:57 +01:00
assets docs: the pictures and the mockup show the tiles as they are in 1.10 2026-11-03 03:48:47 +01:00
cmd feat(auth): two-step sign-in with an authenticator app and recovery codes 2026-10-26 13:42:49 +01:00
docs docs: the pictures and the mockup show the tiles as they are in 1.10 2026-11-03 03:48:47 +01:00
internal release: Docker, Proxmox and the status page, rebuilt; sign-in brought up to date 2026-11-03 03:40:31 +01:00
scripts docs: the outages tab by service, the panel's fifteen lines, results in words 2026-11-02 14:31:04 +01:00
web release: Docker, Proxmox and the status page, rebuilt; sign-in brought up to date 2026-11-03 03:40:31 +01:00
.air.toml chore: rename cmd/dashboard to cmd/lastboard and update references 2026-03-05 20:48:07 +00:00
.dockerignore perf(build): stop embedding duplicate and unused assets 2026-08-01 14:34:16 +02:00
.env.example feat(auth): sign in through an auth proxy in front, for accounts that already exist 2026-10-26 18:38:48 +01:00
.gitignore chore: fix ineffective .gitignore patterns 2026-07-14 07:13:02 +02:00
bun.lock build: update Go to 1.27.3, Bun to 1.4.4, SQLite to 1.61.0 and the CI tooling 2026-10-25 14:15:45 +01:00
CHANGELOG.md chore(release): bump to v1.10.0 2026-11-03 03:40:32 +01:00
CONTRIBUTING.md docs: point CONTRIBUTING bug reports to support 2026-09-30 17:53:03 +02:00
docker-compose.yml feat: optional unprivileged execution via PUID/PGID 2026-06-07 23:16:58 +02:00
Dockerfile build: update Go to 1.27.3, Bun to 1.4.4, SQLite to 1.61.0 and the CI tooling 2026-10-25 14:15:45 +01:00
go.mod build(deps): golang.org/x/net v0.62.0 2026-11-01 17:23:35 +01:00
go.sum build(deps): golang.org/x/net v0.62.0 2026-11-01 17:23:35 +01:00
install.sh fix(install): the reinstall hint is a short line and the command on its own line 2026-10-15 06:55:41 +02:00
LICENSE feat: adopt Apache 2.0 license with proper attribution 2026-02-02 20:43:06 +00:00
Makefile build(release): make the release script fail safely and preview itself 2026-08-02 22:33:01 +02:00
NOTICE fix(notice): attribute gopkg.in/yaml.v3 and drop x/exp, with a test that asks the linker 2026-10-01 20:09:50 +02:00
package.json release: Docker, Proxmox and the status page, rebuilt; sign-in brought up to date 2026-11-03 03:40:31 +01:00
README.md feat(widgets): a click on a row opens only the item's side panel over the board, and the Monitoring settings lose the icon of each service and word their summary line as what it shows 2026-11-03 03:18:58 +01:00
SECURITY.md docs(security): say where to report a vulnerability, and make no promise of a reply time 2026-10-02 07:57:31 +02:00
tsconfig.json feat: Upgrade Go 1.26.2, eliminate 49 unused variables/imports, enforce noUnusedLocals in tsconfig 2026-04-28 11:08:00 +01:00


Lastboard

Lastboard

The personal dashboard you actually want to open every day.

   


Lastboard Dashboard





📖 Read the Official Documentation for detailed guides on installation, configuration, security, and widget usage.


Why Lastboard

Most self-hosted dashboards are either too heavy, too ugly, or too complex to maintain. Lastboard was built with a simple rule: nothing ships unless it's fast and looks good doing it.

It is one static Go binary and one SQLite file. No database server, no Redis, no Node runtime, no YAML to hand-edit before you see a screen, and no account anywhere. The first run is a three-step wizard in the browser. It fits comfortably on a Raspberry Pi or a 512 MB LXC container, and it ships zero runtime JavaScript dependencies on the frontend and a pure-Go SQLite driver on the backend — nothing to compile, nothing to keep in step.

Shape Single static binary (linux/amd64, linux/arm64) or Docker image
Storage One SQLite file — cp lastboard.db is a complete backup
Setup A browser wizard. Zero configuration files
Languages 20, hand-translated, with full RTL support
Licence Apache-2.0
Telemetry None. Ever

Features

The board

  • A native drag-and-drop grid, written from scratch in plain JavaScript — no grid library, no framework. Drag tiles anywhere, resize them a cell at a time from the corner. A live outline shows where a tile will land and turns red when the target is occupied: nothing is ever pushed aside behind your back, and a drop onto a taken cell is refused rather than guessed at.
  • Bookmarks with an icon, a label you can place above, below, inside or hide entirely, a border colour and width of their own, and an optional status dot in any corner that says whether the service is answering.
  • Sections — containers that group bookmarks under a title. Drop tiles inside and they travel together; move the section to another dashboard and its contents follow.
  • Multiple independent dashboards per user, each with its own layout and items, switched from the top bar, reorderable by drag, with one marked as the one that opens first.
  • Move items between dashboards — one at a time from a tile's menu, or many at once with the selection mode. Arrivals are auto-placed and briefly highlighted so you can see where they landed.
  • Live search filters the board by label as you type.
  • A mobile layout with an order of its own — which bookmarks appear on a phone, and in what sequence, is set independently of the desktop grid from a bottom sheet that only commits when you save.
  • Grid density from 3 to 16 columns, per user.

Widgets (9)

Widget Description
Clock The time and date for any city you search for, on that city's time zone — one dashboard, several clocks
Server Health CPU, RAM and temperature as ring gauges: of the host with no agent and no exporter, or of another server through Glances, Netdata or a JSON endpoint
Weather Current conditions and an optional multi-day forecast from Open-Meteo. No API key, no registration
Notepad A rich-text scratchpad with a real toolbar: headings, colours, lists, checklists, links and images
Markdown A Markdown block rendered on the board, with a source/preview toggle and a lock
Monitoring Every monitored service on a tile: status dot, heartbeat, latency and 24-hour uptime
Docker Containers from one or many hosts, with live CPU/RAM and start/stop/restart
Proxmox Your hypervisor's node health and the machines behind your bookmarks, with start and shutdown
API Any JSON endpoint on a tile — 16 guided presets for common self-hosted services, or a fully custom request

The API widget is the escape hatch for everything without a dedicated widget. Sixteen presets — AdGuard Home, Paperless-ngx, Immich, Jellyfin, Sonarr, Radarr, SABnzbd, Tautulli, Overseerr/Jellyseerr, Bazarr, Prowlarr, Home Assistant, Uptime Kuma, Forgejo/Gitea, Speedtest Tracker and Nextcloud — ask you for one to three fields and compose the rest. Anything else goes in Advanced: URL, method, headers, JSON field paths, list or metric layout, and number/bytes/percent formatting. The request runs on the server, so it reaches private IPs and accepts self-signed certificates that a browser would refuse.

Uptime monitoring, built in

Give a bookmark a URL and a status position and Lastboard watches it. No second tool to deploy.

  • Two modes — tab mode checks while somebody has Lastboard open (live dots, nothing stored); 24/7 mode runs a server-side scheduler that keeps probing whether or not anyone is looking.
  • Check interval of 1, 5, 10 or 30 minutes, with 30 days of history, pruned daily.
  • A searchable status page (in 24/7 mode) with every service's state, a strip of recent checks and its 24-hour, 7-day and 30-day uptime, and a tab with every outage — what was down, why, when and for how long.
  • Per-service detail over 24 hours, 7 days or 30 days: uptime percentages, current and average response time, a latency chart with a hover crosshair, a heartbeat strip, and an outage table with durations and recoveries.
  • Alerts down and up via ntfy, Gotify or a webhook, with a failure threshold (1, 2, 3 or 5 consecutive failures) so a blip doesn't wake you, and a Send test button to prove delivery before you rely on it.
  • Private services just work — the probe runs from your server, so 10.x, 192.168.x, .local and self-signed certificates need no extra configuration.

Docker

  • Three ways to connect: local socket, remote TCP or TLS, or the Lastboard Agent — a tiny token-authenticated bridge, so you never expose the Docker daemon over the network.
  • Podman too, rootless, through its socket: the Podman guide has the two settings it needs and Quadlet files to run Lastboard and the agent as services.
  • Hosts belong to your account, set up once in Preferences and chosen by each widget. Many hosts, one list: tick the containers you care about on each host; they appear together, each row naming where it runs.
  • Live state and resource use on the board, and start / stop / restart from a container's panel on the Docker page for any account allowed to control Docker; a click on a row of the widget opens that container's panel over the board. A member reaches Docker only through its own agents; the server's socket and TCP or TLS daemons are the administrator's.
  • A Docker page with an overview of every host (what is running, what needs attention, CPU and memory), an inventory of all the containers, and a side panel for each one: how it is set up — ports, mounts, networks, the names of its environment variables, never their values — and its log, which can follow live. Details and logs on an agent host need Lastboard Agent v1.3.0 or later.
  • A container's panel opens its service, from its bookmark or, failing that, from a lastboard.url or homepage.href label, then its first published port — so containers already labelled for another dashboard work here unchanged.
  • A host that stops answering doesn't make its containers vanish: they stay, greyed out, with the host line saying it isn't responding.

Proxmox VE

  • Read your hypervisors with an API token — read-only if you want. Nodes with CPU, memory, disk, load average and uptime; every storage with how full it is; every VM and container as a tile with a 24-hour CPU trend, and every node foldable so a cluster stays readable.
  • More than one cluster is fine. Connect as many as you run, each with its own token and certificate policy. The page then opens on a short summary — a card each, and the bookmarked services that are down across all of them — and you go into whichever you want.
  • Machines are tied to your bookmarks automatically, by name and by the icon a bookmark wears, with filing prefixes (15-myspeed) stripped and a strict only when exactly one bookmark fits rule. Measured on a real host of 29 containers and 55 bookmarks with nothing configured: 16 matched, none wrongly.
  • That is the point of it. A stopped container doesn't just say stopped — it says which service it takes with it: every stopped tile turns a soft red, the ones serving a bookmark carry its mark in the corner, and the summary names the service by name.
  • Start and shut down a machine with confirmation, only on the hypervisors you connected, and only when the token really carries VM.PowerMgmt — which Lastboard asks the host rather than assuming. Nodes can never be powered off from Lastboard, deliberately.
  • What the hypervisor has been doing: each node and each machine opens its last fifty tasks — backups, starts, migrations, snapshots — with their state and log, which keeps following while a task runs. It needs only Sys.Audit, which the recommended role already has. A node's system log is optional and needs Sys.Syslog as well; without it the page says so and nothing else is affected.
  • Nothing is written to your database: no machine names, no figures, no history. Only the connection (the token secret is never sent back to a browser) and the icons you choose for machines.

Yours to keep

  • Full backup and restore from the browser — every user, every dashboard, every setting and every stored icon, in one file, optionally sealed under a password so nothing in it can be read without it.
  • Export as open, documented YAML: readable, editable, version-controllable.
  • Import from Homepage (services.yaml, bookmarks.yaml), from Dashy (conf.yml), or from a Lastboard export. Import always adds dashboards and never overwrites, and tells you how many items it will create first.
  • Icons are downloaded once and served from your own server. Loading your board reports nothing to a public CDN — not your address, and not which services you run. Boards built before this existed are brought in automatically on startup.

Personal, multi-user and multilingual

  • Multi-user with per-user boards, preferences, avatar and password. Exactly one administrator — the account the wizard creates.
  • Per-account permissions, chosen when the administrator creates an account and editable later: start from View only, Standard or Homelab, or set each one yourself — editing the board, several boards, import and export, fetching icons, API widgets, other machines' health, reaching the local network, the up/down dots, monitoring and alerts, the server's own load, and Docker and Proxmox at none, view or control. What an account may not use is left out of its screens, and the server checks every request. A label of your choosing replaces the role under the name.
  • Real dark/light mode with dedicated colour token sets per theme, not a CSS filter — plus a System option that follows the device and changes with it.
  • Accent colour, a background image per user, and your own panel name and logo in the tab and top bar.
  • Metric or imperial units, applied across every widget that shows one.
  • 20 languages, hand-translated — Arabic, Bengali, Chinese, Dutch, English, Farsi, French, German, Greek, Hindi, Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Russian, Spanish, Turkish, Urdu — with full right-to-left layout for Arabic, Farsi and Urdu. The language is applied on the server for the first paint, so even the login page arrives in your language instead of flashing English.
  • Installable as an app on Android, iOS and the desktop.

Operations

  • A web updater that downloads, verifies the signature and the checksum, extracts, installs and restarts — showing each step as it happens, and putting the old binary back if the swap fails.
  • Beta channel, opt-in per user.
  • One-line install on Linux with a systemd unit, --uninstall, --purge and --reinstall, that tells you which version you have and stops when you already have the latest, and a timestamped copy of your database taken before every upgrade.
  • Runs unprivileged on request (PUID/PGID), fixing data-directory ownership itself before dropping privileges.
  • Structured logging (LOG_FORMAT=json) and a /api/health endpoint.

Security

Lastboard is built with defense-in-depth from the ground up:

  • Two-step sign-in with any authenticator app, with single-use recovery codes; passkeys to sign in with a fingerprint, face or screen lock and no password; and, behind an auth proxy (Authelia, Authentik, oauth2-proxy), signing in through the proxy — off unless configured, and only for accounts that already exist.
  • Sessions stored on the server, carried by an HMAC-SHA256 signed cookie: signing out ends them everywhere, every account can see where it is signed in and close any session, and a password change ends them all; passwords hashed with Argon2id, at most two at a time so a flood of sign-ins cannot exhaust a small server; constant-time verification.
  • CSRF protection on every state-changing method, plus a Sec-Fetch-Site check the page cannot forge.
  • A strict Content-Security-Policy with a per-request nonce, so injected markup cannot execute as script — alongside HSTS, nosniff, X-Frame-Options and Referrer-Policy.
  • Rate limiting at 20 req/s (burst 50) per IP, and a lockout after 5 failed attempts — at sign-in, and per account wherever the password is asked for again (changing it, deleting an account, resetting the instance). Behind a proxy the client IP is read from the entry your proxy appended, not the one the caller sent, so the lockout cannot be evaded with a forged header.
  • Signature-verified updates: checksums.txt is signed with Ed25519 and the public half is embedded in the binary as a list; a missing or invalid signature aborts the update.
  • Optional unprivileged execution via PUID/PGID, with the data directory fixed up automatically before privileges are dropped.
  • Authorization declared route by route, not by a list of public path prefixes inside the middleware — so nothing becomes reachable without a session by accident of its URL, including anything that falls through to the app shell. Stored icons are served with their own sandboxed CSP.

For the full breakdown, see the Security Overview.

Remote Docker hosts are reached through Lastboard Agent, a tiny token-authenticated bridge, so you never have to expose the Docker daemon over TCP.


Installation Methods

The easiest way to get started is using Docker. Images are automatically built and published to our Forgejo registry.

Using Docker Compose:

services:
  lastboard:
    image: git.codigosh.com/codigosh/lastboard:latest
    container_name: lastboard
    ports:
      - "8080:8080"
    environment:
      - TZ=America/New_York
      # - TRUST_PROXY=true   # Uncomment if running behind a reverse proxy
    volumes:
      - ./data:/var/lib/lastboard
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

Using Docker CLI:

# Note: Add `-e TRUST_PROXY=true \` before the image name if running behind a reverse proxy.
docker run -d \
  --name lastboard \
  -p 8080:8080 \
  -e TZ=America/New_York \
  -v $(pwd)/data:/var/lib/lastboard \
  --restart unless-stopped \
  git.codigosh.com/codigosh/lastboard:latest

For advanced configuration options, environment variables, and data backups, please refer to the Configuration Guide.


Quick Install (Linux)

Run this command to install or update Lastboard automatically:

curl -fsSL https://git.codigosh.com/CodigoSH/Lastboard/raw/branch/main/install.sh | sudo bash

For more details on building from source, check the Development Guide.


Updates

Updates come straight from the official repository, with no proxy or intermediary in between, and are verified against a signed checksum file before anything is installed.

For detailed updating instructions, visit the Updates Guide, or see our Security Policy for how update delivery works.


Support & Recognition

We are an open-source initiative managed through Open Collective Europe.

Financial Support

If you find our tools useful, consider supporting our infrastructure through an unconditional donation.

Acknowledgments

Special thanks to everyone supporting our mission.

Organizations

We appreciate the organizations that support us as a gesture of goodwill to help maintain our infrastructure.


Credits

Full attribution, including the Go modules compiled into the binaries, lives in NOTICE.


A project by CodigoSH — built to last.