Sign inSign up

khak1s/dashgate

By khak1s

•Updated 15 days ago

Self-hosted application gateway with multi-method auth and auto-discovery

Image
0

10K+

khak1s/dashgate repository overview

⁠DashGate

DashGate is a self-hosted dashboard for people who run several web services and need control over who sees each app. Sign in with local accounts, LDAP, OIDC, or a trusted reverse proxy; organize apps by group; and review routes found by Docker or a reverse proxy before publishing them.

Try DashGate in five minutes⁠ · Watch the 20-second demo⁠ · Deployment and upgrades⁠ · Discussions⁠ · Security policy⁠

The demo uses an isolated DashGate instance and a sample discovered route.

DashGate dashboard with sample apps

DashGate Login

⁠Questions and feedback

Use GitHub Discussions⁠ for setup questions and feature ideas. Open an issue⁠ for a reproducible bug. Report vulnerabilities privately through the security policy⁠.

⁠Features

  • Multi-method authentication - Local accounts, LDAP, OIDC/OAuth2, and reverse proxy (Authelia/Authentik) support
  • Group-based access control - Show apps only to users in specific groups
  • Automatic app discovery - Discover apps from Docker, Traefik, Nginx, Nginx Proxy Manager, Caddy, and Unraid
  • Health monitoring - Background health checks with real-time status indicators
  • Auto-login redirect - Unauthenticated requests redirect to login page or OIDC provider; API requests get structured JSON 401 with redirect URL
  • First-time setup wizard - Guided configuration on initial deployment
  • Admin panel - Manage users, apps, categories, groups, and discovery sources from the UI
  • Group management - Create and delete managed groups with server-side persistence via admin panel
  • LLDAP integration - Manage users and groups via LLDAP directory
  • API key authentication - Programmatic access with scoped API keys
  • Progressive Web App - Install as a PWA with offline support
  • Encryption at rest - Sensitive configuration values (passwords, secrets) encrypted with AES-256-GCM
  • Audit logging - Track admin actions with audit trail
  • Backup/Restore - Export and import DashGate configuration
  • User self-service - Edit profile (display name, email) and change password via Settings > Profile tab
  • Configurable clock format - Toggle between 12h and 24h time display via Settings
  • Customizable themes - User-selectable accent colors and dark/light mode
  • Security hardened - CSP nonce, CSRF protection, rate limiting, HSTS, security headers

⁠Quick Start

# Create config directory
mkdir -p config

# Run with docker
docker run -d \
  --name dashgate \
  -p 1738:1738 \
  -v "$(pwd)/config:/config" \
  -e PUID=1000 \
  -e PGID=1000 \
  --restart unless-stopped \
  khak1s/dashgate:latest

# Dev builds: ghcr.io/kha-kis/dashgate:dev (multi-arch, pushed on every main commit)

Visit http://localhost:1738 and complete the setup wizard.

For Docker Compose upgrades, see the upgrade guide⁠ for backup, health-check, and recovery guidance. Host schedules and monitoring belong to each operator's infrastructure.

⁠Manual Installation

Prerequisites: Go 1.24+, GCC (for CGO/SQLite)

# Clone and build
git clone https://github.com/khak1s/dashgate.git
cd dashgate
CGO_ENABLED=1 go build -ldflags="-s -w" -o dashgate .

# Run
CONFIG_PATH=./config.yaml DB_PATH=./dashgate.db ICONS_PATH=./static/icons ./dashgate
⁠Windows Development

Requires MSYS2 with MinGW-w64 GCC at C:\msys64\mingw64\bin\gcc.exe.

$env:PATH = "C:\msys64\mingw64\bin;" + $env:PATH
$env:CGO_ENABLED = "1"
go build -o dashgate.exe .

$env:CONFIG_PATH = ".\config.yaml"
$env:DB_PATH = ".\dashgate.db"
$env:TEMPLATES_PATH = ".\templates"
$env:STATIC_PATH = ".\static"
.\dashgate.exe

