Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbde111f01 | ||
|
|
a6bdbbb4ea | ||
|
|
c32a5317ca | ||
|
|
f18033ddaa | ||
|
|
ff2b589380 | ||
|
|
9bc3802b3b | ||
|
|
2049c6ade0 | ||
|
|
e21a0bb6da | ||
|
|
61f22c8e64 | ||
|
|
6cca757493 | ||
|
|
1102ad8342 | ||
|
|
7c00c18a42 | ||
|
|
ea3dac752f | ||
|
|
f994d665d2 | ||
|
|
3358b6337f | ||
|
|
61d3fd5f08 | ||
|
|
3aac106156 | ||
|
|
9d857377c1 | ||
|
|
923905c529 | ||
|
|
a4a903d7c3 | ||
|
|
925b0fb801 | ||
|
|
6db26a0d99 | ||
|
|
bbcbd031fe | ||
|
|
7024a57f56 | ||
|
|
5121356113 | ||
|
|
4f2ab59345 | ||
|
|
73bf68c9a8 | ||
|
|
dea1de5fee | ||
|
|
2bd538e685 | ||
|
|
f0c39ea0d2 | ||
|
|
8a0cf15bf7 | ||
|
|
f1c898efe2 | ||
|
|
724dee55c5 | ||
|
|
50a3bcce69 | ||
|
|
ca7be8f3ad | ||
|
|
134ef48848 | ||
|
|
98aa6f01f2 | ||
|
|
4c88030b0f | ||
|
|
0c11c2785e | ||
|
|
96a6926b2b | ||
|
|
f89487231f | ||
|
|
a62d11b5cd | ||
|
|
28e242417d | ||
|
|
0ffa95c505 | ||
|
|
b708f687fa | ||
|
|
4fd9b04c61 | ||
|
|
378332c8da | ||
|
|
3d9b8e8ae6 | ||
|
|
f7b194fc9f | ||
|
|
eb20b97d5f | ||
|
|
35155b18b9 | ||
|
|
b3aa6155cc | ||
|
|
ac62e5bfd6 | ||
|
|
f57a660088 |
No files matched your search
@@ -37,4 +37,4 @@ Orient from the current checkout before editing. Treat package manifests, export
|
||||
- Cron jobs: `packages/cron-jobs/src/jobs/`
|
||||
- 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`.
|
||||
@@ -32,24 +32,23 @@ Import only from an exported package entrypoint. Do not deep-import `@homarr/com
|
||||
|
||||
## Root exports
|
||||
|
||||
| Area | Public exports | Purpose |
|
||||
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
|
||||
| Objects | `objectKeys`, `objectEntries`, `hashObjectBase64` | Typed key/entry iteration and stable query-key hashing |
|
||||
| Strings | `capitalize`, `isNullOrWhitespace`, `bestMatch`, `normalizeImageName`, `getImageMatchRank` | Text normalization and matching |
|
||||
| Cookies | `parseCookies`, `setClientCookie` | Cookie parsing and browser cookie serialization |
|
||||
| Arrays | `splitToNChunks`, `splitToChunksWithNItems` | Split by number of groups or maximum group size |
|
||||
| Dates | `formatDuration`, `toValidDate`, `isDateWithin` | Duration formatting, safe date coercion, relative-window checks |
|
||||
| Timing | `Stopwatch` | Elapsed-time measurement and formatting |
|
||||
| React hooks | `useTimeAgo`, `useIntegrationConnected` | Relative time and integration freshness state |
|
||||
| URLs | `removeTrailingSlash`, `extractBaseUrlFromHeaders`, `getPortFromUrl`, `isAbsoluteUrl`, `SAFE_NEW_TAB_REL`, `getSafeApplicationUrl`, `getSafeAppHref` | URL normalization, safe navigation, ports, and new-tab policy |
|
||||
| Numbers and bytes | `formatNumber`, `randomInt`, `formatBytes`, `formatBytesPair`, `formatByteRate`, `metricToImperial`, `imperialToMetric` | Compact numbers, byte displays, rates, and unit conversion |
|
||||
| Legacy bytes | `humanFileSize` | Deprecated; use the `formatBytes*` helpers in new code |
|
||||
| Byte types | `ByteUnitSystem`, `FormatBytesOptions` | Options for byte formatting |
|
||||
| Errors | `extractErrorMessage`, `FlattenError` | Unknown-error messages and flattenable domain errors |
|
||||
| Theme | `getMantineColor` | Resolve a Mantine color and shade |
|
||||
| Functions | `isFunction` | Unknown-value function guard |
|
||||
| Grid | `GridAlgorithmItem`, `generateResponsiveGridFor` | Responsive nested-section grid placement |
|
||||
| IDs | `createId` | CUID2 ID creation |
|
||||
| Area | Public exports | Purpose |
|
||||
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
||||
| Objects | `objectKeys`, `objectEntries`, `isRecord`, `hashObjectBase64` | Typed key/entry iteration, record guards, and stable query-key hashing |
|
||||
| Strings | `capitalize`, `isNullOrWhitespace`, `bestMatch`, `normalizeImageName`, `getImageMatchRank` | Text normalization and matching |
|
||||
| Cookies | `parseCookies`, `setClientCookie` | Cookie parsing and browser cookie serialization |
|
||||
| Arrays | `splitToNChunks`, `splitToChunksWithNItems` | Split by number of groups or maximum group size |
|
||||
| Dates | `formatDuration`, `toValidDate`, `isDateWithin` | Duration formatting, safe date coercion, relative-window checks |
|
||||
| Timing | `Stopwatch` | Elapsed-time measurement and formatting |
|
||||
| React hooks | `useTimeAgo`, `useIntegrationConnected` | Relative time and integration freshness state |
|
||||
| URLs | `removeTrailingSlash`, `extractBaseUrlFromHeaders`, `getPortFromUrl`, `isAbsoluteUrl`, `SAFE_NEW_TAB_REL`, `getSafeApplicationUrl`, `getSafeAppHref` | URL normalization, safe navigation, ports, and new-tab policy |
|
||||
| Numbers and bytes | `formatNumber`, `formatBytes`, `formatBytesPair`, `formatByteRate`, `formatBitRate`, `defaultByteUnitSystem`, `metricToImperial` | Compact numbers, byte displays, byte/bit rates, and unit conversion |
|
||||
| Byte types | `ByteUnitSystem`, `FormatBytesOptions`, `FormatBitRateOptions` | Options for byte and bit-rate formatting |
|
||||
| Errors | `extractErrorMessage`, `FlattenError` | Unknown-error messages and flattenable domain errors |
|
||||
| Theme | `getMantineColor` | Resolve a Mantine color and shade |
|
||||
| Functions | `isFunction` | Unknown-value function guard |
|
||||
| Grid | `GridAlgorithmItem`, `generateResponsiveGridFor` | Responsive nested-section grid placement |
|
||||
| IDs | `createId` | CUID2 ID creation |
|
||||
|
||||
The root deliberately does not re-export `types`, `server`, `client`, or `env`; use their named entrypoints.
|
||||
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
---
|
||||
name: documentation-sync
|
||||
description: Keep Homarr's Docusaurus 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
|
||||
|
||||
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 |
|
||||
| ----------------------------------- | -------------------------------------------------------------------- |
|
||||
@@ -40,11 +44,11 @@ For a widget:
|
||||
|
||||
- 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.
|
||||
- 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
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
---
|
||||
name: homarr-custom-widget
|
||||
description: Author, validate, preview, test, install, or configure API-backed Homarr Custom JSX v2 widgets.
|
||||
description: Author, validate, preview, install, or configure Homarr Custom JSX v2/v3 widgets, including static and native integration widgets.
|
||||
---
|
||||
|
||||
# Homarr Custom Widget
|
||||
|
||||
Author one widget or a coordinated set of widgets. Load only needed release-matched context. Run lifecycle tools alone; independent reads may run together. For a set, research once and finish each widget's validation, evidence, and persistence before the next.
|
||||
Load release-matched context. Run lifecycle tools alone; independent reads may run together. For a set, research once, then validate, preview, and persist each widget before the next.
|
||||
|
||||
1. Read primary API documentation. Use web search when documentation is not supplied or may have changed.
|
||||
1. For HTTP widgets, read primary API documentation. For native capabilities, discover installed schemas. Static widgets need no service.
|
||||
2. Create credential-free definitions with keyed `sources`, `requests`, optional `options`, and safe JSX `template`.
|
||||
3. While drafting, use `customWidget_validateTemplate` for focused JSX diagnostics without resending the manifest.
|
||||
4. Send the definition once to `customWidget_previewCreate` and test its queries/actions. For a JSX-only fix, validate, call `customWidget_previewReviseTemplate` with its session, and retest; it inherits the manifest and resets evidence. Create a preview only for source/request/option changes.
|
||||
4. Send the definition once to `customWidget_previewCreate` and test its HTTP/native queries and simulated actions. For a JSX-only fix, validate, call `customWidget_previewReviseTemplate` with its session, and retest; it inherits the manifest and resets evidence. Other definition changes require a fresh preview.
|
||||
5. Configure deployment-specific source URLs and credentials through Homarr; never repeat plaintext.
|
||||
6. Persist each exact final tested preview with `customWidget_createFromPreview`. Do not resend a large definition through `customWidget_create` when a preview session is available.
|
||||
|
||||
Treat a supplied sample or successful preview response as the binding contract. Render every core requested field, guard optional arrays and nested values before indexing, and do not silently drop returned items. Humanize numeric enums with indexed literal label arrays, omit absent numeric values instead of inventing zero, and label timestamp timezones. Give recoverable load errors and empty states a clear refresh or retry path.
|
||||
Treat sample and preview responses as binding contracts. Render requested fields, guard optional values, humanize enums, and label timezones. Give errors and empty states a retry path.
|
||||
|
||||
Use `{option:name}` or `$option` for saved options. Use `{param:name}` or `$param` for values supplied by `SubFetch`, `ActionButton`, or `ToggleSwitch`. Load queries cannot use invocation parameters. Render load queries from `data` and `status` with `RefreshButton`; reserve `SubFetch` for manual parameterized queries. Templates read `data`, `status`, `options`, and temporary `inputs`.
|
||||
|
||||
@@ -24,11 +24,7 @@ For a bound control that depends on another input, declare its default and set `
|
||||
|
||||
Plan capabilities. Use one `customWidget_findComponents` search per job. Batch selected non-obvious binding or interaction documentation with `customWidget_getComponents`; reserve `customWidget_getComponent` for one unknown-prop repair. Failed validation reopens discovery; otherwise search only for a missing capability. The full catalog is for broad exploration; load at most one example. Context never limits composition. Prefer clear hierarchy, responsive grids, divided lists, and aligned actions over nested row cards.
|
||||
|
||||
Do not simplify a useful workflow merely because the template is interpreted. Freely compose any supported installed components with multiple sources, requests, options, `choicesFrom`, bound filters, charts, responsive detail areas, manual queries, and safe actions when they improve the user's job. Complexity must remain purposeful rather than decorative.
|
||||
|
||||
Polish with a divided list or responsive media grid. Make one metric/action asymmetrically primary; keep headers compact, identity/state clear, metadata quiet, and one badge. At base artwork fills its row and caps above xs; never combine full-width media and nowrap.
|
||||
|
||||
Make initial states actionable and wrap variable labels/values on narrow tiles. Do not use an unlabeled decorative icon as an empty state.
|
||||
Compose installed components freely around the requested workflow. Use responsive layouts, clear hierarchy, quiet metadata, and actionable initial states. Wrap variable labels on narrow tiles and label interactive icons.
|
||||
|
||||
Do not use imports, hooks, refs, raw HTML, raw event callbacks, browser requests, arbitrary functions, eval, bigint, npm packages, authored statement blocks, IIFEs, or recursion. Do not pretend MCP tools exist in an offline chat session.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Templates read `data.requestId`, `status.requestId`, `options.name`, and tempora
|
||||
</SubFetch>
|
||||
```
|
||||
|
||||
Manual queries require `trigger: "manual"` on request and `SubFetch`; otherwise they run automatically. `triggerContent` with `triggerAriaLabel` makes custom content the launcher. `SubFetch` owns loading/error/retry; its child receives success plus `{ ok, status, statusText, loading: false }`. Never author `onClick` or fetch callbacks.
|
||||
Manual queries require `trigger: "manual"` on request and `SubFetch`. Use `triggerContent` and `triggerAriaLabel` for a custom launcher. `SubFetch` owns loading/error/retry; its child receives success plus `{ ok, status, statusText, loading: false }`.
|
||||
|
||||
`SubFetch`, `ActionButton`, and `ToggleSwitch` need literal `requestId`; validation rejects missing/computed IDs.
|
||||
|
||||
@@ -35,3 +35,5 @@ Every stateful control must use `bind`, and its `inputs.<name>` value must feed
|
||||
Callback parameters must not shadow the reserved roots `data`, `status`, `options`, or `inputs`. Use `<Icon name="refresh" />` or `<TablerIcon name="refresh" />`; never invent components such as `<IconFoo />`.
|
||||
|
||||
Use expression callbacks for supported collections and trusted slots. No callback blocks, IIFEs, authored recursion, or raw events. Regex is limited to safe string operations.
|
||||
|
||||
V3 adds scoped `className` styles, `View` fragments, `WidgetModal`, `WidgetDrawer`, and `AppEmbed`. Bound controls use `persist` for declared browser preferences or `content` for shared drafts saved with `ContentSaveButton`. `NativeQuery` and `NativeActionButton` invoke declared native IDs; actions retain preview simulation and integration permissions. Fetch component contracts before using these helpers.
|
||||
@@ -13,7 +13,7 @@ interface HomarrCustomWidgetV2 {
|
||||
}
|
||||
```
|
||||
|
||||
The object key `default` is the required source ID; `default` is not a property on a source. Source properties are `name?`, `baseUrl`, `networkScope`, and `auth?`:
|
||||
Sources are keyed by ID. Empty `sources` and `requests` support static widgets. Each HTTP request must reference an existing source; omitting its source selects `default`. Source properties are `name?`, `baseUrl`, `networkScope`, and `auth?`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -47,3 +47,5 @@ Use stable real URLs for public APIs and clear suggested URLs for self-hosted se
|
||||
Paths use `{option:name}` and `{param:name}`; query/body references use `{ "$option": "name" }` and `{ "$param": "name" }`. Constants stay primitive (`take: 10`); `$param` is only for manual helpers, never load queries. Names and types are inferred.
|
||||
|
||||
Every option has `label`, `control`, and `default`. Optional fields are `description`, `choices`, `choicesFrom`, `min`, `max`, `step`, `advanced`, and `group`.
|
||||
|
||||
V3 uses `$schema: "homarr-custom-widget-v3"` and optional `extensions`: `stylesheet`, `fragments`, `preferences`, `content`, and `native`. Read `customWidget_schema` for their exact shapes. Integration options use `control: "integration"`, `default: ""`, and optional `integrationKinds`; installations choose local integrations. Discover native input schemas through `customWidget_nativeCapabilities`. Editor layout is separate from the manifest.
|
||||
@@ -4,4 +4,4 @@ All requests use Homarr's protected server executor. Source origin, network scop
|
||||
|
||||
The JSX interpreter blocks imports, hooks, refs, raw event callbacks, browser requests, eval, arbitrary functions, prototype access, unsafe URLs, global CSS escape, arbitrary portals, bigint, statement blocks, IIFEs, and recursion. Regex literals must be bounded and reject backreferences, lookbehind, nested quantifiers, excessive length, and unsupported flags.
|
||||
|
||||
Credentials are stored separately and never exported or returned to an agent. A published self-hosted source URL is only a suggestion: installers must confirm or replace private and loopback URLs for their own Homarr deployment. Source origins cannot be controlled through widget options.
|
||||
Credentials stay local and are never exported. Installers confirm or replace suggested private and loopback URLs for their deployment. Source origins are fixed by configuration.
|
||||
@@ -1,22 +1,25 @@
|
||||
# Since .env is gitignored, you can use .env.example to build a new `.env` file when you clone the repo.
|
||||
# Keep this file up-to-date when you add new variables to \`.env\`.
|
||||
# Keep this file up-to-date when you add new variables to `.env`.
|
||||
|
||||
# This file will be committed to version control, so make sure not to have any secrets in it.
|
||||
# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.
|
||||
|
||||
# The below secret is not used anywhere but required for Auth.js (Would encrypt JWTs and Mail hashes, both not used)
|
||||
AUTH_SECRET="supersecret"
|
||||
# Generate two different 64-character hex values with `openssl rand -hex 32` before starting Homarr.
|
||||
# Never reuse these values or commit the populated `.env` file.
|
||||
AUTH_SECRET=
|
||||
|
||||
# The below secret is used to encrypt integration secrets in the database.
|
||||
# It should be a 32-byte string, generated by running `openssl rand -hex 32` on Unix
|
||||
# or starting the project without any (which will show a randomly generated one).
|
||||
SECRET_ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000
|
||||
# Homarr will reject an empty or invalid value and print a randomly generated candidate.
|
||||
SECRET_ENCRYPTION_KEY=
|
||||
|
||||
LOG_LEVEL='info'
|
||||
|
||||
# This is how you can use the sqlite driver:
|
||||
DB_DRIVER='better-sqlite3'
|
||||
DB_URL='FULL_PATH_TO_YOUR_SQLITE_DB_FILE'
|
||||
# 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.
|
||||
DB_URL=
|
||||
|
||||
# Those are the two ways to use the mysql2 driver:
|
||||
# 1. Using the URL format:
|
||||
@@ -63,6 +66,8 @@ UNSAFE_ENABLE_MOCK_INTEGRATION=true
|
||||
|
||||
# Public URL contract. Values must be absolute HTTP(S) URLs without credentials,
|
||||
# query strings, or fragments. Trailing slashes are normalized at startup.
|
||||
# Public Homarr origin used by MCP OAuth metadata and redirects behind proxies.
|
||||
# BASE_URL=https://homarr.example.com
|
||||
HOMARR_WEBSITE_URL=https://homarr.dev
|
||||
# PocketBase API used by Homarr and by the standalone documentation site.
|
||||
# Defaults to HOMARR_WEBSITE_URL.
|
||||
|
||||
@@ -25,6 +25,18 @@ body:
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Add any other information related to the bug here, screenshots if applicable.
|
||||
- type: input
|
||||
id: exactBuild
|
||||
attributes:
|
||||
label: Exact build or image
|
||||
description: For preview or development builds, include the commit SHA or image digest. A moving tag such as v2 is not enough to identify the build.
|
||||
placeholder: "Commit SHA, image digest, or release version"
|
||||
- type: input
|
||||
id: lastWorkingVersion
|
||||
attributes:
|
||||
label: Last working version
|
||||
description: If this worked before, include the last version or build where you tried the same action. Leave blank if unknown.
|
||||
placeholder: "Version or commit SHA"
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
@@ -33,6 +45,7 @@ body:
|
||||
options:
|
||||
# The below comment is used to insert a new version with on-release.yml
|
||||
#NEXT_VERSION#
|
||||
- 1.77.0
|
||||
- 1.76.2
|
||||
- 1.76.1
|
||||
- 1.76.0
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
<h3>Homarr</h3>
|
||||
</div>
|
||||
|
||||
**Thank you for your contribution. Please ensure that your pull request meets the following pull request:**
|
||||
**Thank you for your contribution. Please ensure that your pull request meets the following requirements:**
|
||||
|
||||
- [ ] Builds without warnings or errors (`pnpm build`, autofix with `pnpm format:fix`)
|
||||
- [ ] Pull request targets `dev` branch
|
||||
- [ ] Relevant checks pass without warnings or errors
|
||||
- [ ] Pull request targets the intended base branch (`dev` by default; `release/v2` for v2 release work)
|
||||
- [ ] Commits follow the [conventional commits guideline](https://www.conventionalcommits.org/en/v1.0.0/)
|
||||
- [ ] No shorthand variable names are used (eg. `x`, `y`, `i` or any abbrevation)
|
||||
- [ ] Documentation is up to date. Create a pull request [here](https://github.com/homarr-labs/documentation/).
|
||||
- [ ] When using AI; No temp files are checked in, the code style follows the rest of the project
|
||||
- [ ] No shorthand variable names are used (for example, `x`, `y`, `i`, or abbreviations)
|
||||
- [ ] User-facing changes include matching documentation updates under `apps/docs`
|
||||
- [ ] When using AI, no temporary files are checked in and the code style follows the rest of the project
|
||||
|
||||
**When contributing a new integration or widget:**
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.RENOVATE_APPROVE_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.RENOVATE_APPROVE_APP_ID }}
|
||||
client-id: ${{ vars.RENOVATE_APPROVE_CLIENT_ID }}
|
||||
permission-pull-requests: write # required to enable auto-merge
|
||||
|
||||
- name: Install GitHub CLI
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.RENOVATE_APPROVE_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.RENOVATE_APPROVE_APP_ID }}
|
||||
client-id: ${{ vars.RENOVATE_APPROVE_CLIENT_ID }}
|
||||
permission-pull-requests: write # required to approve a pull request and enable auto-merge
|
||||
|
||||
- name: Install GitHub CLI
|
||||
|
||||
@@ -97,17 +97,16 @@ jobs:
|
||||
|
||||
- name: Validate Custom Widget bundle budget
|
||||
run: |
|
||||
pnpm --filter nextjs build
|
||||
pnpm turbo run build --filter=@homarr/nextjs
|
||||
pnpm check:custom-widget-bundle
|
||||
|
||||
- name: Run unit tests
|
||||
run: pnpm test
|
||||
|
||||
container:
|
||||
name: Container and E2E
|
||||
name: Container build
|
||||
# Same-repository previews already build amd64; only build a fallback when no digest is available.
|
||||
needs: [fast-gate, preview-amd64]
|
||||
if: |
|
||||
!cancelled() && needs.fast-gate.result == 'success' &&
|
||||
needs.preview-amd64.result != 'failure' && needs.preview-amd64.outputs.digest == '' &&
|
||||
(
|
||||
github.event_name == 'merge_group' ||
|
||||
(github.event_name == 'push' && github.ref == 'refs/heads/release/v2') ||
|
||||
@@ -115,10 +114,9 @@ jobs:
|
||||
(github.event_name == 'workflow_dispatch' && (inputs.operation == 'validate' || inputs.operation == 'publish'))
|
||||
)
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
timeout-minutes: 20
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
if: "!env.ACT"
|
||||
@@ -126,23 +124,10 @@ jobs:
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || '' }}
|
||||
|
||||
- name: Setup
|
||||
uses: ./tooling/github/setup
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
if: "!env.ACT"
|
||||
if: needs.preview-amd64.outputs.digest == '' && !env.ACT
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Reuse amd64 preview image
|
||||
if: needs.preview-amd64.outputs.digest != '' && !env.ACT
|
||||
env:
|
||||
DIGEST: ${{ needs.preview-amd64.outputs.digest }}
|
||||
run: |
|
||||
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
|
||||
docker pull "${PREVIEW_IMAGE}@${DIGEST}"
|
||||
docker tag "${PREVIEW_IMAGE}@${DIGEST}" homarr-ci
|
||||
docker tag "${PREVIEW_IMAGE}@${DIGEST}" homarr-e2e
|
||||
|
||||
- name: Build container once
|
||||
if: needs.preview-amd64.outputs.digest == '' && !env.ACT
|
||||
uses: docker/build-push-action@v7
|
||||
@@ -152,9 +137,7 @@ jobs:
|
||||
platforms: linux/amd64
|
||||
load: true
|
||||
push: false
|
||||
tags: |
|
||||
homarr-ci
|
||||
homarr-e2e
|
||||
tags: homarr-ci
|
||||
labels: |
|
||||
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
@@ -182,37 +165,7 @@ jobs:
|
||||
fi
|
||||
done
|
||||
DOCKER_BUILDKIT=1 docker build --platform linux/amd64 \
|
||||
--tag homarr-ci --tag homarr-e2e "${secret_args[@]}" .
|
||||
|
||||
- name: Cache Playwright browsers
|
||||
if: "!env.ACT"
|
||||
id: playwright-cache
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: ~/.cache/ms-playwright
|
||||
key: playwright-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install Playwright Chromium
|
||||
if: steps.playwright-cache.outputs.cache-hit != 'true' || env.ACT
|
||||
run: pnpm exec playwright install --with-deps chromium
|
||||
|
||||
- name: Install Playwright system deps
|
||||
if: steps.playwright-cache.outputs.cache-hit == 'true'
|
||||
run: pnpm exec playwright install-deps chromium
|
||||
|
||||
- name: Run E2E tests
|
||||
env:
|
||||
NODE_ENV: development
|
||||
CI: "true"
|
||||
run: pnpm exec vitest e2e --retry 1 --maxWorkers 4
|
||||
|
||||
- name: Upload E2E artifacts
|
||||
if: failure() && !env.ACT
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: playwright-report
|
||||
path: e2e/test-results/
|
||||
retention-days: 7
|
||||
--tag homarr-ci "${secret_args[@]}" .
|
||||
|
||||
preview-amd64:
|
||||
name: Build amd64 preview image
|
||||
@@ -320,10 +273,10 @@ jobs:
|
||||
|
||||
publish-preview:
|
||||
name: Publish multi-platform preview image
|
||||
needs: [container, preview-amd64, preview-arm64]
|
||||
needs: [fast-gate, preview-amd64, preview-arm64]
|
||||
if: |
|
||||
!cancelled() &&
|
||||
needs.container.result == 'success' &&
|
||||
needs.fast-gate.result == 'success' &&
|
||||
needs.preview-amd64.result == 'success' &&
|
||||
needs.preview-arm64.result == 'success' &&
|
||||
(
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.CROWDIN_APP_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.CROWDIN_APP_ID }}
|
||||
client-id: ${{ vars.CROWDIN_CLIENT_ID }}
|
||||
permission-contents: write # required to commit to crowdin branch
|
||||
permission-pull-requests: write # required to create pull request
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ permissions:
|
||||
jobs:
|
||||
create-and-merge-pr:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Discord notification
|
||||
if: ${{ github.event.inputs.send-notifications }}
|
||||
if: ${{ inputs.send-notifications }}
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
@@ -37,11 +37,22 @@ jobs:
|
||||
branch: next
|
||||
- name: 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:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
- name: Discord notification
|
||||
if: ${{ github.event.inputs.send-notifications }}
|
||||
if: ${{ inputs.send-notifications }}
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
@@ -52,19 +63,19 @@ jobs:
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.RENOVATE_APPROVE_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.RENOVATE_APPROVE_APP_ID }}
|
||||
client-id: ${{ vars.RENOVATE_APPROVE_CLIENT_ID }}
|
||||
permission-pull-requests: write
|
||||
- name: Approve PR
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.obtainApprovalToken.outputs.token }}
|
||||
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
|
||||
id: obtainMergeToken
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.RENOVATE_MERGE_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
|
||||
client-id: ${{ vars.RENOVATE_MERGE_CLIENT_ID }}
|
||||
permission-contents: write # write to beta branch (due to merge)
|
||||
permission-pull-requests: write # merge pull request
|
||||
- id: automerge
|
||||
@@ -82,21 +93,21 @@ jobs:
|
||||
MERGE_REQUIRED_APPROVALS: 0 # do not require approvals
|
||||
|
||||
- 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:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
with:
|
||||
args: "Merged PR ${{ steps.create-pull-request.outputs.url }} for release ${{ steps.semver.outputs.next }}-beta"
|
||||
- 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:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
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"
|
||||
- name: Discord Fail Notification
|
||||
if: failure() && github.event.inputs.send-notifications
|
||||
if: ${{ failure() && inputs.send-notifications }}
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
|
||||
@@ -40,6 +40,7 @@ jobs:
|
||||
version: ${{ steps.read-semver.outputs.version || steps.version-fallback.outputs.version }}
|
||||
git_ref: ${{ steps.read-git-ref.outputs.ref || steps.read-semver.outputs.version || github.ref }}
|
||||
skipped: ${{ env.SKIP_RELEASE }}
|
||||
upstream_sync: ${{ steps.update-upstream.outcome }}
|
||||
steps:
|
||||
- run: echo "Manual dispatch redeploys the latest existing release without creating a new one"
|
||||
if: env.SKIP_RELEASE == 'true'
|
||||
@@ -54,7 +55,7 @@ jobs:
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.RENOVATE_MERGE_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
|
||||
client-id: ${{ vars.RENOVATE_MERGE_CLIENT_ID }}
|
||||
permission-contents: write # required to commit package.json & changelog changes, merge them to dev / next and publish the release
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
@@ -115,8 +116,10 @@ jobs:
|
||||
run: |
|
||||
echo "ref=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||
- name: Update dev / next branch
|
||||
id: update-upstream
|
||||
if: env.SKIP_RELEASE == 'false'
|
||||
continue-on-error: true # Prevent pipeline from failing when merge fails
|
||||
# Finish publishing the already-created release, then fail in the publish job if synchronization did not work.
|
||||
continue-on-error: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}
|
||||
UPSTREAM_BRANCH: ${{ github.ref_name == 'main' && 'dev' || 'next' }}
|
||||
@@ -274,7 +277,7 @@ jobs:
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.RENOVATE_MERGE_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
|
||||
client-id: ${{ vars.RENOVATE_MERGE_CLIENT_ID }}
|
||||
permission-contents: write # required to publish the release
|
||||
|
||||
- name: Log in to the Container registry
|
||||
@@ -311,6 +314,12 @@ jobs:
|
||||
run: |
|
||||
gh release edit --repo ${{ github.repository }} ${{ needs.release.outputs.version }} --draft=false
|
||||
|
||||
- name: Verify dev / next synchronization
|
||||
if: needs.release.outputs.skipped == 'false' && needs.release.outputs.upstream_sync != 'success'
|
||||
run: |
|
||||
echo "::error::The released commit was not synchronized back to the upstream development branch."
|
||||
exit 1
|
||||
|
||||
- name: Discord notification
|
||||
if: github.event_name != 'workflow_dispatch' || inputs['send-notifications']
|
||||
env:
|
||||
@@ -318,3 +327,17 @@ jobs:
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
with:
|
||||
args: "Successfully deployed images for branch **${{ github.ref_name }}**. Tagged as **${{env.NEXT_VERSION}}**."
|
||||
|
||||
notify-failure:
|
||||
name: Notify deployment failure
|
||||
if: ${{ always() && (failure() || cancelled()) && (github.event_name != 'workflow_dispatch' || inputs['send-notifications']) }}
|
||||
needs: [release, build-amd64, build-arm64, extract-asset-amd64, extract-asset-arm64, publish]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
steps:
|
||||
- name: Discord failure notification
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
with:
|
||||
args: "The deployment for branch **${{ github.ref_name }}** failed or was cancelled: [run ${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
|
||||
@@ -19,10 +19,10 @@ permissions:
|
||||
jobs:
|
||||
create-and-merge-pr:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Discord notification
|
||||
if: ${{ github.event.inputs.send-notifications }}
|
||||
if: ${{ github.event_name == 'schedule' || inputs.send-notifications }}
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
@@ -38,13 +38,30 @@ jobs:
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
branch: dev
|
||||
noNewCommitBehavior: silent
|
||||
noVersionBumpBehavior: silent
|
||||
- name: No release needed
|
||||
if: ${{ steps.semver.outputs.bump == '' || steps.semver.outputs.bump == 'none' }}
|
||||
run: echo "No release-worthy commits were found since ${{ steps.semver.outputs.current }}." >> "$GITHUB_STEP_SUMMARY"
|
||||
- name: Create pull request
|
||||
id: create-pull-request
|
||||
run: 'gh pr create --title "chore(release): automatic release ${{ steps.semver.outputs.next }}" --body "**This is an automatic release**.<br/>Manual action may be required for major bumps.<br/>Detected change to be ``${{ steps.semver.outputs.bump }}``<br/>Bump version from ``${{ steps.semver.outputs.current }}`` to ``${{ steps.semver.outputs.next }}``" --base main --head dev --label automerge'
|
||||
if: ${{ steps.semver.outputs.bump != '' && steps.semver.outputs.bump != 'none' }}
|
||||
run: |
|
||||
pr_url="$(gh pr list --base main --head dev --state open --json url --jq '.[0].url // empty')"
|
||||
if [[ -z "$pr_url" ]]; then
|
||||
pr_url="$(gh pr create \
|
||||
--title "chore(release): automatic release ${{ steps.semver.outputs.next }}" \
|
||||
--body "**This is an automatic release**.<br/>Manual action may be required for major bumps.<br/>Detected change to be ``${{ steps.semver.outputs.bump }}``<br/>Bump version from ``${{ steps.semver.outputs.current }}`` to ``${{ steps.semver.outputs.next }}``" \
|
||||
--base main \
|
||||
--head dev \
|
||||
--label automerge)"
|
||||
fi
|
||||
echo "url=$pr_url" >> "$GITHUB_OUTPUT"
|
||||
echo "pr_number=${pr_url##*/}" >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
- name: Discord notification
|
||||
if: ${{ github.event.inputs.send-notifications }}
|
||||
if: ${{ steps.create-pull-request.outcome == 'success' && (github.event_name == 'schedule' || inputs.send-notifications) }}
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
@@ -52,26 +69,29 @@ jobs:
|
||||
args: "Created a release PR ${{ steps.create-pull-request.outputs.url }} for version ${{ steps.semver.outputs.next }} (new behaviour: ${{ steps.semver.outputs.bump }})"
|
||||
- name: Obtain token
|
||||
id: obtainApprovalToken
|
||||
if: ${{ steps.create-pull-request.outcome == 'success' }}
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.RENOVATE_APPROVE_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.RENOVATE_APPROVE_APP_ID }}
|
||||
client-id: ${{ vars.RENOVATE_APPROVE_CLIENT_ID }}
|
||||
permission-pull-requests: write
|
||||
- name: Approve PR
|
||||
if: ${{ steps.create-pull-request.outcome == 'success' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.obtainApprovalToken.outputs.token }}
|
||||
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
|
||||
id: obtainMergeToken
|
||||
if: ${{ steps.create-pull-request.outcome == 'success' }}
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.RENOVATE_MERGE_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
|
||||
client-id: ${{ vars.RENOVATE_MERGE_CLIENT_ID }}
|
||||
permission-contents: write # write to main branch (due to merge)
|
||||
permission-pull-requests: write # merge pull request
|
||||
- id: automerge
|
||||
if: ${{ steps.semver.outputs.bump != 'major' }}
|
||||
if: ${{ steps.create-pull-request.outcome == 'success' && steps.semver.outputs.bump != 'major' }}
|
||||
name: automerge
|
||||
uses: "pascalgn/automerge-action@v0.16.4"
|
||||
env:
|
||||
@@ -85,21 +105,21 @@ jobs:
|
||||
MERGE_REQUIRED_APPROVALS: 0 # do not require approvals
|
||||
|
||||
- name: Merged Discord notification
|
||||
if: ${{ steps.automerge.outputs.mergeResult == 'merged' && github.event.inputs.send-notifications }}
|
||||
if: ${{ steps.automerge.outputs.mergeResult == 'merged' && (github.event_name == 'schedule' || inputs.send-notifications) }}
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
with:
|
||||
args: "Merged PR ${{ steps.create-pull-request.outputs.url }} for release ${{ steps.semver.outputs.next }}"
|
||||
- name: Major Bump Discord notification
|
||||
if: ${{ steps.semver.outputs.bump == 'major' && github.event.inputs.send-notifications }}
|
||||
if: ${{ steps.semver.outputs.bump == 'major' && (github.event_name == 'schedule' || inputs.send-notifications) }}
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
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 }}"
|
||||
- name: Discord Fail Notification
|
||||
if: failure() && github.event.inputs.send-notifications
|
||||
if: ${{ failure() && (github.event_name == 'schedule' || inputs.send-notifications) }}
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.4.0
|
||||
|
||||
@@ -26,36 +26,8 @@ jobs:
|
||||
- name: Copy env
|
||||
run: cp .env.example .env
|
||||
|
||||
- name: Start dev server
|
||||
run: pnpm --filter @homarr/nextjs dev &
|
||||
env:
|
||||
TURBO_TELEMETRY_DISABLED: 1
|
||||
DISABLE_TELEMETRY: 1
|
||||
|
||||
- name: Wait for server and fetch spec
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for i in $(seq 1 30); do
|
||||
if curl -fsS http://localhost:3000/api/openapi -o /tmp/openapi.json 2>/dev/null; then
|
||||
echo "Server is up, spec fetched"
|
||||
break
|
||||
fi
|
||||
echo "Waiting for server... ($i/30)"
|
||||
sleep 3
|
||||
done
|
||||
|
||||
if [ ! -f /tmp/openapi.json ]; then
|
||||
echo "::error::Server failed to start within timeout"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jq -e '.openapi and .paths' /tmp/openapi.json > /dev/null || {
|
||||
echo "::error::Fetched file is not a valid OpenAPI spec"
|
||||
exit 1
|
||||
}
|
||||
|
||||
cp /tmp/openapi.json apps/docs/static/api/open-api-schema.json
|
||||
echo "OpenAPI spec updated ($(jq '.paths | length' /tmp/openapi.json) paths)"
|
||||
- name: Generate and validate OpenAPI spec
|
||||
run: pnpm scripts:update-openapi
|
||||
|
||||
- name: Commit updated spec
|
||||
uses: EndBug/add-and-commit@v10
|
||||
|
||||
@@ -5,39 +5,6 @@ on:
|
||||
types: [released]
|
||||
|
||||
jobs:
|
||||
trigger-docs-release:
|
||||
name: Trigger Documentation Release
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
steps:
|
||||
- name: Obtain token
|
||||
id: obtainToken
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.HOMARR_DOCS_RELEASE_APP_PRIVATE_KEY }}
|
||||
client-id: ${{ vars.HOMARR_DOCS_RELEASE_APP_ID }}
|
||||
owner: homarr-labs
|
||||
repositories: |
|
||||
documentation
|
||||
permission-contents: write # required to dispatch repository workflow
|
||||
- name: Trigger documentation release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}
|
||||
SOURCE_TAG: ${{ github.event.release.tag_name }}
|
||||
run: |
|
||||
curl -X POST \
|
||||
-H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
https://api.github.com/repos/homarr-labs/documentation/dispatches \
|
||||
-d @- <<EOF
|
||||
{
|
||||
"event_type": "trigger-release",
|
||||
"client_payload": {
|
||||
"tag": "${SOURCE_TAG}"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
update-bug-report-template:
|
||||
name: Update Bug Report Template
|
||||
runs-on: ubuntu-latest
|
||||
@@ -48,7 +15,7 @@ jobs:
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.RENOVATE_MERGE_PRIVATE_KEY }}
|
||||
client-id: ${{ secrets.RENOVATE_MERGE_APP_ID }}
|
||||
client-id: ${{ vars.RENOVATE_MERGE_CLIENT_ID }}
|
||||
permission-contents: write # required to commit to branch
|
||||
permission-pull-requests: write # required to create pr & enable automerge
|
||||
- name: Checkout code
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.HOMARR_UPDATE_CONTRIBUTORS_PRIVATE_KEY }}
|
||||
client-id: ${{ vars.HOMARR_UPDATE_CONTRIBUTORS_APP_ID }}
|
||||
client-id: ${{ vars.HOMARR_UPDATE_CONTRIBUTORS_CLIENT_ID }}
|
||||
permission-contents: write # required to commit to branch
|
||||
permission-pull-requests: write # required to create pr & enable automerge
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
uses: actions/create-github-app-token@v3
|
||||
with:
|
||||
private-key: ${{ secrets.HOMARR_UPDATE_CONTRIBUTORS_PRIVATE_KEY }}
|
||||
client-id: ${{ vars.HOMARR_UPDATE_CONTRIBUTORS_APP_ID }}
|
||||
client-id: ${{ vars.HOMARR_UPDATE_CONTRIBUTORS_CLIENT_ID }}
|
||||
permission-contents: write # required to commit to branch
|
||||
permission-pull-requests: write # required to create pr & enable automerge
|
||||
- name: Checkout code
|
||||
|
||||
@@ -2,8 +2,36 @@ name: Workshop
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/workshop.yml"
|
||||
- "apps/workshop/**"
|
||||
- "apps/docs/**"
|
||||
- "packages/custom-widgets/**"
|
||||
- "packages/definitions/**"
|
||||
- "packages/workshop/**"
|
||||
- "tooling/typescript/**"
|
||||
- "patches/**"
|
||||
- "package.json"
|
||||
- "pnpm-lock.yaml"
|
||||
- "pnpm-workspace.yaml"
|
||||
- "turbo.json"
|
||||
- ".npmrc"
|
||||
push:
|
||||
branches: [dev, v2, release/v2, main]
|
||||
paths:
|
||||
- ".github/workflows/workshop.yml"
|
||||
- "apps/workshop/**"
|
||||
- "apps/docs/**"
|
||||
- "packages/custom-widgets/**"
|
||||
- "packages/definitions/**"
|
||||
- "packages/workshop/**"
|
||||
- "tooling/typescript/**"
|
||||
- "patches/**"
|
||||
- "package.json"
|
||||
- "pnpm-lock.yaml"
|
||||
- "pnpm-workspace.yaml"
|
||||
- "turbo.json"
|
||||
- ".npmrc"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -15,21 +43,10 @@ concurrency:
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24.18.0
|
||||
- uses: pnpm/action-setup@v6
|
||||
with:
|
||||
run_install: false
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- run: pnpm --filter @homarr/workshop typecheck
|
||||
- run: pnpm --filter @homarr/docs typecheck
|
||||
- run: docker compose --env-file apps/workshop/.env.staging.example -f apps/workshop/docker-compose.staging.yml config --quiet
|
||||
- run: pnpm test:workshop
|
||||
- run: pnpm test:workshop-image
|
||||
|
||||
publish-amd64:
|
||||
if: github.event_name == 'push' && (github.ref_name == 'v2' || github.ref_name == 'release/v2' || github.ref_name == 'main')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"mcpServers": {
|
||||
"mantine": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@mantine/mcp-server@9.5.2"]
|
||||
"args": ["-y", "@mantine/mcp-server@9.6.0"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,12 @@
|
||||
"CHANGELOG.md",
|
||||
"apps/docs/.docusaurus/**",
|
||||
"apps/docs/build/**",
|
||||
"apps/docs/blog/**",
|
||||
"apps/docs/blog/2022/**",
|
||||
"apps/docs/blog/2023/**",
|
||||
"apps/docs/blog/2024/**",
|
||||
"apps/docs/blog/2025/**",
|
||||
"apps/docs/blog/authors.yml",
|
||||
"apps/docs/static/api/open-api-schema.json",
|
||||
"packages/custom-widgets/src/core/component-catalog.generated.json",
|
||||
"apps/docs/static/custom-widgets/component-catalog-v1.json"
|
||||
]
|
||||
|
||||
@@ -59,7 +59,13 @@ homarr/
|
||||
|
||||
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 widget → `apps/docs/docs/widgets/<slug>/index.mdx` + `index.ts`
|
||||
@@ -86,7 +92,7 @@ When modifying user-facing code, you MUST also update the corresponding document
|
||||
- Lint: oxlint (not ESLint)
|
||||
- Format: oxfmt (not Prettier)
|
||||
- UI: Mantine (not Tailwind) — Tailwind is only used in docs app
|
||||
- Mantine: use the project-scoped MCP server in `.mcp.json` for current v9 APIs, and check `packages/ui/` before creating a new primitive.
|
||||
- Mantine: use the `mantine` MCP server in `.mcp.json` for current v9 APIs before writing component code. Prefer built-in primitives (`Combobox`/`useCombobox`, the polymorphic `component` prop, `@mantine/hooks`) and check `packages/ui/` for existing conventions first.
|
||||
- Icons: @tabler/icons-react
|
||||
- Docs app can import from `@homarr/definitions` for shared types
|
||||
- Run `pnpm dev:cli -- dev` to browse local `homarr:*` images and remote PR images.
|
||||
@@ -94,11 +100,15 @@ When modifying user-facing code, you MUST also update the corresponding document
|
||||
- Run `pnpm dev:cli -- build --pr <number>` to build a PR locally from a temporary checkout.
|
||||
- Run Go checks from `tools/homarr-dev` with `go test ./...` and `go vet ./...`.
|
||||
|
||||
## MCP servers
|
||||
|
||||
`.mcp.json` declares project-scoped MCP servers. Keep only keyless definitions there; credentials belong in local dotfiles. See [Mantine LLM tooling](https://mantine.dev/guides/llms/) for client-specific setup.
|
||||
|
||||
## Agent 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
|
||||
- `documentation-sync` — required user-facing documentation updates
|
||||
- `documentation-sync` — documentation for changes users need explained
|
||||
- `mcp-integration` — safe tRPC-to-MCP exposure
|
||||
- `homarr-custom-widget` — safe Custom JSX v2 authoring
|
||||
@@ -1,3 +1,7 @@
|
||||
## [1.77.1](https://github.com/homarr-labs/homarr/compare/v1.77.0...v1.77.1) (2026-09-11)
|
||||
|
||||
## [1.77.0](https://github.com/homarr-labs/homarr/compare/v1.76.2...v1.77.0) (2026-09-06)
|
||||
|
||||
## [1.76.2](https://github.com/homarr-labs/homarr/compare/v1.76.1...v1.76.2) (2026-08-27)
|
||||
|
||||
## [1.76.1](https://github.com/homarr-labs/homarr/compare/v1.76.0...v1.76.1) (2026-08-26)
|
||||
|
||||
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 418 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 618 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,159 @@
|
||||
---
|
||||
authors:
|
||||
- ajnart
|
||||
tags: [homarr, update, version, assistant, custom widgets, dashboards, docker]
|
||||
description: Homarr 2.0 introduces Custom Widgets and Workshop, rebuilt board editing, Assistant tooling, responsive layouts, onboarding, and more.
|
||||
image: ./img/homarr-v2-dashboard.webp
|
||||
draft: false
|
||||
---
|
||||
|
||||
# Homarr 2.0.0 - Workshop, Custom Widgets and a rebuilt board
|
||||
|
||||
First, thank you.
|
||||
|
||||
Many of you used the v2 demo when it was still rough, found bugs and came back to test the next build. Others translated Homarr, answered questions, contributed code or simply kept using it. We would not be shipping this without you.
|
||||
|
||||
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 builds on the dashboard you already use. Here is what changed.
|
||||
|
||||

|
||||
|
||||
<!-- truncate -->
|
||||
|
||||
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.
|
||||
|
||||
## Custom Widgets v2 and Workshop
|
||||
|
||||
### Build almost any widget
|
||||
|
||||
**This is the big one.** We think it is the most important Homarr update we have made.
|
||||
|
||||
Custom Widgets v2 lets you build widgets from JSX, API requests, actions and typed settings. Write one yourself or describe it to Assistant, then test it in the workbench. We think this is enough to make almost any dashboard widget—even that oddly specific component only three people need. Those three people no longer have to wait for us.
|
||||
|
||||
This was partly inspired by [Google's upcoming Create My Widget feature](https://blog.google/products-and-platforms/platforms/android/gemini-intelligence/): describe a widget in normal language and let AI make it. Coding knowledge is optional. Knowing what the API does still helps; AI has not fixed bad documentation. Yet.
|
||||
|
||||

|
||||
|
||||
A `homarr-custom-widget-v2` definition can use several fixed-origin API sources. Credentials are encrypted separately and stay out of exports and Workshop submissions. Actions support `GET`, `POST`, `PUT`, `PATCH` and `DELETE`; requests have host checks, timeouts, size limits, permissions and rate limits. Custom Widgets remain **Beta** in 2.0.
|
||||
|
||||
### Share widgets and Custom CSS
|
||||
|
||||
**Workshop is the other half.** Publish and install Custom Widgets, then update, vote on, comment on and report submissions. Workshop is not only for widgets: you can share your **Custom CSS** there too. Deployment URLs and credentials stay on your Homarr instance.
|
||||
|
||||

|
||||
|
||||
:::warning Workshop is moderated
|
||||
|
||||
AI makes widgets easy to produce. It does not make the first thing it coughs up worth publishing. **Do not dump untested slop into Workshop.** Test it, add a useful screenshot and explain its setup. Workshop is moderated.
|
||||
|
||||
:::
|
||||
|
||||
### The ultimate Homarr update
|
||||
|
||||
We have called this the **"ultimate Homarr update"**. Not because work stops, but because every new service or widget idea no longer needs a full Homarr release; the community can build and share it instead.
|
||||
|
||||
## Board editing, rebuilt
|
||||
|
||||
### Drag and drop
|
||||
|
||||
We threw out the old drag-and-drop system and rebuilt it on [`dnd-kit`](https://dndkit.com/). Moves and eight-direction resizes are transactional: Homarr previews the result, checks collisions and only saves a valid layout. Bad moves roll back instead of wrecking the board. In short: less fighting with your own dashboard.
|
||||
|
||||

|
||||
|
||||
### Goodbye Groups and sections, bonjour Containers
|
||||
|
||||
Groups and dynamic sections did nearly the same job, so **Containers replace both**. They hold apps, widgets and other Containers. Hold <kbd>Ctrl</kbd> or <kbd>Command</kbd> to move several items at once.
|
||||
|
||||
### One board, several layouts
|
||||
|
||||
Boards also have Base and Mobile layouts, plus optional breakpoints. **Reset from Base** creates a Mobile starting point without duplicating the board.
|
||||
|
||||
## Homarr Assistant
|
||||
|
||||
### Work with live Homarr data
|
||||
|
||||
Assistant reads live Homarr data and has tools for boards, apps, integrations, widgets, Docker and supported services. It can answer questions, make approved changes and build Custom Widgets. It follows your permissions: reads can run automatically, while changes require approval by default.
|
||||
|
||||

|
||||
|
||||
Open it with <kbd>Shift</kbd> + <kbd>A</kbd>. <kbd>Cmd</kbd>/<kbd>Ctrl</kbd> + <kbd>/</kbd> searches it.
|
||||
|
||||
### The Homarr provider
|
||||
|
||||
:::note
|
||||
|
||||
Assistant ships with a **"Homarr provider"**. It is free, will never offer paid plans, and is paid for by [Ajnart](https://github.com/ajnart) using the ad revenue from this website.
|
||||
|
||||
It only uses zero-data-retention (ZDR) providers. [The provider is open source](https://github.com/homarr-labs/homarr/blob/release/v2/apps/workshop/homarr_provider.go), and neither prompts nor responses are logged. We are not selling your data. Pinky promise.
|
||||
|
||||
:::
|
||||
|
||||
### External assistants through MCP
|
||||
|
||||
External assistants can use the same permission-checked tools through `/api/mcp`, with an API key or OAuth 2.1 with PKCE.
|
||||
|
||||
## The rest (there is a lot)
|
||||
|
||||
### Brand-new onboarding
|
||||
|
||||
A six-stage setup studio handles the first admin, core settings, Docker discovery, apps, integrations and the first board.
|
||||
|
||||

|
||||
|
||||
### Board switcher
|
||||
|
||||
Boards now live in a searchable gallery with keyboard navigation. Open it from the header or press <kbd>Shift</kbd> + <kbd>C</kbd>.
|
||||
|
||||

|
||||
|
||||
### Command menu and keybinds
|
||||
|
||||
<kbd>Cmd</kbd>/<kbd>Ctrl</kbd> + <kbd>K</kbd> finds resources, pages, settings, users, groups and commands. More
|
||||
keybinds cover Assistant, editing, selection and advanced widget views.
|
||||
|
||||
### Customizable header
|
||||
|
||||
Pick which buttons appear, put them on the left, center or right, and change their order.
|
||||
|
||||

|
||||
|
||||
### Instance branding
|
||||
|
||||
Change the name, logo, favicon, colors, corner styles and login page. Global CSS applies instance-wide; board CSS can override it. Only give that power to admins you trust. CSS remains CSS.
|
||||
|
||||

|
||||
|
||||
### Widgets
|
||||
|
||||
Add content without leaving the board. Settings have live previews, and supported widgets have advanced views. Weather and Clock were redesigned; Air Quality, Countdown and Timer are new.
|
||||
|
||||
### Docker and Podman
|
||||
|
||||
`DOCKER_ENDPOINTS` supports several hosts. Assisted setup and container labels can create apps, integrations, Containers, widgets and health checks.
|
||||
|
||||

|
||||
|
||||
Homepage-compatible labels work too.
|
||||
|
||||
### Permissions
|
||||
|
||||
Groups use a new Viewer, Editor and Admin matrix. The API, Assistant and MCP follow the same rules. LDAP can create users on first sign-in; OIDC can link verified accounts and synchronize groups.
|
||||
|
||||
### Performance
|
||||
|
||||
Board startup work runs in parallel, heavy screens load when opened, and identical integration requests share work instead of doing it twice.
|
||||
|
||||
## Compatibility notes
|
||||
|
||||
- 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.
|
||||
- Custom Widgets remain Beta.
|
||||
- Assistant and MCP do not bypass permissions.
|
||||
|
||||
## Links
|
||||
|
||||
- Try the [live demo](https://demo.homarr.dev/).
|
||||
- See [installation and update instructions](/docs/getting-started/installation/docker).
|
||||
- Browse [Workshop](https://homarr.dev/workshop).
|
||||
- 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).
|
||||
@@ -90,7 +90,7 @@ homarr run dev
|
||||
homarr run --detach dev
|
||||
homarr run --pr 6441
|
||||
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>`).
|
||||
@@ -148,13 +148,18 @@ homarr images rm feature
|
||||
# List data volumes with owner PR/tag and in-use status
|
||||
homarr data
|
||||
|
||||
# Delete data volume (safely stops and removes owning container first)
|
||||
# Preview deleting a data volume and its owning container
|
||||
homarr data rm homarr_feature_data
|
||||
|
||||
# Permanently delete the data after reviewing the preview
|
||||
homarr data rm homarr_feature_data --force
|
||||
|
||||
# Remove stopped containers (prompts without --force)
|
||||
homarr prune --force
|
||||
```
|
||||
|
||||
Forced data deletion removes the derived owner container only when it mounts the exact selected volume. A same-named container that does not own that volume stops the operation.
|
||||
|
||||
### Instance Operations & Diagnostics
|
||||
|
||||
```bash
|
||||
|
||||
@@ -14,4 +14,4 @@ homarr fix-usernames
|
||||
|
||||
This will convert all credential usernames to lowercase and update the database accordingly.
|
||||
|
||||

