Skip to content

Repository files navigation

Server Hub logo

Server Hub

A focused, self-hosted dashboard for the applications and services you use every day.
Live Demo · Features · Quick Start · Configuration · API · Testing

Live Demo Deployed on Vercel Python 3.8 or newer Python standard library only MIT License


Live Demo (free hosted)

Try it now — no install required: https://server-hub-gules.vercel.app

Everyone can use the hosted instance for free. Create an account, manage your own services, bookmarks, and settings — data is isolated per user via Supabase RLS.


Server Hub brings self-hosted applications, infrastructure tools, and frequently used links into one private homepage. It combines a lightweight Python backend (stdlib only) with a static frontend — no build step, no npm install.

Two deployment models are supported:

  • Vercel + Supabase — serverless, multi-user with per-user data isolation (recommended).
  • Standalone Python — single-user installation on a VPS, Proxmox LXC, or any Linux host.

Features

  • Personal dashboard — responsive service cards, category sections, bookmarks, clock, greeting, page title, and subtitle.
  • Search — instant service filtering plus optional passthrough to Google, DuckDuckGo, Bing, Startpage, or a configured SearXNG instance.
  • Automatic categorization — local keyword matching from name, URL, and description with manual overrides.
  • Service management — add, edit, delete, reorder, and configure health pings from the dashboard or Settings.
  • Bookmarks — compact frequently-used links with optional colors and icons.
  • Themes and wallpapers — light / dark / auto, built-in gradients, custom image URLs, and contrast controls.
  • System monitoring — local CPU / memory / disk via /proc, plus multi-server monitoring through Beszel (single beszel or multi-instance beszels array).
  • Multi-user accounts — Supabase Auth with RLS-isolated settings, services, bookmarks, and logs.
  • Two-factor authentication — optional TOTP via authenticator app.
  • Backup and restore — export and import settings, services, and bookmarks as JSON.
  • Security controls — signed HttpOnly sessions, CSRF checks, rate limiting, body-size limits, security headers, and path-traversal protection.

Quick Start

Vercel + Supabase (multi-user)

  1. Create a Supabase project.

  2. Run supabase-schema.sql once in the Supabase SQL Editor.

  3. Import this repository into Vercel.

  4. Add the environment variables described in Configuration.

  5. Deploy and open the resulting Vercel URL — or try the live instance at https://server-hub-gules.vercel.app.

    Note: Vercel deploy requires a Supabase project and running supabase-schema.sql — the one-click Deploy button is omitted because it cannot provision the database automatically.

Vercel uses api/index.py as the Python Function entry point. It adapts the existing backend to Vercel's WSGI runtime while static assets are served through the same application.

Keep SUPABASE_SERVICE_ROLE_KEY private. It is only used server-side for administrative signup and must never be exposed to browser code.

Standalone Python (single-user)

git clone https://github.com/eco-null/server-hub-multi.git
cd server-hub-multi
HUB_PASSWORD=change-me python3 server.py

Open http://localhost:8642 and sign in with the configured username and password. For a persistent Proxmox LXC deployment, see SETUP-LXC.md.

Configuration

Configuration is provided through environment variables. With Supabase variables present, Server Hub runs in multi-user mode; without them it falls back to single-user authentication.

Variable Default Description
SUPABASE_URL (empty) Supabase project URL; enables multi-user mode with SUPABASE_ANON_KEY.
SUPABASE_ANON_KEY (empty) Supabase publishable / anon key for Auth and RLS-scoped requests.
SUPABASE_SERVICE_ROLE_KEY (empty) Server-only key for administrative signup flows. Never expose publicly.
SUPABASE_SERVICE_KEY (empty) Backward-compatible alias for the service-role key.
HUB_USER admin Username in standalone single-user mode.
HUB_PASSWORD Required in standalone mode; use a strong password.
SESSION_SECRET (generated locally) Stable signing key for sessions. Required on Vercel so sessions survive across instances.
HUB_HOST 0.0.0.0 Bind address for standalone mode.
HUB_PORT 8642 Listen port for standalone mode.
HUB_DISK_PATH / Filesystem path for the local disk widget. Use /host when the container exposes the host root there.
BESZEL_URL (empty) Optional Beszel hub URL, e.g. http://beszel:9520.
BESZEL_USER (empty) Beszel account used by the server-side proxy.
BESZEL_PASSWORD (empty) Beszel account password.

Generate secrets with:

openssl rand -base64 32

Supabase setup

The schema creates:

  • profiles — user profile and unique username.
  • user_settings — per-user dashboard settings and layout (JSONB; supports beszel and beszels).
  • user_services and user_bookmarks — per-user links and bookmarks.
  • user_logs — per-user frontend error and conflict logs.
  • Row Level Security policies restricting every record to its owning auth.uid().
  • A signup trigger that creates the initial profile and settings row.

Passwords remain in Supabase Auth. Server Hub forwards the signed-in user's token to the database API and never shares data between users.

