6.0 KiB
6.0 KiB
name, description, tags
| name | description | tags | ||||||
|---|---|---|---|---|---|---|---|---|
| homarr-dashboard-setup | Deploy, configure, and populate a Homarr dashboard — Docker setup, user management, bulk-adding services via direct SQLite manipulation, layout planning, and troubleshooting. |
|
Homarr Dashboard Setup
Populate a Homarr dashboard with all self-hosted services. Homarr stores everything in SQLite -- apps, items (widgets), layout positions. For bulk operations, direct database manipulation is faster than the web UI.
Quick reference
| Path | Value |
|---|---|
| Container | homarr |
| Image | ghcr.io/homarr-labs/homarr:latest |
| Port | 8080:7575 |
| Config dir | ./appdata (bind mount to /appdata) |
| DB location | <config>/db/db.sqlite |
| CLI tool | docker exec homarr homarr <command> |
User management
Create first admin (no users exist)
docker exec homarr homarr recreate-admin --username ray
# Shows a generated password
Set a specific password
docker exec homarr homarr users update-password \
--username ray \
--password 'your-password-here'
Reset password to random (all sessions terminated)
docker exec homarr homarr reset-password --username ray
List users
docker exec homarr homarr users list
Database schema (key tables)
app -- service definitions
id TEXT PRIMARY KEY -- 25-char alphanumeric ID
name TEXT -- display name
description TEXT -- optional tooltip
icon_url TEXT -- URL to icon
href TEXT -- click target URL
ping_url TEXT -- optional separate status-check URL
item -- widgets on the board
id TEXT PRIMARY KEY
board_id TEXT -- FK to board.id
kind TEXT -- 'app' for app widgets, 'clock', 'weather', etc.
options TEXT -- JSON: {"json":{"appId":"<app_id>","openInNewTab":true,"showTitle":true}}
advanced_options TEXT -- usually {"json":{}}
item_layout -- position/size on the grid
item_id TEXT -- FK to item.id
section_id TEXT -- FK to section.id
layout_id TEXT -- FK to layout.id
x_offset INTEGER
y_offset INTEGER
width INTEGER
height INTEGER
board -- the dashboard page
id TEXT PRIMARY KEY
name TEXT -- unique name
section -- a column/grid area on a board
id TEXT PRIMARY KEY
board_id TEXT -- FK to board.id
section_layout -- which layout template a section uses
id TEXT PRIMARY KEY
section_id TEXT -- FK to section.id
Bulk-adding services via SQLite
When adding 10+ services, direct SQLite inserts beat the UI. Steps:
1. Discover running services and their ports
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}'
ss -tlnp | grep LISTEN
2. Get board/section/layout IDs
SELECT id, name FROM board;
SELECT id, board_id FROM section;
SELECT id, section_id FROM section_layout;
3. Icon URLs
Use the Homarr dashboard-icons repository:
https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/<name>.png
https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/svg/<name>.svg
Common icons: immich.png, home-assistant.png, paperless-ngx.png, plex.png,
audiobookshelf.png, mealie.png, qbittorrent.png, pihole.png,
portainer.png, uptime-kuma.png, scrutiny.png, vaultwarden.png,
pocketbase.png, glitchtip.png, searxng.png, sunshine.png
For missing icons, fall back to chrome-beta.png or another generic icon.
4. Generate IDs
Homarr uses ~25-char alphanumeric IDs. Generate them in Python:
import secrets
def gen_id():
return secrets.token_urlsafe(16)[:25].replace('-','0').replace('_','1')
5. Insert apps
INSERT INTO app (id, name, icon_url, href) VALUES
('<id>', '<Name>', '<icon_url>', '<href>');
6. Insert items (one per app)
INSERT INTO item (id, board_id, kind, options, advanced_options) VALUES
('<item_id>', '<board_id>', 'app',
'{"json":{"appId":"<app_id>","openInNewTab":true,"showTitle":true}}',
'{"json":{}}');
7. Insert layout records
INSERT INTO item_layout (item_id, section_id, layout_id, x_offset, y_offset, width, height) VALUES
('<item_id>', '<section_id>', '<layout_id>', 0, 0, 1, 1);
8. Restart container
docker restart homarr
9. Verify
sqlite3 <db_path> \
"SELECT l.x_offset, l.y_offset, l.width, l.height, a.name
FROM item_layout l
JOIN item i ON l.item_id = i.id
LEFT JOIN app a ON json_extract(i.options, '$.json.appId') = a.id
ORDER BY l.y_offset, l.x_offset;"
Pitfalls
- DB owned by root: The SQLite file is created by the Docker container and owned by
root:root. Usesudoordocker execfor DB access. - Duplicate apps: Homarr auto-discovers Docker containers and inserts into the
apptable. You may see duplicate entries -- e.g. the auto-discoveredhomarr+ your manually createdHomarr. Clean up old items/layouts if needed. - Layout columns are
x_offset,y_offset: Notx/y. Forgetting this causes silent misplacement. - IDs must be unique across
itemandapptables: The random generator collisions are astronomically unlikely but verify if you suspect overlap. - Restart required: Direct DB writes are not live-reloaded. Always
docker restart homarrafter inserts. - Container restarts reset uncommitted changes: The DB is on a bind mount, but if your insert script hasn't committed before the container exits, changes are lost. Use explicit
connection.commit(). - json_extract in joins: When joining
itemtoapp, usejson_extract(i.options, '$.json.appId')to extract the app reference from the item's JSON options field. - Nginx proxy vs direct access: For services behind nginx on the same host, use
127.0.0.1:<port>. For services reaching other hosts or directly exposed, use192.168.50.98:<port>.