|
||||

|
||||
|
After Width: | Height: | Size: 768 KiB |
@@ -1,48 +1,66 @@
|
||||
# Command line interface
|
||||
|
||||
The Homarr image ships with a built-in recovery tool. This can be useful, if you do not have access to Homarr or if something is not working.
|
||||
Please note that the CLI is an _emergency tool_, not an API tool.
|
||||
The Homarr image includes a recovery CLI for operations that cannot be completed in the web interface. It is not an
|
||||
application API; use the [API](/docs/management/api) or [MCP endpoint](/docs/management/mcp) for automation.
|
||||
|
||||
:::caution
|
||||
Back up the database and stop Homarr before running a command that changes data.
|
||||
Failed commands print an error and return a non-zero exit code, so shell scripts can stop safely.
|
||||
|
||||
Using the recovery CLi tool can cause problems when requests are being sent to Homarr while the tool is running. \
|
||||
You should also create a backup of the database, in case you break something.
|
||||
## Run the recovery CLI
|
||||
|
||||
:::
|
||||
Open a shell in the container, then pass a command to `homarr`:
|
||||
|
||||
## Execute CLI with Docker
|
||||
```sh
|
||||
docker exec -it <container-id> /bin/bash
|
||||
homarr <command>
|
||||
```
|
||||
|
||||
1. Execute `docker ps | grep homarr` on the root system with Docker to find the container ID of your Homarr container.
|
||||
2. Run `docker exec -it <container-id> /bin/bash homarr <your-command-goes-here>`. \
|
||||
Replace `<container-id>` with your container ID from step 1. \
|
||||
Replace `<your-command-goes-here>` with the command you want to execute (see sub-pages).
|
||||
### QNAP Container Station
|
||||
|
||||
## Execute CLI with QNAP
|
||||
1. Open **Container Station**.
|
||||
|
||||
1. Open Container Station in the QNAP Web Interface 
|
||||
2. Select Containers in the menu bar on the left 
|
||||
3. Select your Homarr Container 
|
||||
4. Click "Execute" in the top right of the Window. 
|
||||
5. Select /bin/bash and click Execute 
|
||||
6. Run the Homarr command and press enter (eg. homarr reset-owner-password) 
|
||||