Beszel monitoring

Set BESZEL_URL, BESZEL_USER, and BESZEL_PASSWORD (env) or configure per-user Beszel instances in Settings. The dashboard supports:

  • Legacy single instance: settings.beszel = { url, user, password }
  • Multi-instance: settings.beszels = [{ id, name, url, user, password }, ...] — the backend aggregates GET /api/beszel across all configured hubs and returns per-system cpu, mem, disk, status, and uptime.

If Beszel is unavailable or not configured, the local /api/stats widget remains available where the host exposes Linux /proc statistics.

API

All API endpoints require an authenticated session unless noted otherwise. Mutating requests must be same-origin. JSON bodies are limited to 64 KiB.

Method Path Description
POST /login Sign in; supports username/email and the second TOTP step.
POST /register Create a Supabase account.
GET /logout End the current session.
GET /api/me Return the current user.
GET /api/bootstrap Coalesced batch: services + bookmarks + settings + layout + user in one round-trip (ETag / 304 supported).
GET/POST /api/services List or create services.
PUT/DELETE /api/services/<id> Update or delete a service.
GET/POST /api/bookmarks List or create bookmarks.
PUT/DELETE /api/bookmarks/<id> Update or delete a bookmark.
GET/PUT /api/settings Read or save settings and layout (supports beszel and beszels array).
GET/POST /api/logs Read or record frontend error / conflict logs.
GET /api/stats Return local host CPU, memory, and disk statistics.
GET/POST /api/beszel GET — return aggregated Beszel systems; POST — test a Beszel connection.
GET /api/2fa/setup Create a pending TOTP setup payload.
POST /api/2fa/enable Enable TOTP after code verification.
POST /api/2fa/disable Disable TOTP after code verification.

Service objects use { id, name, url, desc, icon, ping, categoryOverride }. Bookmark objects use { id, name, url, icon, color }.

Project Structure

File Purpose
index.html Main dashboard, search, service/bookmark editors, pings, stats, and frontend error reporting.
settings.html Theme, wallpaper, feature toggles, Beszel, 2FA, link management, and backup/restore.
login.html Combined sign-in and account creation interface, including the TOTP step.
register.html Compatibility entry point for the registration route.
settings.js Shared settings persistence, local storage, server synchronization, and wallpaper handling.
categorize.js Local category keyword rules and matcher.
server.py Standalone HTTP server, authentication, API routes, persistence, statistics, and Beszel proxy.
api/index.py Vercel WSGI bridge for the Python server.
auth.py Dependency-free Supabase Auth and PostgREST client.
supabase-schema.sql Supabase tables, RLS policies, triggers, and signup helper functions.
services.json Standalone-mode service/bookmark storage; the checked-in file starts empty.
test_server.py Python integration and security test suite (pytest).
tests.html Browser-side test suite.
SETUP-LXC.md Proxmox LXC and systemd deployment guide.
SETUP.md Cloudflare Access and public-domain hardening guide.

Testing

python3 -m pytest test_server.py -q

For the browser suite, serve the repository over HTTP and open tests.html:

python3 -m http.server 8000
# then visit http://localhost:8000/tests.html

Serving over HTTP is required — browsers may restrict localStorage on file:// URLs.

Deployment Notes

  • Vercel — use the included vercel.json, set SESSION_SECRET, and configure Supabase variables.
  • Proxmox LXC — follow SETUP-LXC.md for a systemd service and persistent services.json.
  • Cloudflare Access — follow SETUP.md when placing an additional edge authentication layer in front of a public deployment.

Security

  • Supabase mode isolates user data with Postgres RLS.
  • Sessions use signed cookies with HttpOnly, SameSite=Lax, and Secure when HTTPS is detected (__Host- prefix on Vercel).
  • Passwords are handled by Supabase Auth in multi-user mode and read from environment variables in standalone mode.
  • Login and registration include per-IP rate limiting; API and login request bodies are capped at 64 KiB.
  • Mutating requests enforce same-origin checks and Sec-Fetch-Site validation; responses include nosniff, SAMEORIGIN, no-referrer, and CSP protections.
  • Beszel credentials and TOTP secrets are kept server-side and never returned to the browser.

Known Limitations

  • Standalone-mode sessions are held in memory; restarting server.py signs users out.
  • Standalone-mode links and bookmarks are persisted in services.json; back up this file with the deployment.
  • Local system statistics depend on Linux /proc; use Beszel for cross-host monitoring.
  • The default frontend loads Tailwind, fonts, QRCode.js, and optional wallpaper assets from CDNs. A network-restricted deployment should vendor or replace these assets.

License

MIT


About

Multi-user self-hosted dashboard for your apps and services — Supabase Auth (email+password), per-user services/bookmarks/settings with Row-Level Security, and per-user error/conflict logs. Zero third-party Python dependencies (stdlib only).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages