Compare commits

..
282 changed files with 11309 additions and 7630 deletions

No files matched your search

+1 -1
View File
@@ -37,4 +37,4 @@ Orient from the current checkout before editing. Treat package manifests, export
- Cron jobs: `packages/cron-jobs/src/jobs/` - Cron jobs: `packages/cron-jobs/src/jobs/`
- App routes: `apps/nextjs/src/app/[locale]/` - App routes: `apps/nextjs/src/app/[locale]/`
When a code change affects users, invoke `documentation-sync`. When exposing tRPC through MCP, invoke `mcp-integration`. Invoke `documentation-sync` when hidden capabilities or information not evident to an advanced user change, or existing guidance becomes inaccurate; follow the Documentation Sync criteria in `AGENTS.md`. When exposing tRPC through MCP, invoke `mcp-integration`.
+10 -6
View File
@@ -1,13 +1,17 @@
--- ---
name: documentation-sync name: documentation-sync
description: Keep Homarr's Fumadocs documentation aligned with user-facing code. Use when adding or changing integrations, widgets, APIs, environment variables, CLI commands, authentication, permissions, cron jobs, settings, or UI behavior that users must understand. description: Write concise Homarr docs for advanced users, covering only hidden capabilities and information not evident from the UI. Use when that information changes or existing guidance becomes inaccurate; skip obvious controls and routine fixes.
--- ---
# Documentation Sync # Documentation Sync
Update `apps/docs/` in the same change as user-facing behavior. Inspect adjacent pages and the docs types before copying a pattern; the source and docs evolve together. Apply the audience and scope rules in `AGENTS.md` first. Before adding a passage, identify what an advanced user could not learn directly from the interface. If there is no such information, omit it.
## Map the change For hidden capabilities such as the advanced widget feature, explain discovery, activation, and non-obvious behavior. For visible standard controls such as Delete, omit narration of what the label already conveys. Use the shortest explanation that preserves necessary technical detail; remove redundant prose in the passage being edited.
When an update is warranted, inspect adjacent pages for structure and types, not as a verbosity target. The mappings below locate needed information; they do not require a page for every feature or code change.
## Locate a needed update
| Code change | Documentation target | | Code change | Documentation target |
| ----------------------------------- | -------------------------------------------------------------------- | | ----------------------------------- | -------------------------------------------------------------------- |
@@ -40,12 +44,12 @@ For a widget:
- Add or update `apps/docs/docs/widgets/<slug>/index.ts` with the local `WidgetDefinition` pattern. - Add or update `apps/docs/docs/widgets/<slug>/index.ts` with the local `WidgetDefinition` pattern.
- Add or update `index.mdx` with the established `WidgetHeader`, `WidgetConfig`, and `AddingWidget` components as applicable. - Add or update `index.mdx` with the established `WidgetHeader`, `WidgetConfig`, and `AddingWidget` components as applicable.
- Document options, required integrations, permissions, empty states, and changed behavior that affect setup or use. - Explain only non-obvious option semantics, integration prerequisites, permission constraints, or behavior that the interface does not make clear.
## Completion criteria ## Completion criteria
1. Describe the shipped behavior, not an implementation plan. 1. Every passage adds information an advanced user cannot reasonably infer from the interface. Remove obvious, repetitive, or unnecessary prose.
2. Keep names, defaults, paths, screenshots, links, and prerequisites consistent with code. 2. Keep names, defaults, paths, screenshots, links, and prerequisites consistent with code.
3. Update every affected page and remove superseded guidance. 3. Update every affected page and remove superseded guidance.
4. Run the narrowest useful docs validation. Use `pnpm turbo build --filter=@homarr/docs` when links, MDX, generated definitions, or navigation can fail; otherwise run the docs package formatter on touched files. 4. Run the narrowest useful docs validation. Use `pnpm turbo build --filter=@homarr/docs` when links, MDX, generated definitions, or navigation can fail; otherwise run the docs package formatter on touched files.
5. Treat broken links and anchors as failures; run `pnpm --filter @homarr/docs validate:links` after the static build. 5. Treat broken links and anchors as failures; Docusaurus checks them strictly.
+3 -2
View File
@@ -16,9 +16,10 @@ LOG_LEVEL='info'
# This is how you can use the sqlite driver: # This is how you can use the sqlite driver:
DB_DRIVER='better-sqlite3' DB_DRIVER='better-sqlite3'
# Safe local source-development path. SQLite files are ignored by Git. # Set an absolute writable SQLite path so migrations and the app use the same file.
# Their working directories differ; do not use a relative path here.
# Container images use /appdata/db/db.sqlite by default instead. # Container images use /appdata/db/db.sqlite by default instead.
DB_URL='./db.sqlite' DB_URL=
# Those are the two ways to use the mysql2 driver: # Those are the two ways to use the mysql2 driver:
# 1. Using the URL format: # 1. Using the URL format:
+19 -8
View File
@@ -16,10 +16,10 @@ permissions:
jobs: jobs:
create-and-merge-pr: create-and-merge-pr:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 2 timeout-minutes: 10
steps: steps:
- name: Discord notification - name: Discord notification
if: ${{ github.event.inputs.send-notifications }} if: ${{ inputs.send-notifications }}
env: env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
uses: Ilshidur/action-discord@0.4.0 uses: Ilshidur/action-discord@0.4.0
@@ -37,11 +37,22 @@ jobs:
branch: next branch: next
- name: Create pull request - name: Create pull request
id: create-pull-request id: create-pull-request
run: 'gh pr create --title "chore(release): release ${{ steps.semver.outputs.next }}-beta" --body "Detected change to be ``${{ steps.semver.outputs.bump }}``<br/>Bump version from ``${{ steps.semver.outputs.current }}`` to ``${{ steps.semver.outputs.next }}-beta``" --base beta --head next --label automerge' run: |
pr_url="$(gh pr list --base beta --head next --state open --json url --jq '.[0].url // empty')"
if [[ -z "$pr_url" ]]; then
pr_url="$(gh pr create \
--title "chore(release): release ${{ steps.semver.outputs.next }}-beta" \
--body "Detected change to be ${{ steps.semver.outputs.bump }}<br/>Bump version from ${{ steps.semver.outputs.current }} to ${{ steps.semver.outputs.next }}-beta" \
--base beta \
--head next \
--label automerge)"
fi
echo "url=$pr_url" >> "$GITHUB_OUTPUT"
echo "pr_number=${pr_url##*/}" >> "$GITHUB_OUTPUT"
env: env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- name: Discord notification - name: Discord notification
if: ${{ github.event.inputs.send-notifications }} if: ${{ inputs.send-notifications }}
env: env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
uses: Ilshidur/action-discord@0.4.0 uses: Ilshidur/action-discord@0.4.0
@@ -58,7 +69,7 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ steps.obtainApprovalToken.outputs.token }} GITHUB_TOKEN: ${{ steps.obtainApprovalToken.outputs.token }}
run: | run: |
gh pr review --approve --body "Automatically approved by GitHub Action" gh pr review "${{ steps.create-pull-request.outputs.url }}" --approve --body "Automatically approved by GitHub Action"
- name: Obtain token - name: Obtain token
id: obtainMergeToken id: obtainMergeToken
uses: actions/create-github-app-token@v3 uses: actions/create-github-app-token@v3
@@ -82,21 +93,21 @@ jobs:
MERGE_REQUIRED_APPROVALS: 0 # do not require approvals MERGE_REQUIRED_APPROVALS: 0 # do not require approvals
- name: Merged Discord notification - name: Merged Discord notification
if: ${{ steps.automerge.outputs.mergeResult == 'merged' && github.event.inputs.send-notifications }} if: ${{ steps.automerge.outputs.mergeResult == 'merged' && inputs.send-notifications }}
env: env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
uses: Ilshidur/action-discord@0.4.0 uses: Ilshidur/action-discord@0.4.0
with: with:
args: "Merged PR ${{ steps.create-pull-request.outputs.url }} for release ${{ steps.semver.outputs.next }}-beta" args: "Merged PR ${{ steps.create-pull-request.outputs.url }} for release ${{ steps.semver.outputs.next }}-beta"
- name: Major Bump Discord notification - name: Major Bump Discord notification
if: ${{ steps.semver.outputs.bump == 'major' && github.event.inputs.send-notifications }} if: ${{ steps.semver.outputs.bump == 'major' && inputs.send-notifications }}
env: env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
uses: Ilshidur/action-discord@0.4.0 uses: Ilshidur/action-discord@0.4.0
with: with:
args: "The release PR must be manually merged because the next version is a major version: ${{ steps.create-pull-request.outputs.url }} for release ${{ steps.semver.outputs.next }}-beta" args: "The release PR must be manually merged because the next version is a major version: ${{ steps.create-pull-request.outputs.url }} for release ${{ steps.semver.outputs.next }}-beta"
- name: Discord Fail Notification - name: Discord Fail Notification
if: failure() && github.event.inputs.send-notifications if: ${{ failure() && inputs.send-notifications }}
env: env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
uses: Ilshidur/action-discord@0.4.0 uses: Ilshidur/action-discord@0.4.0
+1 -5
View File
@@ -37,16 +37,12 @@ jobs:
run: pnpm turbo build --filter=@homarr/docs run: pnpm turbo build --filter=@homarr/docs
env: env:
CI: "true" CI: "true"
- name: Validate exported links and search
run: |
pnpm --filter @homarr/docs validate:links
pnpm --filter @homarr/docs verify:search
- name: Setup Pages - name: Setup Pages
uses: actions/configure-pages@v6 uses: actions/configure-pages@v6
- name: Upload pages artifact - name: Upload pages artifact
uses: actions/upload-pages-artifact@v5 uses: actions/upload-pages-artifact@v5
with: with:
path: "apps/docs/out" path: "apps/docs/build"
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -0,0 +1,58 @@
name: "[Docs] Algolia Recrawl"
on:
workflow_run:
workflows: ["[Deployment] Documentation"]
types: [completed]
branches: [dev]
workflow_dispatch:
permissions:
contents: read
jobs:
recrawl:
if: >-
${{
(github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request')
|| github.event_name == 'workflow_dispatch'
}}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- name: Setup
uses: ./tooling/github/setup
- name: Check Algolia crawler secrets
run: |
missing=0
for secret in ALGOLIA_CRAWLER_ID ALGOLIA_CRAWLER_USER_ID ALGOLIA_CRAWLER_API_KEY; do
if [ -z "${!secret}" ]; then
echo "::warning::Missing repository secret: $secret"
missing=1
fi
done
if [ "$missing" -eq 1 ]; then
echo "Add crawler secrets to enable automatic recrawls."
exit 1
fi
env:
ALGOLIA_CRAWLER_ID: ${{ secrets.ALGOLIA_CRAWLER_ID }}
ALGOLIA_CRAWLER_USER_ID: ${{ secrets.ALGOLIA_CRAWLER_USER_ID }}
ALGOLIA_CRAWLER_API_KEY: ${{ secrets.ALGOLIA_CRAWLER_API_KEY }}
- name: Wait for GitHub Pages to serve the new deployment
run: sleep 60
- name: Trigger Algolia DocSearch recrawl
uses: cssnr/algolia-crawler-action@v2
with:
crawler_id: ${{ secrets.ALGOLIA_CRAWLER_ID }}
crawler_user_id: ${{ secrets.ALGOLIA_CRAWLER_USER_ID }}
crawler_api_key: ${{ secrets.ALGOLIA_CRAWLER_API_KEY }}
- name: Verify search index
working-directory: apps/docs
run: pnpm verify:search
@@ -33,7 +33,7 @@ jobs:
- name: Commit updated contributors - name: Commit updated contributors
uses: EndBug/add-and-commit@v10 uses: EndBug/add-and-commit@v10
with: with:
add: "apps/docs/public" add: "apps/docs/static"
default_author: github_actor default_author: github_actor
message: "chore(docs): update contributors" message: "chore(docs): update contributors"
push: true push: true
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
- name: Commit updated spec - name: Commit updated spec
uses: EndBug/add-and-commit@v10 uses: EndBug/add-and-commit@v10
with: with:
add: "apps/docs/public/api/" add: "apps/docs/static/api/"
default_author: github_actor default_author: github_actor
message: "chore(docs): update OpenAPI spec" message: "chore(docs): update OpenAPI spec"
push: true push: true
+11 -5
View File
@@ -6,7 +6,7 @@
homarr/ homarr/
├── apps/ ├── apps/
│ ├── nextjs/ # Main Next.js application (port 3000) │ ├── nextjs/ # Main Next.js application (port 3000)
│ ├── docs/ # Next.js + Fumadocs documentation site (@homarr/docs) │ ├── docs/ # Docusaurus 3 documentation site (@homarr/docs)
│ ├── tasks/ # Cron-job initialization and scheduling runtime │ ├── tasks/ # Cron-job initialization and scheduling runtime
│ ├── websocket/ # Standalone tRPC WebSocket server (port 3001) │ ├── websocket/ # Standalone tRPC WebSocket server (port 3001)
│ └── workshop/ # Go/PocketBase Workshop service │ └── workshop/ # Go/PocketBase Workshop service
@@ -57,9 +57,15 @@ homarr/
## Documentation Sync ## Documentation Sync
The documentation site lives at `apps/docs/` (Next.js + Fumadocs, `@homarr/docs`). The documentation site lives at `apps/docs/` (Docusaurus 3, `@homarr/docs`).
When modifying user-facing code, you MUST also update the corresponding documentation: Write for smart, curious, advanced users. Documentation should contain only information they cannot reasonably discover or understand directly from the interface: hidden capabilities, non-obvious behavior, prerequisites, constraints, configuration contracts, and migration requirements.
Keep docs concise. Every paragraph must add knowledge beyond visible labels and standard UI conventions. Explain how to discover and use a hidden advanced widget feature; omit explanations that the Delete button deletes an item in edit mode. Avoid UI walkthroughs, exhaustive control descriptions, and repetition. When editing a passage, remove obvious or redundant prose rather than preserving verbosity as a precedent.
Update docs only when a change introduces or alters that non-obvious information, or makes existing guidance inaccurate. Routine fixes and self-explanatory UI changes need no docs update. A new feature alone does not require a page; apply the same reader-value test.
When documentation is needed, use these locations:
- New integration → `apps/docs/docs/integrations/<slug>/index.mdx` + `index.ts` - New integration → `apps/docs/docs/integrations/<slug>/index.mdx` + `index.ts`
- New widget → `apps/docs/docs/widgets/<slug>/index.mdx` + `index.ts` - New widget → `apps/docs/docs/widgets/<slug>/index.mdx` + `index.ts`
@@ -75,7 +81,7 @@ When modifying user-facing code, you MUST also update the corresponding document
- `pnpm dev:cli -- dev` — run the developer CLI without installing a global binary - `pnpm dev:cli -- dev` — run the developer CLI without installing a global binary
- `pnpm db:seed` — seed default database data explicitly - `pnpm db:seed` — seed default database data explicitly
- `pnpm docker:dev:up` — start the Redis development service in the background - `pnpm docker:dev:up` — start the Redis development service in the background
- `pnpm dev:docs` — Fumadocs site only - `pnpm dev:docs` — Docusaurus docs site only
- `pnpm turbo build` — build all packages - `pnpm turbo build` — build all packages
- `pnpm turbo build --filter=@homarr/docs` — build docs only - `pnpm turbo build --filter=@homarr/docs` — build docs only
- `pnpm turbo typecheck` — typecheck all packages - `pnpm turbo typecheck` — typecheck all packages
@@ -99,6 +105,6 @@ When modifying user-facing code, you MUST also update the corresponding document
Portable skills live in `.agents/skills/`. Read the relevant `SKILL.md` before working in that domain; detailed references are loaded only when needed. Claude-compatible discovery is provided through `.claude/skills`. Portable skills live in `.agents/skills/`. Read the relevant `SKILL.md` before working in that domain; detailed references are loaded only when needed. Claude-compatible discovery is provided through `.claude/skills`.
- `codebase-context` — architecture, package boundaries, and shared utilities - `codebase-context` — architecture, package boundaries, and shared utilities
- `documentation-sync` — required user-facing documentation updates - `documentation-sync` — documentation for changes users need explained
- `mcp-integration` — safe tRPC-to-MCP exposure - `mcp-integration` — safe tRPC-to-MCP exposure
- `homarr-custom-widget` — safe Custom JSX v2 authoring - `homarr-custom-widget` — safe Custom JSX v2 authoring
+1 -2
View File
@@ -13,7 +13,6 @@
# next.js # next.js
/.next/ /.next/
/out/ /out/
/.source/
# production # production
/build /build
@@ -56,4 +55,4 @@ static/data/configs
# CI Stuff # CI Stuff
screenshots screenshots
test-results test-results
-18
View File
@@ -1,18 +0,0 @@
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.
This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.
<!-- END:nextjs-agent-rules -->
## Fumadocs workflow
- Start with `README.md`, `src/lib/source.ts`, `source.config.ts`, and the matching route under `src/app/`.
- Read current [Fumadocs documentation](https://fumadocs.dev/docs) with Context7 before changing framework APIs. Check the installed version and types; latest examples may use a different search adapter.
- Preserve static export: search uses `staticGET` with the matching static client. Do not introduce a request-time search server into this app.
- Keep integration/widget metadata in the existing typed definitions. Check both rendered HTML and processed Markdown when changing MDX components; JSX alone does not guarantee readable search or AI output.
- Run the README validation commands after content or navigation changes. Search results and table-of-contents links must resolve to rendered anchors.
- Kapa is an independent hosted assistant. Keep its keyboard shortcut disabled so it does not override docs search; follow the README for its build configuration and crawler setup.
-1
View File
@@ -1 +0,0 @@
@AGENTS.md
-37
View File
@@ -1,37 +0,0 @@
# Homarr Documentation
## Register
product
## Users
People who run Homarr, administrators configuring self-hosted infrastructure, and contributors extending Homarr. They arrive with a concrete task such as installing Homarr, connecting a service, configuring a widget, managing users, or building a custom widget, and need an answer they can scan and apply quickly.
## Product Purpose
The documentation is the complete, authoritative operating guide for Homarr. It keeps setup steps, configuration contracts, screenshots, generated integration and widget metadata, API references, and Workshop tooling next to the application code. Success means a reader can find the right page quickly, understand the next action, copy reliable instructions, and verify the result without searching elsewhere.
## Brand Personality
Focused, dependable, and approachable. The writing is direct and practical. The interface should feel calm and familiar during long technical sessions while retaining Homarr's red identity.
## Anti-references
- Generic marketing layouts that replace Homarr's product identity with unrelated slogans or decorative conversion copy.
- Decorative dashboard aesthetics that compete with reading, including glass effects, large radii, card grids, and gratuitous motion.
- Generic generated-docs styling that obscures Homarr's identity or makes navigation feel detached from the main product.
- Dense reference portals that expose structure without giving readers a clear path through a task.
## Design Principles
1. Put the reader's task first: search, navigation, page outline, and the answer must remain easy to reach.
2. Preserve one source of truth: typed Homarr metadata and existing custom components stay connected to the monorepo.
3. Prefer familiar documentation patterns: the interface should disappear while a reader scans, copies, and follows instructions.
4. Make complete content feel manageable through strong hierarchy, progressive disclosure, and precise cross-links.
5. Treat machine readers as users through canonical Markdown, structured metadata, and standard LLM discovery endpoints.
6. Keep the root landing page recognizably Homarr: preserve its self-hosted dashboard promise and real product evidence while documentation routes remain task-first.
## Accessibility & Inclusion
Meet WCAG 2.2 AA for color contrast, keyboard operation, focus visibility, landmarks, headings, and interactive controls. Respect reduced-motion and system color-scheme preferences. Diagrams, screenshots, icons, and emoji must have meaningful text alternatives when they carry information.
+83 -55
View File
@@ -1,84 +1,112 @@
# Homarr documentation (`@homarr/docs`) # Homarr Documentation (`@homarr/docs`)
The source for [homarr.dev](https://homarr.dev), built with Next.js and Fumadocs UI inside the Homarr monorepo. The official [homarr.dev](https://homarr.dev) documentation site, built with [Docusaurus 3](https://docusaurus.io/) and living inside the Homarr monorepo.
## Develop ## Why it's in the monorepo
From the repository root: Having documentation alongside the application code enables:
- **Two-way linking** — the docs app imports from `@homarr/definitions` for type-safe integration/widget metadata, and the main app references doc paths via generated sitemap types
- **Atomic PRs** — code changes and their documentation updates ship in the same pull request
- **Shared tooling** — same Node version, pnpm catalog, oxlint/oxfmt, CI pipeline
- **Build-time validation** — Docusaurus strict mode catches broken links and references at build time
## Development
From the **monorepo root**:
```bash ```bash
# Start the docs dev server (port 3003)
pnpm dev:docs pnpm dev:docs
```
The site runs on `http://127.0.0.1:3003`. To use a local Workshop API: # Or from within this directory
pnpm dev
```bash # Point the docs at a local PocketBase instance
WORKSHOP_API_URL=http://127.0.0.1:8090 pnpm dev:docs WORKSHOP_API_URL=http://127.0.0.1:8090 pnpm dev:docs
``` ```
## Validate The standalone docs use `WORKSHOP_API_URL` for PocketBase and `HOMARR_WEBSITE_URL` for the public site origin. The old
`WORKSHOP_URL` name is a deprecated one-release alias.
## Build
```bash ```bash
pnpm --filter @homarr/docs typecheck # Build docs only
pnpm --filter @homarr/docs build pnpm turbo build --filter=@homarr/docs
pnpm --filter @homarr/docs validate:links
pnpm --filter @homarr/docs verify:search # Build everything (docs + main app + tasks + websocket)
pnpm build
``` ```
The static export is written to `out/`. The build validates that every registered integration and widget has a docs ## Lint & Format
page. The link check validates internal Markdown and MDX links and rendered anchors against that export.
The search check exercises the exported index with title, heading, and body queries and verifies result destinations.
## Write content Uses oxlint and oxfmt (same as the rest of the monorepo):
Documentation lives in `docs/`; project posts live in `blog/`. Navigation is controlled by the nearest `meta.json`. ```bash
Integration and widget folders pair typed `index.ts` metadata with `index.mdx` content. pnpm lint # oxlint
pnpm format # oxfmt (check)
pnpm format:fix # oxfmt (fix)
```
Use standard Markdown and MDX. Shared components live in `src/components/`. Mermaid fences, tabs, callouts, zoomable ## Typecheck
images, and syntax-highlighted code are supported by the Fumadocs pipeline.
When a user-facing change affects setup or behavior, update the matching page in the same pull request. See the ```bash
[documentation-sync skill](../../.agents/skills/documentation-sync/SKILL.md) for the code-to-content map. pnpm typecheck
```
## Published formats ## Content Structure
- `/docs` — searchable documentation with typed navigation ```
- `/api-reference` — interactive reference generated from the OpenAPI schema docs/
- `/llms.txt` — compact documentation and blog index for agents ├── getting-started/ # Installation guides, glossary, prerequisites
- `/llms-full.txt` — complete processed Markdown corpus ├── management/ # Boards, apps, users, integrations, settings, tasks, API
- `/llms.mdx/docs/.../content.md` — raw Markdown for each docs page ├── integrations/ # 56 integration guides (one folder each)
- `/llms.mdx/blog/.../content.md` — raw Markdown for each blog post ├── widgets/ # 43 widget guides (one folder each)
- `/blog/rss.xml` — RSS feed for project posts ├── advanced/ # SSO, env vars, proxy, styling, CLI, development
└── community/ # FAQ, donate, license, translations, get-in-touch
```
Every docs page and blog post includes copy-Markdown and view-source actions. Search is generated at build time and Each integration/widget doc follows a consistent pattern:
runs locally in the browser; it does not depend on an external crawler. Markdown exports and search resolve
integration credentials and widget defaults from the same typed metadata used by the pages.
The getting-started overview and complete Custom JSX component catalog are also included, with property types,
binding contracts, and blocked capabilities taken from the published catalog JSON.
Published Docusaurus `/docs/category/...` addresses remain available as static compatibility pages. They forward to - `index.ts` — typed metadata (`IntegrationDefinition` / `WidgetDefinition`)
the corresponding overview or developer setup guide, preserving query strings and anchors, and provide a direct - `index.mdx` — content using shared React components (`IntegrationHeader`, `WidgetHeader`, etc.)
link when JavaScript is disabled. Their canonical metadata points to the destination; compatibility pages are
excluded from search and the sitemap.
## Kapa AI ## Importing from homarr packages
The **Ask AI** launcher uses Homarr's existing public Kapa Website ID. The root layout loads the widget once across The docs app has `@homarr/definitions` as a workspace dependency. You can import integration kinds, widget kinds, and other definitions directly:
client-side navigation. **Search** and `Ctrl+K` / `Cmd+K` always use Fumadocs search, including when Kapa is unavailable.
Set `KAPA_WEBSITE_ID` at build time to use a different Kapa Website Widget integration. An explicitly empty value ```typescript
disables the widget, for example `KAPA_WEBSITE_ID= pnpm --filter @homarr/docs build`. This is a public integration ID import { IntegrationKind } from "@homarr/definitions";
included in exported pages, not a Kapa API key. Rebuild the static export after changing it. ```
In the Kapa dashboard, confirm the integration is live and enable the production and preview domains. Restoring the This enables type-safe references to homarr domain concepts within documentation code.
script does not verify that the historical integration is still active. Follow the
[Kapa widget setup](https://docs.kapa.ai/integrations/website-widget/quickstart) for domain restrictions and CSP settings.
After changing the documentation structure, review the Website Crawl source in Kapa: use the deployed `/docs` URL as ## Search (Algolia DocSearch)
the start URL and preview `main` as the content selector. Replace any old Docusaurus-specific selector and check that
titles, headings, code samples, and integration details appear in the extracted Markdown. Docs are exported as HTML;
the site also publishes `/sitemap.xml` and permits crawling in `/robots.txt`. The `/llms.txt` exports do not configure
Kapa ingestion automatically. See [Kapa source setup](https://docs.kapa.ai/getting-started/index-your-first-source).
Before publishing, check that Ask AI opens after navigating between pages, ask a documentation question, and verify Search uses the `Docusaurus` Algolia index (crawler `cd77a285-2756-4557-bf21-ee703748df15`). A separate `markdown` index is built for LLM markdown indexing.
its citations point to the current docs. In a separate check, block `widget.kapa.ai` and confirm search still works.
Crawler reference config: [`docsearch.config.js`](docsearch.config.js).
**Verify search health:**
```bash
pnpm verify:search
```
## Tech Stack
| Layer | Technology |
| -------------- | ------------------------------------------- |
| Site generator | Docusaurus 3 (`@docusaurus/preset-classic`) |
| Styling | Tailwind CSS 4 + Docusaurus Infima |
| Icons | `@tabler/icons-react` |
| Diagrams | Mermaid (`@docusaurus/theme-mermaid`) |
| Search | Algolia DocSearch |
| Analytics | PostHog |
| Charts | @nivo/line |
## Contributing
When a Homarr change affects user-facing behavior, update the corresponding documentation in this app. See the
[documentation-sync skill](../../.agents/skills/documentation-sync/SKILL.md) for the code-to-documentation mapping.
@@ -1,7 +1,6 @@
--- ---
slug: documentation-migration slug: documentation-migration
title: Migration of Documentation title: Migration of Documentation
date: 2022-06-22
authors: authors:
- ajnart - ajnart
- manuel-rw - manuel-rw
@@ -13,7 +12,7 @@ The documentation has been re-written partly and includes now many animations, g
We are still figuring things out and highly depend on your feedback. We are still figuring things out and highly depend on your feedback.
{/* Historical excerpt boundary. */} <!-- truncate -->
## Why we migrated ## Why we migrated
@@ -33,4 +32,4 @@ After we've reviewed your changes, we'll merge your PR and this documentation wi
## TL;DR ## TL;DR
The documentation on GitHub Wiki will soon disappear. It will be replaced with this Docusaurus-powered website. You'll find much more information here with higher detail and searchability. The documentation on GitHub Wiki will soon disappear. It will be replaced with this Docusaurus-powered website. You'll find much more information here with higher detail and searchability.
@@ -1,7 +1,6 @@
--- ---
slug: translations slug: translations
title: Help us make Homarr multilingual title: Help us make Homarr multilingual
date: 2022-08-28
authors: authors:
- ajnart - ajnart
- manuel-rw - manuel-rw
@@ -14,8 +13,8 @@ We've been working hard to offer Homarr in many languages. The next update of Ho
![](img/homarr-we-need-you.webp) <br/> ![](img/homarr-we-need-you.webp) <br/>
Yes, we need **YOU**! We want to make Homarr accessible to as many people as possible. Thus, we need to translate all content into many different languages. We need your help for that! [You can help us now to translate Homarr into as many languages as possible](/docs/community/translations). Yes, we need **YOU**! We want to make Homarr accessible to as many people as possible. Thus, we need to translate all content into many different languages. We need your help for that! [You can help us now to translate Homarr into as many languages as possible](/docs/community/translations).
{/* Historical excerpt boundary. */} <!-- truncate -->
### About global translations / translations per user ### About global translations / translations per user
We are aware that many people would like to configure translations globally or configure language per user. Currently, translations are stored in the Cookies, which will expire after some time (currently, it's set to 30 days). We will implement more granular language settings in future versions of Homarr, since it requires major changes to Homarr. Stay tuned! 😎 We are aware that many people would like to configure translations globally or configure language per user. Currently, translations are stored in the Cookies, which will expire after some time (currently, it's set to 30 days). We will implement more granular language settings in future versions of Homarr, since it requires major changes to Homarr. Stay tuned! 😎
@@ -1,6 +1,5 @@
--- ---
title: "We present: Homarr 0.11 - the most complex Homarr version yet!" title: "We present: Homarr 0.11 - the most complex Homarr version yet!"
date: 2023-01-11
authors: authors:
- ajnart - ajnart
- manuel-rw - manuel-rw
@@ -21,7 +20,7 @@ It contains many breaking changes and huge improvements to your favourite dashbo
- Huge design and usability improvements to older components to Homarr - Huge design and usability improvements to older components to Homarr
- Better handeling of exceptions and unexpected issues - Better handeling of exceptions and unexpected issues
{/* Historical excerpt boundary. */} <!-- truncate -->
## Complete implementation of highly customizable drag and drop library "Gridstack" ## Complete implementation of highly customizable drag and drop library "Gridstack"
@@ -1,6 +1,5 @@
--- ---
title: "We present: Homarr 0.12 - The fastest homarr version ever!" title: "We present: Homarr 0.12 - The fastest homarr version ever!"
date: 2023-04-16
authors: authors:
- ajnart - ajnart
- manuel-rw - manuel-rw
@@ -16,12 +15,14 @@ This applies to all widgets, but in the case of the IFrame widget, it enables yo
- Integrate monitoring tools like Grafana, Splunk or Elasticsearch - Integrate monitoring tools like Grafana, Splunk or Elasticsearch
- Integrate your services (for example Sonarr, Radarr and Overseerr) directly into Homarr - Integrate your services (for example Sonarr, Radarr and Overseerr) directly into Homarr
![](https://media.discordapp.net/attachments/988335098493542410/1094665745226539168/update-teaser.png?width=1046&height=666)
## Edit mode password ## Edit mode password
We've added a setting to disable editing completely. This will allow you to restrict edit access without password-protection. We've added a setting to disable editing completely. This will allow you to restrict edit access without password-protection.
use the `EDIT_MODE_PASSWORD` ENV variable to set a password for edit mode. use the `EDIT_MODE_PASSWORD` ENV variable to set a password for edit mode.
turn on `DISABLE_EDIT_MODE=TRUE` to disable edit mode on startup. turn on `DISABLE_EDIT_MODE=TRUE` to disable edit mode on startup.
{/* Historical excerpt boundary. */} <!-- truncate -->
## 😎 Blazingly fast ## 😎 Blazingly fast
We've implemented a new caching system, that will cache all data in your browser, meaning that Homarr will load within milliseconds, as if it was *powered by rust and blazingly fast* !!! We've implemented a new caching system, that will cache all data in your browser, meaning that Homarr will load within milliseconds, as if it was *powered by rust and blazingly fast* !!!
@@ -71,4 +72,4 @@ Now, you can use the following environment variables to configure this:
- ``DOCKER_HOST`` - ``DOCKER_HOST``
- ``DOCKER_PORT`` - ``DOCKER_PORT``
**Full Changelog**: https://github.com/ajnart/homarr/compare/v0.11.5...v0.12.0 **Full Changelog**: https://github.com/ajnart/homarr/compare/v0.11.5...v0.12.0
@@ -1,6 +1,5 @@
--- ---
title: "Authentication in Homarr - 0.14 is here!" title: "Authentication in Homarr - 0.14 is here!"
date: 2023-11-10
authors: authors:
- ajnart - ajnart
- manuel-rw - manuel-rw
@@ -24,7 +23,7 @@ provide you a viable solution today.
- 📝 Overhauled notepad widget with a complex graphical editor that enables easy editing right from your browser. - 📝 Overhauled notepad widget with a complex graphical editor that enables easy editing right from your browser.
- :globe_with_meridians: Live Translation on Crowdin that enable you to directly translate using images to see what exactly you're translating - :globe_with_meridians: Live Translation on Crowdin that enable you to directly translate using images to see what exactly you're translating
{/* Historical excerpt boundary. */} <!-- truncate -->
## Breaking changes ## Breaking changes
@@ -84,4 +83,4 @@ We are aware that this update has many breaking changes and may confuse some use
For that reason, we updated our documentation and will enhance it further within the next few weeks. For that reason, we updated our documentation and will enhance it further within the next few weeks.
We've also added this small button at the bottom of the page were you can ask **your questions** to an AI assistant: We've also added this small button at the bottom of the page were you can ask **your questions** to an AI assistant:
![image](https://github.com/ajnart/homarr/assets/30572287/a56f721a-d022-42ad-813a-d85c89462a8c) ![image](https://github.com/ajnart/homarr/assets/30572287/a56f721a-d022-42ad-813a-d85c89462a8c)
@@ -1,6 +1,5 @@
--- ---
title: "Updated documentation with better organization & design" title: "Updated documentation with better organization & design"
date: 2023-12-22
authors: authors:
- manuel-rw - manuel-rw
tags: [homarr, documentation, design, docs] tags: [homarr, documentation, design, docs]
@@ -9,7 +8,7 @@ tags: [homarr, documentation, design, docs]
We'd like to let you know that we've updated our documentation and reorganized the pages. We'd like to let you know that we've updated our documentation and reorganized the pages.
This means, that some links may no longer be valid - we apologise if this causes any inconvenience for you. This means, that some links may no longer be valid - we apologise if this causes any inconvenience for you.
{/* Historical excerpt boundary. */} <!-- truncate -->
A few highlights include: A few highlights include:
@@ -19,4 +18,4 @@ A few highlights include:
- Bug fixes for image zoom - Bug fixes for image zoom
- Added documentation for management pages and [new CLI tool](/docs/advanced/command-line/password-recovery/) - Added documentation for management pages and [new CLI tool](/docs/advanced/command-line/password-recovery/)
Please [let us know](/docs/community/get-in-touch) is something is not working as expected. Please [let us know](/docs/community/get-in-touch) is something is not working as expected.
@@ -1,10 +1,9 @@
--- ---
title: Homarr 1.0 - complete rewrite of all systems
date: 2024-09-23
authors: authors:
- manuel-rw - manuel-rw
--- ---
# Homarr 1.0 - complete rewrite of all systems
We proudly present to you - Homarr ``1.0``. We proudly present to you - Homarr ``1.0``.
We have started work on this new version back in 2023 and have worked tirelessly for months on this brand-new dashboard. We have started work on this new version back in 2023 and have worked tirelessly for months on this brand-new dashboard.
@@ -29,7 +28,7 @@ reliability and scalability compared to < ``1.0``.
- **Improved performance**: We have upgraded the underlying framework of Homarr and take advantage - **Improved performance**: We have upgraded the underlying framework of Homarr and take advantage
of an in-memory message bus and websockets to deliver data near realtime to you. of an in-memory message bus and websockets to deliver data near realtime to you.
{/* Historical excerpt boundary. */} <!-- truncate -->
## Breaking changes ## Breaking changes
:::warning :::warning
@@ -1,16 +1,16 @@
--- ---
title: Open Beta 1.0
date: 2024-12-17
authors: authors:
- meierschlumpf - meierschlumpf
--- ---
# Open Beta 1.0
We are proud to announce the open beta of Homarr 1.0. This is a major milestone for us and we are excited to share it with you. We are proud to announce the open beta of Homarr 1.0. This is a major milestone for us and we are excited to share it with you.
The open beta allows us to polish the last rough edges and gather feedback from you. The open beta allows us to polish the last rough edges and gather feedback from you.
We are looking forward to your feedback and hope you enjoy the new features. We are looking forward to your feedback and hope you enjoy the new features.
Let us know throgh discord or a [github issues](https://github.com/homarr-labs/homarr/issues/new/choose) if you encounter any issues. Let us know throgh discord or a [github issues](https://github.com/homarr-labs/homarr/issues/new/choose) if you encounter any issues.
{/* Historical excerpt boundary. */} <!-- truncate -->
## How to use the beta with docker ## How to use the beta with docker
@@ -36,4 +36,4 @@ services:
Then, run `docker compose up -d` in the same directory. This will start the Homarr container in the background. Then, run `docker compose up -d` in the same directory. This will start the Homarr container in the background.
Please note that the mounts have changed and it's not backwards compatible with versions before 1.0.0-beta.1. Please note that the mounts have changed and it's not backwards compatible with versions before 1.0.0-beta.1.
You can find a list of all breaking changes [here](/blog/2024/09/23/version-1.0) You can find a list of all breaking changes [here](/blog/2024/09/23/version-1.0)
@@ -1,14 +1,14 @@
--- ---
title: Migrate from 0.15.10+ to 1.0.0
date: 2025-01-19
authors: authors:
- meierschlumpf - meierschlumpf
--- ---
# Migrate from 0.15.10+ to 1.0.0
In this guide, we will show you how to migrate from Homarr 0.15.10+ to 1.0.0. In this guide, we will show you how to migrate from Homarr 0.15.10+ to 1.0.0.
If you are still on a version before 0.15.10, please update to 0.15.10 where we introduced the migration export page. If you are still on a version before 0.15.10, please update to 0.15.10 where we introduced the migration export page.
{/* Historical excerpt boundary. */} <!-- truncate -->
## Preserve your old installation ## Preserve your old installation
@@ -22,7 +22,7 @@ Plan to recreate your apps, integrations, and boards manually in the new install
We highly recommend to create a parallel installation of Homarr 1.0.0. We highly recommend to create a parallel installation of Homarr 1.0.0.
So if something with for example the import does not quite work, the data in the old installation is still available. So if something with for example the import does not quite work, the data in the old installation is still available.
To do this you can follow the appropriate [installation guide](/docs/getting-started) for your system. To do this you can follow the appropriate [installation guide](https://homarr.dev/docs/category/installation-1) for your system.
Please note that if you are using docker you need to specify a diffrent external port for the new installation as the old one had the same port. Please note that if you are using docker you need to specify a diffrent external port for the new installation as the old one had the same port.
So in your compose file the ports would be `7576:7575` instead of `7575:7575`. So in your compose file the ports would be `7576:7575` instead of `7575:7575`.
@@ -1,14 +1,14 @@
--- ---
title: How to use Argus with Homarr
date: 2025-08-02
authors: authors:
- meierschlumpf - meierschlumpf
--- ---
# How to use Argus with Homarr
In `v1.32.0` we added the endpoint `/api/info` which returns the current version of Homarr and can therefore be used in Argus to watch for updates. In `v1.32.0` we added the endpoint `/api/info` which returns the current version of Homarr and can therefore be used in Argus to watch for updates.
This guide will show you how to set up a user with apiKey to access the endpoint without providing admin access through it. This guide will show you how to set up a user with apiKey to access the endpoint without providing admin access through it.
{/* Historical excerpt boundary. */} <!-- truncate -->
![Argus](./img/argus.png) ![Argus](./img/argus.png)
@@ -64,4 +64,4 @@ Now you can configure Argus to use the user and apiKey we created.
![Argus configuration](./img/argus-configuration.png) ![Argus configuration](./img/argus-configuration.png)
Replace the `<secret>` with the apiKey you created and the deployed version url with the url of your Homarr instance. Replace the `<secret>` with the apiKey you created and the deployed version url with the url of your Homarr instance.
+7 -17
View File
@@ -1,6 +1,4 @@
--- ---
title: Homarr 2.0.0 - Workshop, Custom Widgets and a rebuilt board
date: 2026-09-03
authors: authors:
- ajnart - ajnart
tags: [homarr, update, version, assistant, custom widgets, dashboards, docker] tags: [homarr, update, version, assistant, custom widgets, dashboards, docker]
@@ -17,19 +15,13 @@ Many of you used the v2 demo when it was still rough, found bugs and came back t
We are also planning a small batch of **free, limited-edition Homarr swag** for Workshop contributors and a few randomly picked community members. It is not for sale and it is not for profit. No Homarr merch empire, sorry. We are also planning a small batch of **free, limited-edition Homarr swag** for Workshop contributors and a few randomly picked community members. It is not for sale and it is not for profit. No Homarr merch empire, sorry.
Homarr 2.0 is an upgrade, not a brand-new app wearing the same logo. Here is what actually changed. Homarr 2.0 builds on the dashboard you already use. Here is what changed.
![A populated Homarr 2.0 dashboard with compact widgets, an Assistant, and an application rail](./img/homarr-v2-dashboard.webp) ![A populated Homarr 2.0 dashboard with compact widgets, an Assistant, and an application rail](./img/homarr-v2-dashboard.webp)
{/* Historical excerpt boundary. */} <!-- truncate -->
:::warning Back up before upgrading Update your Homarr image as usual. Homarr runs database migrations automatically when the updated container starts; no manual database migration or separate v2 upgrade procedure is needed. Workshop uses the production service by default, with no preview URL configuration required.
Database migrations run automatically when Homarr starts. Create a
[Homarr backup](/docs/management/backup) first. Do not test a prerelease image on your only production volume.
Backups are boring. Restores are worse.
:::
## Custom Widgets v2 and Workshop ## Custom Widgets v2 and Workshop
@@ -152,9 +144,8 @@ Groups use a new Viewer, Editor and Admin matrix. The API, Assistant and MCP fol
Board startup work runs in parallel, heavy screens load when opened, and identical integration requests share work instead of doing it twice. Board startup work runs in parallel, heavy screens load when opened, and identical integration requests share work instead of doing it twice.
## Before upgrading ## Compatibility notes
- Keep a backup and use the final release image, not a prerelease tag.
- Legacy Custom JSX definitions enter a migration state. Homarr keeps encrypted credentials and an archived copy until the v2 definition validates. - Legacy Custom JSX definitions enter a migration state. Homarr keeps encrypted credentials and an archived copy until the v2 definition validates.
- Mobile layouts place rail content in the main flow instead of displaying rails. - Mobile layouts place rail content in the main flow instead of displaying rails.
- Custom Widgets remain Beta. - Custom Widgets remain Beta.
@@ -162,8 +153,7 @@ Board startup work runs in parallel, heavy screens load when opened, and identic
## Links ## Links
- Try the [Homarr 2.0 preview](https://app-v2.preview.homarr.dev). - Try the [live demo](https://demo.homarr.dev/).
- Follow the [v2 beta setup guide](/docs/getting-started/upgrade-v2). - See [installation and update instructions](/docs/getting-started/installation/docker).
- Follow the [v2 release pull request](https://github.com/homarr-labs/homarr/pull/6545) and [public beta thread](https://github.com/homarr-labs/homarr/issues/6600). - Browse [Workshop](https://homarr.dev/workshop).
- Compare [v1.76.2 with the release/v2 branch](https://github.com/homarr-labs/homarr/compare/v1.76.2...release/v2).
- Read the guides for [Boards](/docs/management/boards), [Custom Widgets](/docs/management/custom-widgets), [Assistant](/docs/management/assistant), [MCP](/docs/management/mcp) and [Docker labels](/docs/integrations/docker-labels). - Read the guides for [Boards](/docs/management/boards), [Custom Widgets](/docs/management/custom-widgets), [Assistant](/docs/management/assistant), [MCP](/docs/management/mcp) and [Docker labels](/docs/integrations/docker-labels).
+1 -1
View File
@@ -5,7 +5,7 @@
"tsx": true, "tsx": true,
"tailwind": { "tailwind": {
"config": "", "config": "",
"css": "src/app/global.css", "css": "src/css/custom.css",
"baseColor": "mist", "baseColor": "mist",
"cssVariables": true, "cssVariables": true,
"prefix": "" "prefix": ""
+9
View File
@@ -0,0 +1,9 @@
{
"label": "Advanced",
"collapsed": true,
"position": 5,
"link": {
"type": "generated-index",
"title": "Advanced Concepts or features"
}
}
@@ -0,0 +1,4 @@
{
"collapsed": true,
"label": "Command line interface"
}
@@ -90,7 +90,7 @@ homarr run dev
homarr run --detach dev homarr run --detach dev
homarr run --pr 6441 homarr run --pr 6441
homarr run --pr 6441 --demo homarr run --pr 6441 --demo
homarr --pr 6441 --env WORKSHOP_WEB_URL=https://app-v2.preview.homarr.dev/ homarr --pr 6441 --env WORKSHOP_WEB_URL=https://workshop.example.com/workshop
``` ```
- `--pr <number>`: Pull and run a PR image from GHCR (shorthand: `homarr --pr <number>`). - `--pr <number>`: Pull and run a PR image from GHCR (shorthand: `homarr --pr <number>`).
@@ -1,4 +0,0 @@
{
"title": "Command line interface",
"pages": ["index", "users", "integrations", "password-recovery", "fix-usernames", "development"]
}
@@ -0,0 +1,8 @@
{
"label": "Developer guides",
"position": 6,
"collapsed": true,
"link": {
"type": "generated-index"
}
}
@@ -31,9 +31,13 @@ pnpm install --frozen-lockfile
### Run the Homarr application ### Run the Homarr application
1. Copy `.env.example` to `.env`. 1. Copy `.env.example` to `.env`.
2. Set `DB_URL` to an absolute writable SQLite file path. 2. Run `openssl rand -hex 32` twice. Set `AUTH_SECRET` and `SECRET_ENCRYPTION_KEY` to the two different generated
3. Keep Redis and the optional local databases running in one terminal. values in `.env`; the example leaves both empty. Keep this file private and preserve `SECRET_ENCRYPTION_KEY`
4. Apply migrations and start Next.js in another terminal. when reusing a database.
3. Set `DB_URL` to an absolute writable SQLite file path. Migration and application commands run from different
workspace directories, so a relative path can point them at different databases.
4. Keep Redis and the optional local databases running in one terminal.
5. Apply migrations and start Next.js in another terminal.
```sh ```sh
cp .env.example .env cp .env.example .env
@@ -57,8 +61,22 @@ Homarr becomes the instance administrator.
Use `pnpm docker:dev:up` instead when you only need Redis in the background. Running the migration also seeds the Use `pnpm docker:dev:up` instead when you only need Redis in the background. Running the migration also seeds the
default data; use `pnpm db:seed` to seed it explicitly later. default data; use `pnpm db:seed` to seed it explicitly later.
Workshop contributors can set up PocketBase and Fumadocs with the dedicated `pnpm dev` starts only Next.js. When your work needs scheduled tasks or live subscriptions, run the relevant service
[Workshop development guide](/docs/advanced/development/workshop). in a separate terminal alongside it:
```sh
pnpm --filter @homarr/tasks dev
```
```sh
pnpm --filter @homarr/websocket dev
```
The WebSocket service listens on port 3001. Production startup embeds both services, so these extra commands are
only needed for development.
Workshop contributors can set up PocketBase and Docusaurus with the dedicated
[Workshop development guide](./workshop).
### Useful commands ### Useful commands
@@ -69,7 +87,7 @@ Workshop contributors can set up PocketBase and Fumadocs with the dedicated
- `pnpm dev:cli -- build --pr <number>` — build a pull request from a temporary checkout. - `pnpm dev:cli -- build --pr <number>` — build a pull request from a temporary checkout.
- `pnpm dev:cli -- rebuild <name>` — rebuild an image from its recorded checkout or pull request. - `pnpm dev:cli -- rebuild <name>` — rebuild an image from its recorded checkout or pull request.
- `pnpm dev:cli:install` — optionally install the developer CLI as a `homarr` binary. - `pnpm dev:cli:install` — optionally install the developer CLI as a `homarr` binary.
- `pnpm dev:docs` — Fumadocs on port 3003. - `pnpm dev:docs` — Docusaurus only on port 3003.
- `pnpm docker:dev:up` — Redis development service in the background. - `pnpm docker:dev:up` — Redis development service in the background.
- `pnpm cli` — Homarr operations CLI. - `pnpm cli` — Homarr operations CLI.
- `pnpm db:migration:sqlite:run` — create or update a SQLite database. - `pnpm db:migration:sqlite:run` — create or update a SQLite database.
@@ -80,8 +98,8 @@ Workshop contributors can set up PocketBase and Fumadocs with the dedicated
- `pnpm typecheck` — typecheck all workspaces. - `pnpm typecheck` — typecheck all workspaces.
- `pnpm test` — unit and contract suites. - `pnpm test` — unit and contract suites.
- `pnpm build` — production monorepo build. - `pnpm build` — production monorepo build.
- `docker build -t homarr .` — build a production Docker image. - `docker build -t homarr:local .` — build a production Docker image.
- `docker run -p 7575:7575 -e SECRET_ENCRYPTION_KEY='your_64_character_hex_string' homarr:<name>` — run it. - `docker run -p 7575:7575 -e SECRET_ENCRYPTION_KEY='your_64_character_hex_string' homarr:local` — run it.
## CI and focused validation ## CI and focused validation
@@ -104,21 +122,3 @@ Choose the smallest relevant suite when changing behavior:
Omit `<file>` to run all tests in that command's scope. E2E and screenshot commands use a local image tagged `homarr-e2e`, or an image selected with `HOMARR_E2E_IMAGE`. The default commands run once without automatic retries; coverage is opt-in. The screenshot generator is excluded from both unit and E2E commands. Omit `<file>` to run all tests in that command's scope. E2E and screenshot commands use a local image tagged `homarr-e2e`, or an image selected with `HOMARR_E2E_IMAGE`. The default commands run once without automatic retries; coverage is opt-in. The screenshot generator is excluded from both unit and E2E commands.
Keep behavioral coverage for authorization, migrations, persistence, and widget execution. Avoid tests that only search source code for particular component names, JSX, CSS, or documentation wording. Keep behavioral coverage for authorization, migrations, persistence, and widget execution. Avoid tests that only search source code for particular component names, JSX, CSS, or documentation wording.
## Documentation development
Run `pnpm dev:docs` to open the Next.js and Fumadocs site at `http://127.0.0.1:3003`. Content lives in
`apps/docs/docs/`; the nearest `meta.json` controls navigation. Keep integration and widget setup metadata in their
typed `index.ts` files alongside the page.
After changing content, navigation, or shared MDX components, run:
```sh
pnpm --filter @homarr/docs build
pnpm --filter @homarr/docs validate:links
pnpm --filter @homarr/docs verify:search
```
The build writes a static site to `apps/docs/out/`. Check heading links, search results, and the page's Markdown export
when changing shared components. The [Fumadocs documentation](https://fumadocs.dev/docs) describes supported components
and source APIs; match examples to the versions installed in this repository.
@@ -1,4 +0,0 @@
{
"title": "Developer guides",
"pages": ["getting-started", "widgets-and-integrations", "kubernetes", "workshop", "workshop-operator"]
}
@@ -34,21 +34,6 @@ Workshop uses PocketBase. The production image serves the Workshop website and A
Public URL variables accept HTTP(S) origins without embedded credentials, query strings, or fragments. Restart the Public URL variables accept HTTP(S) origins without embedded credentials, query strings, or fragments. Restart the
container after changing runtime configuration. container after changing runtime configuration.
## Documentation search and AI
The documentation uses Fumadocs search with an index generated during the website build. Search runs in the browser
and needs no hosted search credentials or crawler.
The **Ask AI** launcher connects to Kapa separately. `KAPA_WEBSITE_ID` is a public website integration ID, read when
building the documentation. The default uses Homarr's integration. For a private deployment, pass your own ID or
an empty value to disable it: `docker build --build-arg KAPA_WEBSITE_ID= -f apps/workshop/Dockerfile .`.
Changing this value requires rebuilding the image; setting it on an already-built container has no effect.
For your own Kapa integration, enable the deployment domain in Kapa and configure a Website Crawl source for your
published docs. Preview the `main` content selector and verify extracted headings, code, and integration details.
After a migration, refresh the source and check answer citations. `/llms.txt` alone does not configure Kapa ingestion.
See the [Kapa website widget guide](https://docs.kapa.ai/integrations/website-widget/quickstart).
## Authentication and email ## Authentication and email
Configure both GitHub OAuth variables and use `https://<workshop-host>/api/oauth2-redirect` as the callback. Supplying Configure both GitHub OAuth variables and use `https://<workshop-host>/api/oauth2-redirect` as the callback. Supplying
@@ -4,13 +4,13 @@ sidebar_position: 4
tags: tags:
- Workshop - Workshop
- Developer - Developer
- Fumadocs - Docusaurus
- PocketBase - PocketBase
--- ---
# Workshop development # Workshop development
See the [main development guide](/docs/advanced/development/getting-started) for repository prerequisites. See the [main development guide](./getting-started) for repository prerequisites.
Start PocketBase: Start PocketBase:
@@ -19,7 +19,7 @@ cp apps/workshop/.env.example apps/workshop/.env
docker compose --env-file apps/workshop/.env -f apps/workshop/docker-compose.yml up --build workshop docker compose --env-file apps/workshop/.env -f apps/workshop/docker-compose.yml up --build workshop
``` ```
Start Fumadocs in another terminal: Start Docusaurus in another terminal:
```sh ```sh
WORKSHOP_API_URL=http://127.0.0.1:8090 pnpm dev:docs WORKSHOP_API_URL=http://127.0.0.1:8090 pnpm dev:docs
@@ -139,4 +139,4 @@ The advanced deployments environment variables should only be used if you know w
| `DB_MIGRATIONS_DISABLED` | Disable db migrations. For example for helm charts. | | `DB_MIGRATIONS_DISABLED` | Disable db migrations. For example for helm charts. |
All public URL variables reject non-HTTP protocols, embedded credentials, query strings, and fragments, and normalize All public URL variables reject non-HTTP protocols, embedded credentials, query strings, and fragments, and normalize
trailing slashes when Homarr or the documentation site starts. trailing slashes when Homarr or Docusaurus starts.
-60
View File
@@ -1,60 +0,0 @@
---
title: Advanced configuration
description: Configure deployment, authentication, networking, styling, automation, and development workflows.
---
import {
IconCode,
IconIcons,
IconKey,
IconKeyboard,
IconNetwork,
IconPalette,
IconTerminal2,
IconUserCog,
IconVariable,
} from "@tabler/icons-react";
These guides cover changes that affect how Homarr is deployed, secured, operated, or extended.
## Deploy and secure
<Cards>
<Card icon={<IconVariable />} title="Environment variables" href="/docs/advanced/environment-variables">
Configure Homarr at deployment time.
</Card>
<Card icon={<IconKey />} title="Single sign-on" href="/docs/advanced/single-sign-on">
Connect an external identity provider.
</Card>
<Card icon={<IconNetwork />} title="Proxies and certificates" href="/docs/advanced/proxy">
Run Homarr behind a reverse proxy.
</Card>
<Card icon={<IconUserCog />} title="Run as a different user" href="/docs/advanced/running-as-different-user">
Change the user and group used by the container.
</Card>
</Cards>
## Customize
<Cards>
<Card icon={<IconPalette />} title="Custom styling" href="/docs/advanced/styling">
Apply custom CSS to Homarr.
</Card>
<Card icon={<IconIcons />} title="Icons" href="/docs/advanced/icons">
Configure icon sources and behavior.
</Card>
<Card icon={<IconKeyboard />} title="Keyboard shortcuts" href="/docs/advanced/keyboard-shortcuts">
Navigate and operate Homarr with the keyboard.
</Card>
</Cards>
## Develop and automate
<Cards>
<Card icon={<IconTerminal2 />} title="Command line interface" href="/docs/advanced/command-line">
Use administrative commands from the terminal.
</Card>
<Card icon={<IconCode />} title="Developer guides" href="/docs/advanced/development/getting-started">
Set up a development environment and contribute code.
</Card>
</Cards>
-19
View File
@@ -1,19 +0,0 @@
{
"title": "Advanced",
"defaultOpen": false,
"pages": [
"index",
"---Deploy and secure---",
"environment-variables",
"single-sign-on",
"proxy",
"running-as-different-user",
"---Customize---",
"styling",
"icons",
"keyboard-shortcuts",
"---Develop and automate---",
"command-line",
"development"
]
}
+3 -3
View File
@@ -9,14 +9,14 @@ tags:
- Security - Security
--- ---
import Tabs from "@/components/mdx/legacy-tabs"; import Tabs from "@theme/Tabs";
import { TabItem } from "@/components/mdx/legacy-tabs"; import TabItem from "@theme/TabItem";
## Allowing self-signed certificates ## Allowing self-signed certificates
Some users may come across a barrier, where they're unable to receive a 200 response from the Ping widget for some apps, while using self-signed certificates or a local certificate authory. Some users may come across a barrier, where they're unable to receive a 200 response from the Ping widget for some apps, while using self-signed certificates or a local certificate authory.
:::note[What's going on?] :::note What's going on?
Homarr is trying to communicate to your apps via the integrations. Homarr is trying to communicate to your apps via the integrations.
It usually doesn't matter if Homarr is running on `http` or `https`. It usually doesn't matter if Homarr is running on `http` or `https`.
+157 -149
View File
@@ -10,11 +10,14 @@ tags:
- Active Directory - Active Directory
--- ---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
# Single Sign On # Single Sign On
Homarr supports multiple authentication options, from internal userbase (credentials), to LDAP (with Active directory support), and OIDC. Homarr supports multiple authentication options, from internal userbase (credentials), to LDAP (with Active directory support), and OIDC.
## Common configuration ### Auth configuration common variables
| Environment Variable | Description | Default Value | | Environment Variable | Description | Default Value |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
@@ -23,193 +26,198 @@ Homarr supports multiple authentication options, from internal userbase (credent
| AUTH_SESSION_EXPIRY_TIME | Time for the session to time out. Can be set as pure number, which will automatically be used in seconds, or followed by s, m, h or d for seconds, minutes, hours or days. (ex: "30m") | "30d" | | AUTH_SESSION_EXPIRY_TIME | Time for the session to time out. Can be set as pure number, which will automatically be used in seconds, or followed by s, m, h or d for seconds, minutes, hours or days. (ex: "30m") | "30d" |
| AUTH_COOKIE_PREFIX | Prefix used for all authentication cookies (session, csrf, callback, pkce, state, nonce). Change this if you run another Auth.js/NextAuth app on the same hostname as Homarr (browsers scope cookies by host, not by port) to avoid cookie name collisions. Only letters, numbers, hyphens and underscores are allowed. | `homarr` | | AUTH_COOKIE_PREFIX | Prefix used for all authentication cookies (session, csrf, callback, pkce, state, nonce). Change this if you run another Auth.js/NextAuth app on the same hostname as Homarr (browsers scope cookies by host, not by port) to avoid cookie name collisions. Only letters, numbers, hyphens and underscores are allowed. | `homarr` |
## Credentials provider <Tabs>
<TabItem value="credentials" label="Credentials Provider" default>
This is the default provider. This is the default provider.
First user is created using the onboarding process and the rest can be created by this user (see [user management](/docs/management/users)) First user is created using the onboarding process and the rest can be created by this user (see [user management](/docs/management/users))
## LDAP provider </TabItem>
<TabItem value="ldap" label="LDAP provider">
This provider authenticates against an LDAP server. This provider authenticates against an LDAP server.
Any user in LDAP server that signs in gets created in Homarr database. Any user in LDAP server that signs in gets created in Homarr database.
Roles are fetched from LDAP groups. Groups with the same name of Homarr will be used to synchronize them. Roles are fetched from LDAP groups. Groups with the same name of Homarr will be used to synchronize them.
<details> <details>
<summary> <summary>
Example Setup Example Setup
</summary> </summary>
<div> <div>
In this setup we are using [lldap](https://github.com/lldap/lldap). Install your server using docker or [as a service](https://github.com/lldap/lldap/blob/main/example_configs/lldap.service). In this setup we are using [lldap](https://github.com/lldap/lldap). Install your server using docker or [as a service](https://github.com/lldap/lldap/blob/main/example_configs/lldap.service).
Minimal configuration requires 4 env variables, LDAP URI, base, user and password for querying data. Minimal configuration requires 4 env variables, LDAP URI, base, user and password for querying data.
There's more variables, but all have defaults corresponding to lldap defaults. These might need to be changed if you have different LDAP provider. There's more variables, but all have defaults corresponding to lldap defaults. These might need to be changed if you have different LDAP provider.
``` ```
docker run ... docker run ...
AUTH_PROVIDERS="ldap" AUTH_PROVIDERS="ldap"
AUTH_LDAP_URI="ldap://example.com:3890" AUTH_LDAP_URI="ldap://example.com:3890"
AUTH_LDAP_BASE="dc=example,dc=com" // Same as LLDAP_LDAP_BASE_DN AUTH_LDAP_BASE="dc=example,dc=com" // Same as LLDAP_LDAP_BASE_DN
AUTH_LDAP_BIND_DN="uid=admin,ou=People,dc=example,dc=com" AUTH_LDAP_BIND_DN="uid=admin,ou=People,dc=example,dc=com"
AUTH_LDAP_BIND_PASSWORD="adminpass" // Same as LLDAP_LDAP_USER_PASS AUTH_LDAP_BIND_PASSWORD="adminpass" // Same as LLDAP_LDAP_USER_PASS
``` ```
``` ```
#Docker compose #Docker compose
version: x version: x
services: services:
homarr: homarr:
environment: environment:
AUTH_PROVIDERS: ldap AUTH_PROVIDERS: ldap
AUTH_LDAP_URI: ldap://example.com:3890 AUTH_LDAP_URI: ldap://example.com:3890
AUTH_LDAP_BASE: dc=example,dc=com #Same as LLDAP_LDAP_BASE_DN AUTH_LDAP_BASE: dc=example,dc=com #Same as LLDAP_LDAP_BASE_DN
AUTH_LDAP_BIND_DN: uid=admin,ou=People,dc=example,dc=com AUTH_LDAP_BIND_DN: uid=admin,ou=People,dc=example,dc=com
AUTH_LDAP_BIND_PASSWORD: adminpass #Same as LLDAP_LDAP_USER_PASS AUTH_LDAP_BIND_PASSWORD: adminpass #Same as LLDAP_LDAP_USER_PASS
``` ```
In lldap, create a user and admin group, assign this user to the external admin group configured during onboarding. You can log in using this user and he will be in the group. In lldap, create a user and admin group, assign this user to the external admin group configured during onboarding. You can log in using this user and he will be in the group.
Here is another example for Active Directory: Here is another example for Active Directory:
``` ```
AUTH_LDAP_URI="ldap://ldap.abc.xyz:389 AUTH_LDAP_URI="ldap://ldap.abc.xyz:389
AUTH_LDAP_BASE="DC=abc,DC=xyz" AUTH_LDAP_BASE="DC=abc,DC=xyz"
AUTH_LDAP_BIND_DN="CN=Administrator,CN=Users,DC=abc,DC=xyz" AUTH_LDAP_BIND_DN="CN=Administrator,CN=Users,DC=abc,DC=xyz"
AUTH_LDAP_BIND_PASSWORD="YourAdministratorPassword" AUTH_LDAP_BIND_PASSWORD="YourAdministratorPassword"
AUTH_LDAP_USERNAME_ATTRIBUTE="sAMAccountName" AUTH_LDAP_USERNAME_ATTRIBUTE="sAMAccountName"
AUTH_LDAP_USER_MAIL_ATTRIBUTE="userPrincipalName" AUTH_LDAP_USER_MAIL_ATTRIBUTE="userPrincipalName"
AUTH_LDAP_GROUP_CLASS="group" AUTH_LDAP_GROUP_CLASS="group"
AUTH_LDAP_GROUP_MEMBER_ATTRIBUTE="member" AUTH_LDAP_GROUP_MEMBER_ATTRIBUTE="member"
AUTH_LDAP_GROUP_MEMBER_USER_ATTRIBUTE="dn" AUTH_LDAP_GROUP_MEMBER_USER_ATTRIBUTE="dn"
AUTH_LDAP_SEARCH_SCOPE="sub" AUTH_LDAP_SEARCH_SCOPE="sub"
AUTH_LDAP_USERNAME_FILTER_EXTRA_ARG="(sAMAccountType=805306368)" AUTH_LDAP_USERNAME_FILTER_EXTRA_ARG="(sAMAccountType=805306368)"
``` ```
User mail attribute is set to userPrincipalName as it follows the right schema, but it is recommended to use real emails and the default 'mail' value. User mail attribute is set to userPrincipalName as it follows the right schema, but it is recommended to use real emails and the default 'mail' value.
</div> </div>
</details> </details>
### LDAP configuration ### Configuration
| Environment Variable | Description | Default value | | Environment Variable | Description | Default value |
|-------------------------------------------|-----------------------------------------------------------|---------------------| |-------------------------------------------|-----------------------------------------------------------|---------------------|
| ``AUTH_LDAP_URI`` | URI of your LDAP server | --- | | ``AUTH_LDAP_URI`` | URI of your LDAP server | --- |
| ``AUTH_LDAP_BASE`` | Base dn of your LDAP server | --- | | ``AUTH_LDAP_BASE`` | Base dn of your LDAP server | --- |
| ``AUTH_LDAP_BIND_DN`` | User used for finding users and groups | --- | | ``AUTH_LDAP_BIND_DN`` | User used for finding users and groups | --- |
| ``AUTH_LDAP_BIND_PASSWORD`` | Password for bind user | --- | | ``AUTH_LDAP_BIND_PASSWORD`` | Password for bind user | --- |
| ``AUTH_LDAP_USERNAME_ATTRIBUTE`` | Attribute used for username | uid | | ``AUTH_LDAP_USERNAME_ATTRIBUTE`` | Attribute used for username | uid |
| ``AUTH_LDAP_USER_MAIL_ATTRIBUTE`` | Attribute used for mail field | mail | | ``AUTH_LDAP_USER_MAIL_ATTRIBUTE`` | Attribute used for mail field | mail |
| ``AUTH_LDAP_GROUP_CLASS`` | Class used for querying groups | groupOfUniqueNames | | ``AUTH_LDAP_GROUP_CLASS`` | Class used for querying groups | groupOfUniqueNames |
| ``AUTH_LDAP_GROUP_MEMBER_ATTRIBUTE`` | Attribute used for querying group member | member | | ``AUTH_LDAP_GROUP_MEMBER_ATTRIBUTE`` | Attribute used for querying group member | member |
| ``AUTH_LDAP_GROUP_MEMBER_USER_ATTRIBUTE`` | User attribute used for comparing with group member | dn | | ``AUTH_LDAP_GROUP_MEMBER_USER_ATTRIBUTE`` | User attribute used for comparing with group member | dn |
| ``AUTH_LDAP_SEARCH_SCOPE`` | Serach scopes between base, one and sub | base | | ``AUTH_LDAP_SEARCH_SCOPE`` | Serach scopes between base, one and sub | base |
| ``AUTH_LDAP_USERNAME_FILTER_EXTRA_ARG`` | Extra arguments for user search filter (& based) | --- | | ``AUTH_LDAP_USERNAME_FILTER_EXTRA_ARG`` | Extra arguments for user search filter (& based) | --- |
| ``AUTH_LDAP_GROUP_FILTER_EXTRA_ARG`` | Extra arguments for user's groups search filter (& based) | --- | | ``AUTH_LDAP_GROUP_FILTER_EXTRA_ARG`` | Extra arguments for user's groups search filter (& based) | --- |
## OIDC provider </TabItem>
<TabItem value="oidc" label="OIDC provider">
This provider authenticates using OIDC protocol. This provider authenticates using OIDC protocol.
Users signed in using OIDC are created in Homarr. Users signed in using OIDC are created in Homarr.
Roles are fetched from group claims. This can also be changed to roles for example added to a azure app registration by using the `AUTH_OIDC_GROUPS_ATTRIBUTE`. Roles are fetched from group claims. This can also be changed to roles for example added to a azure app registration by using the `AUTH_OIDC_GROUPS_ATTRIBUTE`.
If you'd rather manage group memberships for OIDC users locally (instead of via the IdP), set `AUTH_OIDC_GROUPS_LOCAL_MANAGEMENT=true`. While enabled, Homarr stops syncing OIDC users' group memberships from the groups claim, and admins can add/remove OIDC users on a group's members page. If you turn this back to `false`, the next login of each user resumes the regular sync and reconciles their groups with the IdP's claim again, which may remove memberships that were added manually while local management was enabled. If you'd rather manage group memberships for OIDC users locally (instead of via the IdP), set `AUTH_OIDC_GROUPS_LOCAL_MANAGEMENT=true`. While enabled, Homarr stops syncing OIDC users' group memberships from the groups claim, and admins can add/remove OIDC users on a group's members page. If you turn this back to `false`, the next login of each user resumes the regular sync and reconciles their groups with the IdP's claim again, which may remove memberships that were added manually while local management was enabled.
To let an existing credentials user also sign in with OIDC, set `AUTH_OIDC_ENABLE_DANGEROUS_CREDENTIALS_LINKING=true`. On the first OIDC sign-in, Homarr links a credentials user with the same email address instead of creating a second user. The user keeps their password login, local username and profile, groups, permissions, boards, settings, and API keys. OIDC profile and group claims do not overwrite the credentials-owned data. Homarr requires the OIDC profile to contain `email_verified: true` while this option is enabled. Only enable this when your OIDC provider verifies email addresses, because a matching email could otherwise be used to take over an existing account. To let an existing credentials user also sign in with OIDC, set `AUTH_OIDC_ENABLE_DANGEROUS_CREDENTIALS_LINKING=true`. On the first OIDC sign-in, Homarr links a credentials user with the same email address instead of creating a second user. The user keeps their password login, local username and profile, groups, permissions, boards, settings, and API keys. OIDC profile and group claims do not overwrite the credentials-owned data. Homarr requires the OIDC profile to contain `email_verified: true` while this option is enabled. Only enable this when your OIDC provider verifies email addresses, because a matching email could otherwise be used to take over an existing account.
<details> <details>
<summary> <summary>
Example Setup Example Setup
</summary> </summary>
<div> <div>
In this example we will be using [Authelia](https://github.com/authelia/authelia). In this example we will be using [Authelia](https://github.com/authelia/authelia).
You can use any setup, but the simplest is [local](https://github.com/authelia/authelia/blob/master/examples/compose/local/authelia/configuration.yml). You can use any setup, but the simplest is [local](https://github.com/authelia/authelia/blob/master/examples/compose/local/authelia/configuration.yml).
You also have to [enable OIDC in Authelia](https://www.authelia.com/configuration/identity-providers/open-id-connect/). You also have to [enable OIDC in Authelia](https://www.authelia.com/configuration/identity-providers/open-id-connect/).
Create a client for homarr. To generate client secret you can [use authelia](https://www.authelia.com/integration/openid-connect/frequently-asked-questions/#how-do-i-generate-client-secrets). This is an example config: Create a client for homarr. To generate client secret you can [use authelia](https://www.authelia.com/integration/openid-connect/frequently-asked-questions/#how-do-i-generate-client-secrets). This is an example config:
```yaml ```yaml
identity_providers: identity_providers:
oidc: oidc:
... ...
clients: clients:
- id: homarr - id: homarr
secret: <secret_hash> secret: <secret_hash>
public: false public: false
authorization_policy: one_factor authorization_policy: one_factor
redirect_uris: redirect_uris:
- https://example.com/api/auth/callback/oidc - https://example.com/api/auth/callback/oidc
- http://localhost:3000/api/auth/callback/oidc - http://localhost:3000/api/auth/callback/oidc
scopes: scopes:
- openid - openid
- groups - groups
- profile - profile
- email - email
userinfo_signing_algorithm: none userinfo_signing_algorithm: none
consent_mode: implicit # self hosted consent_mode: implicit # self hosted
``` ```
In Homarr use following env variables. In Homarr use following env variables.
``` ```
AUTH_PROVIDERS="oidc" AUTH_PROVIDERS="oidc"
AUTH_OIDC_ISSUER="https://auth.example.com" AUTH_OIDC_ISSUER="https://auth.example.com"
AUTH_OIDC_CLIENT_SECRET="client_secret" AUTH_OIDC_CLIENT_SECRET="client_secret"
AUTH_OIDC_CLIENT_ID="homarr" AUTH_OIDC_CLIENT_ID="homarr"
AUTH_OIDC_CLIENT_NAME="Authelia" AUTH_OIDC_CLIENT_NAME="Authelia"
AUTH_OIDC_FORCE_USERINFO="true" --> from v4.39 of authelia and above this is required AUTH_OIDC_FORCE_USERINFO="true" --> from v4.39 of authelia and above this is required
``` ```
For an azure app registration the setup could look like this: For an azure app registration the setup could look like this:
``` ```
AUTH_PROVIDERS="oidc" AUTH_PROVIDERS="oidc"
AUTH_OIDC_ISSUER="https://login.microsoftonline.com/<teanant-id>/v2.0" AUTH_OIDC_ISSUER="https://login.microsoftonline.com/<teanant-id>/v2.0"
AUTH_OIDC_CLIENT_SECRET="<client-secret>" AUTH_OIDC_CLIENT_SECRET="<client-secret>"
AUTH_OIDC_CLIENT_ID="<client-id>" AUTH_OIDC_CLIENT_ID="<client-id>"
AUTH_OIDC_CLIENT_NAME="Azure" AUTH_OIDC_CLIENT_NAME="Azure"
AUTH_OIDC_SCOPE_OVERWRITE="openid email profile" # Groups scope does not exist in azure AUTH_OIDC_SCOPE_OVERWRITE="openid email profile" # Groups scope does not exist in azure
AUTH_OIDC_GROUPS_ATTRIBUTE="roles" # We use the roles of the app registration so that we don't need to use uuids as our groups AUTH_OIDC_GROUPS_ATTRIBUTE="roles" # We use the roles of the app registration so that we don't need to use uuids as our groups
``` ```
</div> </div>
</details> </details>
### OIDC configuration ### Configuration
| Environment Variable | Description | Default value | | Environment Variable | Description | Default value |
|-----------------------------|------------------------------------------------------------|---------------| |-----------------------------|------------------------------------------------------------|---------------|
| ``AUTH_OIDC_ISSUER`` | Issuer URI of OIDC provider. This has generally to be **without trailing slash** except for **Authentik** | --- | | ``AUTH_OIDC_ISSUER`` | Issuer URI of OIDC provider. This has generally to be **without trailing slash** except for **Authentik** | --- |
| ``AUTH_OIDC_CLIENT_ID`` | ID of OIDC client (application) | --- | | ``AUTH_OIDC_CLIENT_ID`` | ID of OIDC client (application) | --- |
| ``AUTH_OIDC_CLIENT_SECRET`` | Secret of OIDC client (application) | --- | | ``AUTH_OIDC_CLIENT_SECRET`` | Secret of OIDC client (application) | --- |
| ``AUTH_OIDC_CLIENT_NAME`` | Display name of provider (in login screen) | OIDC | | ``AUTH_OIDC_CLIENT_NAME`` | Display name of provider (in login screen) | OIDC |
| ``AUTH_OIDC_AUTO_LOGIN`` | Automatically redirect to OIDC login | false | | ``AUTH_OIDC_AUTO_LOGIN`` | Automatically redirect to OIDC login | false |
| ``AUTH_OIDC_SCOPE_OVERWRITE`` | Overwrite default scopes (openid, profile, email) | openid email profile groups | | ``AUTH_OIDC_SCOPE_OVERWRITE`` | Overwrite default scopes (openid, profile, email) | openid email profile groups |
| ``AUTH_OIDC_GROUPS_ATTRIBUTE`` | Attribute used for groups (roles) claim. Dot-separated paths such as `resource_access.homarr.roles` are supported. | groups | | ``AUTH_OIDC_GROUPS_ATTRIBUTE`` | Attribute used for groups (roles) claim. Dot-separated paths such as `resource_access.homarr.roles` are supported. | groups |
| ``AUTH_OIDC_GROUPS_LOCAL_MANAGEMENT`` | Stop syncing group memberships of OIDC users from the groups claim and manage them locally via the group members page instead | false | | ``AUTH_OIDC_GROUPS_LOCAL_MANAGEMENT`` | Stop syncing group memberships of OIDC users from the groups claim and manage them locally via the group members page instead | false |
| ``AUTH_OIDC_NAME_ATTRIBUTE_OVERWRITE`` | Overwrite name attribute. Dot-separated paths are supported. By default it will use preferred_username if it does not contain a `@` and otherwise name. | --- | | ``AUTH_OIDC_NAME_ATTRIBUTE_OVERWRITE`` | Overwrite name attribute. Dot-separated paths are supported. By default it will use preferred_username if it does not contain a `@` and otherwise name. | --- |
| ``AUTH_OIDC_FORCE_USERINFO`` | Force userinfo endpoint to be used for user information. | false | | ``AUTH_OIDC_FORCE_USERINFO`` | Force userinfo endpoint to be used for user information. | false |
| ``AUTH_OIDC_ENABLE_DANGEROUS_ACCOUNT_LINKING`` | Enable account linking for OIDC provider. This will link the OIDC accounts by email. Be sure that you have verified emails to prevent stealing accounts. | false | | ``AUTH_OIDC_ENABLE_DANGEROUS_ACCOUNT_LINKING`` | Enable account linking for OIDC provider. This will link the OIDC accounts by email. Be sure that you have verified emails to prevent stealing accounts. | false |
| ``AUTH_OIDC_ENABLE_DANGEROUS_CREDENTIALS_LINKING`` | Link an OIDC identity to an existing credentials user with the same email. The credentials login and existing user data are preserved. Requires the OIDC profile to contain `email_verified: true`. | false | | ``AUTH_OIDC_ENABLE_DANGEROUS_CREDENTIALS_LINKING`` | Link an OIDC identity to an existing credentials user with the same email. The credentials login and existing user data are preserved. Requires the OIDC profile to contain `email_verified: true`. | false |
| ``AUTH_OIDC_TOKEN_ENDPOINT_AUTH_METHOD`` | Override method for the token endpoint authentication. Supported values are `client_secret_basic`, `client_secret_post`, `client_secret_jwt` and `none`. | client_secret_basic | | ``AUTH_OIDC_TOKEN_ENDPOINT_AUTH_METHOD`` | Override method for the token endpoint authentication. Supported values are `client_secret_basic`, `client_secret_post`, `client_secret_jwt` and `none`. | client_secret_basic |
### OIDC permissions ### Permission System
To give a user special permissions, first create a new group in homarr and assign the permission desired. To give a user special permissions, first create a new group in homarr and assign the permission desired.
For example if the group on homarr is called `homarr-admins` a new group on the oidc provider, for example authentik needs to be created with the same name, that would be `homarr-admins`. For example if the group on homarr is called `homarr-admins` a new group on the oidc provider, for example authentik needs to be created with the same name, that would be `homarr-admins`.
After assigning the group on the oidc provider to the user, and logging again into homarr, the user should automatically get placed in that group and inherit the permissions defined. After assigning the group on the oidc provider to the user, and logging again into homarr, the user should automatically get placed in that group and inherit the permissions defined.
</TabItem>
</Tabs>
## Example setups ## Example setups
@@ -239,7 +247,7 @@ After assigning the group on the oidc provider to the user, and logging again in
Generate `SECRET_ENCRYPTION_KEY` with `openssl rand -hex 32`; do not copy an example key between installs. Generate `SECRET_ENCRYPTION_KEY` with `openssl rand -hex 32`; do not copy an example key between installs.
```bash ```env
OIDC_CLIENT_ID=<REPLACE_WITH_OIDC_CLIENT_ID> OIDC_CLIENT_ID=<REPLACE_WITH_OIDC_CLIENT_ID>
OIDC_CLIENT_SECRET=<REPLACE_WITH_OIDC_CLIENT_SECRET> OIDC_CLIENT_SECRET=<REPLACE_WITH_OIDC_CLIENT_SECRET>
OIDC_SLUG=homarr #Application slug in Authentik OIDC_SLUG=homarr #Application slug in Authentik
@@ -290,7 +298,7 @@ After assigning the group on the oidc provider to the user, and logging again in
</div> </div>
</details> </details>
See [OIDC configuration](#oidc-configuration) for additional options. Additional OIDC configuration options are described in the OIDC tab above.
</TabItem> </TabItem>
<TabItem value="google" label="Google (OIDC) Example" default> <TabItem value="google" label="Google (OIDC) Example" default>
@@ -318,7 +326,7 @@ After assigning the group on the oidc provider to the user, and logging again in
Generate `SECRET_ENCRYPTION_KEY` with `openssl rand -hex 32`; do not copy an example key between installs. Generate `SECRET_ENCRYPTION_KEY` with `openssl rand -hex 32`; do not copy an example key between installs.
```bash ```env
OIDC_CLIENT_ID=<REPLACE_WITH_GOOGLE_CLIENT_ID> OIDC_CLIENT_ID=<REPLACE_WITH_GOOGLE_CLIENT_ID>
OIDC_CLIENT_SECRET=<REPLACE_WITH_GOOGLE_CLIENT_SECRET> OIDC_CLIENT_SECRET=<REPLACE_WITH_GOOGLE_CLIENT_SECRET>
HOMARR_FQDN=homarr.example.com #Homarr FQDN HOMARR_FQDN=homarr.example.com #Homarr FQDN
@@ -356,7 +364,7 @@ After assigning the group on the oidc provider to the user, and logging again in
</div> </div>
</details> </details>
See [OIDC configuration](#oidc-configuration) for additional options. Additional OIDC configuration options are described in the OIDC tab above.
</TabItem> </TabItem>
</Tabs> </Tabs>
+8
View File
@@ -0,0 +1,8 @@
{
"label": "Community",
"position": 6,
"collapsed": true,
"link": {
"type": "generated-index"
}
}
-10
View File
@@ -1,10 +0,0 @@
---
title: Community
description: Get help, contribute to Homarr, and support the project.
---
- [Frequently asked questions](/docs/community/faq): resolve common setup and operation issues.
- [Get in touch](/docs/community/get-in-touch): choose the right support or discussion channel.
- [Translations](/docs/community/translations): improve Homarr in your language.
- [Donate](/docs/community/donate): support ongoing development.
- [License](/docs/community/license): understand how Homarr is licensed.
-5
View File
@@ -1,5 +0,0 @@
{
"title": "Community",
"defaultOpen": false,
"pages": ["index", "faq", "get-in-touch", "translations", "donate", "license"]
}
@@ -0,0 +1,9 @@
{
"label": "Getting started",
"position": 1,
"collapsed": false,
"link": {
"type": "generated-index",
"title": "Getting started"
}
}
@@ -6,68 +6,11 @@ tags:
- Configuration - Configuration
--- ---
import { On first launch, onboarding creates the administrator, connects optional services, and builds the first board. A
IconAdjustments, compatible SQLite backup can also be restored from the welcome screen.
IconChecklist,
IconLayoutDashboard,
IconPlugConnected,
IconSearch,
IconSparkles,
} from "@tabler/icons-react";
import onboardingWelcome from "./img/onboarding-v2-welcome.png"; If onboarding returns after a restart, check that `/appdata` is writable and persisted. See the
import onboardingBoard from "./img/onboarding-v2-board.png"; [Docker installation guide](/docs/getting-started/installation/docker).
import onboardingReview from "./img/onboarding-v2-review.png";
After Homarr starts, open its URL. An unfinished installation redirects to the onboarding screen at `/init`. Choose
**Get started** for a new installation or **Restore backup** to import a compatible SQLite backup.
<Callout type="info" title="Persist /appdata before you continue">
Onboarding writes the administrator and board configuration to the database. If onboarding returns after a restart,
check that `/appdata` is writable and persisted. See the
[Docker installation guide](/docs/getting-started/installation/docker).
</Callout>
## Complete onboarding
Onboarding is split into six short sections. Integrations, Workshop, Assistant, and MCP are optional; skip them when you
only need a working board.
<Cards>
<Card icon={<IconAdjustments />} title="1. Essentials">
Choose the language, theme, usual server address, and anonymous analytics preference.
</Card>
<Card icon={<IconSearch />} title="2. Discover">
Review the database, Docker, Kubernetes, Assistant, and Workshop capabilities Homarr can reach.
</Card>
<Card icon={<IconPlugConnected />} title="3. Connect">
Import detected services or add integrations manually. Unfinished integrations can be skipped.
</Card>
<Card icon={<IconLayoutDashboard />} title="4. Board">
Set the board name, colors, corner radius, column count, and optional sidebars.
</Card>
<Card icon={<IconSparkles />} title="5. Extend">
Optionally connect the Workshop, configure an Assistant provider, or review the MCP endpoint.
</Card>
<Card icon={<IconChecklist />} title="6. Review">
Check the final summary, then build the board. Homarr opens the exact board it configured.
</Card>
</Cards>
The final screen links directly to the new board and the management area. Board layout, integrations, apps, and
appearance can all be changed later.
<Cards>
<Card title="Start or restore">
<img src={onboardingWelcome.src} alt="Homarr onboarding welcome screen with Get started and Restore backup actions" />
</Card>
<Card title="Configure the board">
<img src={onboardingBoard.src} alt="Board onboarding section for colors, columns, corner radius, and sidebars" />
</Card>
<Card title="Review before building">
<img src={onboardingReview.src} alt="Onboarding review showing the board settings Homarr will create" />
</Card>
</Cards>
## Core concepts ## Core concepts
@@ -97,7 +40,7 @@ Docker. Integrations provide data and actions to widgets. They can also be linke
![Integration catalog with compatible widgets](./img/after-installation-integrations.webp) ![Integration catalog with compatible widgets](./img/after-installation-integrations.webp)
See [Managing integrations](/docs/management/integrations) and the See [Managing integrations](/docs/management/integrations) and the
[integration catalog](/docs/integrations). [integration catalog](/docs/category/integrations).
### Widgets ### Widgets
@@ -106,7 +49,7 @@ supported integrations, and non-obvious limitations are documented on each widge
![Board in edit mode with the add-content menu](./img/after-installation-widgets.webp) ![Board in edit mode with the add-content menu](./img/after-installation-widgets.webp)
See the [widget catalog](/docs/widgets). See the [widget catalog](/docs/category/widgets).
### Containers and rails ### Containers and rails
Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 KiB

@@ -0,0 +1,9 @@
{
"label": "Installation",
"position": 1,
"collapsed": true,
"link": {
"type": "generated-index",
"title": "Getting started"
}
}
@@ -24,6 +24,10 @@ see [Managing integrations](/docs/management/integrations#configuration).
### Update ### Update
Update the image and recreate the container with the same configuration. Homarr runs database migrations automatically
at startup, including when moving from v1 to v2; no separate upgrade procedure is needed. Keep the `/appdata` mount and
`SECRET_ENCRYPTION_KEY` unchanged. Workshop connects to the production service by default.
```sh ```sh
docker compose pull docker compose pull
docker compose up -d docker compose up -d
@@ -1,84 +0,0 @@
---
title: Install Homarr
description: Choose the installation method that matches your infrastructure.
full: true
---
import {
IconApps,
IconBox,
IconBrandDocker,
IconBrandGithub,
IconCloud,
IconContainer,
IconDatabase,
IconHexagons,
IconHome,
IconLayoutDashboard,
IconServer2,
IconTrain,
} from "@tabler/icons-react";
Docker Compose is the best starting point for most self-hosters. Choose a platform-specific guide when Homarr will run inside an existing server manager or managed service.
<Callout type="idea" title="Not sure which guide to choose?">
Start with **Docker Compose**. It is the recommended path, has the broadest community support, and makes updates and
backups straightforward.
</Callout>
## Recommended
<Cards>
<Card icon={<IconBrandDocker />} title="Docker Compose" href="/docs/getting-started/installation/docker">
The recommended installation for most Linux and Windows servers.
</Card>
<Card icon={<IconHexagons />} title="Kubernetes with Helm" href="/docs/getting-started/installation/helm">
Deploy Homarr into an existing Kubernetes cluster.
</Card>
<Card icon={<IconBrandGithub />} title="Build from source" href="/docs/getting-started/installation/source">
Build and run Homarr directly from the repository.
</Card>
</Cards>
## Self-hosting platforms
<Cards>
<Card icon={<IconServer2 />} title="Unraid" href="/docs/getting-started/installation/unraid">
Install Homarr from the Unraid Community Apps catalog.
</Card>
<Card icon={<IconDatabase />} title="Synology" href="/docs/getting-started/installation/synology">
Run Homarr on a Synology NAS with Container Manager.
</Card>
<Card icon={<IconServer2 />} title="Proxmox" href="/docs/getting-started/installation/proxmox">
Add Homarr to a Proxmox-based homelab.
</Card>
<Card icon={<IconHome />} title="Home Assistant Add-on" href="/docs/getting-started/installation/home-assistant">
Install Homarr alongside your Home Assistant environment.
</Card>
<Card icon={<IconContainer />} title="Portainer" href="/docs/getting-started/installation/portainer">
Deploy and manage Homarr through Portainer stacks.
</Card>
<Card icon={<IconDatabase />} title="QNAP" href="/docs/getting-started/installation/qnap">
Run Homarr on a QNAP NAS.
</Card>
<Card icon={<IconApps />} title="Runtipi" href="/docs/getting-started/installation/runtipi">
Add Homarr from the Runtipi app store.
</Card>
</Cards>
## Managed and app platforms
<Cards>
<Card icon={<IconLayoutDashboard />} title="EasyPanel" href="/docs/getting-started/installation/easy-panel">
Deploy Homarr from an Easypanel template.
</Card>
<Card icon={<IconTrain />} title="Railway" href="/docs/getting-started/installation/railway">
Launch Homarr as a managed Railway service.
</Card>
<Card icon={<IconCloud />} title="PikaPods" href="/docs/getting-started/installation/pika-pods">
Use a hosted Homarr instance without managing a server.
</Card>
<Card icon={<IconBox />} title="Saltbox" href="/docs/getting-started/installation/saltbox">
Add Homarr to a Saltbox deployment.
</Card>
</Cards>
@@ -1,24 +0,0 @@
{
"title": "Installation",
"defaultOpen": false,
"pages": [
"index",
"---Recommended---",
"docker",
"helm",
"source",
"---Self-hosting platforms---",
"unraid",
"synology",
"proxmox",
"home-assistant",
"portainer",
"qnap",
"runtipi",
"---Managed and app platforms---",
"easy-panel",
"railway",
"pika-pods",
"saltbox"
]
}
@@ -21,8 +21,8 @@ This method is only useful, when you want to develop on Homarr or extend it with
## Prerequisites ## Prerequisites
- [Node.js](https://nodejs.org/en/download/) - [Node.js](https://nodejs.org/en/download/) 24.18 or newer
- [pnpm](https://pnpm.io/installation) - [pnpm](https://pnpm.io/installation) at the version pinned in the repository's `package.json`
- [Redis](https://redis.io/download) - [Redis](https://redis.io/download)
## Steps ## Steps
@@ -38,9 +38,9 @@ This method is only useful, when you want to develop on Homarr or extend it with
Install all dependencies using <code>pnpm install</code> Install all dependencies using <code>pnpm install</code>
</li> </li>
<li> <li>
Copy the `.env.example` file to `.env`. Its `DB_URL='./db.sqlite'` value is ready for local use and stores the Copy `.env.example` to `.env` and set `DB_URL` to an absolute writable path, such as
database in the cloned repository. Replace it with an absolute writable path such as `DB_URL='/home/username/homarr/db.sqlite'`. Migration and application commands run from different workspace
`DB_URL='/home/username/homarr/db.sqlite'` if you want to store the database elsewhere. directories, so a relative path can point them at different databases.
</li> </li>
<li> <li>
Run `openssl rand -hex 32` twice and set `AUTH_SECRET` and `SECRET_ENCRYPTION_KEY` to the two different generated Run `openssl rand -hex 32` twice and set `AUTH_SECRET` and `SECRET_ENCRYPTION_KEY` to the two different generated
@@ -1,4 +1,4 @@
import Link from "@/components/mdx/link"; import Link from "@docusaurus/Link";
import { IconDownload } from "@tabler/icons-react"; import { IconDownload } from "@tabler/icons-react";
# Unraid # Unraid
-5
View File
@@ -1,5 +0,0 @@
{
"title": "Getting started",
"defaultOpen": false,
"pages": ["index", "installation", "after-the-installation", "upgrade-v2", "glossary"]
}
@@ -1,88 +0,0 @@
---
title: Try the v2 beta
sidebar_position: 2
tags:
- Getting started
- Upgrade
- Migration
- Backup
---
This page covers the temporary Homarr v2 public beta. Try the [live demo](https://app-v2.preview.homarr.dev/)
without installing anything, or run the beta image published in the
[public beta announcement](https://github.com/homarr-labs/homarr/issues/6600):
```sh
docker pull ghcr.io/homarr-labs/homarr-test:v2
```
For a fresh beta installation, follow the [Docker installation guide](/docs/getting-started/installation/docker),
use `ghcr.io/homarr-labs/homarr-test:v2` as the image, and use a separate `/appdata` volume.
Set `WORKSHOP_API_URL=https://v2.preview.homarr.dev` to use the preview Workshop.
Homarr runs database migrations automatically at startup; no manual database migration command is needed.
Once v2 is released, existing installations can use their normal update process. The beta image below is temporary.
:::danger Back up before starting v2
In Homarr v1, go to **Management → Tools → Backup**, export a backup, and keep the downloaded file somewhere safe
before starting v2. See [Backup and restore](/docs/management/backup) for details.
:::
## Try the beta with existing v1 data
1. Change the Homarr image to `ghcr.io/homarr-labs/homarr-test:v2`.
2. Keep the existing `/appdata` mount, database variables, Redis configuration, and `SECRET_ENCRYPTION_KEY` unchanged.
3. Start one Homarr replica and follow its logs. Startup must reach `Migration complete`; Homarr aborts startup when a
database migration fails.
4. Open Homarr and sign in. Confirm **Management → About** reports v2 before starting additional replicas.
5. Keep using the beta image for beta updates. To return to v1, restore the pre-beta backup as described below.
Keep your other existing Compose settings, including environment variables. For Docker Compose, update the image and preview Workshop URL before the usual update:
```yaml
services:
homarr:
image: ghcr.io/homarr-labs/homarr-test:v2
environment:
WORKSHOP_API_URL: https://v2.preview.homarr.dev
```
```sh
docker compose pull
docker compose up -d
docker compose logs --follow homarr
```
Do not add `-v` when stopping the Compose deployment; that can remove named volumes.
## What v2 migrates
The startup migration:
- creates the Custom Widget v2, Assistant, header preference, and branding storage;
- adds Base/Mobile layout roles and left/right board gutters;
- converts legacy Categories and dynamic sections into Containers and rails;
- preserves legacy Custom Widget definitions, encrypted secrets, and board references for explicit migration.
Legacy Custom Widgets are not silently rewritten. In **Management → Custom Widgets**, entries marked
**Migration required** provide a credential-free migration prompt. Review and test the resulting v2 definition before
removing the archived v1 version. See [Custom Widgets: Import and Workshop](/docs/management/custom-widgets#import-and-workshop).
## Verify the upgraded instance
- Sign in with each enabled authentication method and verify administrator access.
- Open every important board on desktop and mobile. Check Containers, former Categories, rails, item placement, and
home-board assignments.
- Test at least one read and one permitted action for each critical integration. Recheck integration and board access
for representative Viewer, Editor, and Admin groups.
- Check Docker or Podman endpoints, search engines, uploaded media, trusted certificates, scheduled tasks, WebSockets,
and external Redis when used.
- Review every legacy Custom Widget and migrate it only after its v2 preview and requests work.
- Restart Homarr once more and confirm the logs contain no migration, database, Redis, authentication, or task errors.
## Roll back
Use the backup exported before the upgrade if you need to restore your v1 installation. Do not reuse a database that
v2 has already migrated with v1.
-72
View File
@@ -1,72 +0,0 @@
---
title: Homarr documentation
description: Install, configure, operate, and extend Homarr.
---
import {
IconApi,
IconArrowUp,
IconBuildingStore,
IconChecklist,
IconCode,
IconComponents,
IconDownload,
IconLayoutDashboard,
IconPlugConnected,
IconSettings,
IconUsers,
IconVocabulary,
} from "@tabler/icons-react";
Use these guides to get Homarr running, connect your services, build useful boards, and manage an installation over time.
## Install or upgrade
<Cards>
<Card icon={<IconDownload />} title="Install Homarr" href="/docs/getting-started/installation">
Choose the installation method for your system.
</Card>
<Card icon={<IconArrowUp />} title="Upgrade from v1" href="/docs/getting-started/upgrade-v2">
Move an existing Homarr installation to v2.
</Card>
<Card icon={<IconChecklist />} title="Finish setup" href="/docs/getting-started/after-the-installation">
Add apps, integrations, and widgets after installation.
</Card>
<Card icon={<IconVocabulary />} title="Learn the concepts" href="/docs/getting-started">
Understand boards, apps, integrations, and widgets.
</Card>
</Cards>
## Configure Homarr
<Cards>
<Card icon={<IconLayoutDashboard />} title="Boards and content" href="/docs/management">
Configure boards, apps, users, settings, and administration.
</Card>
<Card icon={<IconPlugConnected />} title="Connect services" href="/docs/integrations">
Find the setup guide for an integration.
</Card>
<Card icon={<IconComponents />} title="Choose widgets" href="/docs/widgets">
Find the content and controls available for boards.
</Card>
<Card icon={<IconSettings />} title="Advanced configuration" href="/docs/advanced">
Configure deployment, authentication, networking, and automation.
</Card>
</Cards>
## Extend and contribute
<Cards>
<Card icon={<IconCode />} title="Custom Widgets" href="/docs/management/custom-widgets">
Author and publish Custom JSX widgets.
</Card>
<Card icon={<IconBuildingStore />} title="Community Workshop" href="/docs/workshop">
Use and operate the community extension registry.
</Card>
<Card icon={<IconApi />} title="API reference" href="/api-reference">
Inspect Homarr's HTTP API.
</Card>
<Card icon={<IconUsers />} title="Get help and contribute" href="/docs/community">
Find support and ways to contribute.
</Card>
</Cards>
@@ -0,0 +1,10 @@
{
"label": "Integrations",
"collapsed": true,
"position": 3,
"link": {
"type": "generated-index",
"title": "Integrations",
"description": "Connect Homarr to supported services so widgets can display data and run actions. Choose an integration to see its setup requirements and compatible widgets."
}
}
@@ -21,7 +21,7 @@ import { coolifyWidget } from "../../widgets/coolify";
<AddingIntegration /> <AddingIntegration />
:::info[URL configuration] :::info URL configuration
Use the root URL of your Coolify instance, for example `https://coolify.example.com`. Homarr calls Coolify endpoints under `/api` and `/api/v1` automatically. Use the root URL of your Coolify instance, for example `https://coolify.example.com`. Homarr calls Coolify endpoints under `/api` and `/api/v1` automatically.
::: :::
+1 -1
View File
@@ -9,7 +9,7 @@ import { IntegrationCapabilites } from "@site/src/components/integrations/widget
import { AddingIntegration } from "@site/src/components/integrations/adding"; import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets"; import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react"; import { IconDownload } from "@tabler/icons-react";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
import { delugeIntegration } from "."; import { delugeIntegration } from ".";
import { downloadsWidget } from "@site/docs/widgets/downloads"; import { downloadsWidget } from "@site/docs/widgets/downloads";
+1 -1
View File
@@ -117,7 +117,7 @@ updating a Homarr resource still requires confirmation. If one endpoint is unava
endpoints remain visible. endpoints remain visible.
The `homarr.hide` label excludes a container. Other `homarr.*` labels can provide apps, integrations, groups, and widgets The `homarr.hide` label excludes a container. Other `homarr.*` labels can provide apps, integrations, groups, and widgets
during onboarding; see [Docker label discovery](/docs/integrations/docker-labels). during onboarding; see [Docker label discovery](../docker-labels).
## Security ## Security
-21
View File
@@ -1,21 +0,0 @@
---
title: Integrations
description: Connect Homarr to the applications and infrastructure you operate.
---
import { DocsDirectory } from "@/components/docs/docs-directory";
An integration stores the connection and authentication details Homarr needs to communicate with another service. Widgets and management tools can then reuse that connection.
Each guide identifies the required URL and credentials, supported capabilities, and the widgets that use the integration.
<DocsDirectory section="integrations" />
## Before you connect a service
1. Confirm that Homarr can reach the service from its own network.
2. Create the least-privileged account, token, or API key supported by the service.
3. Add the integration in **Manage → Integrations**.
4. Test the connection before adding dependent widgets.
See [Manage integrations](/docs/management/integrations) for the shared workflow.
-5
View File
@@ -1,5 +0,0 @@
{
"title": "Integrations",
"defaultOpen": false,
"pages": ["index", "..."]
}
@@ -9,7 +9,7 @@ import { IntegrationCapabilites } from "@site/src/components/integrations/widget
import { AddingIntegration } from "@site/src/components/integrations/adding"; import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets"; import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconCalendar } from "@tabler/icons-react"; import { IconCalendar } from "@tabler/icons-react";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
import { nextcloudIntegration } from "."; import { nextcloudIntegration } from ".";
import { calendarWidget } from "@site/docs/widgets/calendar"; import { calendarWidget } from "@site/docs/widgets/calendar";
import { notificationsWidget } from "@site/docs/widgets/notifications"; import { notificationsWidget } from "@site/docs/widgets/notifications";
+1 -1
View File
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets"; import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react"; import { IconDownload } from "@tabler/icons-react";
import { nzbgetIntegration } from "."; import { nzbgetIntegration } from ".";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
import { downloadsWidget } from "@site/docs/widgets/downloads"; import { downloadsWidget } from "@site/docs/widgets/downloads";
<IntegrationHeader integration={nzbgetIntegration} categories={["Usenet client"]} /> <IntegrationHeader integration={nzbgetIntegration} categories={["Usenet client"]} />
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets"; import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconHeartRateMonitor } from "@tabler/icons-react"; import { IconHeartRateMonitor } from "@tabler/icons-react";
import { openMediaVaultIntegration } from "."; import { openMediaVaultIntegration } from ".";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
import { healthMonitoringWidget } from "@site/docs/widgets/health-monitoring"; import { healthMonitoringWidget } from "@site/docs/widgets/health-monitoring";
import { systemResourcesWidget } from "@site/docs/widgets/system-resources"; import { systemResourcesWidget } from "@site/docs/widgets/system-resources";
@@ -8,6 +8,7 @@ import { IntegrationHeader } from "@site/src/components/integrations/header";
import { IntegrationCapabilites } from "@site/src/components/integrations/widgets"; import { IntegrationCapabilites } from "@site/src/components/integrations/widgets";
import { AddingIntegration } from "@site/src/components/integrations/adding"; import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets"; import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import Alert from "@theme/Admonition";
import { dnsHoleSummaryWidget } from "@site/docs/widgets/dns-hole-summary"; import { dnsHoleSummaryWidget } from "@site/docs/widgets/dns-hole-summary";
import { dnsHoleControlsWidget } from "@site/docs/widgets/dns-hole-controls"; import { dnsHoleControlsWidget } from "@site/docs/widgets/dns-hole-controls";
import { piHoleIntegration } from "."; import { piHoleIntegration } from ".";
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets"; import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react"; import { IconDownload } from "@tabler/icons-react";
import { qBittorentIntegration } from "."; import { qBittorentIntegration } from ".";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
import { downloadsWidget } from "@site/docs/widgets/downloads"; import { downloadsWidget } from "@site/docs/widgets/downloads";
<IntegrationHeader integration={qBittorentIntegration} categories={["Torrent client"]} /> <IntegrationHeader integration={qBittorentIntegration} categories={["Torrent client"]} />
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets"; import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react"; import { IconDownload } from "@tabler/icons-react";
import { sabnzbdIntegration } from "."; import { sabnzbdIntegration } from ".";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
import { downloadsWidget } from "@site/docs/widgets/downloads"; import { downloadsWidget } from "@site/docs/widgets/downloads";
<IntegrationHeader integration={sabnzbdIntegration} categories={["Usenet client"]} /> <IntegrationHeader integration={sabnzbdIntegration} categories={["Usenet client"]} />
@@ -12,7 +12,7 @@ import { synologyIntegration } from ".";
import { systemResourcesWidget } from "@site/docs/widgets/system-resources"; import { systemResourcesWidget } from "@site/docs/widgets/system-resources";
import { systemDisksWidget } from "@site/docs/widgets/system-disks"; import { systemDisksWidget } from "@site/docs/widgets/system-disks";
import { healthMonitoringWidget } from "@site/docs/widgets/health-monitoring"; import { healthMonitoringWidget } from "@site/docs/widgets/health-monitoring";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
<IntegrationHeader integration={synologyIntegration} categories={["NAS", "Hardware"]} /> <IntegrationHeader integration={synologyIntegration} categories={["NAS", "Hardware"]} />
@@ -8,7 +8,7 @@ import { IntegrationHeader } from "@site/src/components/integrations/header";
import { IntegrationCapabilites } from "@site/src/components/integrations/widgets"; import { IntegrationCapabilites } from "@site/src/components/integrations/widgets";
import { AddingIntegration } from "@site/src/components/integrations/adding"; import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets"; import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
import { technitiumDnsIntegration } from "."; import { technitiumDnsIntegration } from ".";
import { dnsHoleSummaryWidget } from "@site/docs/widgets/dns-hole-summary"; import { dnsHoleSummaryWidget } from "@site/docs/widgets/dns-hole-summary";
import { dnsHoleControlsWidget } from "@site/docs/widgets/dns-hole-controls"; import { dnsHoleControlsWidget } from "@site/docs/widgets/dns-hole-controls";
@@ -21,11 +21,11 @@ import { traefikWidget } from "../../widgets/traefik";
<AddingIntegration /> <AddingIntegration />
:::info[URL configuration] :::info URL configuration
Use the URL where Traefik exposes its dashboard/API, for example `http://traefik:8080` or `https://traefik.example.com`. Homarr calls Traefik endpoints under `/api` automatically. Use the URL where Traefik exposes its dashboard/API, for example `http://traefik:8080` or `https://traefik.example.com`. Homarr calls Traefik endpoints under `/api` automatically.
::: :::
:::warning[API requirement] :::warning API requirement
Traefik must have the API enabled. For local or internal setups this is commonly exposed through `api.insecure=true`; for production setups, expose the `api@internal` service through an authenticated router. Traefik must have the API enabled. For local or internal setups this is commonly exposed through `api.insecure=true`; for production setups, expose the `api@internal` service through an authenticated router.
::: :::
@@ -10,7 +10,7 @@ import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets"; import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { IconDownload } from "@tabler/icons-react"; import { IconDownload } from "@tabler/icons-react";
import { transmissionIntegration } from "."; import { transmissionIntegration } from ".";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
import { downloadsWidget } from "@site/docs/widgets/downloads"; import { downloadsWidget } from "@site/docs/widgets/downloads";
<IntegrationHeader integration={transmissionIntegration} categories={["Torrent client"]} /> <IntegrationHeader integration={transmissionIntegration} categories={["Torrent client"]} />
@@ -11,7 +11,7 @@ import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { truenasIntegration } from "."; import { truenasIntegration } from ".";
import { systemResourcesWidget } from "@site/docs/widgets/system-resources"; import { systemResourcesWidget } from "@site/docs/widgets/system-resources";
import { healthMonitoringWidget } from "@site/docs/widgets/health-monitoring"; import { healthMonitoringWidget } from "@site/docs/widgets/health-monitoring";
import Alert from "@/components/mdx/admonition"; import Alert from "@theme/Admonition";
<IntegrationHeader integration={truenasIntegration} categories={["NAS", "Hardware"]} /> <IntegrationHeader integration={truenasIntegration} categories={["NAS", "Hardware"]} />
+1 -1
View File
@@ -21,7 +21,7 @@ import { umamiWidget } from "../../widgets/umami";
<AddingIntegration /> <AddingIntegration />
:::tip[URL configuration] :::tip URL configuration
- **Umami Cloud:** Use `https://api.umami.is/v1` - **Umami Cloud:** Use `https://api.umami.is/v1`
- **Self-hosted:** Use `http://your-umami-host:3000/api` - **Self-hosted:** Use `http://your-umami-host:3000/api`
@@ -23,13 +23,15 @@ The What's Up Docker integration lets Homarr connect to your [WUD](https://githu
<AddingIntegration /> <AddingIntegration />
:::info[URL configuration] :::info URL configuration
Use the root URL of your WUD instance, for example `https://wud.example.com`. Homarr calls the `/api/app` and `/api/containers` endpoints under that URL automatically. Use the root URL of your WUD instance, for example `https://wud.example.com`. Homarr uses `/api/containers` under that URL for both connection testing and widget data.
::: :::
### Secrets ### Secrets
WUD does not require authentication by default. If your instance is protected with [Basic Authentication](https://github.com/getwud/wud/blob/main/docs/configuration/authentications/basic/README.md), you can provide a username and password. WUD 9 requires authentication. Enter your WUD username and password in Homarr; the initial admin credentials configured with `WUD_AUTH_ADMIN_USER` and `WUD_AUTH_ADMIN_PASSWORD` work with Basic authentication. Older WUD versions without authentication can leave both fields empty.
Credentials are sent to the configured URL over HTTP or HTTPS. Use HTTPS outside a trusted internal network.
<IntegrationSecrets <IntegrationSecrets
secrets={[ secrets={[
@@ -40,7 +42,7 @@ WUD does not require authentication by default. If your instance is protected wi
{ {
credentials: ["username", "password"], credentials: ["username", "password"],
steps: [ steps: [
"Open your WUD instance's configuration and configure a WUD_AUTH_BASIC_* user as described in the WUD documentation", "Use your WUD account credentials; older versions can use a configured WUD_AUTH_BASIC_* user",
"Enter that username and password in Homarr — Basic authentication is handled automatically", "Enter that username and password in Homarr — Basic authentication is handled automatically",
], ],
}, },
@@ -0,0 +1,9 @@
{
"label": "Management",
"collapsed": true,
"position": 2,
"link": {
"type": "generated-index",
"title": "Management pages"
}
}
+2 -2
View File
@@ -96,5 +96,5 @@ integration fails, the query returns an error.
Authenticated administrators can retrieve the current Custom Widget authoring prompt, schema, component catalog, skill, Authenticated administrators can retrieve the current Custom Widget authoring prompt, schema, component catalog, skill,
and focused references under `/api/custom-widgets/`. and focused references under `/api/custom-widgets/`.
Use [Custom Widget agent authoring](/docs/management/custom-widgets/agent-authoring) for the lifecycle and Use [Custom Widget agent authoring](../custom-widgets/agent-authoring) for the lifecycle and
[MCP](/docs/management/mcp) when the client supports Model Context Protocol. [MCP](../mcp) when the client supports Model Context Protocol.
+4 -4
View File
@@ -27,13 +27,13 @@ model, and enable Assistant. Users can choose another available model for a conv
Provider presets cover common APIs. **Custom endpoint** accepts an OpenAI-compatible Chat Completions API. For a model Provider presets cover common APIs. **Custom endpoint** accepts an OpenAI-compatible Chat Completions API. For a model
server outside the Homarr container, use a hostname that the container can resolve instead of `localhost`. server outside the Homarr container, use a hostname that the container can resolve instead of `localhost`.
The [Homarr provider](/docs/workshop/homarr-provider) is available through the Community Workshop without an administrator The [Homarr provider](../workshop/homarr-provider) is available through the Community Workshop without an administrator
API key and has a daily request allowance. API key and has a daily request allowance.
## Access ## Access
Open Assistant from the user menu, with `Shift+A`, from search with `Cmd/Ctrl+/`, or through the Open Assistant from the user menu, with `Shift+A`, from search with `Cmd/Ctrl+/`, or through the
[Assistant widget](/docs/widgets/assistant). [Assistant widget](../widgets/assistant).
Assistant can work with boards, apps, integrations, widgets, Custom Widgets, and supported connected services. Mention Assistant can work with boards, apps, integrations, widgets, Custom Widgets, and supported connected services. Mention
Homarr resources with `@`; the model loads additional live context only when needed. Homarr resources with `@`; the model loads additional live context only when needed.
@@ -47,8 +47,8 @@ Conversations are stored per user and can be searched, renamed, exported, or del
- Provider keys and custom headers are encrypted and are not returned to the browser. - Provider keys and custom headers are encrypted and are not returned to the browser.
- Prompts, attachments, tool definitions, and tool results are sent to the selected model provider. - Prompts, attachments, tool definitions, and tool results are sent to the selected model provider.
See [MCP](/docs/management/mcp) to connect an external AI client and See [MCP](./mcp) to connect an external AI client and
[Custom Widget agent authoring](/docs/management/custom-widgets/agent-authoring) for widget generation. [Custom Widget agent authoring](./custom-widgets/agent-authoring) for widget generation.
## Troubleshooting ## Troubleshooting
+1 -1
View File
@@ -98,4 +98,4 @@ inside a board.
Defaults can be set for a user, group, or the whole server. User settings take priority, followed by matching groups, Defaults can be set for a user, group, or the whole server. User settings take priority, followed by matching groups,
the `Everyone` group, and server defaults. Server-wide fallback boards must be public. the `Everyone` group, and server defaults. Server-wide fallback boards must be public.
See [Users and groups](/docs/management/users) and [Server settings](/docs/management/settings#boards). See [Users and groups](../users) and [Server settings](../settings#boards).
@@ -0,0 +1,9 @@
{
"label": "Custom Widgets",
"collapsed": true,
"position": 8,
"link": {
"type": "doc",
"id": "management/custom-widgets/index"
}
}
@@ -41,5 +41,5 @@ authenticated administrator completes it in Homarr; the agent receives the statu
Agents can also search, inspect, install, and configure existing Workshop widgets instead of regenerating them. Agents can also search, inspect, install, and configure existing Workshop widgets instead of regenerating them.
See [MCP](/docs/management/mcp) for client configuration and [requests and security](/docs/management/custom-widgets/requests-and-security) for the See [MCP](/docs/management/mcp) for client configuration and [requests and security](./requests-and-security) for the
runtime limits. runtime limits.
@@ -17,9 +17,8 @@ Changing the definition, options, or credentials invalidates the previous previe
Widget options support text, textarea, number, switch, select, multi-select, slider, date, time, color, icon, URL, Widget options support text, textarea, number, switch, select, multi-select, slider, date, time, color, icon, URL,
duration, time zone, and JSON controls. Dynamic choices can come from a load query. duration, time zone, and JSON controls. Dynamic choices can come from a load query.
See the [safe JSX runtime](/docs/management/custom-widgets/custom-jsx), See the [safe JSX runtime](./custom-jsx), [component reference](./component-reference), and
[component reference](/docs/management/custom-widgets/component-reference), and [request reference](./requests-and-security) for the authoring contract.
[request reference](/docs/management/custom-widgets/requests-and-security) for the authoring contract.
## Create with another AI service ## Create with another AI service
@@ -27,4 +26,4 @@ See the [safe JSX runtime](/docs/management/custom-widgets/custom-jsx),
must return one fenced `json` block containing the complete definition. Paste that block into the workbench, add must return one fenced `json` block containing the complete definition. Paste that block into the workbench, add
credentials separately, and validate it against a real preview. credentials separately, and validate it against a real preview.
For an MCP-connected agent, use the [Homarr Custom Widget skill](/docs/management/custom-widgets/agent-authoring) instead. For an MCP-connected agent, use the [Homarr Custom Widget skill](./agent-authoring) instead.
@@ -37,12 +37,12 @@ boards; actions require authentication and the permission declared by the reques
## Authoring ## Authoring
- [Create a Custom Widget](/docs/management/custom-widgets/authoring) in the workbench or from a copied AI prompt. - [Create a Custom Widget](./authoring) in the workbench or from a copied AI prompt.
- [Use the safe JSX runtime](/docs/management/custom-widgets/custom-jsx) for data bindings, temporary inputs, and components. - [Use the safe JSX runtime](./custom-jsx) for data bindings, temporary inputs, and components.
- [Browse the component reference](/docs/management/custom-widgets/component-reference). - [Browse the component reference](./component-reference).
- [Configure requests and security](/docs/management/custom-widgets/requests-and-security). - [Configure requests and security](./requests-and-security).
- [Connect an agent](/docs/management/custom-widgets/agent-authoring) through MCP and the Homarr skill. - [Connect an agent](./agent-authoring) through MCP and the Homarr skill.
- [Troubleshoot a definition](/docs/management/custom-widgets/troubleshooting). - [Troubleshoot a definition](./troubleshooting).
The workbench validates the same schema used by imports, Workshop, HTTP authoring resources, and MCP. Test every query The workbench validates the same schema used by imports, Workshop, HTTP authoring resources, and MCP. Test every query
and simulate relevant actions before saving. Live preview actions are opt-in because they can change the source service. and simulate relevant actions before saving. Live preview actions are opt-in because they can change the source service.
@@ -57,5 +57,5 @@ Legacy definitions show **Migration required**. The migration prompt excludes cr
describe the visible behavior separately, import the returned v2 definition, and verify it before removing the archived describe the visible behavior separately, import the returned v2 definition, and verify it before removing the archived
version. version.
Back up the database and `SECRET_ENCRYPTION_KEY` before upgrading or rolling back. Multi-replica installations must use Keep `SECRET_ENCRYPTION_KEY` unchanged when updating Homarr so existing credentials remain readable. Multi-replica
the same Redis service so cached responses invalidate consistently. installations must use the same Redis service so cached responses invalidate consistently.
@@ -1,12 +0,0 @@
{
"title": "Custom Widgets",
"pages": [
"index",
"authoring",
"agent-authoring",
"custom-jsx",
"component-reference",
"requests-and-security",
"troubleshooting"
]
}
@@ -39,7 +39,7 @@ stale cached query on another replica.
## Runtime warnings ## Runtime warnings
`UNKNOWN_MANTINE_PROP` means the installed Mantine component does not document that property. Check the `UNKNOWN_MANTINE_PROP` means the installed Mantine component does not document that property. Check the
[component reference](/docs/management/custom-widgets/component-reference). `BLOCKED_CAPABILITY` means the runtime rejected an unsafe component, [component reference](./component-reference). `BLOCKED_CAPABILITY` means the runtime rejected an unsafe component,
property, URL, or style capability. property, URL, or style capability.
## Workshop unavailable ## Workshop unavailable
-82
View File
@@ -1,82 +0,0 @@
---
title: Manage Homarr
description: Configure boards, content, access, automation, and server-wide behavior.
---
import {
IconApi,
IconApps,
IconCertificate,
IconChecklist,
IconComponents,
IconDatabaseExport,
IconLayoutDashboard,
IconLogs,
IconPhoto,
IconPlugConnected,
IconRobot,
IconSearch,
IconSettings,
IconTerminal2,
IconUsers,
} from "@tabler/icons-react";
## Everyday configuration
<Cards>
<Card icon={<IconLayoutDashboard />} title="Boards" href="/docs/management/boards">
Create, organize, share, and configure boards.
</Card>
<Card icon={<IconApps />} title="Apps" href="/docs/management/apps">
Add the services and links shown on boards.
</Card>
<Card icon={<IconPlugConnected />} title="Integrations" href="/docs/management/integrations">
Configure reusable service connections.
</Card>
<Card icon={<IconUsers />} title="Users and groups" href="/docs/management/users">
Control access and permissions.
</Card>
<Card icon={<IconSettings />} title="Settings" href="/docs/management/settings">
Change server and user preferences.
</Card>
</Cards>
## Content and extensions
<Cards>
<Card icon={<IconPhoto />} title="Media" href="/docs/management/media">
Manage uploaded assets.
</Card>
<Card icon={<IconSearch />} title="Search engines" href="/docs/management/search-engines">
Configure search shortcuts.
</Card>
<Card icon={<IconComponents />} title="Custom Widgets" href="/docs/management/custom-widgets">
Build Custom JSX widgets.
</Card>
<Card icon={<IconRobot />} title="Assistant" href="/docs/management/assistant">
Configure Homarr's assistant features.
</Card>
</Cards>
## Operations
<Cards>
<Card icon={<IconApi />} title="API" href="/docs/management/api">
Configure API keys and use the generated reference.
</Card>
<Card icon={<IconTerminal2 />} title="Model Context Protocol" href="/docs/management/mcp">
Connect external assistants to Homarr.
</Card>
<Card icon={<IconChecklist />} title="Tasks" href="/docs/management/tasks">
Inspect scheduled and background tasks.
</Card>
<Card icon={<IconLogs />} title="Logs" href="/docs/management/logs">
Inspect application logs.
</Card>
<Card icon={<IconCertificate />} title="Certificates" href="/docs/management/certificates">
Trust certificates used by connected services.
</Card>
<Card icon={<IconDatabaseExport />} title="Backups" href="/docs/management/backup">
Export and restore Homarr data.
</Card>
</Cards>
@@ -14,7 +14,7 @@ actions to widgets and can be linked to apps.
![The integration catalog](../img/integrations-catalog.png) ![The integration catalog](../img/integrations-catalog.png)
See the [integration catalog](/docs/integrations) for service-specific URLs, credentials, and supported See the [integration catalog](/docs/category/integrations) for service-specific URLs, credentials, and supported
widgets. widgets.
## Browser and server routes ## Browser and server routes
@@ -57,6 +57,6 @@ If a connection test fails:
1. Check the integration page for the required base URL and credentials. 1. Check the integration page for the required base URL and credentials.
2. Test name resolution and HTTP access from the Homarr container or pod, not only from the host or browser. 2. Test name resolution and HTTP access from the Homarr container or pod, not only from the host or browser.
3. Check Homarr and upstream-service logs, then any reverse proxy, firewall, VLAN, VPN, or DNS between them. 3. Check Homarr and upstream-service logs, then any reverse proxy, firewall, VLAN, VPN, or DNS between them.
4. For a self-signed certificate, add the expected certificate under [Certificates](/docs/management/certificates). 4. For a self-signed certificate, add the expected certificate under [Certificates](../certificates).
Do not disable upstream security controls as a general troubleshooting step. Do not disable upstream security controls as a general troubleshooting step.
+2 -2
View File
@@ -64,10 +64,10 @@ Inspect the **AI / MCP** tab or your client's tool list for available actions.
Custom Widget and Workshop authoring tools, prompts, and resources require administrator access. Custom Widget and Workshop authoring tools, prompts, and resources require administrator access.
For Custom Widgets, install the official skill and follow the preview-and-evidence workflow described in For Custom Widgets, install the official skill and follow the preview-and-evidence workflow described in
[Connect an agent](/docs/management/custom-widgets/agent-authoring). Secret values are configured in Homarr and are never returned [Connect an agent](./custom-widgets/agent-authoring). Secret values are configured in Homarr and are never returned
through MCP. through MCP.
The built-in [Assistant](/docs/management/assistant) uses the same tool catalog with the current Homarr session and asks for approval The built-in [Assistant](./assistant) uses the same tool catalog with the current Homarr session and asks for approval
before mutations by default. before mutations by default.
## Verify the connection ## Verify the connection
-25
View File
@@ -1,25 +0,0 @@
{
"title": "Management",
"defaultOpen": false,
"pages": [
"index",
"---Everyday configuration---",
"boards",
"apps",
"integrations",
"users",
"settings",
"---Content and extensions---",
"search-engines",
"media",
"custom-widgets",
"assistant",
"---Operations---",
"api",
"mcp",
"tasks",
"logs",
"certificates",
"backup"
]
}
+4 -3
View File
@@ -18,8 +18,9 @@ password. Decimal units are the default. Change them from the user form or **Com
Preferences → Data size units**. Byte rates follow the same preference; bit rates stay decimal and use labels such as Preferences → Data size units**. Byte rates follow the same preference; bit rates stay decimal and use labels such as
Mb/s. Deleting a user does not delete boards they created. Mb/s. Deleting a user does not delete boards they created.
In demo mode (`DEMO_MODE=true`), user deletion and password changes are disabled for everyone, including administrators, In demo mode (`DEMO_MODE=true`), user deletion, password changes, and local username changes are disabled for everyone,
even when `DEMO_READ_ONLY=false` allows other changes. This applies to the UI and API. including administrators, even when `DEMO_READ_ONLY=false` allows other changes. With demo editing enabled, other
profile preferences remain editable. This applies to the UI and API.
![The Users management page](../img/users.png) ![The Users management page](../img/users.png)
@@ -67,7 +68,7 @@ specific users or groups:
- Board access uses View, Modify, and Full levels. - Board access uses View, Modify, and Full levels.
- Integration access uses Use, Interact, and Full levels. - Integration access uses Use, Interact, and Full levels.
See [Boards](/docs/management/boards#access-control) and [Integrations](/docs/management/integrations#permissions). See [Boards](../boards#access-control) and [Integrations](../integrations#permissions).
## Invitations ## Invitations
-3
View File
@@ -1,3 +0,0 @@
{
"pages": ["index", "getting-started", "management", "integrations", "widgets", "workshop", "advanced", "community"]
}
+11
View File
@@ -0,0 +1,11 @@
{
"label": "Widgets",
"position": 3,
"collapsed": true,
"link": {
"type": "generated-index",
"title": "Widgets",
"description": "Widgets display data or provide actions on a board. Choose a widget to see its configuration, supported integrations, and limitations.",
"image": "/img/pictures/widgets/widget-dark.jpg"
}
}
+2 -2
View File
@@ -9,8 +9,8 @@ import { WidgetInteractionGuide } from "@site/src/components/widgets/interaction
import { WidgetHeader } from "@site/src/components/widgets/header"; import { WidgetHeader } from "@site/src/components/widgets/header";
import { AddingWidget } from "@site/src/components/widgets/adding"; import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations"; import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import Tabs from "@/components/mdx/legacy-tabs"; import Tabs from "@theme/Tabs";
import { TabItem } from "@/components/mdx/legacy-tabs"; import TabItem from "@theme/TabItem";
import { firewallWidget } from "."; import { firewallWidget } from ".";
import { opnsenseIntegration } from "../../integrations/opnsense"; import { opnsenseIntegration } from "../../integrations/opnsense";
@@ -11,8 +11,8 @@ import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetConfig } from "@site/src/components/widgets/configuration"; import { WidgetConfig } from "@site/src/components/widgets/configuration";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations"; import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import { IconAd } from "@tabler/icons-react"; import { IconAd } from "@tabler/icons-react";
import Tabs from "@/components/mdx/legacy-tabs"; import Tabs from "@theme/Tabs";
import { TabItem } from "@/components/mdx/legacy-tabs"; import TabItem from "@theme/TabItem";
import { healthMonitoringWidget } from "."; import { healthMonitoringWidget } from ".";
import { dashDotIntegration } from "@site/docs/integrations/dash-dot"; import { dashDotIntegration } from "@site/docs/integrations/dash-dot";
import { openMediaVaultIntegration } from "@site/docs/integrations/open-media-vault"; import { openMediaVaultIntegration } from "@site/docs/integrations/open-media-vault";
-21
View File
@@ -1,21 +0,0 @@
---
title: Widgets
description: Configure the information and controls shown on Homarr boards.
---
import { DocsDirectory } from "@/components/docs/docs-directory";
Widgets turn apps, integrations, and Homarr data into useful board content. Some work on their own; others require one or more configured integrations.
Each widget guide explains its configuration, required integrations, supported interactions, permissions, and important empty or error states.
## Add a widget
1. Open a board and enter edit mode.
2. Select **Add item**, then choose **Widget**.
3. Pick a widget and complete its configuration.
4. Move or resize it, then leave edit mode to use it.
<DocsDirectory section="widgets" />
See [After installation](/docs/getting-started/after-the-installation) for the complete first-board workflow.
@@ -11,8 +11,8 @@ import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetConfig } from "@site/src/components/widgets/configuration"; import { WidgetConfig } from "@site/src/components/widgets/configuration";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations"; import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import { IconAd } from "@tabler/icons-react"; import { IconAd } from "@tabler/icons-react";
import Tabs from "@/components/mdx/legacy-tabs"; import Tabs from "@theme/Tabs";
import { TabItem } from "@/components/mdx/legacy-tabs"; import TabItem from "@theme/TabItem";
import { mediaRequestListWidget } from "."; import { mediaRequestListWidget } from ".";
import { jellyseerrIntegration } from "@site/docs/integrations/jellyseerr"; import { jellyseerrIntegration } from "@site/docs/integrations/jellyseerr";
import { overseerrIntegration } from "@site/docs/integrations/overseerr"; import { overseerrIntegration } from "@site/docs/integrations/overseerr";
@@ -11,8 +11,8 @@ import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetConfig } from "@site/src/components/widgets/configuration"; import { WidgetConfig } from "@site/src/components/widgets/configuration";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations"; import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import { IconAd } from "@tabler/icons-react"; import { IconAd } from "@tabler/icons-react";
import Tabs from "@/components/mdx/legacy-tabs"; import Tabs from "@theme/Tabs";
import { TabItem } from "@/components/mdx/legacy-tabs"; import TabItem from "@theme/TabItem";
import { mediaRequestStatsWidget } from "."; import { mediaRequestStatsWidget } from ".";
import { jellyseerrIntegration } from "@site/docs/integrations/jellyseerr"; import { jellyseerrIntegration } from "@site/docs/integrations/jellyseerr";
import { overseerrIntegration } from "@site/docs/integrations/overseerr"; import { overseerrIntegration } from "@site/docs/integrations/overseerr";
@@ -11,8 +11,8 @@ import { AddingWidget } from "@site/src/components/widgets/adding";
import { WidgetConfig } from "@site/src/components/widgets/configuration"; import { WidgetConfig } from "@site/src/components/widgets/configuration";
import { WidgetIntegrations } from "@site/src/components/widgets/integrations"; import { WidgetIntegrations } from "@site/src/components/widgets/integrations";
import { IconAd } from "@tabler/icons-react"; import { IconAd } from "@tabler/icons-react";
import Tabs from "@/components/mdx/legacy-tabs"; import Tabs from "@theme/Tabs";
import { TabItem } from "@/components/mdx/legacy-tabs"; import TabItem from "@theme/TabItem";
import { mediaTranscodingWidget } from "."; import { mediaTranscodingWidget } from ".";
import { tdarrIntegration } from "@site/docs/integrations/tdarr"; import { tdarrIntegration } from "@site/docs/integrations/tdarr";
-5
View File
@@ -1,5 +0,0 @@
{
"title": "Widgets",
"defaultOpen": false,
"pages": ["index", "..."]
}
Loaded 100 of 282 files, more files were not shown because too many files have changed in this diff. Show more