|
||||
|
||||
2. Select **Containers**.
|
||||
|
||||

|
||||
|
||||
3. Select the Homarr container.
|
||||
|
||||

|
||||
|
||||
4. Select **Execute**.
|
||||
|
||||

|
||||
|
||||
5. Select `/bin/bash`, then select **Execute**.
|
||||
|
||||

|
||||
|
||||
6. Run `homarr <command>` in the console.
|
||||
|
||||

|
||||
|
||||
See the pages in this section for available commands.
|
||||
|
||||
## Build a local branch harness
|
||||
|
||||
The host-side operations CLI can build the current checkout and run it as a named, browser-ready Docker harness. This is separate from the recovery CLI described above and does not open the interactive developer TUI.
|
||||
The repository's host-side CLI can build the current checkout and run it as a named Docker harness:
|
||||
|
||||

|
||||
|
||||
```sh
|
||||
pnpm cli harness setup feature-board
|
||||
```
|
||||
|
||||
The command builds `homarr:feature-board`, starts a container with a persistent data volume, enables demo mode, and keeps demo mutations writable (`DEMO_READ_ONLY=false`). Docker assigns a free host port by default; use the URL printed by the command or query it later:
|
||||
|
||||
The demo board includes every widget kind. Integration-backed widgets use the bundled mock integration; media widgets use public stock assets.
|
||||
This creates `homarr:feature-board`, starts it with persistent demo data, and prints the assigned URL. Query the port
|
||||
again with:
|
||||
|
||||
```sh
|
||||
pnpm cli harness port feature-board
|
||||
```
|
||||
|
||||
Pass environment overrides by repeating `--env`:
|
||||
Pass environment overrides with repeated `--env` options:
|
||||
|
||||
```sh
|
||||
pnpm cli harness setup feature-board \
|
||||
@@ -50,4 +68,4 @@ pnpm cli harness setup feature-board \
|
||||
--env FEATURE_FLAG=true
|
||||
```
|
||||
|
||||
Other commands are `harness build <name>`, `harness run <name>`, and `harness stop <name>`. Use the returned URL with a browser automation harness for feature validation; do not assume the host port is `7575`.
|
||||
Related commands are `harness build <name>`, `harness run <name>`, and `harness stop <name>`.
|
||||
@@ -10,10 +10,10 @@ Using this command, you can forcefully reset the password of a user.
|
||||
It will be set to a random value and the hash for the user will be updated.
|
||||
All sessions for that user will be terminated and the user must re-login.
|
||||
|
||||

|
||||

|
||||
|
||||
Using the `--username` parameter, you can specify who you want to reset the password for.
|
||||
Executing the command will create a new random password, update the database and display the new password.
|
||||
All sessions for this user will be terminated and they must re-login.
|
||||
|
||||

|
||||

