Dashy: Ultimate Customizable Dashboard
Highly configurable dashboard with themes, widgets, and status monitoring. YAML-powered personalization.
Overview
Dashy is a highly customizable, privacy-respecting dashboard that puts configuration-as-code first. Unlike point-and-click dashboards, Dashy uses YAML configuration files that can be version-controlled, backed up, and shared. With 50+ built-in themes, dozens of widgets, status checks for every service, and advanced features like keyboard shortcuts and multi-page layouts, Dashy is for homelabbers who want complete control.
Built with privacy in mind, Dashy doesn’t phone home, doesn’t track usage, and runs completely locally. Every feature works offline, and your data never leaves your network unless you explicitly configure external integrations.
What you’ll learn:
- Installing Dashy with Docker Compose
- Writing YAML configuration for services and sections
- Configuring themes and visual customization
- Adding widgets (weather, system stats, RSS, crypto, etc.)
- Setting up status checks and health monitoring
- Implementing authentication and access control
- Advanced features: keyboard shortcuts, search, icons
- Configuration best practices and troubleshooting
Why Dashy for Homelabs?
Your dashboard configuration lives in Git. Share your config with the community. Switch between dozens of themes instantly. Check the health of 50 services at a glance. Search across all your services with keyboard shortcuts. Customize every pixel with CSS. This is the power-user’s dashboard.
Prerequisites
Before starting, ensure you have:
- Docker and Docker Compose installed
- Basic YAML knowledge (we’ll cover the syntax)
- Text editor for editing configuration files
- Hardware requirements:
- 256 MB RAM minimum (runs lighter than most dashboards)
- 500 MB storage
- Network: Port 8080 (customizable)
Optional but helpful:
- Git for version control
- Services to add to dashboard
- Basic CSS knowledge for advanced customization
Understanding Dashy’s Philosophy
Configuration-as-Code Approach
Traditional dashboards:
- Point and click in web UI
- Configuration stored in database
- Hard to backup, version, or share
Dashy:
- YAML configuration file
- Version control friendly
- Backup = copy file
- Share configs with community
Example configuration:
pageInfo:
title: My Homelab
description: Welcome to my services
sections:
- name: Media
items:
- title: Plex
url: http://plex.local:32400
icon: plex.png Privacy-First Design
What Dashy does NOT do:
- Send telemetry or analytics
- Call external APIs (unless you configure widgets to do so)
- Track your usage
- Require internet connection
- Store data in cloud
What this means:
- Fully functional offline
- No privacy concerns
- Complete data control
- Faster load times (no external dependencies)
Core Features
Multi-Section Layout:
- Organize services into logical groups
- Collapsible sections
- Search within/across sections
Extensive Theming:
- 50+ built-in themes
- Custom theme creation
- Per-section theming
- CSS customization
Status Checks:
- HTTP ping checks
- Custom status endpoints
- Visual health indicators
- Automatic retry logic
Widgets:
- Weather, calendar, RSS feeds
- System stats, crypto prices
- Custom HTML/JS widgets
- Iframe embeddings
Authentication:
- Simple auth (built-in)
- Keycloak integration
- Per-user configurations
- Guest access control
Installation with Docker Compose
Basic Installation
Create docker-compose.yml:
version: '3.8'
services:
dashy:
image: lissy93/dashy:latest
container_name: dashy
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./dashy/conf.yml:/app/public/conf.yml
- ./dashy/item-icons:/app/public/item-icons
environment:
- NODE_ENV=production
- UID=1000
- GID=1000 Create initial configuration:
Create dashy/conf.yml:
---
pageInfo:
title: My Homelab Dashboard
description: Welcome to my self-hosted services
navLinks:
- title: GitHub
path: https://github.com
- title: Documentation
path: https://dashy.to/docs
appConfig:
theme: nord
layout: auto
iconSize: medium
language: en
startingView: default
defaultOpeningMethod: newtab
statusCheck: true
statusCheckInterval: 60
sections:
- name: Getting Started
icon: fas fa-rocket
items:
- title: Dashy Documentation
description: Read the documentation
icon: hl-dashy
url: https://dashy.to/docs
target: newtab Start Dashy:
mkdir -p ~/dashy/dashy
cd ~/dashy
# Create conf.yml (above)
nano dashy/conf.yml
# Start container
docker-compose up -d
# Check logs
docker-compose logs -f dashy Access Dashy:
Navigate to http://localhost:8080 or http://YOUR-SERVER-IP:8080
YAML Configuration Deep Dive
Configuration File Structure
---
# Page metadata
pageInfo:
title: Dashboard Title
description: Dashboard description
navLinks: [] # Top navigation links
footerText: Footer content
# App-wide settings
appConfig:
theme: nord
layout: auto
language: en
statusCheck: true
# Service sections
sections:
- name: Section Name
icon: section-icon
items:
- title: Service Name
url: https://service.url
icon: service-icon Page Info Configuration
pageInfo:
title: My Homelab
description: Self-hosted services dashboard
# Top navigation links
navLinks:
- title: GitHub
path: https://github.com/yourusername
- title: Documentation
path: https://docs.homelab.local
- title: Status Page
path: https://status.homelab.local
# Footer customization
footerText: 'Built with [Dashy](https://dashy.to) | Homelab 2025'
# Optional logo
logo: https://example.com/logo.png App Config Options
appConfig:
# Theming
theme: nord # Or: default, colorful, nord, dracula, etc.
customColors:
primary: '#3B82F6'
background: '#1F2937'
# Layout
layout: auto # Or: horizontal, vertical, auto
iconSize: medium # Or: small, medium, large
colCount: 1 # Number of columns (or 'auto')
# Behavior
startingView: default # Or: minimal, workspace
defaultOpeningMethod: newtab # Or: sametab, modal, workspace
statusCheck: true
statusCheckInterval: 60 # Seconds
# Search
enableFuzzySearch: true
searchHotkey: '/'
# Authentication
auth:
enableAuth: true
users:
- user: admin
hash: 4D3F... # bcrypt hash
type: admin Service Items Configuration
Basic service:
items:
- title: Portainer
description: Container management platform
url: http://portainer.local:9443
icon: hl-portainer
target: newtab Service with status check:
items:
- title: Jellyfin
url: http://jellyfin.local:8096
icon: hl-jellyfin
statusCheck: true
statusCheckUrl: http://jellyfin.local:8096/health
statusCheckAllowInsecure: true # For self-signed certs Service with custom icon:
items:
- title: Custom Service
url: http://custom.local
icon: /item-icons/custom-icon.png # Local file
# Or use Font Awesome
icon: fas fa-server
# Or use Homelab Icons library
icon: hl-proxmox Sections and Organization
Creating Service Sections
sections:
- name: Media Services
icon: fas fa-photo-video
displayData:
sortBy: default # Or: most-used, last-used, alphabetical
rows: 1
cols: 1
collapsed: false
hideForGuests: false
items:
- title: Jellyfin
url: http://jellyfin.local:8096
icon: hl-jellyfin
statusCheck: true
- title: Plex
url: http://plex.local:32400
icon: hl-plex
statusCheck: true
- title: Sonarr
url: http://sonarr.local:8989
icon: hl-sonarr
statusCheck: true Section Organization Patterns
By service category:
sections:
- name: Media
items: [...]
- name: Downloads
items: [...]
- name: Infrastructure
items: [...]
- name: Monitoring
items: [...] By environment:
sections:
- name: Production Services
items: [...]
- name: Development Services
items: [...]
- name: Staging Environment
items: [...] By physical location:
sections:
- name: Main Server
items: [...]
- name: NAS Services
items: [...]
- name: Raspberry Pi Services
items: [...] Collapsible and Hidden Sections
sections:
- name: Rarely Used Services
displayData:
collapsed: true # Start collapsed
hideForGuests: true # Hide from unauthenticated users
items: [...] Themes and Visual Customization
Built-in Themes
Popular themes:
appConfig:
theme: nord # Nord color palette
# Or:
theme: dracula # Dracula dark theme
theme: colorful # Vibrant colors
theme: nord-frost # Nord with blue accent
theme: material-dark # Material design dark
theme: material-light # Material design light
theme: gruvbox # Gruvbox color scheme
theme: high-contrast-light
theme: high-contrast-dark Switch themes easily:
Settings (cog icon) → Theme → Select from dropdown → Apply
Creating Custom Themes
appConfig:
customColors:
primary: '#3B82F6' # Primary accent color
background: '#1F2937' # Main background
background-darker: '#111827' # Darker background areas
item-background: '#374151' # Service tile background
item-background-hover: '#4B5563'
item-text-color: '#F9FAFB'
heading-text-color: '#F9FAFB'
settings-background: '#1F2937' Custom CSS
Add custom CSS:
Create dashy/custom.css:
/* Glassmorphism effect */
section {
background: rgba(255, 255, 255, 0.05) !important;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
/* Larger service tiles */
.item {
min-height: 80px;
padding: 1rem;
}
/* Custom hover effects */
.item:hover {
transform: translateY(-4px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
}
/* Custom section headers */
.section-title {
font-size: 1.5rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 2px;
} Reference in conf.yml:
appConfig:
customCss: '/item-icons/custom.css' Icon Customization
Icon sources:
Homelab Icons (built-in):
icon: hl-plex icon: hl-sonarr icon: hl-proxmoxFont Awesome:
icon: fas fa-server icon: fab fa-github icon: far fa-chart-barEmoji:
icon: emoji-rocket icon: emoji-gearCustom local icons:
icon: /item-icons/my-icon.pngExternal URLs:
icon: https://example.com/icon.png
Upload custom icons:
Place in /dashy/item-icons/ directory:
cp my-icon.png ~/dashy/dashy/item-icons/ Reference in config:
icon: /item-icons/my-icon.png Widgets
Adding Widgets
Widget configuration structure:
sections:
- name: Widgets
displayData:
hideForGuests: false
widgets:
- type: weather
options:
apiKey: your-api-key
city: New York
- type: clock
options:
format: en-US Popular Widgets
Weather widget:
widgets:
- type: weather
options:
apiKey: your-openweather-api-key
city: New York
units: imperial # Or: metric
hideDetails: false System info widget:
widgets:
- type: glances
options:
hostname: http://glances.local:61208
username: optional-username
password: optional-password Install Glances for system stats:
docker run -d --name glances --restart=always -p 61208:61208 -e GLANCES_OPT="-w" -v /var/run/docker.sock:/var/run/docker.sock:ro nicolargo/glances RSS feed widget:
widgets:
- type: rss-feed
options:
rssUrl: https://news.ycombinator.com/rss
apiKey: optional-rss2json-key
limit: 10
orderBy: pubDate Crypto price widget:
widgets:
- type: crypto-watch-list
options:
assets:
- bitcoin
- ethereum
- cardano
currency: USD
sortBy: marketCap
limit: 10 Public IP widget:
widgets:
- type: public-ip
options: {} Iframe widget (embed any site):
widgets:
- type: iframe
options:
url: https://grafana.local/dashboard
height: 400 Widget Layout
Arrange widgets in grid:
sections:
- name: Dashboard Widgets
displayData:
cols: 2 # Two columns of widgets
rows: 2 # Two rows
widgets:
- type: weather
options: [...]
- type: clock
options: [...]
- type: rss-feed
options: [...]
- type: crypto-watch-list
options: [...] Status Checks and Health Monitoring
Enabling Global Status Checks
appConfig:
statusCheck: true
statusCheckInterval: 60 # Seconds between checks Per-Service Status Checks
Basic HTTP ping:
items:
- title: Jellyfin
url: http://jellyfin.local:8096
statusCheck: true
statusCheckUrl: http://jellyfin.local:8096 # Optional: different check URL Custom health endpoint:
items:
- title: API Server
url: http://api.local
statusCheck: true
statusCheckUrl: http://api.local/health
statusCheckHeaders:
Authorization: Bearer token123 Accept self-signed certificates:
items:
- title: Proxmox
url: https://proxmox.local:8006
statusCheck: true
statusCheckAllowInsecure: true Expected status codes:
items:
- title: Service
url: http://service.local
statusCheck: true
statusCheckAcceptCodes: '200,201,204' # Accept any of these Status Indicators
Visual feedback:
- Green dot: Service is up (200-299 status)
- Red dot: Service is down (timeout or error)
- Orange dot: Service returned unexpected status code
- Grey dot: Status check disabled or pending
Click status indicator to see details:
- Last check time
- Response time (ms)
- Status code
- Error message (if any)
Authentication and Access Control
Enabling Authentication
Simple authentication:
appConfig:
auth:
enableAuth: true
users:
- user: admin
hash: 5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8 # SHA-256 hash of 'password'
type: admin
- user: viewer
hash: 1BA3D16E9881959F8C9A9762854F72C6E6321AC8F4748538BE0A
91C258F63BB # Hash of 'viewer123'
type: normal Generate password hash:
# Using Node.js
node -e "console.log(require('crypto').createHash('sha256').update('your-password').digest('hex'))"
# Or online tool (use with caution)
# https://emn178.github.io/online-tools/sha256.html Keycloak integration (advanced):
appConfig:
auth:
enableAuth: true
authType: keycloak
keycloak:
serverUrl: https://keycloak.local
realm: homelab
clientId: dashy Guest Access
Allow guest with limited access:
appConfig:
auth:
enableAuth: true
enableGuestAccess: true
sections:
- name: Public Services
displayData:
hideForGuests: false # Visible to guests
items: [...]
- name: Admin Services
displayData:
hideForGuests: true # Hidden from guests
items: [...] Advanced Features
Keyboard Shortcuts
Default shortcuts:
/- Focus searchEsc- Close search/modalAlt + M- Toggle minimal viewAlt + W- Toggle workspace viewAlt + T- Toggle theme
Custom keyboard shortcuts:
appConfig:
customKeyboardShortcuts:
- key: 'Alt+G'
action: 'open-search'
- key: 'Alt+1'
action: 'open-section'
section: 0 # First section
- key: 'Ctrl+R'
action: 'reload-page' Multi-Page Layouts
Create separate pages:
pages:
- name: Home
path: home.yml
- name: Media
path: media.yml
- name: Infrastructure
path: infra.yml Navigation between pages:
Top menu automatically shows page links.
Search Functionality
Global search:
- Press
/or click search icon - Type service name
- Results filter in real-time
- Press Enter to open first result
Fuzzy search:
appConfig:
enableFuzzySearch: true # Allows typos in search Web search integration:
appConfig:
webSearch:
searchEngine: duckduckgo # Or: google, bing, brave, etc.
openingMethod: newtab
searchBangs:
/r: reddit
/gh: github
/w: wikipedia Type /r homelab in search to search Reddit for “homelab”
Continuous Status Checks
Monitor services continuously:
appConfig:
statusCheck: true
statusCheckInterval: 30 # Check every 30 seconds
# Get browser notifications on status changes
enableNotifications: true Webhook on status change:
appConfig:
statusCheckWebhook:
url: https://webhook.site/your-unique-url
onDown: true
onUp: true Configuration Best Practices
Version Control
Track configuration in Git:
cd ~/dashy
git init
git add dashy/conf.yml
git commit -m "Initial Dashy configuration"
# Add remote
git remote add origin https://github.com/yourusername/dashy-config.git
git push -u origin main Benefits:
- History of changes
- Easy rollback
- Share with community
- Clone to new instances
Configuration Organization
Modular configs with includes:
# conf.yml
---
pageInfo:
title: Main Dashboard
sections:
- !include sections/media.yml
- !include sections/infrastructure.yml
- !include sections/monitoring.yml Separate files:
dashy/
├── conf.yml
├── sections/
│ ├── media.yml
│ ├── infrastructure.yml
│ └── monitoring.yml
└── item-icons/
└── custom-icons... Secrets Management
Don’t commit API keys:
# Use environment variables
appConfig:
auth:
users:
- user: admin
hash: ${ADMIN_PASSWORD_HASH}
widgets:
- type: weather
options:
apiKey: ${OPENWEATHER_API_KEY} Set environment variables:
# docker-compose.yml
services:
dashy:
environment:
- ADMIN_PASSWORD_HASH=5E884898DA...
- OPENWEATHER_API_KEY=your-api-key Backup Strategy
Automated backups:
#!/bin/bash
# backup-dashy.sh
BACKUP_DIR=~/dashy-backups
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup
cp ~/dashy/dashy/conf.yml $BACKUP_DIR/conf-$DATE.yml
# Keep only last 30 backups
ls -t $BACKUP_DIR/conf-*.yml | tail -n +31 | xargs rm -f
echo "Backup created: conf-$DATE.yml" Schedule with cron:
# Daily backup at 3 AM
0 3 * * * /home/user/backup-dashy.sh Real-World Configuration Examples
Media-Focused Dashboard
sections:
- name: Media Servers
icon: fas fa-play-circle
items:
- title: Jellyfin
url: http://jellyfin.local:8096
icon: hl-jellyfin
statusCheck: true
- title: Plex
url: http://plex.local:32400
icon: hl-plex
statusCheck: true
- name: Media Management
icon: fas fa-download
items:
- title: Sonarr
url: http://sonarr.local:8989
icon: hl-sonarr
statusCheck: true
- title: Radarr
url: http://radarr.local:7878
icon: hl-radarr
statusCheck: true
- title: Prowlarr
url: http://prowlarr.local:9696
icon: hl-prowlarr
statusCheck: true
- name: Download Clients
icon: fas fa-cloud-download-alt
items:
- title: qBittorrent
url: http://qbit.local:8080
icon: hl-qbittorrent
statusCheck: true Infrastructure Dashboard
sections:
- name: Virtualization
items:
- title: Proxmox
url: https://proxmox.local:8006
icon: hl-proxmox
statusCheck: true
statusCheckAllowInsecure: true
- title: TrueNAS
url: https://truenas.local
icon: hl-truenas
statusCheck: true
- name: Container Management
items:
- title: Portainer
url: https://portainer.local:9443
icon: hl-portainer
statusCheck: true
- title: Docker Registry
url: https://registry.local
icon: fab fa-docker
statusCheck: true
- name: Monitoring
items:
- title: Grafana
url: https://grafana.local:3000
icon: hl-grafana
statusCheck: true
- title: Uptime Kuma
url: https://uptime.local:3001
icon: hl-uptime-kuma
statusCheck: true Troubleshooting
Configuration Not Loading
Symptom: Changes to conf.yml don’t appear
Solutions:
# 1. Check YAML syntax
# Use online validator: https://www.yamllint.com/
# 2. Restart container
docker-compose restart dashy
# 3. Check logs for errors
docker logs dashy
# 4. Verify volume mount
docker inspect dashy | grep -A 5 Mounts Status Checks Failing
Symptom: All services show red/down
Solutions:
# 1. Allow more time
appConfig:
statusCheckInterval: 120 # Increase interval
# 2. Allow insecure HTTPS
items:
- title: Service
statusCheckAllowInsecure: true
# 3. Use correct URL
statusCheckUrl: http://service.local:port/health # Include port! Icons Not Displaying
Symptom: Broken image icons
Solutions:
# 1. Verify icon file exists
ls ~/dashy/dashy/item-icons/
# 2. Check volume mount
docker inspect dashy | grep item-icons
# 3. Use built-in icons
icon: hl-jellyfin # Instead of custom file Conclusion and Next Steps
Dashy delivers ultimate customization and privacy with its configuration-as-code approach and extensive feature set. You’ve learned:
- Installing and configuring Dashy via YAML
- Creating organized service sections
- Implementing themes and visual customization
- Adding interactive widgets
- Setting up status checks and monitoring
- Enabling authentication and access control
Key Takeaways
- Configuration-as-code enables version control and sharing
- Privacy-first design with no external dependencies
- Extensive theming with 50+ built-in options
- Powerful widgets for weather, stats, RSS, and more
- Status monitoring keeps track of service health
Recommended Next Steps
- Deploy Dashy and create your configuration
- Add all services with status checks enabled
- Customize theme to your preference
- Add widgets for weather, system stats
- Version control config in Git
Related Guides
- Homarr - Alternative dashboard with Docker focus
- Homepage - Simpler bookmark dashboard
- Uptime Kuma - Dedicated uptime monitoring
- Grafana - Advanced metrics visualization
Resources
- Official Documentation: dashy.to/docs
- GitHub: github.com/Lissy93/dashy
- Live Demo: demo.dashy.to
- Community Configs: github.com/Lissy93/dashy/discussions
Document Version: 1.0 Last Updated: December 16, 2025 Based on: Dashy 2.1+ Estimated Completion Time: 50 minutes
Happy dashboarding!