⁠Configuration

⁠Environment Variables
VariableDefaultDescription
PUID1000User ID for file permissions (NAS/Unraid compatibility)
PGID1000Group ID for file permissions (NAS/Unraid compatibility)
PORT1738HTTP server port
CONFIG_PATH/config/config.yamlPath to YAML app configuration
DB_PATH/config/dashgate.dbSQLite database path
ICONS_PATH/config/iconsPersistent icons directory (bundled icons seeded on first run)
DEV_MODEfalseEnable live template reloading
TEMPLATES_PATH/app/templatesTemplates directory (used in dev mode)
ENCRYPTION_KEY(auto-generated)64 hex character AES-256 key for encrypting secrets at rest
LOGIN_RATE_LIMIT5Max login attempts per IP per window
COOKIE_SECURE(auto)Set to false to allow cookies over HTTP (useful behind reverse proxies)
UNRAID_DISCOVERYfalseEnable Unraid container discovery
UNRAID_URLUnraid server URL (e.g., http://tower.local)
UNRAID_API_KEYUnraid API key for GraphQL access
⁠App Catalog (config.yaml)

Apps are organized into categories:

title: My DashGate
categories:
  - name: Media
    apps:
      - name: Plex
        url: https://plex.example.com
        icon: plex
        description: Media server
        groups:
          - media
          - admins
      - name: Jellyfin
        url: https://jellyfin.example.com
        icon: jellyfin
        description: Media streaming
        groups:
          - media

  - name: Tools
    apps:
      - name: Portainer
        url: https://portainer.example.com
        icon: portainer
        groups:
          - admins

Each app supports:

  • name - Display name
  • url - Application URL
  • icon - Icon name (matches files in static/icons/) or URL
  • description - Short description
  • groups - List of groups that can see this configured app (empty = admin-only)
  • depends_on - List of app names this app depends on (for dependency graph)

⁠Authentication

DashGate supports multiple authentication methods that can be enabled simultaneously:

⁠Local Authentication

Local user accounts stored in SQLite with bcrypt-hashed passwords. Create your first admin user during the setup wizard.

⁠LDAP Authentication

Bind-based LDAP authentication. Configure in the setup wizard or admin settings:

  • Server URL (e.g., ldap://ldap.example.com:389)
  • Bind DN and password (service account)
  • Base DN, user filter, attribute mappings
  • Optional StartTLS with configurable certificate verification
⁠OIDC/OAuth2

OpenID Connect authentication with any compliant provider (Authelia, Authentik, Keycloak, etc.):

  • Issuer URL, Client ID, Client Secret
  • Configurable scopes and groups claim name
  • Automatic user creation on first login

For group-based access and admin rights, configure the identity provider to include the chosen groups claim in the ID token. The group value must match DashGate's Admin Group (or an app's assigned group). If an OIDC user signs in without expected access, check the token claim mapping and exact group names first.

New apps created in the admin UI include the configured Admin Group by default. To show one to an OIDC user, select an additional Access Group that appears in that user's ID token. Managed groups can be created under Admin > Users when local auth is enabled, but OIDC membership still comes from the identity provider.

⁠Proxy Authentication (Authelia/Authentik)

Trust authentication headers from a reverse proxy:

  • Remote-User, Remote-Groups, Remote-Name, Remote-Email
  • Configure trusted proxy IP ranges to prevent header spoofing
  • Works with Authelia, Authentik, and similar auth proxies
  • Each trusted proxy username gets its own user record, so settings, favorites, and My Apps sync across browsers and devices
  • A proxy username already used by a local, LDAP, or OIDC account is rejected; use distinct usernames for each authentication source
  • If a proxy email belongs to another account, DashGate leaves that account unchanged and stores the proxy user without an email
⁠API Keys

Create scoped API keys for programmatic access:

  • Prefix-based lookup with bcrypt verification
  • Optional expiration dates
  • Group-scoped permissions

⁠App Discovery

Background workers automatically discover apps from various sources every 60 seconds:

⁠Docker

Enable with DOCKER_DISCOVERY=true. Discovers containers with labels:

labels:
  - "dashgate.enable=true"
  - "dashgate.name=My App"
  - "dashgate.url=https://app.example.com"
  - "dashgate.icon=app-icon"
  - "dashgate.description=Description"

DashGate also discovers containers labeled for Homepage when both homepage.name and homepage.href are present:

labels:
  - "homepage.name=My App"
  - "homepage.href=https://app.example.com"
  - "homepage.description=Description" # optional

The route appears in the existing discovery inbox for admin review. Only the name, HTTP(S) URL, and description are read. Homepage's group is a display category and is never used as a DashGate access group; icon and widget.* labels are not imported. Configure the category, icon, and access groups in DashGate before publishing. An explicit dashgate.enable=false excludes a container, and dashgate.enable=true uses only DashGate labels.

Docker discovery needs access to the Docker API. A direct socket mount such as -v /var/run/docker.sock:/var/run/docker.sock:ro grants broad daemon access: :ro protects the mounted socket file from filesystem writes but does not make API operations read-only. Prefer a socket proxy limited to the API sections and methods discovery needs.

Using a Docker Socket Proxy (recommended for security):

Instead of mounting the Docker socket directly, you can use a socket proxy like docker-socket-proxy⁠ to limit API access:

services:
  socket-proxy:
    image: tecnativa/docker-socket-proxy
    environment:
      - CONTAINERS=1 # Allow the container API section
      - POST=0       # Disable write methods
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  dashgate:
    image: khak1s/dashgate:latest
    environment:
      - DOCKER_DISCOVERY=true
      - DOCKER_SOCKET=tcp://socket-proxy:2375
    # No socket mount needed
⁠Traefik

Enable with TRAEFIK_DISCOVERY=true and TRAEFIK_URL=http://traefik:8080. Discovers HTTP routers from the Traefik API.

⁠Nginx

Enable with NGINX_DISCOVERY=true and NGINX_CONFIG_PATH=/etc/nginx/conf.d. Parses Nginx configuration files for server blocks.

⁠Nginx Proxy Manager (NPM)

Enable with NPM_DISCOVERY=true, NPM_URL, NPM_EMAIL, and NPM_PASSWORD. Discovers proxy hosts from the NPM API.

⁠Caddy

Enable with CADDY_DISCOVERY=true and CADDY_ADMIN_URL=http://localhost:2019. Discovers reverse proxy routes from the Caddy admin API.

⁠Unraid

Enable with UNRAID_DISCOVERY=true, UNRAID_URL, and UNRAID_API_KEY. Discovers Docker containers with WebUI URLs configured via the Unraid GraphQL API (requires Unraid 7.2+).

To create an API key on your Unraid server:

unraid-api apikey --name "DashGate" --create --roles ADMIN --json

Or configure via the admin UI under Discovery settings — enter your Unraid server URL and API key, then test the connection.

Discovery sources enabled by environment variables are read-only in the admin UI. Change those variables in your deployment configuration and restart DashGate; sources configured in the UI are saved to the database.

⁠Discovery Diagnostics

In Admin > Discovery, each source shows its latest scan state below the enable switch: Disabled, Waiting for first scan, Scanning, Completed, Completed with warnings, or Failed. The summary includes the last attempt and last successful scan. The open Discovery tab updates as scans finish, including scheduled scans. A failed scan may leave its previous routes visible; the count is explicitly labeled Last successful so it is not mistaken for a result from the failed attempt. Scan history is held in memory and resets when DashGate restarts or a source is disabled and re-enabled. Source connection tests check connectivity but do not count as completed discovery scans.

Open View scan details under a source to search its currently discovered routes by name or URL and filter them by disposition: Inbox, Already added, Ignored, Rule matched, or Configured. The reason beside each route uses the same grouping rules as the Content inbox. A Hidden override remains in Inbox. Old Ignored entries that are no longer reported remain restorable in Content, but they are not counted as current routes in Discovery.

Refresh requests a new scan and updates the status when that attempt starts and finishes. If a URL is absent from the latest successful route list, the search reports that it was not found; DashGate cannot infer why the upstream source or parser did not produce it. Scan failures and warnings show safe summaries here; server logs hold more detail.

⁠Managing Discovered Apps

Discovered apps are hidden by default. Use the admin panel to:

  • Show/hide discovered apps on the DashGate dashboard
  • Override names, icons, URLs, and descriptions
  • Assign groups and categories
  • Test discovery connections

The Discovered Apps inbox lists unconfigured and Hidden routes. Search by name or URL and filter by source across the inbox and the collapsed Ignored list. Use Dismiss on a row or select several rows and choose Dismiss selected to clear routes you do not want to configure. Dismissed routes move to Ignored, where Restore returns them to the inbox. Ignored entries remain available for restoration even if a source stops reporting them. Dismissing a route does not publish, hide, or change dashboard access for an app; it only removes that source and URL pair from the inbox.

Unconfigured routes whose URL matches a published dashboard app appear in the collapsed Already added list instead of the inbox. You can search and filter this list to inspect the route and its matching app. The match uses the full HTTP(S) URL, including path and query; routes with different paths or query strings stay in the inbox. Removing or changing the published app returns the route to the inbox. Already added is a display-only grouping and does not change publication or dashboard access. Hidden discovered apps remain in the inbox.

For repeated routes such as health checks, use Ignore similar routes on an inbox row or New ignore rule in Ignore rules. A rule applies to one discovery source, one HTTP(S) origin (scheme, host, and port), and a whole-segment path prefix: /health matches /health and /health/live, but not /healthz. The root path / is not allowed. Preview shows up to 100 currently actionable matches and their full count before Save is enabled. It is a snapshot; later discovery scans may find more matching routes, and a preview with zero matches can still be saved. Enabled rules move matches out of the inbox into the collapsed Rule matched list, where search and source filters also apply. Edit, disable, or delete a rule to change its effect; routes return to the inbox unless another active rule or a separate manual Dismiss still covers them. Restoring a manually dismissed route does not override an active rule. Rules only affect inbox triage and never change publication, Hidden state, or dashboard access.

A published discovered app with no assigned groups is visible to every authenticated user. An unpublished or hidden discovered app does not appear, including for admins.

⁠Explaining App Access

In Admin > Users > Explain App Access, select a saved user and an app to see whether the app appears on that user's dashboard and why. The explanation shows the app source, effective app groups, stored user groups, and any matching group. OIDC, LDAP, and proxy groups are snapshots saved by DashGate and may differ from the identity provider's current membership. The checker is read-only and available only to admins.

⁠LLDAP Integration

Optional integration with LLDAP⁠ for user and group management:

environment:
  - LLDAP_URL=http://lldap:17170
  - LLDAP_ADMIN_USERNAME=admin
  - LLDAP_ADMIN_PASSWORD=changeme

This enables viewing LLDAP users and groups in the admin panel.

⁠API Reference

All API endpoints return JSON. State-changing requests require a X-CSRF-Token header matching the dashgate_csrf cookie.

⁠Public Endpoints
MethodPathDescription
GET/healthHealth check (returns version; returns JSON 401 with redirect URL when unauthenticated)
GET/api/auth/configEnabled auth methods
⁠Authenticated Endpoints
MethodPathDescription
GET/api/auth/meCurrent user info
POST/api/auth/logoutEnd session
GET/api/healthApp health statuses
GET/PUT/api/user/preferencesSettings, favorites, My Apps
GET/PUT/api/user/profileUser profile (display name, email)
POST/api/user/passwordChange password (local users only)
GET/api/discovered-appsList discovered apps
GET/api/dependenciesService dependency graph

API keys cannot access user preferences; these settings belong to a signed-in user. Personal apps in Settings > My Personal Apps sync through these preferences and appear on the dashboard, including when no shared categories are configured. After upgrading from a browser-only My Apps version, review the restoration notice in Settings > My Personal Apps. Confirm the full browser and account lists before restoring: restoration replaces the account list. DashGate keeps a local backup until the restore succeeds. If a personal-app change cannot reach the server, DashGate keeps an account-scoped pending copy. Retry sync shows the latest account list and asks before replacing it. Choose Keep account apps to discard the pending browser copy and continue editing the server list. Quick Links, Quick Notes, and the weather location remain local to each browser.

⁠Admin Endpoints

All require admin group membership.

MethodPathDescription
GET/api/admin/appsList all apps (config + discovered, deduplicated by URL)
GET/api/admin/checkVerify admin access
GET/POST/api/admin/local-usersList/create local users
PUT/DELETE/api/admin/local-users/:idUpdate/delete user
POST/api/admin/local-users/:id/passwordReset password
GET/POST/api/admin/api-keysList/create API keys
GET/PUT/api/admin/system-configGet/update system config
GET/POST/api/admin/config/appsManage app catalog
GET/POST/api/admin/config/categoriesManage categories
GET/api/admin/config/iconsList available icons
POST/api/admin/config/icons/uploadUpload custom icon
GET/POST/api/admin/docker-discoveryDocker discovery config
GET/POST/api/admin/traefik-discoveryTraefik discovery config
GET/POST/api/admin/nginx-discoveryNginx discovery config
GET/POST/api/admin/npm-discoveryNPM discovery config
GET/POST/api/admin/caddy-discoveryCaddy discovery config
GET/POST/PUT/api/admin/unraid-discoveryUnraid discovery config
POST/api/admin/unraid-discovery/testTest Unraid connection
GET/api/admin/backupDownload backup
POST/api/admin/restoreRestore from backup
GET/api/admin/audit-logView audit log
GET/api/admin/usersList LLDAP users
GET/api/admin/groupsList LLDAP groups
GET/POST/api/admin/managed-groupsList/create managed groups
DELETE/api/admin/managed-groups/{name}Delete a managed group

⁠Security

⁠Built-in Protections
  • CSRF protection - Double-submit cookie pattern with constant-time comparison
  • Content Security Policy - Per-request nonces for inline scripts
  • Rate limiting - Per-IP rate limiting on login endpoints (configurable)
  • Security headers - X-Content-Type-Options, X-Frame-Options, HSTS, Referrer-Policy
  • Session security - Cryptographic session tokens, old sessions invalidated on new login
  • Encryption at rest - Sensitive values (LDAP passwords, OIDC secrets) encrypted with AES-256-GCM
  • Directory listing disabled - Static file server blocks directory browsing
  • Input validation - Open redirect prevention, URL validation
  • Body size limits - 1 MB max request body to prevent DoS
  • Trusted proxy validation - Proxy auth headers only accepted from configured IP ranges
⁠Recommendations for Production
  1. Always use HTTPS - Deploy behind a reverse proxy with TLS termination
  2. Set ENCRYPTION_KEY - Provide a stable encryption key via environment variable rather than relying on auto-generation. Generate one with: openssl rand -hex 32
  3. Configure trusted proxies - If using proxy auth, restrict to your proxy's IP range
  4. Regular backups - Use the admin backup feature to export configuration
  5. Review audit logs - Monitor admin actions via the audit log endpoint
  6. Update regularly - Keep the application and its dependencies up to date

⁠Development

⁠Project Structure
dashgate/
  main.go                  # Entry point, routing, server setup
  config.yaml              # App catalog
  internal/
    auth/                  # Authentication (OIDC, LDAP, local, proxy, API keys)
    config/                # YAML config loading and app mappings
    database/              # SQLite schema, system config, encryption, audit
    discovery/             # Auto-discovery (Docker, Traefik, Nginx, NPM, Caddy, Unr

Tag summary

Content type

Image

Digest

sha256:8f9329850…

Size

9.2 MB

Last updated

15 days ago

docker pull khak1s/dashgate