|
||||
@@ -31,9 +31,13 @@ pnpm install --frozen-lockfile
|
||||
### Run the Homarr application
|
||||
|
||||
1. Copy `.env.example` to `.env`.
|
||||
2. Set `DB_URL` to an absolute writable SQLite file path.
|
||||
3. Keep Redis and the optional local databases running in one terminal.
|
||||
4. Apply migrations and start Next.js in another terminal.
|
||||
2. Run `openssl rand -hex 32` twice. Set `AUTH_SECRET` and `SECRET_ENCRYPTION_KEY` to the two different generated
|
||||
values in `.env`; the example leaves both empty. Keep this file private and preserve `SECRET_ENCRYPTION_KEY`
|
||||
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
|
||||
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
|
||||
default data; use `pnpm db:seed` to seed it explicitly later.
|
||||
|
||||
`pnpm dev` starts only Next.js. When your work needs scheduled tasks or live subscriptions, run the relevant service
|
||||
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/development).
|
||||
[Workshop development guide](./workshop).
|
||||
|
||||
### Useful commands
|
||||
|
||||
@@ -80,5 +98,27 @@ Workshop contributors can set up PocketBase and Docusaurus with the dedicated
|
||||
- `pnpm typecheck` — typecheck all workspaces.
|
||||
- `pnpm test` — unit and contract suites.
|
||||
- `pnpm build` — production monorepo build.
|
||||
- `docker build -t homarr .` — build a production Docker image.
|
||||
- `docker run -p 7575:7575 -e SECRET_ENCRYPTION_KEY='your_64_character_hex_string' homarr:<name>` — run it.
|
||||
- `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:local` — run it.
|
||||
|
||||
## CI and focused validation
|
||||
|
||||
The main CI workflow runs lint, typechecking, affected workspace builds, workspace configuration checks, OpenAPI validation, and Custom Widget architecture and bundle checks. Unit and E2E suites do not run in CI. Preview images publish after the Fast gate and both architecture builds succeed; browser tests do not block publication. The container job builds an amd64 image when no preview image was built.
|
||||
|
||||
Workshop CI runs only when its workflow or Docker build inputs change. It validates Compose configuration and publishes production images on its configured release branches. Its Docker integration and image tests are manual; workspace typechecks run in the main Fast gate.
|
||||
|
||||
Choose the smallest relevant suite when changing behavior:
|
||||
|
||||
| Command | Scope | Requirements |
|
||||
| ------------------------------------------------- | -------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| `pnpm test <file>` | Focused unit or contract tests | Workspace dependencies |
|
||||
| `pnpm test` | All unit and contract tests, without Docker integration suites | Workspace dependencies |
|
||||
| `pnpm test:coverage` | Unit and contract tests with coverage | Workspace dependencies |
|
||||
| `pnpm test:integration <file>` | Docker-backed service and database compatibility tests | Docker |
|
||||
| `pnpm test:e2e <file>` | Browser and container scenarios | Docker; Playwright Chromium and system dependencies for browser tests |
|
||||
| `pnpm test:docs-screenshots` | Regenerate Assistant documentation screenshots | Same browser prerequisites |
|
||||
| `pnpm test:workshop` / `pnpm test:workshop-image` | Workshop integration / production-image validation | Docker |
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: Workshop operator guide
|
||||
sidebar_label: Operator guide
|
||||
sidebar_position: 3
|
||||
tags:
|
||||
- Workshop
|
||||
- Deployment
|
||||
- Environment variables
|
||||
- PocketBase
|
||||
---
|
||||
|
||||
# Workshop operator guide
|
||||
|
||||
Workshop uses PocketBase. The production image serves the Workshop website and API from one origin and stores state in
|
||||
`/pb_data`.
|
||||
|
||||
## Environment variables
|
||||
|
||||
| Variable | Purpose | Default |
|
||||
| -------------------------------------- | -------------------------------------------- | ------------------------------ |
|
||||
| `HOMARR_WEBSITE_URL` | Documentation/site base used by Homarr links | `https://homarr.dev` |
|
||||
| `WORKSHOP_API_URL` | PocketBase API used by Homarr and docs | `HOMARR_WEBSITE_URL` |
|
||||
| `WORKSHOP_WEB_URL` | Public Workshop URL | `HOMARR_WEBSITE_URL/workshop` |
|
||||
| `WORKSHOP_PUBLIC_ORIGIN` | PocketBase-generated links and email | Required in production |
|
||||
| `PB_ALLOWED_ORIGINS` | Allowed browser origins | `*` |
|
||||
| `GITHUB_CLIENT_ID` | GitHub OAuth application ID | — |
|
||||
| `GITHUB_CLIENT_SECRET` | GitHub OAuth application secret | — |
|
||||
| `OPENROUTER_API_KEY` | Enables the Homarr Assistant provider | Provider disabled when empty |
|
||||
| `HOMARR_AI_DAILY_REQUEST_LIMIT` | Per-user daily request allowance | `50` |
|
||||
| `HOMARR_AI_GLOBAL_DAILY_REQUEST_LIMIT` | Shared daily request ceiling | `10000` |
|
||||
| `HOMARR_AI_OPENROUTER_BASE_URL` | OpenRouter-compatible upstream | `https://openrouter.ai/api/v1` |
|
||||
| `HOMARR_AI_OPENROUTER_MODEL` | Upstream model behind `homarr/model` | Selected by the Homarr team |
|
||||
|
||||
Public URL variables accept HTTP(S) origins without embedded credentials, query strings, or fragments. Restart the
|
||||
container after changing runtime configuration.
|
||||
|
||||
## Authentication and email
|
||||
|
||||
Configure both GitHub OAuth variables and use `https://<workshop-host>/api/oauth2-redirect` as the callback. Supplying
|
||||
only one OAuth variable is a startup error. Configure SMTP for comment, report, and removal notifications.
|
||||
|
||||
For the central community, `PB_ALLOWED_ORIGINS=*` permits requests from self-hosted Homarr origins. A private deployment
|
||||
can use a comma-separated allowlist.
|
||||
|
||||
## Homarr provider
|
||||
|
||||
`OPENROUTER_API_KEY` enables the [Homarr provider](/docs/workshop/homarr-provider). The Workshop server chooses the upstream model and
|
||||
enforces per-user and global daily limits. It requests zero-data-retention routing, disables data-collecting providers,
|
||||
and does not retain prompts or responses.
|
||||
|
||||
Keep an OpenRouter account-level credit limit as the monetary backstop; request limits are not cost limits.
|
||||
|
||||
## Deployment
|
||||
|
||||
The v2 image is `ghcr.io/homarr-labs/workshop:v2`; immutable `sha-<commit>` tags are preferable for promotion. The
|
||||
service listens on port 8090.
|
||||
|
||||
When using a reverse proxy, forward the complete hostname, including `/api`, `/_/`, and
|
||||
`/workshop-runtime-config.js`. Use a dedicated hostname when Homarr already occupies the intended origin.
|
||||
|
||||
Verify `/api/health`, the Workshop page, a public listing request, GitHub sign-in, and one installation after deployment.
|
||||
|
||||
## Backup and restore
|
||||
|
||||
Stop writes and copy `/pb_data` for a consistent backup. A restore replaces the selected PocketBase data directory, so
|
||||
preserve the current volume and verify that the backup contains `data.db` first. Rehearse the restore outside production
|
||||
and verify sign-in and one installation afterward.
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: Workshop development
|
||||
sidebar_position: 4
|
||||
tags:
|
||||
- Workshop
|
||||
- Developer
|
||||
- Docusaurus
|
||||
- PocketBase
|
||||
---
|
||||
|
||||
# Workshop development
|
||||
|
||||
See the [main development guide](./getting-started) for repository prerequisites.
|
||||
|
||||
Start PocketBase:
|
||||
|
||||
```sh
|
||||
cp apps/workshop/.env.example apps/workshop/.env
|
||||
docker compose --env-file apps/workshop/.env -f apps/workshop/docker-compose.yml up --build workshop
|
||||
```
|
||||
|
||||
Start Docusaurus in another terminal:
|
||||
|
||||
```sh
|
||||
WORKSHOP_API_URL=http://127.0.0.1:8090 pnpm dev:docs
|
||||
```
|
||||
|
||||
PocketBase runs at `http://127.0.0.1:8090`; create the first superuser under `/_/`. Workshop is available at
|
||||
`http://127.0.0.1:3003/workshop`.
|
||||
|
||||
To connect a local Homarr instance, set:
|
||||
|
||||
```dotenv
|
||||
HOMARR_WEBSITE_URL=http://127.0.0.1:3003
|
||||
WORKSHOP_API_URL=http://127.0.0.1:8090
|
||||
WORKSHOP_WEB_URL=http://127.0.0.1:3003/workshop
|
||||
```
|
||||
|
||||
Restart the affected development process after changing these variables. See
|
||||
[`apps/workshop/README.md`](https://github.com/homarr-labs/homarr/blob/HEAD/apps/workshop/README.md) for OAuth,
|
||||
moderation, tests, and service maintenance.
|
||||
@@ -30,7 +30,8 @@ Using the `PUID` and `PGID` will require you to set the correct permissions on t
|
||||
| `PUID` | User ID to run the container as | Any valid user ID | `0` |
|
||||
| `PGID` | Group ID to run the container as | Any valid group ID | `0` |
|
||||
| `LOG_LEVEL` | Log level to use | `debug` / `info` / `warn` / `error` | `info` |
|
||||
| `NO_EXTERNAL_CONNECTION` | Disables Homarr's internet-backed requests, including update checks, weather, and RSS feeds | `true` or `false` | `false` |
|
||||
| `BASE_URL` | Public Homarr origin used by MCP OAuth metadata and redirects. Set this when a reverse proxy does not preserve the public host and protocol. | HTTP(S) origin without a path | - |
|
||||
| `NO_EXTERNAL_CONNECTION` | Disables Homarr's internet-backed requests, including update checks, weather, location search, and RSS feeds | `true` or `false` | `false` |
|
||||
| `ENABLE_DNS_CACHING` | Enables dns caching. Enabled by default, but if you experience issues with IPv6 or static IPs, see [#4006](https://github.com/homarr-labs/homarr/issues/4006) or disable this flag | `true` or `false` | `true` |
|
||||
| `HOMARR_DISABLE_IPV6` | Disables the IPv6 listener of the internal nginx proxy, even when the host supports IPv6. IPv6 is normally disabled automatically when the host has no IPv6 configured. See [#4596](https://github.com/homarr-labs/homarr/issues/4596) | `true` or `false` | `false` |
|
||||
| `HOMARR_WEBSITE_URL` | Main Homarr documentation/site base used by runtime links. Must be an absolute HTTP(S) URL. | HTTP(S) URL | `https://homarr.dev` |
|
||||
@@ -38,7 +39,7 @@ Using the `PUID` and `PGID` will require you to set the correct permissions on t
|
||||
| `WORKSHOP_WEB_URL` | Public Workshop website used by links in Homarr, Custom Widgets, onboarding, and assistant context. | HTTP(S) URL | `HOMARR_WEBSITE_URL/workshop` |
|
||||
|
||||
Workshop service operators can find its server-only configuration in the
|
||||
[Workshop operator guide](../../workshop/operator#environment-variables).
|
||||
[Workshop operator guide](/docs/advanced/development/workshop-operator#environment-variables).
|
||||
|
||||
### Workshop service
|
||||
|
||||
|
||||
@@ -53,20 +53,6 @@ Commands at a grid boundary or at the tile's minimum size are ignored and announ
|
||||
|
||||
On touch screens, press and hold a tile before moving it; a quick tap does not start a drag. Resize handles accept direct touch input. During a pointer or touch move or resize, `Esc` cancels the interaction and restores the layout from before it started.
|
||||
|
||||
## Board editing
|
||||
|
||||
When a tile is focused in edit mode:
|
||||
|
||||
| Shortcut | Description |
|
||||
| -------------------- | --------------------------------------------------------------------------- |
|
||||
| `Enter` or `Space` | Starts or stops keyboard editing |
|
||||
| Arrow keys | Moves the focused tile within its current canvas, rail, or Container |
|
||||
| `Shift` + Arrow keys | Resizes from the tile's lower-right corner: Left/Up shrink; Right/Down grow |
|
||||
| `Esc` | Stops keyboard editing without undoing its changes |
|
||||
|
||||
Keyboard moves and resizes apply immediately. To move an item between a canvas, rail, or Container, drag it there or use **Move / resize item** for precise numeric placement.
|
||||
Commands at a grid boundary or at the tile's minimum size are ignored and announced instead of moving or shrinking the tile.
|
||||
|
||||
:::tip
|
||||
|
||||
Here `MOD` refers to the modifier key, which is `Ctrl` on Windows and `Cmd` on macOS.
|
||||
|
||||
@@ -40,7 +40,7 @@ services:
|
||||
volumes:
|
||||
- ./homarr/appdata:/appdata
|
||||
environment:
|
||||
- BASE_URL=your.internal.dns.address.here.com
|
||||
- BASE_URL=https://your.internal.dns.address.here.com
|
||||
- SECRET_ENCRYPTION_KEY=your_64_character_hex_string # <--- can be generated with `openssl rand -hex 32`
|
||||
networks:
|
||||
- proxy
|
||||
@@ -143,7 +143,7 @@ networks:
|
||||
```
|
||||
|
||||
:::important
|
||||
Homarr needs to be on the same network so you will need to add the following property to your homarr install:
|
||||
Homarr and Caddy must share the same Docker network:
|
||||
|
||||
```yaml
|
||||
homarr:
|
||||
|
||||
@@ -13,7 +13,8 @@ You can change the user and group by using the `PUID` and `PGID` environment var
|
||||
Important to note is, that you'll also need to change the permissions for the mounted directories accordingly.
|
||||
|
||||
:::info
|
||||
When starting up an updated version of the container it will have about **10 seconds longer to start** as it has to change the permissions of the app directories
|
||||
At startup, Homarr updates ownership of its data directories and runtime caches for the selected user and group.
|
||||
Startup time depends on the amount of persistent data; application code and dependencies do not need ownership changes.
|
||||
:::
|
||||
|
||||
## Without mounted Docker socket
|
||||
|
||||
@@ -202,9 +202,9 @@ Homarr supports multiple authentication options, from internal userbase (credent
|
||||
| ``AUTH_OIDC_CLIENT_NAME`` | Display name of provider (in login screen) | OIDC |
|
||||
| ``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_GROUPS_ATTRIBUTE`` | Attribute used for groups (roles) claim | 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_NAME_ATTRIBUTE_OVERWRITE`` | Overwrite name attribute. 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_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 |
|
||||
@@ -244,18 +244,21 @@ Homarr supports multiple authentication options, from internal userbase (credent
|
||||
- Create a group (e.g., `homarr-admins`) and assign users who require admin access.
|
||||
|
||||
**2. Example .env file:**
|
||||
|
||||
Generate `SECRET_ENCRYPTION_KEY` with `openssl rand -hex 32`; do not copy an example key between installs.
|
||||
|
||||
```env
|
||||
OIDC_CLIENT_ID=identificationid #OIDC client ID
|
||||
OIDC_CLIENT_SECRET=secretsecretsecret #OIDC client secret
|
||||
OIDC_CLIENT_ID=<REPLACE_WITH_OIDC_CLIENT_ID>
|
||||
OIDC_CLIENT_SECRET=<REPLACE_WITH_OIDC_CLIENT_SECRET>
|
||||
OIDC_SLUG=homarr #Application slug in Authentik
|
||||
AUTH_DOMAIN=auth.example.com #Authentik FQDN
|
||||
ADMIN_GROUP=homarr-admins #Authentik group for Homarr admins
|
||||
HOMARR_FQDN=homarr.example.com #Homarr FQDN
|
||||
SECRET_ENCRYPTION_KEY=encryptencryptencrypt #Homarr encryption key
|
||||
SECRET_ENCRYPTION_KEY=<REPLACE_WITH_64_HEX_CHARACTERS>
|
||||
```
|
||||
|
||||
**3. Example Docker Compose configuration:**
|
||||
```yaml {14-26}
|
||||
```yaml {14-24}
|
||||
services:
|
||||
homarr:
|
||||
image: ghcr.io/homarr-labs/homarr:latest
|
||||
@@ -269,8 +272,6 @@ Homarr supports multiple authentication options, from internal userbase (credent
|
||||
environment:
|
||||
- TZ=America/Los_Angeles
|
||||
- SECRET_ENCRYPTION_KEY=${SECRET_ENCRYPTION_KEY}
|
||||
- BASE_URL=https://${HOMARR_FQDN}
|
||||
- NEXTAUTH_URL=https://${HOMARR_FQDN}
|
||||
- AUTH_PROVIDERS=oidc #(optional: include ',credentials' to keep local accounts as fallback)
|
||||
- AUTH_OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
|
||||
- AUTH_OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
|
||||
@@ -322,15 +323,18 @@ Homarr supports multiple authentication options, from internal userbase (credent
|
||||
- Record the `Client-ID` and `Client Key` (secret).
|
||||
|
||||
**2. Example .env file (Homarr):**
|
||||
|
||||
Generate `SECRET_ENCRYPTION_KEY` with `openssl rand -hex 32`; do not copy an example key between installs.
|
||||
|
||||
```env
|
||||
OIDC_CLIENT_ID=identificationid #Google Client-ID
|
||||
OIDC_CLIENT_SECRET=secretsecretsecret #Google Client Key (secret)
|
||||
OIDC_CLIENT_ID=<REPLACE_WITH_GOOGLE_CLIENT_ID>
|
||||
OIDC_CLIENT_SECRET=<REPLACE_WITH_GOOGLE_CLIENT_SECRET>
|
||||
HOMARR_FQDN=homarr.example.com #Homarr FQDN
|
||||
SECRET_ENCRYPTION_KEY=encryptencryptencrypt #Homarr encryption key
|
||||
SECRET_ENCRYPTION_KEY=<REPLACE_WITH_64_HEX_CHARACTERS>
|
||||
```
|
||||
|
||||
**3. Example Docker Compose configuration (Homarr):**
|
||||
```yaml {16-22}
|
||||
```yaml {14-20}
|
||||
services:
|
||||
homarr:
|
||||
image: ghcr.io/homarr-labs/homarr:latest
|
||||
@@ -344,8 +348,6 @@ Homarr supports multiple authentication options, from internal userbase (credent
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
- SECRET_ENCRYPTION_KEY=${SECRET_ENCRYPTION_KEY}
|
||||
- BASE_URL=https://${HOMARR_FQDN}
|
||||
- NEXTAUTH_URL=https://${HOMARR_FQDN}
|
||||
- AUTH_PROVIDERS=oidc #(optional: include ',credentials' to keep local accounts as fallback)
|
||||
- AUTH_OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
|
||||
- AUTH_OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
|
||||
|
||||
@@ -1,102 +1,37 @@
|
||||
# Styling
|
||||
|
||||
:::tip
|
||||
Homarr uses Mantine and supports custom CSS at two scopes:
|
||||
|
||||
This page is directed at more experienced users with knowledge about CSS and browsers.
|
||||
We recommend you to [look into the board customizations instead](/docs/management/boards#appearance),
|
||||
if you do not have experience with writing custom styles or CSS.
|
||||
- **Global:** **Management → Settings → Instance branding → Custom CSS**.
|
||||
- **Board:** **Board settings → Custom CSS**. Board CSS loads after the global stylesheet and can override it.
|
||||
|
||||
:::
|
||||
Both editors accept direct CSS and Workshop imports.
|
||||
|
||||
:::warning
|
||||
|
||||
Our support specifically excludes custom CSS, and we will not help you to write CSS.
|
||||
However, we may help you by adding new CSS classes if required.
|
||||
Custom CSS can break after updates and is not an authorization boundary. Hidden controls remain accessible to users who
|
||||
have permission to use them.
|
||||
|
||||
:::
|
||||
|
||||
Homarr uses https://mantine.dev/ under the hood. You can change the look & feel of Homarr
|
||||
using custom CSS, that extends or overwrites the styles from Mantine.
|
||||
## Target elements
|
||||
|
||||
## Getting into CSS
|
||||
Use browser developer tools to inspect the element and test a selector. Prefer stable semantic or Mantine class names;
|
||||
avoid generated classes such as `mantine-Card-x2fske`, which change between builds.
|
||||
|
||||
If you don't have any experience with CSS,
|
||||
we strongly recommend you to go through the courses here: https://www.w3schools.com/css/.
|
||||
Due to the infinite scenarios and setups possible with custom CSS,
|
||||
our support team will not provide any support with your own written CSS.
|
||||
To target one widget, add a custom class under **Edit item → Advanced options** and use that class in the board CSS.
|
||||
|
||||
## Limitations and dangers
|
||||
Use `!important` only when the existing cascade requires it.
|
||||
|
||||
When using custom CSS, you can break the page or certain functionalities.
|
||||
Although CSS can improve the design & feel of the page, it **<ins>cannot do any of the following</ins>**:
|
||||
## Theme variables
|
||||
|
||||
- Implement new features, widgets or integrations
|
||||
- Securely hide elements you don't want users to interact / have permission to
|
||||
- Completely revamp the design of the page, only smaller changes are possible
|
||||
|
||||
Here are some dangers of using custom CSS:
|
||||
|
||||
- Updates may contain breaking changes in the structure, built-in styling or how styling is processed. Therefore,
|
||||
custom CSS may break unexpectedly without any warning
|
||||
- Custom CSS may make certain elements invisible or not possible to click / interact with
|
||||
- Custom CSS could make readability and accessibility worse for impaired people
|
||||
|
||||
## How to inspect the page
|
||||
|
||||
When styling the page, you can use the `Inspector` to inspect elements on the page and try out styles.
|
||||
This may vary depending on your browser and operating system, but the workflow usually goes like this:
|
||||
|
||||
- Open the Homarr page
|
||||
- Press `Ctrl` + `Shift` + `I` at the same time.
|
||||
Alternatively, right-click on the page and choose `Inspect` or `Inspect element`.
|
||||
- Open the tab `Elements` if it isn't open yet.
|
||||
- Search the element you want to change in the DOM tree or use the element picker (usually at the top left)
|
||||
to select it by clicking on the page.
|
||||
- Experiment by changing the CSS code on the right side
|
||||
|
||||
When writing custom CSS, it is important to also remember or create a selector, which tells the browser
|
||||
which element to apply the styles to. If you accidentally broke something or want to revert your changes in the inspector,
|
||||
simply reload the page.
|
||||
|
||||
## Using Homarr's classes
|
||||
|
||||
Homarr's elements will already have a lot of classes and styles pre-applied.
|
||||
You can reuse those classes to apply additional styles or overwrite them.
|
||||
When overwriting, remember to add the `!important` flag to your CSS property to tell the browser to use our instruction instead.
|
||||
|
||||
Classes with random number suffixes, such as `mantine-Card-x2fske`, should be avoided, since those are dynamic
|
||||
CSS classes that will change with every build. This means, every time you update Homarr,
|
||||
your styles will no longer apply to them
|
||||
|
||||
## Defining custom classes for widgets
|
||||
|
||||
If you want to apply the styles only for one widget, you can define custom class names only for that widget.
|
||||
To do that, enter edit mode on your board, click the three dots of your widget, click `Edit item` and click `Advanced options`.
|
||||
Then, you can enter as many custom classes as you'd like:
|
||||
|
||||

|
||||
|
||||
To save them, click `Save changes` on both modals and exit edit mode.
|
||||
|
||||
## Where to enter custom CSS
|
||||
|
||||
After you wrote your custom CSS, it is time to permanently save it, so you don't need to use the inspector anymore.
|
||||
To do this, enter the board settings:
|
||||
|
||||

|
||||
|
||||
Scroll to the **Custom CSS** section on the board settings page. It is part of the unified settings form; enter your CSS
|
||||
there and save the board settings to apply it to that board.
|
||||
|
||||

|
||||
|
||||
## Using variables
|
||||
|
||||
You can also change the values of the theme variables, which are located here: https://mantine.dev/styles/css-variables-list/.
|
||||
To do this, see the following example CSS:
|
||||
Mantine exposes [CSS variables](https://mantine.dev/styles/css-variables-list/) that can be overridden globally or per
|
||||
board:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--mantine-primary-color-filled: #ffbb00;
|
||||
}
|
||||
```
|
||||
|
||||
CSS changes presentation only; use widgets, integrations, permissions, or application code for behavior.
|
||||
@@ -8,22 +8,7 @@ tags:
|
||||
|
||||
# Donate
|
||||
|
||||
## Why to donate
|
||||
Donations fund Homarr's development infrastructure and community services.
|
||||
|
||||
Our team of 4 developers is working on Homarr in their free time.
|
||||
Homarr has become a big part of our daily things we work on - and therefore we invest a lot of time into maintaining Homarr,
|
||||
providing support and implementing new features.
|
||||
We also incur monetary costs while developing Homarr for the tools that we need.
|
||||
A few examples include:
|
||||
|
||||
- Renting for a Cloud VPS for our cloud services (status page, monitoring, email, analytics, [demo instance](https://demo.homarr.dev/), ...)
|
||||
- Paying for (IDE-) licenses
|
||||
|
||||
Using a donation, you help us to cover these expenses and enable the development of Homarr.
|
||||
Homarr is completely free to use. We'd highly appreciate if you consider donating, especially if you use Homarr in a commercial environment.
|
||||
|
||||
## Where to donate
|
||||
|
||||
We accept donations on our official [OpenCollective](https://opencollective.com/homarr).
|
||||
You may also sponsor us directly by providing a useful service / product to us other means.
|
||||
You can get into contact with us [here](/docs/community/get-in-touch).
|
||||
Support the project through [OpenCollective](https://opencollective.com/homarr). For sponsorships or donated services,
|
||||
use the private contact listed on [Get in touch](/docs/community/get-in-touch).
|
||||
@@ -1,110 +1,51 @@
|
||||
---
|
||||
title: Frequently Asked Questions
|
||||
description: Answers to common Homarr questions about installation, customization, connectivity, support, and commercial use.
|
||||
tags:
|
||||
- Community
|
||||
- Help
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs";
|
||||
import TabItem from "@theme/TabItem";
|
||||
## Can Homarr run on a Raspberry Pi?
|
||||
|
||||
### Can I install Homarr on a Raspberry Pi?
|
||||
Yes, when the device uses a supported `linux/arm64` operating system. `linux/arm/v7` is not supported. See
|
||||
[Prerequisites](/docs/getting-started).
|
||||
|
||||
Yes, Homarr is compatible with the architecture of the Raspberry Pi. Have a look in our <a href="/docs/category/installation-1">installation guide</a> on how to do so.
|
||||
## Can I use custom app icons?
|
||||
|
||||
### I have a suggestion / idea for improvement or want to report a bug
|
||||
Yes. Use a direct image URL, one of Homarr's icon sources, or upload an image. See [Icons](/docs/advanced/icons).
|
||||
|
||||
You can report issues, suggestions, or ideas for improvements <a href="https://github.com/homarr-labs/homarr/issues/new/choose">here</a>.
|
||||
## Can I create widgets?
|
||||
|
||||
### Can I use my own custom icons for apps?
|
||||
Yes. [Custom Widgets](/docs/management/custom-widgets) use server-side API requests and safe JSX. They can be written in
|
||||
the workbench or created with an MCP-connected agent.
|
||||
|
||||
Yes, check out our guide on <a href="/docs/advanced/customizations/icons">how to add your custom icons</a>.
|
||||
## Can Homarr be exposed to the internet?
|
||||
|
||||
### Some of my online icons are not working (anymore)
|
||||
Homarr supports authenticated and public deployments. Terminate HTTPS at a reverse proxy, keep Homarr updated, and grant
|
||||
public board access only when anonymous viewing is intended. See [Board access control](/docs/management/boards#access-control)
|
||||
and [Single sign-on](/docs/advanced/single-sign-on).
|
||||
|
||||
It seems the `cdn.jsdelivr.net` database of icon sometimes appear in the lists for DNS-Holes (PiHole, AdGuard Home...). <br />
|
||||
So make sure to manually whitelist this address.
|
||||
## Where are the logs?
|
||||
|
||||
### Can I add my own widgets? Do I need programming skills?
|
||||
Use **Management → Tools → Logs** for retained and live application logs. Container startup failures and older events are
|
||||
available through the deployment platform, for example `docker container logs homarr`.
|
||||
|
||||
Yes. A [Custom Widget](/docs/management/custom-widgets) can read a public or private HTTP API.
|
||||
Use the browser developer console only for client-side failures. Review logs before sharing them because URLs and other
|
||||
deployment details may be present.
|
||||
|
||||
It can show responsive Mantine JSX. It can also use widget options and actions with board permission checks.
|
||||
## Why can Homarr not reach a service behind Gluetun?
|
||||
|
||||
Custom JSX v2 is the only Custom Widget format. Write the JSON and JSX in the workbench.
|
||||
Gluetun's firewall blocks traffic that is not explicitly allowed. Configure its
|
||||
[`FIREWALL_OUTBOUND_SUBNETS`](https://github.com/qdm12/gluetun-wiki/blob/main/setup/options/firewall.md) for the relevant
|
||||
LAN or Docker subnet, and use an address reachable from the Homarr container.
|
||||
|
||||
You can also use the AI copy prompt. An MCP agent can validate and preview a definition before it saves the definition.
|
||||
## Where do I report a bug or request a feature?
|
||||
|
||||
The workbench reads a pasted AI response. It shows request capabilities and redacted diagnostics.
|
||||
Use the [GitHub issue templates](https://github.com/homarr-labs/homarr/issues/new/choose). For community support, see
|
||||
[Get in touch](/docs/community/get-in-touch).
|
||||
|
||||
A template cannot import packages or run arbitrary JavaScript. It cannot call browser `fetch`.
|
||||
## Can Homarr be used commercially?
|
||||
|
||||
Named requests use the Homarr server. The server applies board permissions and the network policy.
|
||||
|
||||
Before installation, examine the origins, methods, permissions, and actions. Use the same review before publication.
|
||||
|
||||
### Is it secure to expose Homarr to the web?
|
||||
|
||||
Yes, since v0.14.0, we are confident that Homarr is secure enough to be exposed to the web.
|
||||
Make sure to enable the "allow anonymous access" [option in the settings](/docs/management/boards#access-control), if you want to allow people without an account to be able to see your dashboard (not edit)
|
||||
|
||||
### How do I open the console / log?
|
||||
|
||||
There are two different sources of information:
|
||||
|
||||
- console: This is your client (browser). It can tell us, if there is an issue on the client (crash, bug, ...).
|
||||
- log: This is your server. It will tell us, if there are issues with connections for the integrations, crashes and errors.
|
||||
|
||||
Both variants _can_ contain personal data. It's recommended, that you don't post them publicly or remove personal data from it.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="apple" label="Read console" default>
|
||||
|
||||
> Note: This will not work on most mobile browsers.
|
||||
|
||||
Open your browser and ensure, that Homarr is your current tab.
|
||||
Press `CTRL` + `SHIFT` + `I` on your keyboard. If this shortcut doesn't work, please use one of the alternatives: https://developer.chrome.com/docs/devtools/open/.
|
||||
Click on `Console` in the new window, that opened. There, you should see white, orange and sometimes red messages. You can use the Windows Snip & Sketch tool (or your respective tool on Linux / MacOS) to screenshot those messages.
|
||||
|
||||
> Please never execute any commands in the console. Scammers are using the console to let you execute harmful commands. If you want to resolve an issue in Homarr, **you'll never have to execute any commands here**
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="orange" label="Read log">
|
||||
|
||||
This depends on your installation method. If you use Unraid, you can simply click on the App and on `Log`. If you have a bare Docker install, use `docker container logs homarr`. If you used a different name than `homarr` for your container, you need to replace said argument. Here is some additional information about the command: https://geekflare.com/check-docker-logs/.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### How do I post logs?
|
||||
|
||||
Please check [the section above](#how-do-i-open-the-console--log), on how to obtain logs. Logs should always be posted to https://pastebin.com/ or https://rentry.co/.
|
||||
|
||||
### Can I use Homarr at my company?
|
||||
|
||||
Yes, you can! But please consider a donation, if our work has been useful to you.
|
||||
|
||||
### I think I found a bug. What can I do?
|
||||
|
||||
If you think, that you found a bug, please create an issue <a href="https://github.com/homarr-labs/homarr/issues/new/choose">here</a>.
|
||||
|
||||
### Why can't I use my custom icons?
|
||||
|
||||
You need to restart the Homarr Docker container after adding icons.
|
||||
|
||||
### Why can't homarr see/ping containers running locally behind GluetunVPN?
|
||||
|
||||
This is because GluetunVPN, and many other docker VPN services, secure their VPN connections with strict firewalls. These firewalls often block access to local containers, even on the same docker network. The workaround for <a href="https://github.com/qdm12/gluetun-wiki/blob/main/setup/options/firewall.md">GluetunVPN</a> is to add "- FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/24" into the environmental variables of the docker compose file. If you are using a firewall on your system, you will need to add a rule that allows requests from ip's in the range of 192.168.xxx.xxx . If you are using UFW the command would be "sudo ufw allow from 192.168.0.0/16".
|
||||
Tip: If you are running your torrent client behind a VPN, and running Sonarr (or something similar) normally, make sure to open your torrent client's port in your firewall. If you don't, Sonarr will not be able to see it. Furthermore, use your machines IP (192.168.x.x) rather then 127.0.0.1 or localhost.
|
||||
|
||||
### Can I get in touch with you?
|
||||
|
||||
Yes, go <a href="/docs/community/get-in-touch">here</a> to get with us in touch.
|
||||
|
||||
<hr />
|
||||
|
||||
:::tip
|
||||
|
||||
Haven't found the solution to your problem / question? We are eager to help you on [our Discord](/docs/community/get-in-touch#discord) or in a [GitHub Issue](https://github.com/homarr-labs/homarr/issues/new/choose).
|
||||
|
||||
:::
|
||||
Yes. Homarr is licensed under the [Apache License 2.0](/docs/community/license). Commercial users can support development
|
||||
through [OpenCollective](/docs/community/donate).
|
||||
@@ -1,24 +1,23 @@
|
||||
---
|
||||
title: Get In Touch
|
||||
description: Still have a question? Click here!
|
||||
title: Get in touch
|
||||
description: Community, support, and private contact channels.
|
||||
tags:
|
||||
- Help
|
||||
- Community
|
||||
---
|
||||
|
||||
We're happy to talk with you! Shoot us a message at the following places:
|
||||
# Get in touch
|
||||
|
||||
## E-Mail
|
||||
## GitHub
|
||||
|
||||
We are open to discuss sponsorships, security vulnerabilities and other private requests through our email.
|
||||
Please do not report any bugs / feature requests here - they will be ignored and deleted.
|
||||
|
||||
[homarr-labs@proton.me](mailto:homarr-labs@proton.me)
|
||||
Use the [issue templates](https://github.com/homarr-labs/homarr/issues/new/choose) for bugs and feature requests.
|
||||
|
||||
## Discord
|
||||
|
||||
We have a Discord Server, where we announce new releases, discuss features and bugs and show off our dashboards.
|
||||
There are over 4'000 members and we're happy to answer your questions or concerns.
|
||||
You're also open to discuss new / upcoming features and any offtopic selfhosting content.
|
||||
Use the [Homarr Discord server](https://discord.gg/aCsmEV5RgA) for community support, release discussion, and dashboard
|
||||
showcases.
|
||||
|
||||
[__](https://discord.gg/aCsmEV5RgA)
|
||||
## Email
|
||||
|
||||
Use [homarr-labs@proton.me](mailto:homarr-labs@proton.me) for security reports, sponsorships, and other private matters.
|
||||
Bug reports and feature requests belong on GitHub.
|
||||
@@ -5,51 +5,24 @@ tags:
|
||||
- Translations
|
||||
---
|
||||
|
||||
We want to make Homarr accessible for everyone.
|
||||
But to do that, we need your help.
|
||||
We are running a community program that enables everyone to translate Homarr into their language – no programming required.
|
||||
We are using [Crowdin](https://crowdin.com/) to manage our translations.
|
||||
You can find the translations [here](https://translate.homarr.dev/).
|
||||
# Translations
|
||||
|
||||
## How to translate
|
||||
Homarr translations are managed on [Crowdin](https://translate.homarr.dev/). Select a language, translate strings in
|
||||
context, and submit them for proofreading. Approved translations ship with a later Homarr release.
|
||||
|
||||
### Using crowdin's online platform
|
||||
## Translate from Homarr
|
||||
|
||||
Go to the [Crowdin translations](https://translate.homarr.dev/) and select a language you want to translate.
|
||||
You can then enter the translation mode and start translating.
|
||||
After you've submitted your translations, a Proofreader will review your changes.
|
||||
After a translation has been approved, it will be merged to the language development branch.
|
||||
We merge this one periodically to the development branch.
|
||||
After the next update of Homarr, all changes from the development branch will be merged, including the changes in the translations.
|
||||
Select **Crowdin (live translations)** as the application language, connect a Crowdin account, and choose the target
|
||||
language. Select text in Homarr or use Crowdin's in-context panel to edit a string.
|
||||
|
||||
### Using live translate
|
||||
|
||||
You can also help translate homarr directly from the app!
|
||||
For this you can simply change your language to "Crowdin (live translations)"
|
||||
|
||||

|
||||
|
||||
Then you'll be prompted to connect to your Crowdin account and choose the language in which you want to transalte.
|
||||
You can then start translating directly from the app by selecting some text on the app.
|
||||
If some text cannot be selected to be edited with the live translation tool, you can still translate it inside of the In-Context popup at the Home tab, it will be red if it's not translated yet.
|
||||
|
||||

|
||||
|
||||
:::caution
|
||||
Although you are translating directly from the app, your translations will not be directly be available inside of your language, they will be in the next update of Homarr, because we have to push the new translations to a new docker image.
|
||||
|
||||
If you really want to use them you can enable the "preview transaltions" option in the live translate settings, but be aware that this is not recommended for performance reasons.
|
||||
:::
|
||||
|
||||
:::tip
|
||||
|
||||
Do you want to become a proofreader? [Let us know on our Discord](/docs/community/get-in-touch#discord)! We will add you to the proofreader team. You can then review the translations and approve them. **Note:** You must speak the language fluently, have it as your native language or lots of experience with it.
|
||||
|
||||
:::
|
||||
Live translation submits changes to Crowdin; it does not update the installed Homarr image. Crowdin's preview option can
|
||||
show pending translations before the next Homarr release.
|
||||
|
||||
## Guidelines
|
||||
|
||||
1. Translate with context: Some translations can't be translated 1:1 - they need context. Ensure that your translations make sense in the context.
|
||||
2. Keep things simple and original - no additional characters are needed.
|
||||
3. Don't translate the same thing twice - if you see a translation that is already translated, don't translate it again unless you have a better translation.
|
||||
4. Keep your translations as close to the original as possible.
|
||||
- Preserve the meaning and context of the English source.
|
||||
- Keep terminology consistent with existing translations.
|
||||
- Do not add punctuation, formatting, or explanatory text that is absent from the source.
|
||||
- Improve an existing translation only when the replacement is more accurate.
|
||||
|
||||
Contact the [Discord community](/docs/community/get-in-touch#discord) to help proofread a language.
|
||||
@@ -6,397 +6,76 @@ tags:
|
||||
- Configuration
|
||||
---
|
||||
|
||||
import manageBoardNoApp from "./img/manage-board-no-app.png";
|
||||
import currentKeyboardTileEditing from "../management/boards/img/keyboard-tile-editing.png";
|
||||
import boardDesktopCurrent from "./img/onboarding-board-desktop-current.png";
|
||||
import boardEditModeCurrent from "./img/onboarding-board-edit-mode-current.png";
|
||||
import addContentMenuCurrent from "./img/onboarding-add-content-menu-current.png";
|
||||
import chooseItemCurrent from "./img/onboarding-choose-item-current.png";
|
||||
import editItemCurrent from "./img/onboarding-edit-item-current.png";
|
||||
import boardsHomeMobileMenu from "./img/onboarding-boards-home-mobile-menu.png";
|
||||
import moveResizeMenuCurrent from "./img/onboarding-move-resize-menu-current.png";
|
||||
import currentBoardMobileView from "./img/onboarding-board-mobile-current.png";
|
||||
On first launch, onboarding creates the administrator, connects optional services, and builds the first board. A
|
||||
compatible SQLite backup can also be restored from the welcome screen.
|
||||
|
||||
:::tip
|
||||
If onboarding returns after a restart, check that `/appdata` is writable and persisted. See the
|
||||
[Docker installation guide](/docs/getting-started/installation/docker).
|
||||
|
||||
Read our [glossary](/docs/getting-started/glossary) if you are new to Homarr.
|
||||
## Core concepts
|
||||
|
||||
:::
|
||||
### Boards
|
||||
|
||||
Congratulations on installing Homarr. Now it's time to get yourself familiar with the concepts of Homarr and how to use it.
|
||||
A **board** is a dashboard page containing apps, widgets, and Containers. Boards can be public or restricted to users
|
||||
and groups. Each user can choose a home board.
|
||||
|
||||
## Onboarding
|
||||

|
||||
|
||||
Onboarding appears the first time Homarr starts. Its goal is to create a useful responsive board, not merely an
|
||||
administrator account. The setup uses one guided studio, so you can keep the safe defaults and finish quickly or review
|
||||
every detected service before anything is added to the board.
|
||||
See [Boards](/docs/management/boards) for responsive layouts, access control, appearance, and home-board settings.
|
||||
|
||||
:::note
|
||||
### Apps
|
||||
|
||||
If you see this screen repeatedly after restarting the Homarr container, your Docker mounting paths may be missing,
|
||||
incorrect or read-only. Read [our installation instructions](/docs/getting-started/installation/docker) again to fix this issue.
|
||||
An **app** is a saved shortcut: a name, URL, icon, and optional status check. Add an App tile or a Bookmarks widget to
|
||||
show apps on a board.
|
||||
|
||||
:::
|
||||

|
||||
|
||||
### Restore or start fresh
|
||||
See [Apps](/docs/management/apps) or [Icons](/docs/advanced/icons).
|
||||
|
||||
SQLite installations can restore a complete Homarr database backup from the welcome screen. This restores current
|
||||
boards, people, apps, integrations, and settings. The pre-1.0 ZIP importer is no longer included.
|
||||
### Integrations
|
||||
|
||||
For a new installation, Homarr first creates either a credentials administrator or an administrator group matching your
|
||||
LDAP/OIDC provider. The browser that starts setup claims the first-run session; refreshes are safe, while another browser
|
||||
cannot change credentials or integrations during that setup.
|
||||
An **integration** is a server-side connection from Homarr to a supported service such as Sonarr, Home Assistant, or
|
||||
Docker. Integrations provide data and actions to widgets. They can also be linked to apps.
|
||||
|
||||
### Setup studio
|
||||

|
||||
|
||||
The studio keeps related choices together:
|
||||
See [Managing integrations](/docs/management/integrations) and the
|
||||
[integration catalog](/docs/category/integrations).
|
||||
|
||||
1. **Essentials** sets the default language, color scheme, analytics preference, and the usual host, IP address, domain, or reverse-proxy path used by your services. URL suggestions can use separate ports, subdomains, or one path per service.
|
||||
2. **Discover** checks the actual database, Docker-compatible sockets, Kubernetes configuration, Workshop, and Assistant capabilities. Unavailable sources never block manual setup.
|
||||
3. **Connect** shows detected integrations and apps first, identifying whether each app came from an explicit [`homarr.*` or Homepage Docker label](/docs/integrations/docker-labels) or image matching. Select several integrations and apps at once, review every URL, and use the service-specific link to open its API-key settings when one is available. If a container has no published port or URL label, add its HTTP or HTTPS address before importing it.
|
||||
4. **Board** previews the Base layout, colors, widget radius, sidebars, selected apps, and widgets inferred from integrations or Docker labels. Choose 8 columns for a focused board, 10 for a balanced board, 12 for a wide board, or use the slider for a custom width up to 24 columns. Homarr still creates and reflows the protected Mobile layout automatically. A fast setup adds the integration-free Clock, Weather, and Bookmarks starter widgets.
|
||||
5. **Extend** explains and optionally configures Assistant, the community Workshop, and the separate Homarr MCP endpoint.
|
||||
6. **Review** tests the selected connections, then saves integrations, apps, widgets, settings, and the exact first board together. If any part fails, the database changes are rolled back and your form stays available to correct.
|
||||
### Widgets
|
||||
|
||||
Docker discovery reports each configured host separately. Results from reachable hosts remain selectable if another socket
|
||||
is unavailable, which is useful for remote Docker, rootless Docker, Synology, and mixed deployments. On Kubernetes or
|
||||
bare-metal installations without a Docker socket, enter services manually and use the same integration catalog.
|
||||
A **widget** is a board tile. Some widgets work on their own; others require one or more integrations. Configuration,
|
||||
supported integrations, and non-obvious limitations are documented on each widget page.
|
||||
|
||||
After setup, **Open my board** takes you directly to the configured board. The in-product tour then introduces edit mode,
|
||||
responsive layouts, widgets, and search without delaying completion.
|
||||

|
||||
|
||||
## Creating another board
|
||||
See the [widget catalog](/docs/category/widgets).
|
||||
|
||||
In Homarr, you organize your apps and widgets on boards.
|
||||
Boards use fixed-size tiles so the same widget keeps the same proportions on every screen.
|
||||
Drag, resize, and section controls are available in edit mode.
|
||||
Onboarding already created the first board. To create another one, navigate to `Manage` > `Boards` > `New board`:
|
||||

|
||||
### Containers and rails
|
||||
|
||||
A board must always have a name and can either be public or private.
|
||||
Public boards are also accessible for users, that are not logged in ([see access control for boards](/docs/management/boards/#access-control)).
|
||||
A **Container** groups board items and can be nested. A **rail** reserves a fixed area at the left or right of a
|
||||
responsive layout. Both are configured in board edit mode.
|
||||
|
||||

|
||||

|
||||
|
||||
Congratulations - you've just created another board. You can see the boards you have access to on this page:
|
||||
See [Boards](/docs/management/boards#containers-and-rails).
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={boardsHomeMobileMenu}
|
||||
alt="Boards management page showing a Home badge and separate desktop and mobile home-board menu entries"
|
||||
style={{ maxWidth: "100%" }}
|
||||
/>
|
||||
<figcaption>The Boards page selects the board opened from Home separately for desktop and mobile.</figcaption>
|
||||
</figure>
|
||||
### Users, groups, and permissions
|
||||
|
||||
The board marked **Home** is the board opened from the desktop Home route. **Set as your mobile board** selects which board
|
||||
opens on phones. This is separate from the **Mobile** layout: the home-board setting chooses a board, while **Mobile** and
|
||||
**Base** are responsive layouts inside that board. A phone can therefore open a different home board and still use that
|
||||
board's Mobile layout.
|
||||
Users inherit permissions and default boards from their groups. Resource-specific access can further restrict boards
|
||||
and integrations.
|
||||
|
||||
New boards start with **Mobile** and **Base** responsive layouts automatically, so you can edit the board for phones and
|
||||
desktops without creating extra layouts first. Mobile starts at `0px` with 3 columns and Base at `768px` with 10 columns.
|
||||
Each layout keeps its own tile positions and sizes.
|
||||

|
||||
|
||||
## Add your first app to Homarr
|
||||
See [Users and groups](/docs/management/users) and [single sign-on](/docs/advanced/single-sign-on).
|
||||
|
||||
To add links to your dashboard, you must first add them as an "app".
|
||||
Navigate to this page to add an app:
|
||||
## Explore further
|
||||
|
||||

|
||||
- [Server settings](/docs/management/settings)
|
||||
- [Assistant](/docs/management/assistant)
|
||||
- [Custom Widgets](/docs/management/custom-widgets)
|
||||
- [Community Workshop](/docs/workshop)
|
||||
- [API](/docs/management/api) and [MCP](/docs/management/mcp)
|
||||
- [Keyboard shortcuts](/docs/advanced/keyboard-shortcuts)
|
||||
|
||||
Next, click on the `New app` button. You'll need to provide a name and an icon to create an app.
|
||||
The name must be at least one character long but you can provide any image URL for the icon.
|
||||
Homarr ships with over 11K icons - so you can just search by entering a search text instead.
|
||||
|
||||

|
||||
|
||||
After you created the app, you'll see in on the apps page:
|
||||
|
||||

|
||||
|
||||
## Arrange and organize your board
|
||||
|
||||
Let's add your freshly created app, from the previous step, to the board.
|
||||
To do this, edit your previously created board by clicking on the big `Open board` button:
|
||||
|
||||
<figure>
|
||||
<img src={boardDesktopCurrent} alt="Current Homarr board opened from the Boards page" style={{ maxWidth: "100%" }} />
|
||||
<figcaption>Open a board to view its dashboard, then enter edit mode to arrange its content.</figcaption>
|
||||
</figure>
|
||||
|
||||
Here you have the following options in the header:
|
||||
|
||||

|
||||
|
||||
- **Search**: Here you can search for data. You can search for integrations, boards, actions, sites and much more. Some actions may be context dependent (eg. will only show when certain widgets are on your page)
|
||||
- **Edit board**: Clicking this button will toggle edit mode. In this mode you can edit the contents of your board.
|
||||
- **Settings**: Clicking this button will redirect you to a settings page where you can adjust the board settings (page title, colors, ...).
|
||||
- **Profile**: This avatar will be visible on every page. Its menu includes the board switcher; press `Shift+C` to open
|
||||
it directly. The current board is left out of the results.
|
||||
|
||||
When entering the edit mode, you'll get some additional buttons to work with:
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={boardEditModeCurrent}
|
||||
alt="Current Homarr board editor with tile controls visible"
|
||||
style={{ maxWidth: "100%" }}
|
||||
/>
|
||||
<figcaption>The current editor keeps the board visible while its editing controls are available.</figcaption>
|
||||
</figure>
|
||||
|
||||
- **Add board content**: Click this button to create a new item, app, integration, or Container.
|
||||
- **Save board**: Click this button to save your changes and leave edit mode. If you leave with unsaved changes, Homarr asks whether to discard them.
|
||||
|
||||
Outside edit mode, right-click a widget for its live status, refresh, settings, quick options, and supported actions.
|
||||
Hold `Shift` while hovering a widget that supports advanced view to expand it in place while the rest of the board
|
||||
stays visible but dimmed. Release `Shift` to close it. Hold `Shift` plus `Ctrl` on Windows/Linux or `Cmd` on macOS to
|
||||
keep its advanced view open until you close it. Widgets without a distinct advanced experience adapt in place.
|
||||
|
||||
To continue, click **New item** in the add-content menu. New content is placed at the first available position on the main
|
||||
canvas; it is not inserted at a clicked empty cell or directly into a rail or Container:
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={addContentMenuCurrent}
|
||||
alt="Current add board content menu with item, app, integration, and Container actions"
|
||||
style={{ maxWidth: "100%" }}
|
||||
/>
|
||||
<figcaption>The add-content menu provides the four supported ways to place new content on the board.</figcaption>
|
||||
</figure>
|
||||
|
||||
Next, you can choose what item you'd like to add.
|
||||
We will discuss the other options in the following sections - for now choose "App" to continue.
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={chooseItemCurrent}
|
||||
alt="Current item picker showing the App card and other item types"
|
||||
style={{ maxWidth: "100%" }}
|
||||
/>
|
||||
<figcaption>Choose the App item from the current picker to add an app tile.</figcaption>
|
||||
</figure>
|
||||
|
||||
As soon as you chose the app, the modal will close and you'll get the following item on your board:
|
||||
|
||||
<img src={manageBoardNoApp} alt="Screenshot of the No app element on the board" />
|
||||
|
||||
This is expected, because you haven't told Homarr what app it should show in this item.
|
||||
To configure this, click on the small 3 dots at the top of the item in the edit mode and choose "Edit item" in the menu.
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={moveResizeMenuCurrent}
|
||||
alt="Current board tile menu showing Edit item and Move or resize item"
|
||||
style={{ maxWidth: "450px" }}
|
||||
/>
|
||||
<figcaption>The tile menu contains the item editor and the separate move-and-resize tools.</figcaption>
|
||||
</figure>
|
||||
|
||||
In the modal you can edit the app that you want to display:
|
||||
|
||||
<figure>
|
||||
<img src={editItemCurrent} alt="Current Edit item modal for an App tile" style={{ maxWidth: "620px" }} />
|
||||
<figcaption>
|
||||
The Edit item workspace previews option changes as you configure the tile. Save changes to apply them to the board.
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
When adding a widget, set its initial grid width and height directly in the preview. These size controls are only shown before the widget is added.
|
||||
|
||||
As soon as you save your changes, the tile on the board will refresh and display your app.
|
||||
Resize from any visible edge or corner handle. For a Container, activate its top-left grip before using its resize handles.
|
||||
Press and hold a handle, move the pointer, and release it when the tile has the size you want.
|
||||
|
||||
To move a tile in edit mode, press and hold its inert content area, move it to the desired position, and release it.
|
||||
Widget content is disabled while editing so its controls do not intercept the drag; use the tile's settings button for edit actions.
|
||||
The tile snaps to the grid. A single compatible collision may swap the two items when both resulting placements fit;
|
||||
otherwise the collision chain reflows neighboring tiles automatically.
|
||||
|
||||
Every `1 × 1` tile has a logical content size of `200 × 200` pixels.
|
||||
Larger tiles use multiples of that fixed unit, with a consistent gap between cells.
|
||||
Homarr scales the complete board uniformly, like zooming a page.
|
||||
The complete canvas always fits the available width without horizontal board scrolling. Below 100%, Homarr preserves the
|
||||
widget's readable typography and control density instead of shrinking each widget independently.
|
||||
It does not squeeze or reflow the content of individual widgets, so a widget keeps the same design and proportions across screen sizes.
|
||||
|
||||
On a narrow screen, Homarr uses the **Mobile layout** for the selected board and stacks the board content vertically while
|
||||
preserving each widget's fixed logical proportions:
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={currentBoardMobileView}
|
||||
alt="Homarr's Mobile layout in a 390-pixel-wide viewport, with tiles scaled to fit and stacked vertically"
|
||||
style={{ maxWidth: "390px" }}
|
||||
/>
|
||||
<figcaption>
|
||||
At phone width, the selected board uses its Mobile layout and fits the complete canvas to the viewport.
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
:::note
|
||||
|
||||
Viewing a board initially uses the lightweight, non-interactive layout.
|
||||
For users with edit access, Homarr prepares drag-and-drop and resize controls in the background after the board becomes interactive.
|
||||
If you enter edit mode before that finishes, the existing board stays visible until the editor is ready.
|
||||
|
||||
:::
|
||||
|
||||
:::tip
|
||||
|
||||
We recommend you to experiment for a few minutes, before you start building your actual dashboard.
|
||||
This helps you to explore the capabilities of Homarr before you build your board in a suboptimal way.
|
||||
|
||||
:::
|
||||
|
||||
Keyboard users can focus a tile, press Enter or Space, then use arrow keys to move and Shift plus arrow keys to resize
|
||||
within its current canvas, rail, or Container. Press Escape to stop keyboard editing. Touch dragging starts after a short
|
||||
hold of about `200 ms`; resize handles accept direct touch input. During a pointer or touch move or resize, press Escape
|
||||
to cancel and restore the previous layout. For cross-grid moves or precise numeric controls, choose **Move / resize item**
|
||||
from the tile's edit menu.
|
||||
Keyboard commands at a grid boundary or minimum tile size are ignored and announced; they do not move or shrink the tile.
|
||||
|
||||
<img src={currentKeyboardTileEditing} alt="A board tile focused for keyboard editing" style={{ maxWidth: "100%" }} />
|
||||
|
||||
Open **Move / resize item** from the tile menu to move the tile to another section or rail and enter precise numeric
|
||||
coordinates and dimensions. After making changes, click **Save board** to persist them and leave edit mode.
|
||||
|
||||
## Adding your first integration
|
||||
|
||||
Now it's time to integrate some basic data into your board.
|
||||
To do this, we first need to create an integration.
|
||||
An integration is a connection between Homarr and a third party application - usually something that you run and deploy yourself.
|
||||
|
||||
Navigate to `Manage` > `Integrations` (for example via your user menu).
|
||||
As an example, we are going to use the public demo instance of **Dash.** - a popular application to monitor CPU / hardware usage.
|
||||
Choose the **Dash.** integration from the list of available integrations:
|
||||
|
||||

|
||||
|
||||
Next, choose a name (or leave it at default), enter `https://dash.mauz.dev/` as the URL in the form and click on `Test connection and create`.
|
||||
Pressing the save button will perform a test request to the integration, to confirm that the networking setup is working as expected.
|
||||
Sometimes invalid configurations, firewalls and other mistakes can lead to connectivity problems - [follow this guide here](/docs/management/integrations/#troubleshooting-connection) if you experience issues.
|
||||
|
||||
If connection was successful, you will be redirect back to the list of integrations.
|
||||
Now let's embed it to your board (see next section).
|
||||
|
||||
:::note
|
||||
|
||||
Some integrations may require additional configuration, such as a username, password or API tokens.
|
||||
Depending on your networking setup and applications, the connection from Homarr might also get blocked by firewalls,
|
||||
the target application or your router.
|
||||
|
||||
:::
|
||||
|
||||
## Embed integration data using widgets
|
||||
|
||||
Let's add your integration, that you have configured in the section above, as a widget to your board.
|
||||
First, navigate back to your board that you want to add it to.
|
||||
Next, enter edit mode again and add another item to your board:
|
||||
|
||||
<figure>
|
||||
<img
|
||||
src={addContentMenuCurrent}
|
||||
alt="Current add board content menu with item, app, integration, and Container actions"
|
||||
style={{ maxWidth: "100%" }}
|
||||
/>
|
||||
<figcaption>Use the same add-content menu to place an integration widget on the board.</figcaption>
|
||||
</figure>
|
||||
|
||||
Instead of choosing an app, let's choose `System Health Monitoring` this time.
|
||||
Click on "Add to board":
|
||||
|
||||

|
||||
|
||||
Resize the item slightly and then edit it using the three dots menu at the top:
|
||||
|
||||

|
||||
|
||||
Next, choose your newly created Dash. integration in the integrations dropdown:
|
||||
|
||||

|
||||
|
||||
:::note
|
||||
|
||||
Some widgets may support multiple integrations at the same time.
|
||||
If they do not support multiple integrations, you will be unable to select more than one.
|
||||
|
||||
:::
|
||||
|
||||
Confirm your changes by pressing save.
|
||||
Editing a widget will trigger a data update and data will soon appear:
|
||||
|
||||

|
||||
|
||||
As with every change, click **Save board** to persist your board changes and leave edit mode.
|
||||
|
||||
## Organizing items with Containers
|
||||
|
||||
Containers are resizable areas for apps, widgets, and nested Containers.
|
||||
The same Container works on the main canvas, inside a fixed rail, or inside another Container.
|
||||
Each Container can configure:
|
||||
|
||||
- Its label and whether that label is visible.
|
||||
- Allow or disable collapsing.
|
||||
- Show or hide **Open all in new tabs**.
|
||||
- Change its border color and custom CSS classes.
|
||||
|
||||
Open the add-content menu and choose **New container**.
|
||||
In edit mode, move and resize it like any other item, then drag items into or out of it.
|
||||
Nested content stays within the Container's bounds.
|
||||
While resizing, the solid outline follows the pointer continuously and the dashed grid preview shows the size that will be saved on release.
|
||||
|
||||
### Collapsing and opening apps
|
||||
|
||||
Users can collapse an eligible Container like an accordion in view mode without changing its saved expanded size.
|
||||
The full-width header becomes the compact expansion bar, so the half-row state has no empty pill-shaped spacer.
|
||||
Expanding it restores its bounds and makes room for its contents.
|
||||
If **Open all in new tabs** is enabled, the Container menu can open every app link it contains.
|
||||
|
||||
### Fixed rails
|
||||
|
||||
Open the board's **Layout** settings to enable the left or right rail for each responsive layout.
|
||||
Choose one, two, or three columns with the slider and use the preview to check the remaining canvas width.
|
||||
The rail reserves those columns from the dashboard, so Homarr moves canvas items into the next available positions.
|
||||
Rail content stays visible while the page scrolls and remains editable.
|
||||
Each responsive layout keeps its own rail widths, item positions, and item sizes.
|
||||
|
||||
## Guided tours
|
||||
|
||||
After completing the onboarding, Homarr provides interactive guided tours to help you discover key features.
|
||||
|
||||
### Management tour
|
||||
|
||||
When you first visit the management area (`/manage`), Homarr walks you through the main pages: boards, apps, integrations, and users (admin only).
|
||||
Each page highlights the list view and the create action so you know where to find and add things.
|
||||
|
||||
### Board tour
|
||||
|
||||
When you first open a board, a tour highlights the board header elements: search, edit mode, settings, and the user menu.
|
||||
|
||||
### Tour controls
|
||||
|
||||
- Press **Enter** (or click **Next**) to advance through tour steps
|
||||
- Tours auto-start on first visit and do not repeat once completed
|
||||
- Tours are skipped on mobile screens (below `sm` breakpoint)
|
||||
- You can **reset tours** from the user settings page under **Manage > Users > [Your user] > General**
|
||||
|
||||
## Next steps
|
||||
|
||||
You're done with the basic setup 🔥. Now it's time to organize and customize even more.
|
||||
We highly recommend you to experiment with different options, styles and configurations.
|
||||
See these curated pages for your next steps:
|
||||
|
||||
- Create new apps using the [apps management](/docs/management/apps/)
|
||||
- Customize your board or add more boards using the [boards management](/docs/management/boards/)
|
||||
- Integrate software that you use using the [integrations management](/docs/management/integrations/)
|
||||
- Choose from our beautiful and interactive [widgets](/docs/category/widgets)
|
||||
- See [all supported integrations](/docs/category/integrations)
|
||||
- Integrate with Homarr with your own application using [the API](/docs/management/api/)
|
||||
|
||||
:::danger
|
||||
|
||||
The Homarr Team will never ask for your credentials. Do not send people your credentials, as they manage the access to your applications and can cause harm to your device if they are abused.
|
||||
|
||||
:::
|
||||
See the [glossary](/docs/getting-started/glossary) for a compact list of Homarr terms.
|
||||
@@ -2,12 +2,19 @@
|
||||
|
||||
This glossary explains Homarr's main components and the terms used for them.
|
||||
|
||||
| Term | Definition |
|
||||
| ----------- | --------------------------------------------------------------------------------------- |
|
||||
| Apps | A piece of software that you or a third party hosts (for example, Google) |
|
||||
| Integration | A connection to a service outside of Homarr |
|
||||
| Container | A resizable area that can hold apps, widgets, and nested Containers |
|
||||
| Widget | A tile that uses your integrations to display data or enables you to interact with them |
|
||||
| Edit mode | A temporary state where you can drag, resize, edit, or customize your board |
|
||||
| Board | A customizable page where apps, widgets, and Containers are arranged |
|
||||
| Tasks | Workloads that are performed in the background, even if no user is present |
|
||||
| Term | Definition |
|
||||
| --------------- | -------------------------------------------------------------------------------- |
|
||||
| App | A saved shortcut with a name, destination, icon, and optional status check |
|
||||
| Assistant | A conversation interface that can use model responses and Homarr tools |
|
||||
| Board | A dashboard page where apps, widgets, and Containers are arranged |
|
||||
| Container | A resizable board area containing apps, widgets, or nested Containers |
|
||||
| Custom Widget | A validated definition for an API-backed board tile |
|
||||
| Edit mode | The board state used to add, move, resize, configure, or remove content |
|
||||
| Homarr provider | An Assistant provider routed through Workshop with a per-user allowance |
|
||||
| Integration | A server-side connection from Homarr to a supported service |
|
||||
| Layout | An arrangement of board items selected for a viewport width |
|
||||
| Provider | The model API selected for Assistant |
|
||||
| Rail | A fixed area at the left or right of a non-Mobile board layout |
|
||||
| Task | A background workload that runs without an active browser session |
|
||||
| Widget | A board tile that displays information or provides actions |
|
||||
| Workshop | A separate community service for sharing Custom Widget definitions and board CSS |
|
||||
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 561 KiB |
|
Before Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 33 KiB |
@@ -1,45 +1,31 @@
|
||||
---
|
||||
title: Prerequisites
|
||||
title: Getting started
|
||||
sidebar_position: 1
|
||||
tags:
|
||||
- Getting Started
|
||||
- Installation
|
||||
- Docker
|
||||
- Unraid
|
||||
---
|
||||
|
||||
import Link from "@docusaurus/Link";
|
||||
import { IconArrowRight } from "@tabler/icons-react";
|
||||
import {
|
||||
GettingStartedOverview,
|
||||
InstallationPaths,
|
||||
} from "@site/src/components/pages/getting-started/getting-started-overview";
|
||||
|
||||
Before you try to install Homarr, please review if your device meets the requirements.
|
||||
Installing on an unsupported device may lead to unstable behaviour and no support will be provided.
|
||||
<GettingStartedOverview />
|
||||
|
||||
## Hardware
|
||||
## Requirements
|
||||
|
||||
- At least 500MB RAM
|
||||
- At least 600MB of free disk space for the Docker image. SSD is preferred.
|
||||
- Single or dual core CPU
|
||||
- Stable network connection, Wi-Fi use is not recommended
|
||||
- `linux/amd64` or `linux/arm64`;
|
||||
- 500 MB RAM;
|
||||
- 600 MB free disk space for the container image;
|
||||
- a persistent writable `/appdata` directory.
|
||||
|
||||
## Architecture
|
||||
`linux/arm/v7` is not supported.
|
||||
|
||||
We build Homarr for a bunch of different architectures, including ARM. Please ensure that your device architecture is supported by Homarr. We won't be able to provide support for unusual or outdated architectures.
|
||||
## Choose an installation method
|
||||
|
||||
| Architecture | Supported |
|
||||
| ------------ | ---------------- |
|
||||
| linux/amd64 | ✅ Supported |
|
||||
| linux/arm64 | ✅ Supported |
|
||||
| linux/arm/v7 | ❌ Not supported |
|
||||
<InstallationPaths />
|
||||
|
||||
## Getting started with installation
|
||||
|
||||
<Link
|
||||
data-attr="Go to installation"
|
||||
className={"button button--secondary button--lg rounded-3xl dark:border-zinc-600 dark:bg-zinc-800"}
|
||||
to="/docs/category/installation-1"
|
||||
>
|
||||
<div className={"flex items-center gap-3"}>
|
||||
<span className={"dark:text-gray-200"}>Go to Installation</span>
|
||||
<IconArrowRight className={"dark:text-gray-200"} size={20} />
|
||||
</div>
|
||||
</Link>
|
||||
After Homarr starts, open it in a browser and complete onboarding. Then continue with
|
||||
[After the installation](/docs/getting-started/after-the-installation) for the core concepts and the most useful next
|
||||
links.
|
||||
@@ -2,106 +2,56 @@ import { DockerInstallSnippet } from "@site/src/components/pages/installation/do
|
||||
|
||||
# Docker
|
||||
|
||||
Docker is our recommended installation method for beginners and professionals.
|
||||
It is easy to use, ships with all dependencies inside a single container and is easy to use and maintain.
|
||||
It requires at least some basic knowledge of [Docker](https://www.docker.com/).
|
||||
We recommend [NetworkChuck's Docker Containers 101](https://www.youtube.com/watch?v=eGz9DS-aIeY) as a good start for complete beginners.
|
||||
Docker Compose is the recommended installation method. Install
|
||||
[Docker Engine](https://docs.docker.com/engine/install/) and the
|
||||
[Compose plugin](https://docs.docker.com/compose/install/).
|
||||
|
||||
## Docker compose
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- A Linux or Windows based system that meets the [hardware prerequisites](/docs/getting-started/#hardware) and [architecture prerequisites](/docs/getting-started/#architecture).
|
||||
- [Docker](https://docs.docker.com/get-docker/)
|
||||
- [Docker Compose](https://docs.docker.com/compose/install/) - _preinstalled on many systems nowadays_
|
||||
|
||||
### Installation
|
||||
## Docker Compose
|
||||
|
||||
<DockerInstallSnippet data-visual-test="blackout" />
|
||||
Finally, run ``docker compose up -d`` in the same directory. This will start the Homarr container in the background.
|
||||
|
||||
:::caution
|
||||
Start Homarr from the directory containing `docker-compose.yaml`:
|
||||
|
||||
Docker compose creates a network by default. Some integrations may not work (specifically Dash.) when the network internal hostname is used since clients do not know this name. It is recommended that you either use a local network wide hostname or the IP directly. An alternative is to create a DNS record with the same internal compose stack hostname for all clients outside.
|
||||
```sh
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
:::
|
||||
Persist `/appdata`; it contains the database and configuration. Mount the Docker socket only when Homarr needs Docker
|
||||
discovery or management.
|
||||
|
||||
### Updating
|
||||
Integration URLs must be reachable from the Homarr container. Browser-facing app URLs may use a different hostname;
|
||||
see [Managing integrations](/docs/management/integrations#configuration).
|
||||
|
||||
To update, navigate to the directory with the `docker-compose.yaml` located.
|
||||
### Update
|
||||
|
||||
- Stop Homarr using `docker compose down`
|
||||
- Pull the newest image of Homarr using `docker compose pull`
|
||||
- Start Homarr again using `docker compose up -d` (`-d` for detached mode - start in background)
|
||||
- Delete the old image using `docker image prune` (_Warning: this also removes you other unused images - not just Homarr_)
|
||||
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.
|
||||
|
||||
You can automate this process using [Watchtower](https://containrrr.dev/watchtower/).
|
||||
```sh
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Uninstalling
|
||||
### Uninstall
|
||||
|
||||
To uninstall, navigate to the directory with the `docker-compose.yaml` located.
|
||||
`docker compose down` removes the containers and Compose network. Delete the configured `/appdata` host directory or
|
||||
volume only when the Homarr data is no longer needed.
|
||||
|
||||
- Stop Homarr using `docker compose down`
|
||||
- Delete the created directories & files on your root file system (check `docker-compose.yaml` file for your specific locations)
|
||||
- Delete compose file using `rm docker-compose.yaml`
|
||||
- Prune unused Docker images using `docker image prune` (_Warning: this also removes you other unused images - not just Homarr_)
|
||||
- (Optional): Prune any network or volumes if you use any.
|
||||
- (Optional): Remove Homarr from your reverse proxy, VPNs or tunnels if you use any.
|
||||
## Docker CLI
|
||||
|
||||
## Docker standalone
|
||||
The equivalent standalone container is:
|
||||
|
||||
:::caution
|
||||
|
||||
[Docker Compose](#docker-compose) is easier and recommended for beginners. Consider using compose instead.
|
||||
|
||||
:::
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- A Linux or Windows based system that meets the [hardware prerequisites](/docs/getting-started/#hardware) and [architecture prerequisites](/docs/getting-started/#architecture).
|
||||
- [Docker](https://docs.docker.com/get-docker/)
|
||||
|
||||
### Installation
|
||||
|
||||
To install Homarr using Docker, simply run the following command.
|
||||
|
||||
```bash
|
||||
docker run \
|
||||
```sh
|
||||
docker run \
|
||||
--name homarr \
|
||||
--restart unless-stopped \
|
||||
-p 7575:7575 \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v <your-path>/homarr/appdata:/appdata \
|
||||
-v /absolute/path/to/homarr/appdata:/appdata \
|
||||
-e SECRET_ENCRYPTION_KEY='your_64_character_hex_string' \
|
||||
-d ghcr.io/homarr-labs/homarr:latest
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
Docker will mount the configuration files and icons to your host machine. Please make sure to replace `<your-path>` from the docker run command with your desired storage location. The path must be absolute.
|
||||
|
||||
:::
|
||||
|
||||
### Updating
|
||||
|
||||
To update Homarr, you must remove your container first. Make sure that you've mounted your data and that you have access to it, so your configuration doesn't get lost.
|
||||
|
||||
1. Run `docker rm homarr` to remove the container.
|
||||
2. Pull the latest Homarr image `docker pull ghcr.io/homarr-labs/homarr:latest`.
|
||||
3. Re-run the command you used to install Homarr.
|
||||
|
||||
This process can get tideous, if you update frequently. Thus, we recommend [using docker-compose](#docker-compose)
|
||||
|
||||
:::tip
|
||||
|
||||
Want to update all your containers automatically? Checkout [Watchtower](https://containrrr.dev/watchtower/) a service which will automatically update your containers on a set interval.
|
||||
|
||||
:::
|
||||
|
||||
### Uninstalling
|
||||
|
||||
1. Obtain the container ID of your Homarr container using `docker ps | grep homarr`.
|
||||
2. Delete the container using `docker rm <your-container-id>`
|
||||
3. Prune unused Docker images using `docker image prune` (_Warning: this also removes you other unused images - not just Homarr_)
|
||||
4. (Optional): Prune any network or volumes if you use any.
|
||||
5. (Optional): Remove Homarr from your reverse proxy, VPNs or tunnels if you use any.
|
||||
Remove the Docker socket mount when it is not required. To update, pull the current image, recreate the container with
|
||||
the same arguments, and keep the `/appdata` mount and `SECRET_ENCRYPTION_KEY` unchanged.
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
<img src="https://raw.githubusercontent.com/homarr-labs/charts/refs/heads/main/charts/homarr/icon.svg" align="right" width="92" alt="homarr logo">
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
A Helm chart to deploy homarr for Kubernetes
|
||||
|
||||
@@ -437,7 +437,7 @@ All available values are listed on the [artifacthub](https://artifacthub.io/pack
|
||||
| httproute.rules[0].matches[0].path.value | string | `"/"` | Path value to match |
|
||||
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
|
||||
| image.repository | string | `"ghcr.io/homarr-labs/homarr"` | Image repository |
|
||||
| image.tag | string | `"v1.76.1"` | Overrides the image tag whose default is the chart appVersion |
|
||||
| image.tag | string | `"v1.76.2"` | Overrides the image tag whose default is the chart appVersion |
|
||||
| imagePullSecrets | list | `[]` | Secrets for Docker registry |
|
||||
| ingress.annotations | object | `{}` | Ingress annotations |
|
||||
| ingress.enabled | bool | `false` | Enable ingress |
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
Pika Pods is a hosting platform for open source apps. You can deploy Homarr on Pika Pods with just a few clicks:
|
||||
|
||||
[__](https://www.pikapods.com/pods?run=homarr-v1)
|
||||
[__](https://www.pikapods.com/pods?run=homarr)
|
||||
@@ -1,14 +1,8 @@
|
||||
# Portainer
|
||||
|
||||
## Portainer Stacks
|
||||
## Install with a stack
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [Portainer Stacks](https://www.portainer.io/blog/stacks-docker-compose-the-portainer-way)
|
||||
|
||||
### Installing
|
||||
|
||||
To install Homarr using Portainer Stacks, simply create a new stack and paste the following code into it.
|
||||
Create a Portainer stack with this Compose file:
|
||||
|
||||
```yml title="docker-compose.yml"
|
||||
#---------------------------------------------------------------------#
|
||||
@@ -28,21 +22,12 @@ services:
|
||||
- "7575:7575"
|
||||
```
|
||||
|
||||
:::note
|
||||
Portainer will mount the files to your host machine. Please make sure to replace `<your-path>` from the docker run command with your desired storage location. The path must be absolute.
|
||||
:::
|
||||
|
||||
Then, click on `Deploy the stack` and wait until the container has started.
|
||||
|
||||
:::tip
|
||||
|
||||
If you're unsure how to create a stack, checkout the [Portainer Documentation](https://docs.portainer.io/user/docker/stacks/add).
|
||||
|
||||
:::
|
||||
Replace `<your-path>` with an absolute host path, generate `SECRET_ENCRYPTION_KEY`, then deploy the stack. See
|
||||
[Portainer's stack documentation](https://docs.portainer.io/user/docker/stacks/add) for Portainer-specific options.
|
||||
|
||||
### Updating
|
||||
|
||||
To update Homarr using Docker Compose or Portainer Stacks, simply pull the latest image and restart the container.
|
||||
Pull the current image and redeploy the stack:
|
||||
|
||||
1. Run `docker pull ghcr.io/homarr-labs/homarr:latest` to pull the latest image.
|
||||
2. Re-run `docker-compose up -d` or re-deploy the stack in Portainer.
|
||||
@@ -1,9 +1,11 @@
|
||||
# QNAP
|
||||
|
||||
:::caution
|
||||
QNAP installation guide has not updated to 1.0 yet. There guide is still for 0.15.10.
|
||||
|
||||
The available QNAP guides target Homarr 0.15.10 and have not been updated for 1.0.
|
||||
|
||||
:::
|
||||
|
||||
When installing on QNAP, we recommend you to install Homarr using [Container Station](https://www.qnap.com/en/software/container-station) or [this third-party image](https://www.myqnap.org/product/homarr/).
|
||||
|
||||
There is also a guide available, but note that it is written in Chinese: https://post.smzdm.com/p/awzm7op2/
|
||||
Run Homarr with [Container Station](https://www.qnap.com/en/software/container-station) or the
|
||||
[third-party QNAP package](https://www.myqnap.org/product/homarr/). A community
|
||||
[Container Station guide](https://post.smzdm.com/p/awzm7op2/) is available in Chinese.
|
||||
@@ -1,33 +1,12 @@
|
||||
# Runtipi
|
||||
|
||||
Runtipi is a self-hosted orchestrator that makes it easy to manage and run multiple services on a single server. It is based on Docker and comes with a simple web interface to manage your services. Runtipi is designed to be easy to use, so you don't have to worry about manual configuration or networking.
|
||||
Homarr is available in the default [Runtipi](https://runtipi.io) app store.
|
||||
|
||||
https://runtipi.io
|
||||
## Installation
|
||||
|
||||
## Prerequisites
|
||||
Install **Homarr** from the Runtipi app store and select either a port or domain for access.
|
||||
|
||||
- [Runtipi](https://runtipi.io/docs/getting-started/installation)
|
||||
Runtipi manages start, stop, update, backup, and log operations under **My apps → Homarr**. Use a
|
||||
[user-config](https://runtipi.io/docs/guides/customize-app-config) to override the generated Compose configuration.
|
||||
|
||||
# Installation
|
||||
|
||||
Installing Homarr is pretty untuitive, the app is available in the default appstore :
|
||||
|
||||
1. Search for **"Homarr"** in the App-Store page and select it
|
||||
2. Click on **"Install"**.
|
||||
3. Choose the method you want to access Homarr, through any port or domain name then select **"Install"**
|
||||
|
||||
# Maintenance
|
||||
|
||||
After installation, all you need is available from the WebUI in **"My apps"** > **"Homarr"** :
|
||||
|
||||
- Start/Stop
|
||||
- Update
|
||||
- Backup
|
||||
- Logs
|
||||
|
||||
If you like to tinker with your apps, you can also edit your app's docker-compose with a [user-config](https://runtipi.io/docs/guides/customize-app-config).
|
||||
|
||||
# Getting help
|
||||
|
||||
- If you are looking for help with anything in Runtipi. They provide support on their [Discord](https://discord.gg/Bu9qEPnHsc) and [forums](https://forums.runtipi.io/). If you found vulnerabilities or bugs, [create a new issue here](https://github.com/runtipi/runtipi-appstore/issues).
|
||||
- If you are looking to report a bug, vulnerability or request a new feature for Homarr, use https://github.com/homarr-labs/homarr . You can ask for help on our Discord.
|
||||
See the [Runtipi installation documentation](https://runtipi.io/docs/getting-started/installation) for host setup.
|
||||
@@ -21,8 +21,8 @@ This method is only useful, when you want to develop on Homarr or extend it with
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Node.js](https://nodejs.org/en/download/)
|
||||
- [pnpm](https://pnpm.io/installation)
|
||||
- [Node.js](https://nodejs.org/en/download/) 24.18 or newer
|
||||
- [pnpm](https://pnpm.io/installation) at the version pinned in the repository's `package.json`
|
||||
- [Redis](https://redis.io/download)
|
||||
|
||||
## Steps
|
||||
@@ -38,13 +38,14 @@ This method is only useful, when you want to develop on Homarr or extend it with
|
||||
Install all dependencies using <code>pnpm install</code>
|
||||
</li>
|
||||
<li>
|
||||
Copy the `.env.example` file to `.env` and replace `DB_URL` with the full path you want to use for the sqlite
|
||||
database file. For example `DB_URL='/home/username/homarr/db.sqlite`
|
||||
Copy `.env.example` to `.env` and set `DB_URL` to an absolute writable path, such as
|
||||
`DB_URL='/home/username/homarr/db.sqlite'`. Migration and application commands run from different workspace
|
||||
directories, so a relative path can point them at different databases.
|
||||
</li>
|
||||
<li>
|
||||
Replace `AUTH_SECRET` and `SECRET_ENCRYPTION_KEY` both with a secure random string by using `openssl rand -hex 32`
|
||||
Run `openssl rand -hex 32` twice and set `AUTH_SECRET` and `SECRET_ENCRYPTION_KEY` to the two different generated
|
||||
values. Keep both values secret and preserve `SECRET_ENCRYPTION_KEY` with your backups.
|
||||
</li>
|
||||
<li>Replace `CRON_JOB_API_KEY` with a secure random string by using `openssl rand -base64 32`</li>
|
||||
<li>Run `pnpm run db:migration:sqlite:run` and wait that it completes</li>
|
||||
<li>Build the source using `pnpm build`</li>
|
||||
<li>
|
||||
|
||||
@@ -30,7 +30,7 @@ You can install Homarr directly from your Unraid Dashboard, no terminal required
|
||||
|
||||
Don't know whether you have the plugin installed or not? Search for this tab in the navigation:
|
||||
|
||||

|
||||

|
||||
:::
|
||||
|
||||
#### Installing
|
||||
@@ -41,7 +41,7 @@ After you've installed the Community Apps Plugin, you can install Homarr from th
|
||||
2. Search for "Homarr" and click on the result.
|
||||
3. Click on "Install" and adjust the settings to your liking.
|
||||
|
||||

|
||||

|
||||
|
||||
After you've installed Homarr, you can find it under the tab "Docker".
|
||||
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"title": "Integrations",
|
||||
"description": "Integration are a principal part of homarr, it's where you can connect your other apps to interact with them with widgets or other capabilities, Homarr currently integrates with the following applications:"
|
||||
"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."
|
||||
}
|
||||
}
|
||||
@@ -1,114 +1,25 @@
|
||||
---
|
||||
title: "Docker"
|
||||
description: "Docker is a platform where you can run your applications in containers, allowing for easy deployment and management of applications."
|
||||
description: "Connect Homarr to Docker-compatible container engines."
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
import { IntegrationHeader } from "@site/src/components/integrations/header";
|
||||
import { IntegrationCapabilites } from "@site/src/components/integrations/widgets";
|
||||
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
|
||||
import { IconBrandDocker, IconTool } from "@tabler/icons-react";
|
||||
import { dockerIntegration } from ".";
|
||||
import { dockerContainersWidget } from "@site/docs/widgets/docker-containers";
|
||||
|
||||
<IntegrationHeader integration={dockerIntegration} categories={["Containers"]} />
|
||||
|
||||
### Widgets & Capabilities
|
||||
### Widgets and capabilities
|
||||
|
||||
<IntegrationCapabilites
|
||||
items={[
|
||||
{
|
||||
widget: dockerContainersWidget,
|
||||
note: "This widget can only be used with administrator privileges",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<IntegrationCapabilites items={[{ widget: dockerContainersWidget, note: "Requires administrator access" }]} />
|
||||
|
||||
## Connecting Docker to Homarr
|
||||
Docker endpoints are configured with environment variables rather than under **Management → Integrations**.
|
||||
|
||||
Docker connections come directly from Homarr's environment variables. They are automatically available in the Docker management table and Docker widget; you do not create a Docker integration under **Management → Integrations**.
|
||||
## Local socket
|
||||
|
||||
If Homarr runs directly on a host with Docker installed, it uses `/var/run/docker.sock` by default. When Homarr runs in a container, mount the [Docker socket](https://docs.docker.com/engine/security/protect-access/) into it so Homarr can interact with Docker.
|
||||
|
||||
In Docker Compose, you can simply add this line:
|
||||
|
||||
```yaml {10}
|
||||
#---------------------------------------------------------------------#
|
||||
# Homarr - A simple, yet powerful dashboard for your server. #
|
||||
#---------------------------------------------------------------------#
|
||||
services:
|
||||
homarr:
|
||||
container_name: homarr
|
||||
image: ghcr.io/homarr-labs/homarr:latest
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock # <--- add this line here!
|
||||
- ./homarr/appdata:/appdata
|
||||
environment:
|
||||
- SECRET_ENCRYPTION_KEY=your_64_character_hex_string # <--- can be generated with `openssl rand -hex 32`
|
||||
ports:
|
||||
- "7575:7575"
|
||||
```
|
||||
|
||||
With docker run, add this parameter: `-v /var/run/docker.sock:/var/run/docker.sock`.
|
||||
In Windows, you'll need to adjust the slashes: `-v //var/run/docker.sock:/var/run/docker.sock`
|
||||
|
||||
### Using Podman
|
||||
|
||||
On Linux, Homarr can connect to Podman's [Docker-compatible API](https://docs.podman.io/en/latest/markdown/podman-system-service.1.html).
|
||||
The Podman API socket must be running and mounted into the Homarr container.
|
||||
The socket grants full access to Podman, including arbitrary code execution as the user running the API, so only mount it into trusted containers.
|
||||
|
||||
For rootless Podman, enable the socket for the user that runs Homarr:
|
||||
|
||||
```bash
|
||||
systemctl --user enable --now podman.socket
|
||||
```
|
||||
|
||||
The rootless socket is located at `$XDG_RUNTIME_DIR/podman/podman.sock` (usually `/run/user/<uid>/podman/podman.sock`).
|
||||
You can confirm the path with:
|
||||
|
||||
```bash
|
||||
podman info --format '{{.Host.RemoteSocket.Path}}'
|
||||
```
|
||||
|
||||
Mount that socket into the Homarr container and point `DOCKER_SOCKET_PATHS` to its path **inside** the container:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
homarr:
|
||||
container_name: homarr
|
||||
image: ghcr.io/homarr-labs/homarr:latest
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ${XDG_RUNTIME_DIR}/podman/podman.sock:/var/run/podman.sock
|
||||
- ./homarr/appdata:/appdata
|
||||
environment:
|
||||
SECRET_ENCRYPTION_KEY: your_64_character_hex_string
|
||||
DOCKER_SOCKET_PATHS: /var/run/podman.sock
|
||||
ports:
|
||||
- "7575:7575"
|
||||
```
|
||||
|
||||
Start Homarr with `podman compose up -d`.
|
||||
Run the compose project as the same user that owns the rootless Podman socket so `$XDG_RUNTIME_DIR` resolves to the correct path.
|
||||
To keep the user socket available after logout and across reboots, enable lingering with `loginctl enable-linger <user>`.
|
||||
|
||||
For rootful Podman, enable the system socket with `sudo systemctl enable --now podman.socket`.
|
||||
Its default path is `/run/podman/podman.sock`; mount that path instead and start Homarr with `sudo podman compose up -d`.
|
||||
|
||||
:::note SELinux
|
||||
On systems with SELinux enabled, Podman's documentation recommends disabling label separation for a container that accesses the API socket.
|
||||
Add the following to the Homarr service:
|
||||
|
||||
```yaml
|
||||
security_opt:
|
||||
- label=disable
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
You can connect Homarr to multiple Docker-compatible sockets by mounting each socket and listing their in-container paths, separated by commas:
|
||||
Mount the Docker socket into the Homarr container:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
@@ -116,12 +27,34 @@ services:
|
||||
image: ghcr.io/homarr-labs/homarr:latest
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ${XDG_RUNTIME_DIR}/podman/podman.sock:/var/run/podman.sock
|
||||
environment:
|
||||
DOCKER_SOCKET_PATHS: /var/run/docker.sock,/var/run/podman.sock
|
||||
- ./homarr/appdata:/appdata
|
||||
```
|
||||
|
||||
For remote socket proxies, list the hostnames and matching ports in the same order:
|
||||
`/var/run/docker.sock` is the default. For other in-container paths, set a comma-separated list:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DOCKER_SOCKET_PATHS: /var/run/docker.sock,/var/run/podman.sock
|
||||
```
|
||||
|
||||
## Podman
|
||||
|
||||
Homarr uses Podman's Docker-compatible API. Start the Podman socket, mount it, and include its in-container path in
|
||||
`DOCKER_SOCKET_PATHS`.
|
||||
|
||||
For rootless Podman:
|
||||
|
||||
```sh
|
||||
systemctl --user enable --now podman.socket
|
||||
podman info --format '{{.Host.RemoteSocket.Path}}'
|
||||
```
|
||||
|
||||
Run Homarr as the user that owns the socket. On SELinux systems, Podman may require `security_opt: [label=disable]` for
|
||||
the Homarr container. Rootful Podman normally exposes `/run/podman/podman.sock`.
|
||||
|
||||
## Remote endpoints
|
||||
|
||||
For Docker socket proxies, list aligned hostnames and ports:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
@@ -129,193 +62,71 @@ environment:
|
||||
DOCKER_PORTS: 2375,2375
|
||||
```
|
||||
|
||||
Homarr automatically discovers each comma-separated entry as a separate Docker environment. All environments are selected by default; the Docker widget lets you select one or more without any additional setup.
|
||||
:::warning Plaintext Docker API
|
||||
|
||||
Unauthenticated Docker TCP provides control of the Docker host. Keep a socket proxy on a private network or use TLS.
|
||||
|
||||
:::warning[Plaintext TCP]
|
||||
Plaintext Docker TCP can grant unauthenticated control of the Docker host. Prefer a local socket, a least-privilege socket proxy on a private Docker network, or TLS.
|
||||
:::
|
||||
|
||||
### Advanced endpoint configuration
|
||||
|
||||
Most users should use the comma-separated variables above. Use `DOCKER_ENDPOINTS` only when you need custom names, TLS, or restricted capabilities. It is a JSON array where every endpoint declares its identity, transport, and capabilities:
|
||||
Use `DOCKER_ENDPOINTS` for named endpoints, TLS, or restricted capabilities:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
homarr:
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./docker-ca.pem:/run/secrets/docker-ca.pem:ro
|
||||
environment:
|
||||
DOCKER_ENDPOINTS: >-
|
||||
[
|
||||
{
|
||||
"id": "local",
|
||||
"name": "Local Docker",
|
||||
"kind": "docker",
|
||||
"transport": { "type": "socket", "path": "/var/run/docker.sock" },
|
||||
"capabilities": ["inventory", "logs", "lifecycle", "remove"]
|
||||
},
|
||||
{
|
||||
"id": "remote-read-only",
|
||||
"name": "Production inventory",
|
||||
"kind": "docker",
|
||||
"transport": {
|
||||
"type": "tls",
|
||||
"host": "docker.example.com",
|
||||
"port": 2376,
|
||||
"caPath": "/run/secrets/docker-ca.pem"
|
||||
},
|
||||
"capabilities": ["inventory", "logs"]
|
||||
}
|
||||
]
|
||||
environment:
|
||||
DOCKER_ENDPOINTS: >-
|
||||
[
|
||||
{
|
||||
"id": "local",
|
||||
"name": "Local Docker",
|
||||
"kind": "docker",
|
||||
"transport": { "type": "socket", "path": "/var/run/docker.sock" },
|
||||
"capabilities": ["inventory", "logs", "lifecycle", "remove"]
|
||||
},
|
||||
{
|
||||
"id": "production",
|
||||
"name": "Production inventory",
|
||||
"kind": "docker",
|
||||
"transport": {
|
||||
"type": "tls",
|
||||
"host": "docker.example.com",
|
||||
"port": 2376,
|
||||
"caPath": "/run/secrets/docker-ca.pem"
|
||||
},
|
||||
"capabilities": ["inventory", "logs"]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
The stable `id` keeps containers from different endpoints distinct. `name` is shown in the interface, and `kind` can be `docker` or `podman`. Every endpoint must include the `inventory` capability; optionally add `logs`, `lifecycle`, and `remove`. Homarr hides or disables actions the endpoint does not allow and also enforces the same capabilities on the server.
|
||||
Each endpoint requires a stable `id`, display `name`, `kind` (`docker` or `podman`), transport, and the `inventory`
|
||||
capability. Optional capabilities are `logs`, `lifecycle`, and `remove`.
|
||||
|
||||
Supported transports are:
|
||||
| Transport | Required values |
|
||||
| --------- | ----------------------------------------------------------------------------------- |
|
||||
| `socket` | Absolute in-container `path` |
|
||||
| `tls` | `host`, `port`, absolute `caPath`; optional `certPath` and `keyPath` for mutual TLS |
|
||||
| `tcp` | `host`, `port`, and `allowInsecure: true` |
|
||||
|
||||
- `socket`: an absolute in-container `path`
|
||||
- `tls`: `host`, `port`, and an absolute `caPath`; add both `certPath` and `keyPath` for mutual TLS
|
||||
- `tcp`: `host`, `port`, and the explicit acknowledgement `allowInsecure: true`
|
||||
`DOCKER_ENDPOINTS` takes precedence over the socket, hostname, and port lists.
|
||||
|
||||
The structured configuration refuses TCP unless `allowInsecure` is explicitly set to `true`. When `DOCKER_ENDPOINTS` is set, it takes precedence over `DOCKER_SOCKET_PATHS`, `DOCKER_HOSTNAMES`, and `DOCKER_PORTS`.
|
||||
## Use in Homarr
|
||||
|
||||
### Managing your Docker containers within Homarr
|
||||
The Docker management page lists containers from every configured endpoint and can show logs, resource use, and
|
||||
permitted lifecycle actions. The Docker widget can include all endpoints or a selected subset.
|
||||
|
||||
Homarr allows you to interact with Docker containers running on your system.
|
||||
The collapsed **Assisted Docker setup** helper optionally compares visible containers with your existing Homarr apps and integrations. Open it only when you want setup suggestions; it never blocks normal container management. Every service stays distinct by Docker endpoint and container ID, including multiple containers that use the same integration type.
|
||||
Assisted setup compares discovered containers with existing apps and integrations. Discovery is read-only; creating or
|
||||
updating a Homarr resource still requires confirmation. If one endpoint is unavailable, containers from healthy
|
||||
endpoints remain visible.
|
||||
|
||||
Homarr can show a service as:
|
||||
The `homarr.hide` label excludes a container. Other `homarr.*` labels can provide apps, integrations, groups, and widgets
|
||||
during onboarding; see [Docker label discovery](../docker-labels).
|
||||
|
||||
- **Ready to connect** when its image or name matches a supported integration
|
||||
- **New service** when it can be added as an app but no integration is recognized
|
||||
- **Already represented** or **Linked** when an app or integration already matches
|
||||
- **Address changed** when a service appears to match an integration but its reachable address has changed
|
||||
## Security
|
||||
|
||||
Set the usual server address once, then choose whether services normally use different ports, subdomains, or paths. Homarr uses that pattern to prefill every detected service. Each suggestion has one editable URL field with the generated and Docker-reported addresses available as autocomplete options, so you can select a suggestion or type any address directly.
|
||||
A Docker or Podman socket grants extensive host control. Prefer a least-privilege socket proxy when lifecycle access is
|
||||
not required.
|
||||
|
||||
:::info[Review before changing]
|
||||
Service discovery is read-only. Homarr never creates or changes an app or integration automatically. **Set up integration** opens the standard prefilled integration form, while **Create app** opens the existing Docker app form, so you can review and confirm the final setup.
|
||||
:::
|
||||
Homarr needs `CONTAINERS=1` for inventory and `POST=1` for standard lifecycle actions with common proxies. LSIO's proxy
|
||||
can instead expose `ALLOW_START=1`, `ALLOW_STOP=1`, and `ALLOW_RESTARTS=1` while keeping `POST=0`; removal is then
|
||||
unavailable.
|
||||
|
||||
Suggestions appear as a compact task list. Expand an item only when you want to edit its URL or inspect relevant setup statuses. Use the filters to focus on services that need attention or those already represented in Homarr. Refresh runs discovery again. Dismissed suggestions are stored in the current browser using their endpoint-qualified service identity and can be restored from the same helper. If multiple existing items could match, Homarr marks the result as ambiguous and does not choose one automatically.
|
||||
|
||||
Compact status icons summarize the setup information Homarr can act on. Unknown and non-applicable runtime layers are omitted to keep the helper focused; use the integration form's connection test or the relevant board action for live diagnostics.
|
||||
|
||||
If one Docker endpoint is unavailable, Homarr reports that endpoint while continuing to show services from healthy endpoints. An unavailable endpoint is not treated as an empty Docker installation.
|
||||
|
||||
Each container row has an action menu with the following options:
|
||||
|
||||
- **View logs** - opens a dedicated logs page with a live terminal
|
||||
- **Start** - start a stopped container
|
||||
- **Stop** - stop a running container
|
||||
- **Restart** - restart a container
|
||||
- **Remove** - remove a container
|
||||
- **Add to Homarr** - create a bookmark app from the container
|
||||
|
||||
You can also search and filter containers by **container** or **image** name:
|
||||
|
||||

|
||||
|
||||
#### Viewing container logs
|
||||
|
||||
You can view the real-time logs of any container by selecting **View logs** from the row action menu.
|
||||
This opens a dedicated page with an xterm.js terminal that streams the container's log output.
|
||||
|
||||
#### CPU and Memory columns
|
||||
|
||||
The Docker management table supports optional **CPU usage** and **Memory usage** columns.
|
||||
These columns are hidden by default and can be toggled on from the table column visibility settings.
|
||||
|
||||
#### Choosing Docker environments in the widget
|
||||
|
||||
The Docker widget can show one or more configured Docker environments. Leave **Docker environments** empty to include every endpoint, which is also the default for existing widgets. Selecting one or more entries limits container and statistics requests to those endpoints.
|
||||
|
||||
#### Add apps from containers
|
||||
|
||||
Homarr also lets you add apps from containers. You can simply select all containers you want to add an app for and then click the `Add to Homarr` button.
|
||||
This will open a dialog where you can specify the web addresses for all of them:
|
||||
|
||||

|
||||
|
||||
Once you've changed the web addresses, click the `Add` button to add the apps to Homarr.
|
||||
They are then available in the app list and can be used as normally added apps.
|
||||
|
||||

|
||||
|
||||
### Container labels
|
||||
|
||||
`homarr.hide` excludes a container from the Docker Containers widget, tools page, and onboarding discovery whenever the
|
||||
label is present.
|
||||
|
||||
During first-run onboarding, Homarr can also discover apps, integrations, groups, and compatible widgets from
|
||||
`homarr.*` labels, with Homepage labels as a fallback. See the complete [Docker label reference](/docs/integrations/docker-labels).
|
||||
|
||||
### Security
|
||||
|
||||
Mounting docker sockets can be risky, as they permit full control over your docker service.
|
||||
As an example, a thread actor could abuse Homarr use the socket to start, stop or delete containers on your system.
|
||||
|
||||
Therefore we recommend the usage of a socket proxy, which can prohibit certain actions.
|
||||
A few examples include:
|
||||
|
||||
- https://github.com/linuxserver/docker-socket-proxy
|
||||
- https://github.com/Tecnativa/docker-socket-proxy
|
||||
|
||||
See documentation of the respective proxies on how to configure them.
|
||||
Homarr may behave in unexpected ways when you use proxies.
|
||||
|
||||
#### Permissions
|
||||
|
||||
Homarr needs the following permissions from the Docker API:
|
||||
|
||||
- Containers/Start
|
||||
- Containers/Stop
|
||||
- Containers/Restart
|
||||
- Containers/Remove
|
||||
|
||||
For socket proxies, you will need these permissions:
|
||||
|
||||
- `CONTAINERS=1`
|
||||
- `POST=1`
|
||||
|
||||
**Caution:** `POST` access is security critical as it provides extensive capabilities to modify your docker environment. Please leave it disabled if you're concerned about this.
|
||||
|
||||
As a workaround, you can use [LSIO's socket proxy](https://github.com/linuxserver/docker-socket-proxy) and set the following:
|
||||
|
||||
- ALLOW_START=1
|
||||
- ALLOW_STOP=1
|
||||
- ALLOW_RESTARTS=1
|
||||
|
||||
These will work even with `POST=0`.
|
||||
|
||||
You lose the ability to remove containers, but start, stop and restarts should work just fine.
|
||||
|
||||
#### Connecting to Docker via Socket Proxies
|
||||
|
||||
To connect to Docker via a socket proxy, you'll need to add these two environment variables in the compose file:
|
||||
|
||||
- `DOCKER_HOSTNAMES=<name of the socket proxy container>`
|
||||
- `DOCKER_PORTS=<socket proxy port, usually 2375>`
|
||||
|
||||
Refer: https://homarr.dev/docs/advanced/environment-variables/
|
||||
|
||||
You will also need to add Homarr to the network of your socket proxy. You can do it like this:
|
||||
|
||||
1. Add the network to your compose file (with appropriate changes):
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
socket-proxy:
|
||||
name: socket-proxy # <--- change this to the name of the network as set up by the socket proxy
|
||||
external: true
|
||||
```
|
||||
|
||||
2. Add the network to the homarr service in the compose file:
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
- socket-proxy
|
||||
```
|
||||
|
||||
3. Finally, if it is present, remove the default docker socket connection under `volumes` in the homarr service.
|
||||
Add Homarr to the proxy's Docker network and configure its service name and port with `DOCKER_HOSTNAMES` and
|
||||
`DOCKER_PORTS`.
|
||||
@@ -28,6 +28,8 @@ import { smartHomeExecuteAutomationWidget } from "@site/docs/widgets/smart-home-
|
||||
]}
|
||||
/>
|
||||
|
||||
Entity toggles and automation triggers send JSON requests to Home Assistant. A rejected action is shown as a failure.
|
||||
|
||||
### Adding the integration
|
||||
|
||||
<AddingIntegration />
|
||||
|
||||
@@ -8,7 +8,6 @@ import { IntegrationHeader } from "@site/src/components/integrations/header";
|
||||
import { IntegrationCapabilites } from "@site/src/components/integrations/widgets";
|
||||
import { AddingIntegration } from "@site/src/components/integrations/adding";
|
||||
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
|
||||
import { IconZoomQuestion, IconChartBar, IconSearch } from "@tabler/icons-react";
|
||||
import { icalIntegration } from ".";
|
||||
import { calendarWidget } from "@site/docs/widgets/calendar";
|
||||
|
||||
@@ -39,6 +38,5 @@ import { calendarWidget } from "@site/docs/widgets/calendar";
|
||||
]}
|
||||
/>
|
||||
|
||||
## Using the iCal integration
|
||||
|
||||
The iCal integration allows you to add external calendars to Homarr. Any calendar that provides a public iCal URL can be integrated, such as Google Calendar, Apple Calendar, or Outlook.
|
||||
The integration accepts any public iCal URL, including calendars published by Google Calendar, Apple Calendar, and
|
||||
Outlook.
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Immich"
|
||||
description: "Self-hosted photo and video management solution"
|
||||
description: "Self-hosted photo and video management."
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
@@ -14,7 +14,7 @@ import { immichServerStatsWidget } from "../../widgets/immich-server-stats";
|
||||
|
||||
<IntegrationHeader integration={immichIntegration} categories={["Photo server"]} />
|
||||
|
||||
### Widgets & Capabilities
|
||||
### Widgets and capabilities
|
||||
|
||||
<IntegrationCapabilites items={[{ widget: immichAlbumCarouselWidget }, { widget: immichServerStatsWidget }]} />
|
||||
|
||||
@@ -24,34 +24,16 @@ import { immichServerStatsWidget } from "../../widgets/immich-server-stats";
|
||||
|
||||
### Secrets
|
||||
|
||||
<IntegrationSecrets secrets={[{
|
||||
credentials: ['apiKey'],
|
||||
steps: [
|
||||
'Navigate to your Immich instance',
|
||||
'Open your account settings or navigate to https://YOUR_IMMICH/user-settings',
|
||||
'Scroll down to "API Keys"',
|
||||
'Click "New API Key"',
|
||||
'Enter a name, e.g. "Homarr"',
|
||||
(
|
||||
Create an API key under **Immich user settings → API Keys** with these permissions:
|
||||
|
||||
<span>
|
||||
`album.statistics`, `album.read`, `album.create`, `user.read`, `user.update`, `asset.read`, `asset.view`,
|
||||
`asset.download`, `asset.statistics`, `server.statistics`, and `server.about`.
|
||||
|
||||
Select the following permissions:{" "}
|
||||
<code>album.statistics</code>,{" "}
|
||||
<code>album.read</code>,{" "}
|
||||
<code>album.create</code>,{" "}
|
||||
<code>user.read</code>,{" "}
|
||||
<code>user.update</code>,{" "}
|
||||
<code>asset.read</code>,{" "}
|
||||
<code>asset.view</code>,{" "}
|
||||
<code>asset.download</code>,{" "}
|
||||
<code>asset.statistics</code>,{" "}
|
||||
<code>server.statistics</code>,{" "}
|
||||
<code>server.about</code>.
|
||||
|
||||
</span>
|
||||
|
||||
),
|
||||
'Create the integration in Homarr and copy the API key to there'
|
||||
]
|
||||
}]} />
|
||||
<IntegrationSecrets
|
||||
secrets={[
|
||||
{
|
||||
credentials: ["apiKey"],
|
||||
steps: ["Create the API key in Immich and copy its value into the Homarr integration."],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
@@ -1,55 +1,33 @@
|
||||
---
|
||||
title: "Kubernetes"
|
||||
description: "Kubernetes is a powerful container orchestration platform that automates the deployment, scaling, and management of containerized applications."
|
||||
description: "Read Kubernetes resources and cluster metrics in Homarr."
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
import { IntegrationHeader } from "@site/src/components/integrations/header";
|
||||
import { IntegrationCapabilites } from "@site/src/components/integrations/widgets";
|
||||
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
|
||||
import { IconBrandDocker, IconTool } from "@tabler/icons-react";
|
||||
import { kubernetesIntegration } from ".";
|
||||
|
||||
<IntegrationHeader integration={kubernetesIntegration} categories={["Containers"]} />
|
||||
|
||||
Homarr provides a user-friendly Kubernetes dashboard that offers an overview of your cluster’s resources in a clear and structured interface. It allows users to view key Kubernetes objects, including `Pods`, `Services`, `Ingresses`, `Nodes`, `ConfigMaps`, `Secrets`, `Namespaces`, and `Volumes`, as well as basic metrics when the Kubernetes Metrics Server is enabled.
|
||||
Homarr provides a read-only view of pods, services, ingresses, nodes, ConfigMaps, Secrets, namespaces, and volumes.
|
||||
Metrics Server is optional; without it, inventory and reserved capacity remain available but live CPU and memory do not.
|
||||
|
||||
Docker service discovery does not convert Kubernetes resources into Homarr apps or integrations. Kubernetes remains a separate, read-only operational view, so a cluster resource is never changed or linked automatically.
|
||||
## In-cluster access
|
||||
|
||||
:::warning[Read only]
|
||||
This integration is read-only, meaning Homarr does not modify or manage cluster resources but serves as an informational tool to enhance visibility into your Kubernetes environment.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before deploying Homarr in Kubernetes, ensure the following prerequisites are met:
|
||||
|
||||
- Kubernetes (Version >= 1.24.0)
|
||||
- Metrics Server ([install from here](https://github.com/kubernetes-sigs/metrics-server)) is optional. Without it, Homarr still shows cluster inventory, node status, and reserved capacity, and identifies live CPU and memory usage as unavailable.
|
||||
- RBAC Enabled (Required for Homarr Helm chart)
|
||||
|
||||
### Configuring RBAC in Helm Chart
|
||||
|
||||
To enable RBAC for Homarr, configure the Helm chart values file as follows:
|
||||
Enable RBAC in the Homarr Helm values:
|
||||
|
||||
```yaml
|
||||
rbac:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
:::tip[What Does rbac.enabled Do?]
|
||||
Enabling RBAC in the Helm chart creates the necessary Kubernetes Role-Based Access Control (RBAC) resources to allow Homarr to view various Kubernetes objects. These include:
|
||||
The chart creates the service account and read-only Role/ClusterRole bindings used by Homarr. Kubernetes 1.24 or newer is
|
||||
required.
|
||||
|
||||
- Service Account: A dedicated service account for Homarr.
|
||||
- Role & RoleBinding: Grants permissions within a specific namespace to list, watch, and get pods, services, secrets, configmaps, and more.
|
||||
- ClusterRole & ClusterRoleBinding: Extends the same permissions cluster-wide for additional flexibility.
|
||||
:::
|
||||
## Kubeconfig contexts
|
||||
|
||||
### Multiple Kubernetes contexts
|
||||
|
||||
When Homarr runs outside a cluster, set `KUBECONFIG` explicitly so Homarr loads the contexts from the referenced kubeconfig file or files. Mount the kubeconfig read-only and set the standard `KUBECONFIG` environment variable to its path inside the Homarr container:
|
||||
When Homarr runs outside the cluster, mount a kubeconfig read-only and set `KUBECONFIG` to its in-container path:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
@@ -60,20 +38,7 @@ services:
|
||||
KUBECONFIG: /app/config/kubeconfig
|
||||
```
|
||||
|
||||
The Kubernetes management pages include a context selector. The selected context is stored in the page URL, so each React Query cache entry and every API request remains context-specific. Resources with the same namespace and name in two contexts therefore remain separate.
|
||||
The management page exposes every configured context. An unavailable context does not hide healthy contexts; a context
|
||||
without Metrics Server is marked **Metrics unavailable**.
|
||||
|
||||
Context status is checked independently. If one context is unavailable, the selector still lists healthy contexts. A context is shown as **Metrics unavailable** when its Kubernetes API is reachable but Metrics Server is not; inventory remains available without live CPU and memory usage.
|
||||
|
||||
When Homarr runs inside Kubernetes without `KUBECONFIG`, it keeps using the in-cluster service account as the single default context.
|
||||
|
||||
### Homarr Dashboard Overview
|
||||
|
||||
Once deployed, Homarr provides a dashboard displaying Kubernetes metrics and resource information. The main page includes:
|
||||
|
||||
- Pods: Lists running and pending pods.
|
||||
- Services: Shows available services and their configurations.
|
||||
- Ingresses: Displays ingress rules and associated routes.
|
||||
- Nodes: Provides an overview of cluster nodes and their status.
|
||||
- ConfigMaps & Secrets: Lists configuration data and secrets used within the cluster.
|
||||
- Namespaces: Displays all available namespaces in the cluster.
|
||||
- Volumes: Shows persistent and ephemeral storage resources.
|
||||
Kubernetes resources are not converted into Homarr apps or integrations during Docker discovery.
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: "llama.cpp"
|
||||
description: "Connect Homarr to a llama.cpp llama-server to monitor your local LLM: health, loaded model, generation speed and request status."
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
import { IntegrationHeader } from "@site/src/components/integrations/header";
|
||||
import { IntegrationCapabilites } from "@site/src/components/integrations/widgets";
|
||||
import { AddingIntegration } from "@site/src/components/integrations/adding";
|
||||
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
|
||||
import { llamacppIntegration } from ".";
|
||||
import { llamacppWidget } from "@site/docs/widgets/llama-cpp";
|
||||
|
||||
<IntegrationHeader integration={llamacppIntegration} categories={["System Monitoring"]} />
|
||||
|
||||
The llama.cpp integration lets Homarr connect to a [llama-server](https://github.com/ggml-org/llama.cpp) instance so you can see the health of your local LLM, which model is loaded, and how fast it is generating — all from your dashboard.
|
||||
|
||||
### Widgets & Capabilities
|
||||
|
||||
<IntegrationCapabilites items={[{ widget: llamacppWidget }]} />
|
||||
|
||||
### Adding the integration
|
||||
|
||||
<AddingIntegration />
|
||||
|
||||
:::info URL configuration
|
||||
Use the root URL of your `llama-server`, for example `http://192.168.1.50:8080`. Homarr calls the `/health`, `/v1/models`, `/metrics` and `/slots` endpoints under that URL automatically.
|
||||
:::
|
||||
|
||||
:::tip Metrics
|
||||
Generation speed and token counters are read from the Prometheus endpoint at `/metrics`. Start `llama-server` with the `--metrics` flag so these values are available:
|
||||
|
||||
```shell
|
||||
llama-server --model /path/to/model.gguf --metrics
|
||||
```
|
||||
|
||||
Without `--metrics` the widget still shows health, model information, and active-request speed from `/slots`; metrics-backed counters and aggregate speed stay empty.
|
||||
:::
|
||||
|
||||
:::info Context and per-request speed
|
||||
Context (KV cache) usage and the in-flight request data are read from the `/slots` endpoint, which is available on every recent llama-server build and requires no extra flags. The per-request generation speed shown while a request is running is derived by tracking the request's decoded token count across polls, so it reflects the average speed of the request that is currently being generated.
|
||||
:::
|
||||
|
||||
### Secrets
|
||||
|
||||
llama-server does not require authentication by default. The integration only needs the URL of your server.
|
||||
|
||||
<IntegrationSecrets
|
||||
secrets={[
|
||||
{
|
||||
credentials: [],
|
||||
steps: [],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
@@ -0,0 +1,9 @@
|
||||
import { IntegrationDefinition } from "@site/src/types";
|
||||
|
||||
export const llamacppIntegration: IntegrationDefinition = {
|
||||
name: "llama.cpp",
|
||||
description:
|
||||
"Connect to a local llama.cpp llama-server to show model, throughput and request status on your dashboard.",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/llama-cpp.svg",
|
||||
path: "../../integrations/llama-cpp",
|
||||
};
|
||||
@@ -30,6 +30,8 @@ import { systemResourcesWidget } from "@site/docs/widgets/system-resources";
|
||||
]}
|
||||
/>
|
||||
|
||||
Disk temperatures are matched to filesystem partitions, including device names without the `/dev/` prefix.
|
||||
|
||||
### Adding the integration
|
||||
|
||||
<AddingIntegration />
|
||||
|
||||