From f767ff047f51984d0e902251673fdff0ad8a3ab4 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 11:23:52 -0700 Subject: [PATCH 01/89] Add HOMEPAGE_ALLOWED_HOSTS to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2f1e7d9e..8d9fe74b 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ services: image: ghcr.io/gethomepage/homepage:latest container_name: homepage environment: + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required when deploying via public URL PUID: 1000 # optional, your user id PGID: 1000 # optional, your group id ports: @@ -94,6 +95,7 @@ or docker run: ```bash docker run --name homepage \ + -e HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev \ -e PUID=1000 \ -e PGID=1000 \ -p 3000:3000 \ From 6ab57b7b14ba4eee6b57c7f81d9d8c64d5adc703 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 11:58:44 -0700 Subject: [PATCH 02/89] Update middleware.js --- src/middleware.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middleware.js b/src/middleware.js index b62bf823..f2011903 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -11,7 +11,7 @@ export function middleware(req) { if (!host || !allowedHosts.includes(host)) { // eslint-disable-next-line no-console console.error( - `Host validation failed for: ${host}. Hint: Set the HOMEPAGE_ALLOWED_HOSTS environment variable to allow requests from this host.`, + `Host validation failed for: ${host}. Hint: Set the HOMEPAGE_ALLOWED_HOSTS environment variable to allow requests from this host / port.`, ); return NextResponse.json({ error: "Host validation failed. See logs for more details." }, { status: 400 }); } From 471800d5bc17054830379171f391ffb03bb6e6a3 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 12:18:57 -0700 Subject: [PATCH 03/89] Update index.md --- docs/installation/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/index.md b/docs/installation/index.md index 22712015..0037b61e 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -29,4 +29,4 @@ You have a few options for deploying homepage, depending on your needs. We offer ### `HOMEPAGE_ALLOWED_HOSTS` -As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated list of allowed hosts that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for examples. +As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for examples. From 5629440acf167721b276812b02a34983221b0d4c Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 12:20:10 -0700 Subject: [PATCH 04/89] Fix: fix fiveColumns option (#4924) --- src/components/services/group.jsx | 2 +- tailwind.config.js | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/services/group.jsx b/src/components/services/group.jsx index 06fb83e1..433c0fa7 100644 --- a/src/components/services/group.jsx +++ b/src/components/services/group.jsx @@ -31,7 +31,7 @@ export default function ServicesGroup({ className={classNames( "services-group flex-1", layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4", - layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "", + layout?.style !== "row" && fiveColumns ? "2xl:basis-1/5" : "", groupPadding, isSubgroup ? "subgroup" : "", )} diff --git a/tailwind.config.js b/tailwind.config.js index 5d425938..a4fa5b53 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -30,10 +30,6 @@ module.exports = { 900: "rgb(var(--color-900) / )", }, }, - screens: { - "3xl": "1800px", - // => @media (min-width: 1800px) { ... } - }, }, }, plugins: [tailwindForms, tailwindScrollbars], From a090f98fab057b5274eecc57de463174af3081aa Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 11:23:52 -0700 Subject: [PATCH 05/89] Add HOMEPAGE_ALLOWED_HOSTS to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2f1e7d9e..8d9fe74b 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ services: image: ghcr.io/gethomepage/homepage:latest container_name: homepage environment: + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required when deploying via public URL PUID: 1000 # optional, your user id PGID: 1000 # optional, your group id ports: @@ -94,6 +95,7 @@ or docker run: ```bash docker run --name homepage \ + -e HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev \ -e PUID=1000 \ -e PGID=1000 \ -p 3000:3000 \ From 91518d972d35c392742d3aa24292c819fbb1bb70 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 12:18:57 -0700 Subject: [PATCH 06/89] Update index.md --- docs/installation/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/index.md b/docs/installation/index.md index 22712015..0037b61e 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -29,4 +29,4 @@ You have a few options for deploying homepage, depending on your needs. We offer ### `HOMEPAGE_ALLOWED_HOSTS` -As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated list of allowed hosts that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for examples. +As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for examples. From f7889eab276469be6889edb568ea1f1952653747 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 12:31:10 -0700 Subject: [PATCH 07/89] Clarify port --- docs/installation/docker.md | 4 ++-- docs/installation/source.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/installation/docker.md b/docs/installation/docker.md index 07c38071..cbe0fa32 100644 --- a/docs/installation/docker.md +++ b/docs/installation/docker.md @@ -38,7 +38,7 @@ services: - /path/to/config:/app/config # Make sure your local config directory exists - /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations, see alternative methods environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required when deploying via public URL + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev:1234 # required when deploying via public URL PUID: $PUID PGID: $PGID ``` @@ -46,7 +46,7 @@ services: ### With Docker Run ```bash -docker run -p 3000:3000 -e HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev -v /path/to/config:/app/config -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/gethomepage/homepage:latest +docker run -p 3000:3000 -e HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev:1234 -v /path/to/config:/app/config -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/gethomepage/homepage:latest ``` ### Using Environment Secrets diff --git a/docs/installation/source.md b/docs/installation/source.md index 38fcc2c5..f0f07140 100644 --- a/docs/installation/source.md +++ b/docs/installation/source.md @@ -21,7 +21,7 @@ If this is your first time starting, copy the `src/skeleton` directory to `confi Finally, run the server: ```bash -HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev pnpm start +HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev:1234 pnpm start ``` When updating homepage versions you will need to re-build the static files i.e. repeat the process above. From 0c7cac74ea29e24ea7fb0f0c023d9ed5f6039446 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 12:47:32 -0700 Subject: [PATCH 08/89] Update docker.md --- docs/installation/docker.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/installation/docker.md b/docs/installation/docker.md index cbe0fa32..f2498fab 100644 --- a/docs/installation/docker.md +++ b/docs/installation/docker.md @@ -16,7 +16,7 @@ services: - /path/to/config:/app/config # Make sure your local config directory exists - /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required when deploying via public URL + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port ``` ### Running as non-root @@ -38,7 +38,7 @@ services: - /path/to/config:/app/config # Make sure your local config directory exists - /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations, see alternative methods environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev:1234 # required when deploying via public URL + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port PUID: $PUID PGID: $PGID ``` @@ -46,7 +46,7 @@ services: ### With Docker Run ```bash -docker run -p 3000:3000 -e HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev:1234 -v /path/to/config:/app/config -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/gethomepage/homepage:latest +docker run -p 3000:3000 -e HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev -v /path/to/config:/app/config -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/gethomepage/homepage:latest ``` ### Using Environment Secrets From a2f4dd289b065812bcd129cbe9f563c9e19820c5 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 12:31:31 -0700 Subject: [PATCH 09/89] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d9fe74b..fff2dfa4 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ services: image: ghcr.io/gethomepage/homepage:latest container_name: homepage environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required when deploying via public URL + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port PUID: 1000 # optional, your user id PGID: 1000 # optional, your group id ports: From 8190260400a38df415411d493cf7003a411ccfb4 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:12:33 -0700 Subject: [PATCH 10/89] Fix: fix plex total size with larger libraries (#4933) --- src/widgets/plex/proxy.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/widgets/plex/proxy.js b/src/widgets/plex/proxy.js index 53931aca..c092ebaa 100644 --- a/src/widgets/plex/proxy.js +++ b/src/widgets/plex/proxy.js @@ -111,7 +111,8 @@ export default async function plexProxyHandler(req, res) { : `/library/sections/${library._attributes.key}/albums`; // music [status, apiData] = await fetchFromPlexAPI(libraryURL, widget); if (apiData && apiData.MediaContainer) { - const size = parseInt(apiData.MediaContainer._attributes.size, 10); + const sizeProp = apiData.MediaContainer._attributes["totalSize"] ? "totalSize" : "size"; + const size = parseInt(apiData.MediaContainer._attributes[sizeProp], 10); if (library._attributes.type === "movie") { movies += size; } else if (library._attributes.type === "show") { From a0dc8c9ccb9fb5d6435997e2ba6c4f2522698848 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:20:33 -0700 Subject: [PATCH 11/89] Fix: fix larger breakpoint (#4935) --- src/components/services/group.jsx | 2 +- src/styles/globals.css | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/services/group.jsx b/src/components/services/group.jsx index 433c0fa7..06fb83e1 100644 --- a/src/components/services/group.jsx +++ b/src/components/services/group.jsx @@ -31,7 +31,7 @@ export default function ServicesGroup({ className={classNames( "services-group flex-1", layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4", - layout?.style !== "row" && fiveColumns ? "2xl:basis-1/5" : "", + layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "", groupPadding, isSubgroup ? "subgroup" : "", )} diff --git a/src/styles/globals.css b/src/styles/globals.css index f671b1d0..27d6c2ff 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -2,6 +2,10 @@ @config '../../tailwind.config.js'; +@theme { + --breakpoint-3xl: 112rem; +} + /* The default border color has changed to `currentColor` in Tailwind CSS v4, so we've added these compatibility styles to make sure everything still From 66a8b1c21ec0dfdbc914b640fba14519aba1f1e1 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 15:11:37 -0700 Subject: [PATCH 12/89] Just remove hostname --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2c15dc6c..3c87c46f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,7 +56,6 @@ COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/ RUN apk add --no-cache su-exec -ENV HOSTNAME=:: ENV PORT=3000 EXPOSE $PORT From 6fca9e342d7dd69b320962e49438b41ee5a82de7 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 15:42:56 -0700 Subject: [PATCH 13/89] Bump version to 1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7603c18..065f97d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.0.0", + "version": "1.0.1", "private": true, "scripts": { "preinstall": "npx only-allow pnpm", From 90dd8e59674c7b11b881dab5e31b3282f5bc80d3 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 16:59:52 -0700 Subject: [PATCH 14/89] Update index.md --- docs/installation/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/index.md b/docs/installation/index.md index 0037b61e..dd8c18f3 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -29,4 +29,4 @@ You have a few options for deploying homepage, depending on your needs. We offer ### `HOMEPAGE_ALLOWED_HOSTS` -As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for examples. +As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated (no spaces) list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for examples. From dd8e9270f24c2d89c99419d5d8566956ba015ed7 Mon Sep 17 00:00:00 2001 From: shamoon Date: Fri, 14 Mar 2025 17:59:05 -0700 Subject: [PATCH 15/89] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 065f97d4..21653f19 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.0.1", + "version": "1.0.2", "private": true, "scripts": { "preinstall": "npx only-allow pnpm", From 8656b8e2f177e3d3b75a10f478f530d35a7c4f5a Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 17:34:43 -0700 Subject: [PATCH 16/89] Revert hostname change --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 3c87c46f..2c15dc6c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,6 +56,7 @@ COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/ RUN apk add --no-cache su-exec +ENV HOSTNAME=:: ENV PORT=3000 EXPOSE $PORT From 9b06212a92b67e692807320ab0286b0abe587a62 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 18:29:27 -0700 Subject: [PATCH 17/89] Fix: wrapping in bookmarks (#4945) --- src/components/bookmarks/item.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/bookmarks/item.jsx b/src/components/bookmarks/item.jsx index dd18bb71..4208f070 100644 --- a/src/components/bookmarks/item.jsx +++ b/src/components/bookmarks/item.jsx @@ -22,7 +22,7 @@ export default function Item({ bookmark, iconOnly = false }) { className={classNames( settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? "-" : ""}${settings.cardBlur}`, "text-left cursor-pointer transition-all rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10", - iconOnly ? "h-[60px] w-[60px] grid" : "block w-full h-8 mb-3", + iconOnly ? "h-[60px] w-[60px] grid" : "block w-full h-full mb-3", )} > {iconOnly ? ( From b5ac6175973b6fd612990819bf666662a064610c Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 21:09:46 -0700 Subject: [PATCH 18/89] Fix: fix kavita API body with key (#4948) --- src/widgets/kavita/proxy.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/widgets/kavita/proxy.js b/src/widgets/kavita/proxy.js index af29d048..842e4b87 100644 --- a/src/widgets/kavita/proxy.js +++ b/src/widgets/kavita/proxy.js @@ -14,7 +14,11 @@ async function login(widget, service) { const endpoint = "Account/login"; const api = widgets?.[widget.type]?.api; const loginUrl = new URL(formatApiCall(api, { endpoint, ...widget })); - const loginBody = {}; + const loginBody = { + username: "", + password: "", + apiKey: "", + }; if (widget.username && widget.password) { loginBody.username = widget.username; loginBody.password = widget.password; From 733a3140d13eefd966d5bbe12ff95e4ae02b2b86 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 21:16:20 -0700 Subject: [PATCH 19/89] Documentation: note komga api key --- docs/widgets/services/komga.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/widgets/services/komga.md b/docs/widgets/services/komga.md index fc76127f..e71ae19a 100644 --- a/docs/widgets/services/komga.md +++ b/docs/widgets/services/komga.md @@ -20,4 +20,5 @@ widget: url: http://komga.host.or.ip:port username: username password: password + key: komgaapikey # optional ``` From ea1375e57583941f0a0c112e36d9376e71ebbaaf Mon Sep 17 00:00:00 2001 From: brikim Date: Sat, 15 Mar 2025 00:02:13 -0500 Subject: [PATCH 20/89] Fix: correct units for speedtest tracker API v2 (#4950) Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com> --- src/widgets/speedtest/component.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widgets/speedtest/component.jsx b/src/widgets/speedtest/component.jsx index b4fbeaa6..e34f53ac 100644 --- a/src/widgets/speedtest/component.jsx +++ b/src/widgets/speedtest/component.jsx @@ -36,14 +36,14 @@ export default function Component({ service }) { From 97f4bcbdb0acfb5e9b98b4cdd23207b14d7bf9e6 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 22:35:47 -0700 Subject: [PATCH 21/89] Documentation: note disable ipv6 --- docs/troubleshooting/index.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/troubleshooting/index.md b/docs/troubleshooting/index.md index 1c72ba31..7f73f2dd 100644 --- a/docs/troubleshooting/index.md +++ b/docs/troubleshooting/index.md @@ -12,6 +12,7 @@ hide: - Check config/logs/homepage.log, on docker simply e.g. `docker logs homepage`. This may provide some insight into the reason for an error. - Check the browser error console, this can also sometimes provide useful information. - Consider setting the `ENV` variable `LOG_LEVEL` to `debug`. +- If certain widgets are failing when connecting to public APIs, consider [disabling IPv6](#disabling-ipv6). ## Service Widget Errors @@ -66,3 +67,24 @@ All service widgets work essentially the same, that is, homepage makes a proxied ## Missing custom icons If, after correctly adding and mapping your custom icons via the [Icons](../configs/services.md#icons) instructions, you are still unable to see your icons please try recreating your container. + +## Disabling IPv6 + +If you are having issues with certain widgets that are unable to reach public APIs (e.g. weather), you may need to disable IPv6 on your host machine. This can be done by adding the following to your `docker-compose.yml` file (or for docker run, the equivalent flag): + +```yaml +services: + homepage: + ... + sysctls: + - net.ipv6.conf.all.disable_ipv6=1 +``` + +or disable IPv6 for the docker network: + +```yaml +networks: + some_network: + driver: bridge + enable_ipv6: false +``` From 9d40b67d499a51dc91ebd4e72f664b7eace587d7 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 14 Mar 2025 22:51:07 -0700 Subject: [PATCH 22/89] Change: prefer IPv4 in docker image (#4954) --- Dockerfile | 4 ++-- src/middleware.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2c15dc6c..7963407c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,12 +56,12 @@ COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/ RUN apk add --no-cache su-exec -ENV HOSTNAME=:: +ENV HOSTNAME=0.0.0.0 ENV PORT=3000 EXPOSE $PORT HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \ - CMD wget --no-verbose --tries=1 --spider --no-check-certificate http://localhost:$PORT/api/healthcheck || exit 1 + CMD wget --no-verbose --tries=1 --spider --no-check-certificate http://127.0.0.1:$PORT/api/healthcheck || exit 1 ENTRYPOINT ["docker-entrypoint.sh"] CMD ["node", "server.js"] diff --git a/src/middleware.js b/src/middleware.js index f2011903..853a0094 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -4,7 +4,7 @@ export function middleware(req) { // Check the Host header, if HOMEPAGE_ALLOWED_HOSTS is set const host = req.headers.get("host"); const port = process.env.PORT || 3000; - let allowedHosts = [`localhost:${port}`]; + let allowedHosts = [`localhost:${port}`, `127.0.0.1:${port}`]; if (process.env.HOMEPAGE_ALLOWED_HOSTS) { allowedHosts = allowedHosts.concat(process.env.HOMEPAGE_ALLOWED_HOSTS.split(",")); } From 4761a56b3ddccdb7dcbd92a7be7adc3b0c0891f4 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 07:13:23 -0700 Subject: [PATCH 23/89] Remove reference to helm chart --- docs/installation/k8s.md | 79 ---------------------------------------- 1 file changed, 79 deletions(-) diff --git a/docs/installation/k8s.md b/docs/installation/k8s.md index cd9184ee..a8cdc8d6 100644 --- a/docs/installation/k8s.md +++ b/docs/installation/k8s.md @@ -3,85 +3,6 @@ title: Kubernetes Installation description: Install on Kubernetes --- -## Install with Helm - -There is an [unofficial helm chart](https://github.com/jameswynn/helm-charts/tree/main/charts/homepage) that creates all the necessary manifests, including the service account and RBAC entities necessary for service discovery. - -```sh -helm repo add jameswynn https://jameswynn.github.io/helm-charts -helm install homepage jameswynn/homepage -f values.yaml -``` - -The helm chart allows for all the configurations to be inlined directly in your `values.yaml`: - -```yaml -config: - bookmarks: - - Developer: - - Github: - - abbr: GH - href: https://github.com/ - services: - - My First Group: - - My First Service: - href: http://localhost/ - description: Homepage is awesome - - - My Second Group: - - My Second Service: - href: http://localhost/ - description: Homepage is the best - - - My Third Group: - - My Third Service: - href: http://localhost/ - description: Homepage is 😎 - widgets: - # show the kubernetes widget, with the cluster summary and individual nodes - - kubernetes: - cluster: - show: true - cpu: true - memory: true - showLabel: true - label: "cluster" - nodes: - show: true - cpu: true - memory: true - showLabel: true - - search: - provider: duckduckgo - target: _blank - kubernetes: - mode: cluster - settings: - -# The service account is necessary to allow discovery of other services -serviceAccount: - create: true - name: homepage - -# This enables the service account to access the necessary resources -enableRbac: true - -ingress: - main: - enabled: true - annotations: - # Example annotations to add Homepage to your Homepage! - gethomepage.dev/enabled: "true" - gethomepage.dev/name: "Homepage" - gethomepage.dev/description: "Dynamically Detected Homepage" - gethomepage.dev/group: "Dynamic" - gethomepage.dev/icon: "homepage.png" - hosts: - - host: homepage.example.com - paths: - - path: / - pathType: Prefix -``` - ## Install with Kubernetes Manifests If you don't want to use the unofficial Helm chart, you can also create your own Kubernetes manifest(s) and apply them with `kubectl apply -f filename.yaml`. From 16c1b2da9bcb2b78364377095c364f1ce4e92566 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 07:14:41 -0700 Subject: [PATCH 24/89] Enhancement: allow disabling host header checking (#4967) --- docs/installation/index.md | 6 +++++- src/middleware.js | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/installation/index.md b/docs/installation/index.md index dd8c18f3..38fb30ea 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -29,4 +29,8 @@ You have a few options for deploying homepage, depending on your needs. We offer ### `HOMEPAGE_ALLOWED_HOSTS` -As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated (no spaces) list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for examples. +As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated (no spaces) list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for more information. + +`localhost:3000` and the loopback address `127.0.0.1:3000` are always allowed, but you can add a domain or IP address to this list to allow access from that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.io:1234,gethomepage.dev`, etc. + +This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended. diff --git a/src/middleware.js b/src/middleware.js index 853a0094..a2b24f4a 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -4,11 +4,11 @@ export function middleware(req) { // Check the Host header, if HOMEPAGE_ALLOWED_HOSTS is set const host = req.headers.get("host"); const port = process.env.PORT || 3000; - let allowedHosts = [`localhost:${port}`, `127.0.0.1:${port}`]; + const allowAll = process.env.HOMEPAGE_ALLOWED_HOSTS === "*"; if (process.env.HOMEPAGE_ALLOWED_HOSTS) { allowedHosts = allowedHosts.concat(process.env.HOMEPAGE_ALLOWED_HOSTS.split(",")); } - if (!host || !allowedHosts.includes(host)) { + if (!allowAll && (!host || !allowedHosts.includes(host))) { // eslint-disable-next-line no-console console.error( `Host validation failed for: ${host}. Hint: Set the HOMEPAGE_ALLOWED_HOSTS environment variable to allow requests from this host / port.`, From 0d0f465e16942ea4cb849d49e89fe80c4bcd5a79 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 07:16:42 -0700 Subject: [PATCH 25/89] Update index.md --- docs/installation/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation/index.md b/docs/installation/index.md index 38fb30ea..cc5f7a07 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -31,6 +31,6 @@ You have a few options for deploying homepage, depending on your needs. We offer As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated (no spaces) list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for more information. -`localhost:3000` and the loopback address `127.0.0.1:3000` are always allowed, but you can add a domain or IP address to this list to allow access from that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.io:1234,gethomepage.dev`, etc. +`localhost:3000` and `127.0.0.1:3000` are always allowed, but you can add a domain or IP address to this list to allow access from that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.1.2:1234`, etc. This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended. From 133a0a65398515f28a38b2c65da94ce6fc34fede Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 07:31:15 -0700 Subject: [PATCH 26/89] Fix this --- src/middleware.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/middleware.js b/src/middleware.js index a2b24f4a..bb9fbea5 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -4,6 +4,7 @@ export function middleware(req) { // Check the Host header, if HOMEPAGE_ALLOWED_HOSTS is set const host = req.headers.get("host"); const port = process.env.PORT || 3000; + let allowedHosts = [`localhost:${port}`, `127.0.0.1:${port}`]; const allowAll = process.env.HOMEPAGE_ALLOWED_HOSTS === "*"; if (process.env.HOMEPAGE_ALLOWED_HOSTS) { allowedHosts = allowedHosts.concat(process.env.HOMEPAGE_ALLOWED_HOSTS.split(",")); From 607a14083eb3a17078af0266abf3c3f63d81b628 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 07:38:35 -0700 Subject: [PATCH 27/89] Fix: jellyfin handle empty episode numbers (#4970) --- src/widgets/emby/component.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/widgets/emby/component.jsx b/src/widgets/emby/component.jsx index b37b5018..41220e22 100644 --- a/src/widgets/emby/component.jsx +++ b/src/widgets/emby/component.jsx @@ -35,8 +35,8 @@ function generateStreamTitle(session, enableUser, showEpisodeNumber) { let streamTitle = ""; if (Type === "Episode" && showEpisodeNumber) { - const seasonStr = `S${ParentIndexNumber.toString().padStart(2, "0")}`; - const episodeStr = `E${IndexNumber.toString().padStart(2, "0")}`; + const seasonStr = ParentIndexNumber ? `S${ParentIndexNumber.toString().padStart(2, "0")}` : ""; + const episodeStr = IndexNumber ? `E${IndexNumber.toString().padStart(2, "0")}` : ""; streamTitle = `${SeriesName}: ${seasonStr} · ${episodeStr} - ${Name}`; } else { streamTitle = `${Name}${SeriesName ? ` - ${SeriesName}` : ""}`; From 964991781c3e710ca938ebc7c466b8e8cfb60348 Mon Sep 17 00:00:00 2001 From: Xavier Alexander Date: Sat, 15 Mar 2025 10:40:26 -0400 Subject: [PATCH 28/89] Documentation: add HOMEPAGE_ALLOWED_HOSTS to k8s docs (#4969) --- docs/installation/k8s.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/installation/k8s.md b/docs/installation/k8s.md index cd9184ee..2aeff8ec 100644 --- a/docs/installation/k8s.md +++ b/docs/installation/k8s.md @@ -302,6 +302,9 @@ spec: - name: homepage image: "ghcr.io/gethomepage/homepage:latest" imagePullPolicy: Always + env: + - name: HOMEPAGE_ALLOWED_HOSTS + value: gethomepage.dev # required, may need port ports: - name: http containerPort: 3000 From 6292a0709ce0aedcc03b479eb7b6863003c229f8 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 07:43:43 -0700 Subject: [PATCH 29/89] Bump version to 1.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 21653f19..02ebaf3f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.0.2", + "version": "1.0.3", "private": true, "scripts": { "preinstall": "npx only-allow pnpm", From 82b159bf14be385763c6d8981b52778d058ee144 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 09:29:35 -0700 Subject: [PATCH 30/89] Improve docs --- docs/installation/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installation/index.md b/docs/installation/index.md index cc5f7a07..093f43f0 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -29,8 +29,8 @@ You have a few options for deploying homepage, depending on your needs. We offer ### `HOMEPAGE_ALLOWED_HOSTS` -As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated (no spaces) list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for more information. +As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated (no spaces) list of allowed hosts (sometimes with the port) that can host your homepage install. See the [docker](docker.md) and [source](source.md) installation pages for more information. -`localhost:3000` and `127.0.0.1:3000` are always allowed, but you can add a domain or IP address to this list to allow access from that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.1.2:1234`, etc. +`localhost:3000` and `127.0.0.1:3000` are always allowed, but you can add a domain or IP address to this list to allow that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.1.2:1234`, etc. This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended. From b35dd80e8c4f74939a364f303a6838e504be7a2d Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 09:29:35 -0700 Subject: [PATCH 31/89] Improve docs --- docs/installation/index.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/installation/index.md b/docs/installation/index.md index cc5f7a07..3aaa4144 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -29,8 +29,10 @@ You have a few options for deploying homepage, depending on your needs. We offer ### `HOMEPAGE_ALLOWED_HOSTS` -As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated (no spaces) list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for more information. +As of v1.0 there is one required environment variable to access homepage via a URL other than `localhost`, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated (no spaces) list of allowed hosts (sometimes with the port) that can host your homepage install. See the [docker](docker.md) and [source](source.md) installation pages for more information. -`localhost:3000` and `127.0.0.1:3000` are always allowed, but you can add a domain or IP address to this list to allow access from that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.1.2:1234`, etc. +`localhost:3000` and `127.0.0.1:3000` are always allowed, but you can add a domain or IP address to this list to allow that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.1.2:1234`, etc. + +If you are seeing errors about host validation, check the homepage logs and ensure that the host as listed in the logs is in the `HOMEPAGE_ALLOWED_HOSTS` list. This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended. From 801ce479d8a392f91af7662fe46acb2cad936381 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:18:26 -0700 Subject: [PATCH 32/89] Add links to docs --- README.md | 2 +- docs/installation/docker.md | 4 ++-- docs/installation/k8s.md | 2 +- docs/installation/source.md | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fff2dfa4..090973bd 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ services: image: ghcr.io/gethomepage/homepage:latest container_name: homepage environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts PUID: 1000 # optional, your user id PGID: 1000 # optional, your group id ports: diff --git a/docs/installation/docker.md b/docs/installation/docker.md index f2498fab..6d9148dd 100644 --- a/docs/installation/docker.md +++ b/docs/installation/docker.md @@ -16,7 +16,7 @@ services: - /path/to/config:/app/config # Make sure your local config directory exists - /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts ``` ### Running as non-root @@ -38,7 +38,7 @@ services: - /path/to/config:/app/config # Make sure your local config directory exists - /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations, see alternative methods environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts PUID: $PUID PGID: $PGID ``` diff --git a/docs/installation/k8s.md b/docs/installation/k8s.md index 87112f0f..172b9b29 100644 --- a/docs/installation/k8s.md +++ b/docs/installation/k8s.md @@ -225,7 +225,7 @@ spec: imagePullPolicy: Always env: - name: HOMEPAGE_ALLOWED_HOSTS - value: gethomepage.dev # required, may need port + value: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts ports: - name: http containerPort: 3000 diff --git a/docs/installation/source.md b/docs/installation/source.md index f0f07140..6697eb92 100644 --- a/docs/installation/source.md +++ b/docs/installation/source.md @@ -25,3 +25,5 @@ HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev:1234 pnpm start ``` When updating homepage versions you will need to re-build the static files i.e. repeat the process above. + +See [HOMEPAGE_ALLOWED_HOSTS](index.md#homepage_allowed_hosts) for more information on this environment variable. From 6e9339b14c7022405e1528968213b817d4b88ea1 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 15:30:21 -0700 Subject: [PATCH 33/89] Chore: update minecraftstatuspinger to 1.2.2 (#4982) --- package.json | 2 +- pnpm-lock.yaml | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 02ebaf3f..2b8bd695 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "json-rpc-2.0": "^1.7.0", "luxon": "^3.5.0", "memory-cache": "^0.2.0", - "minecraftstatuspinger": "^1.2.1", + "minecraftstatuspinger": "^1.2.2", "next": "^15.1.7", "next-i18next": "^12.1.0", "ping": "^0.4.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6100111b..6b5c5910 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,8 +48,8 @@ importers: specifier: ^0.2.0 version: 0.2.0 minecraftstatuspinger: - specifier: ^1.2.1 - version: 1.2.1 + specifier: ^1.2.2 + version: 1.2.2 next: specifier: ^15.1.7 version: 15.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -101,10 +101,6 @@ importers: xml-js: specifier: ^1.6.11 version: 1.6.11 - optionalDependencies: - osx-temperature-sensor: - specifier: ^1.0.8 - version: 1.0.8 devDependencies: '@tailwindcss/forms': specifier: ^0.5.10 @@ -151,6 +147,10 @@ importers: typescript: specifier: ^5.7.3 version: 5.7.3 + optionalDependencies: + osx-temperature-sensor: + specifier: ^1.0.8 + version: 1.0.8 packages: @@ -1911,9 +1911,9 @@ packages: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - minecraftstatuspinger@1.2.1: - resolution: {integrity: sha512-Qo/3TzV0UeULbVyqMqS9sUPbNKGFK7U7as1xlS/xeXryQQEwitOz5SkVhVphY4fCTacl5a+E4VXiTq6TPKYDKw==} - engines: {node: '>=16.0.0'} + minecraftstatuspinger@1.2.2: + resolution: {integrity: sha512-3PDWcifjw6cliGnGqw0+nJVWWPOcpLDyNLh4D84vCNzPD2h9REbN5Ne11I//CMkIu5xJiIuyGwI44gyRYYbpuw==} + engines: {node: '>=14.0.0'} mini-svg-data-uri@1.4.4: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} @@ -3918,7 +3918,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.2(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.2)(eslint@9.21.0(jiti@2.4.2)): dependencies: debug: 3.2.7 optionalDependencies: @@ -3940,7 +3940,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.21.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.2(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.2)(eslint@9.21.0(jiti@2.4.2)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -4652,7 +4652,7 @@ snapshots: mimic-response@4.0.0: {} - minecraftstatuspinger@1.2.1: {} + minecraftstatuspinger@1.2.2: {} mini-svg-data-uri@1.4.4: {} From 65370a766851c4b888431dae1e2f08aa476df86b Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 16:23:29 -0700 Subject: [PATCH 34/89] Fix: fix Kubernetes stats in v1.0.0 (#4984) Co-authored-by: djeinstine <2105133+djeinstine@users.noreply.github.com> --- src/pages/api/kubernetes/stats/[...service].js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/pages/api/kubernetes/stats/[...service].js b/src/pages/api/kubernetes/stats/[...service].js index 029f5a1d..3c89dc39 100644 --- a/src/pages/api/kubernetes/stats/[...service].js +++ b/src/pages/api/kubernetes/stats/[...service].js @@ -71,8 +71,8 @@ export default async function handler(req, res) { let depMem = 0; let depCpu = 0; const podMetrics = await metricsApi - .getPodMetrics(namespace, pod.metadata.name) - .then((response) => response) + .getPodMetrics(namespace, pod.items) + .then((response) => response.items) .catch((err) => { // 404 generally means that the metrics have not been populated yet if (err.statusCode !== 404) { @@ -81,9 +81,11 @@ export default async function handler(req, res) { return null; }); if (podMetrics) { - podMetrics.containers.forEach((container) => { - depMem += parseMemory(container.usage.memory); - depCpu += parseCpu(container.usage.cpu); + podMetrics.forEach((metrics) => { + metrics.containers.forEach((container) => { + depMem += parseMemory(container.usage.memory); + depCpu += parseCpu(container.usage.cpu); + }); }); } return { From 7b7244211405d2661bde06317cc669cba12265c9 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 16:29:02 -0700 Subject: [PATCH 35/89] Update index.md --- docs/installation/index.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/installation/index.md b/docs/installation/index.md index 3aaa4144..d1f95dbe 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -29,10 +29,12 @@ You have a few options for deploying homepage, depending on your needs. We offer ### `HOMEPAGE_ALLOWED_HOSTS` -As of v1.0 there is one required environment variable to access homepage via a URL other than `localhost`, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated (no spaces) list of allowed hosts (sometimes with the port) that can host your homepage install. See the [docker](docker.md) and [source](source.md) installation pages for more information. +As of v1.0 there is one required environment variable to access homepage via a URL other than `localhost`, HOMEPAGE_ALLOWED_HOSTS. The setting helps prevent certain kinds of attacks when retrieving data from the homepage API proxy. -`localhost:3000` and `127.0.0.1:3000` are always allowed, but you can add a domain or IP address to this list to allow that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.1.2:1234`, etc. +The value is a comma-separated (no spaces) list of allowed hosts (sometimes with the port) that can host your homepage install. See the [docker](docker.md), [kubernetes](k8s.md) and [source](source.md) installation pages for more information about where / how to set the variable. -If you are seeing errors about host validation, check the homepage logs and ensure that the host as listed in the logs is in the `HOMEPAGE_ALLOWED_HOSTS` list. +`localhost:3000` and `127.0.0.1:3000` are always included, but you can add a domain or IP address to this list to allow that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.1.2:1234`, etc. + +If you are seeing errors about host validation, check the homepage logs and ensure that the host exactly as output in the logs is in the `HOMEPAGE_ALLOWED_HOSTS` list. This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended. From 564dfb7ce3983418dc44fd2d0d5183dc2c6e7bf7 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 15 Mar 2025 21:05:11 -0700 Subject: [PATCH 36/89] Add k3d ingress setting and HOMEPAGE_ALLOWED_HOSTS --- k3d/k3d-helm-values.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/k3d/k3d-helm-values.yaml b/k3d/k3d-helm-values.yaml index 60b6fe38..ad23f7e5 100644 --- a/k3d/k3d-helm-values.yaml +++ b/k3d/k3d-helm-values.yaml @@ -43,9 +43,14 @@ config: target: _blank kubernetes: mode: cluster + ingress: true docker: settings: +env: + - name: HOMEPAGE_ALLOWED_HOSTS + value: "homepage.k3d.localhost:8080" + serviceAccount: create: true name: homepage From 95507aab5428d2d483b6267595f33b482a65d818 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 16 Mar 2025 02:35:43 -0700 Subject: [PATCH 37/89] Change: re-enable k8s ingress by default (#4988) --- docs/configs/kubernetes.md | 4 ++-- k3d/k3d-helm-values.yaml | 1 - src/utils/kubernetes/ingress-list.js | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/configs/kubernetes.md b/docs/configs/kubernetes.md index 718095ef..49158e6b 100644 --- a/docs/configs/kubernetes.md +++ b/docs/configs/kubernetes.md @@ -25,13 +25,13 @@ To configure Kubernetes gateway-api, ingress or ingressRoute service discovery, Example settings: ```yaml -ingress: true # enable ingress only +ingress: true # default, enable ingress only ``` or ```yaml -ingress: true # enable ingress +ingress: true # default, enable ingress traefik: true # enable traefik ingressRoute gateway: true # enable gateway-api ``` diff --git a/k3d/k3d-helm-values.yaml b/k3d/k3d-helm-values.yaml index ad23f7e5..13bb9229 100644 --- a/k3d/k3d-helm-values.yaml +++ b/k3d/k3d-helm-values.yaml @@ -43,7 +43,6 @@ config: target: _blank kubernetes: mode: cluster - ingress: true docker: settings: diff --git a/src/utils/kubernetes/ingress-list.js b/src/utils/kubernetes/ingress-list.js index 2e44d4a1..49b5d667 100644 --- a/src/utils/kubernetes/ingress-list.js +++ b/src/utils/kubernetes/ingress-list.js @@ -8,7 +8,7 @@ const kc = getKubeConfig(); export default async function listIngress() { const networking = kc.makeApiClient(NetworkingV1Api); - const { ingress } = getKubernetes(); + const { ingress = true } = getKubernetes(); let ingressList = []; if (ingress) { From 9545757bb9b286ca7c35497ee58a2c27965084e8 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 16 Mar 2025 07:33:30 -0700 Subject: [PATCH 38/89] Fix: fix bookmark heights again (#4997) --- src/components/bookmarks/item.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/bookmarks/item.jsx b/src/components/bookmarks/item.jsx index 4208f070..c9b84eac 100644 --- a/src/components/bookmarks/item.jsx +++ b/src/components/bookmarks/item.jsx @@ -22,7 +22,7 @@ export default function Item({ bookmark, iconOnly = false }) { className={classNames( settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? "-" : ""}${settings.cardBlur}`, "text-left cursor-pointer transition-all rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10", - iconOnly ? "h-[60px] w-[60px] grid" : "block w-full h-full mb-3", + iconOnly ? "h-[60px] w-[60px] grid" : "block w-full mb-3", )} > {iconOnly ? ( From 5ea46881eedcbfc3899f039798e77293cb81e418 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 16 Mar 2025 08:32:27 -0700 Subject: [PATCH 39/89] Fix: re-add tailwind css safelist (#4999) --- src/pages/_app.jsx | 49 ++++++++++++++++++++++++++++++++++++++++++++++ tailwind.config.js | 44 ----------------------------------------- 2 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index bf46e3f6..052412d9 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -12,6 +12,55 @@ import { TabProvider } from "utils/contexts/tab"; import nextI18nextConfig from "../../next-i18next.config"; +// eslint-disable-next-line no-unused-vars +const tailwindSafelist = [ + // TODO: remove pending https://github.com/tailwindlabs/tailwindcss/pull/17147 + "backdrop-blur", + "backdrop-blur-sm", + "backdrop-blur-md", + "backdrop-blur-xl", + "backdrop-saturate-0", + "backdrop-saturate-50", + "backdrop-saturate-100", + "backdrop-saturate-150", + "backdrop-saturate-200", + "backdrop-brightness-0", + "backdrop-brightness-50", + "backdrop-brightness-75", + "backdrop-brightness-90", + "backdrop-brightness-95", + "backdrop-brightness-100", + "backdrop-brightness-105", + "backdrop-brightness-110", + "backdrop-brightness-125", + "backdrop-brightness-150", + "backdrop-brightness-200", + "grid-cols-1", + "md:grid-cols-1", + "md:grid-cols-2", + "lg:grid-cols-1", + "lg:grid-cols-2", + "lg:grid-cols-3", + "lg:grid-cols-4", + "lg:grid-cols-5", + "lg:grid-cols-6", + "lg:grid-cols-7", + "lg:grid-cols-8", + // for status + "bg-white", + "bg-black", + "dark:bg-white", + "bg-orange-400", + "dark:bg-orange-400", + // yep + "h-0 h-1 h-2 h-3 h-4 h-5 h-6 h-7 h-8 h-9 h-10 h-11 h-12 h-13 h-14 h-15 h-16 h-17 h-18 h-19 h-20 h-21 h-22 h-23 h-24 h-25 h-26 h-27 h-28 h-29 h-30 h-31 h-32 h-33 h-34 h-35 h-36 h-37 h-38 h-39 h-40 h-41 h-42 h-43 h-44 h-45 h-46 h-47 h-48 h-49 h-50 h-51 h-52 h-53 h-54 h-55 h-56 h-57 h-58 h-59 h-60 h-61 h-62 h-63 h-64 h-65 h-66 h-67 h-68 h-69 h-70 h-71 h-72 h-73 h-74 h-75 h-76 h-77 h-78 h-79 h-80 h-81 h-82 h-83 h-84 h-85 h-86 h-87 h-88 h-89 h-90 h-91 h-92 h-93 h-94 h-95 h-96", + "sm:h-0 sm:h-1 sm:h-2 sm:h-3 sm:h-4 sm:h-5 sm:h-6 sm:h-7 sm:h-8 sm:h-9 sm:h-10 sm:h-11 sm:h-12 sm:h-13 sm:h-14 sm:h-15 sm:h-16 sm:h-17 sm:h-18 sm:h-19 sm:h-20 sm:h-21 sm:h-22 sm:h-23 sm:h-24 sm:h-25 sm:h-26 sm:h-27 sm:h-28 sm:h-29 sm:h-30 sm:h-31 sm:h-32 sm:h-33 sm:h-34 sm:h-35 sm:h-36 sm:h-37 sm:h-38 sm:h-39 sm:h-40 sm:h-41 sm:h-42 sm:h-43 sm:h-44 sm:h-45 sm:h-46 sm:h-47 sm:h-48 sm:h-49 sm:h-50 sm:h-51 sm:h-52 sm:h-53 sm:h-54 sm:h-55 sm:h-56 sm:h-57 sm:h-58 sm:h-59 sm:h-60 sm:h-61 sm:h-62 sm:h-63 sm:h-64 sm:h-65 sm:h-66 sm:h-67 sm:h-68 sm:h-69 sm:h-70 sm:h-71 sm:h-72 sm:h-73 sm:h-74 sm:h-75 sm:h-76 sm:h-77 sm:h-78 sm:h-79 sm:h-80 sm:h-81 sm:h-82 sm:h-83 sm:h-84 sm:h-85 sm:h-86 sm:h-87 sm:h-88 sm:h-89 sm:h-90 sm:h-91 sm:h-92 sm:h-93 sm:h-94 sm:h-95 sm:h-96", + "md:h-0 md:h-1 md:h-2 md:h-3 md:h-4 md:h-5 md:h-6 md:h-7 md:h-8 md:h-9 md:h-10 md:h-11 md:h-12 md:h-13 md:h-14 md:h-15 md:h-16 md:h-17 md:h-18 md:h-19 md:h-20 md:h-21 md:h-22 md:h-23 md:h-24 md:h-25 md:h-26 md:h-27 md:h-28 md:h-29 md:h-30 md:h-31 md:h-32 md:h-33 md:h-34 md:h-35 md:h-36 md:h-37 md:h-38 md:h-39 md:h-40 md:h-41 md:h-42 md:h-43 md:h-44 md:h-45 md:h-46 md:h-47 md:h-48 md:h-49 md:h-50 md:h-51 md:h-52 md:h-53 md:h-54 md:h-55 md:h-56 md:h-57 md:h-58 md:h-59 md:h-60 md:h-61 md:h-62 md:h-63 md:h-64 md:h-65 md:h-66 md:h-67 md:h-68 md:h-69 md:h-70 md:h-71 md:h-72 md:h-73 md:h-74 md:h-75 md:h-76 md:h-77 md:h-78 md:h-79 md:h-80 md:h-81 md:h-82 md:h-83 md:h-84 md:h-85 md:h-86 md:h-87 md:h-88 md:h-89 md:h-90 md:h-91 md:h-92 md:h-93 md:h-94 md:h-95 md:h-96", + "lg:h-0 lg:h-1 lg:h-2 lg:h-3 lg:h-4 lg:h-5 lg:h-6 lg:h-7 lg:h-8 lg:h-9 lg:h-10 lg:h-11 lg:h-12 lg:h-13 lg:h-14 lg:h-15 lg:h-16 lg:h-17 lg:h-18 lg:h-19 lg:h-20 lg:h-21 lg:h-22 lg:h-23 lg:h-24 lg:h-25 lg:h-26 lg:h-27 lg:h-28 lg:h-29 lg:h-30 lg:h-31 lg:h-32 lg:h-33 lg:h-34 lg:h-35 lg:h-36 lg:h-37 lg:h-38 lg:h-39 lg:h-40 lg:h-41 lg:h-42 lg:h-43 lg:h-44 lg:h-45 lg:h-46 lg:h-47 lg:h-48 lg:h-49 lg:h-50 lg:h-51 lg:h-52 lg:h-53 lg:h-54 lg:h-55 lg:h-56 lg:h-57 lg:h-58 lg:h-59 lg:h-60 lg:h-61 lg:h-62 lg:h-63 lg:h-64 lg:h-65 lg:h-66 lg:h-67 lg:h-68 lg:h-69 lg:h-70 lg:h-71 lg:h-72 lg:h-73 lg:h-74 lg:h-75 lg:h-76 lg:h-77 lg:h-78 lg:h-79 lg:h-80 lg:h-81 lg:h-82 lg:h-83 lg:h-84 lg:h-85 lg:h-86 lg:h-87 lg:h-88 lg:h-89 lg:h-90 lg:h-91 lg:h-92 lg:h-93 lg:h-94 lg:h-95 lg:h-96", + "xl:h-0 xl:h-1 xl:h-2 xl:h-3 xl:h-4 xl:h-5 xl:h-6 xl:h-7 xl:h-8 xl:h-9 xl:h-10 xl:h-11 xl:h-12 xl:h-13 xl:h-14 xl:h-15 xl:h-16 xl:h-17 xl:h-18 xl:h-19 xl:h-20 xl:h-21 xl:h-22 xl:h-23 xl:h-24 xl:h-25 xl:h-26 xl:h-27 xl:h-28 xl:h-29 xl:h-30 xl:h-31 xl:h-32 xl:h-33 xl:h-34 xl:h-35 xl:h-36 xl:h-37 xl:h-38 xl:h-39 xl:h-40 xl:h-41 xl:h-42 xl:h-43 xl:h-44 xl:h-45 xl:h-46 xl:h-47 xl:h-48 xl:h-49 xl:h-50 xl:h-51 xl:h-52 xl:h-53 xl:h-54 xl:h-55 xl:h-56 xl:h-57 xl:h-58 xl:h-59 xl:h-60 xl:h-61 xl:h-62 xl:h-63 xl:h-64 xl:h-65 xl:h-66 xl:h-67 xl:h-68 xl:h-69 xl:h-70 xl:h-71 xl:h-72 xl:h-73 xl:h-74 xl:h-75 xl:h-76 xl:h-77 xl:h-78 xl:h-79 xl:h-80 xl:h-81 xl:h-82 xl:h-83 xl:h-84 xl:h-85 xl:h-86 xl:h-87 xl:h-88 xl:h-89 xl:h-90 xl:h-91 xl:h-92 xl:h-93 xl:h-94 xl:h-95 xl:h-96", + "2xl:h-0 2xl:h-1 2xl:h-2 2xl:h-3 2xl:h-4 2xl:h-5 2xl:h-6 2xl:h-7 2xl:h-8 2xl:h-9 2xl:h-10 2xl:h-11 2xl:h-12 2xl:h-13 2xl:h-14 2xl:h-15 2xl:h-16 2xl:h-17 2xl:h-18 2xl:h-19 2xl:h-20 2xl:h-21 2xl:h-22 2xl:h-23 2xl:h-24 2xl:h-25 2xl:h-26 2xl:h-27 2xl:h-28 2xl:h-29 2xl:h-30 2xl:h-31 2xl:h-32 2xl:h-33 2xl:h-34 2xl:h-35 2xl:h-36 2xl:h-37 2xl:h-38 2xl:h-39 2xl:h-40 2xl:h-41 2xl:h-42 2xl:h-43 2xl:h-44 2xl:h-45 2xl:h-46 2xl:h-47 2xl:h-48 2xl:h-49 2xl:h-50 2xl:h-51 2xl:h-52 2xl:h-53 2xl:h-54 2xl:h-55 2xl:h-56 2xl:h-57 2xl:h-58 2xl:h-59 2xl:h-60 2xl:h-61 2xl:h-62 2xl:h-63 2xl:h-64 2xl:h-65 2xl:h-66 2xl:h-67 2xl:h-68 2xl:h-69 2xl:h-70 2xl:h-71 2xl:h-72 2xl:h-73 2xl:h-74 2xl:h-75 2xl:h-76 2xl:h-77 2xl:h-78 2xl:h-79 2xl:h-80 2xl:h-81 2xl:h-82 2xl:h-83 2xl:h-84 2xl:h-85 2xl:h-86 2xl:h-87 2xl:h-88 2xl:h-89 2xl:h-90 2xl:h-91 2xl:h-92 2xl:h-93 2xl:h-94 2xl:h-95 2xl:h-96", +]; + function MyApp({ Component, pageProps }) { return ( Date: Sun, 16 Mar 2025 13:12:20 -0700 Subject: [PATCH 40/89] Fix: fix custom quicklaunch search without search widget (#5003) --- src/pages/api/search/searchSuggestion.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/pages/api/search/searchSuggestion.js b/src/pages/api/search/searchSuggestion.js index 7d5d250b..dbe072ea 100644 --- a/src/pages/api/search/searchSuggestion.js +++ b/src/pages/api/search/searchSuggestion.js @@ -1,5 +1,6 @@ import { searchProviders } from "components/widgets/search/search"; +import { getSettings } from "utils/config/config"; import cachedFetch from "utils/proxy/cached-fetch"; import { widgetsFromConfig } from "utils/config/widget-helpers"; @@ -12,8 +13,16 @@ export default async function handler(req, res) { const widgets = await widgetsFromConfig(); const searchWidget = widgets.find((w) => w.type === "search"); - provider.url = searchWidget.options.url; - provider.suggestionUrl = searchWidget.options.suggestionUrl; + if (searchWidget) { + provider.url = searchWidget.options.url; + provider.suggestionUrl = searchWidget.options.suggestionUrl; + } else { + const settings = getSettings(); + if (settings.quicklaunch && settings.quicklaunch.provider === "custom") { + provider.url = settings.quicklaunch.url; + provider.suggestionUrl = settings.quicklaunch.suggestionUrl; + } + } } if (!provider.suggestionUrl) { From 59cd5564f8f82b84406d3dceb87210a7a9720dd8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 16 Mar 2025 14:12:30 -0700 Subject: [PATCH 41/89] New Crowdin translations by GitHub Action (#4985) Co-authored-by: Crowdin Bot --- public/locales/eu/common.json | 208 +++++++++++++++++----------------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/public/locales/eu/common.json b/public/locales/eu/common.json index c122d734..f935b928 100644 --- a/public/locales/eu/common.json +++ b/public/locales/eu/common.json @@ -85,16 +85,16 @@ "ping": { "error": "Error", "ping": "Ping", - "down": "Down", - "up": "Up", + "down": "Behera", + "up": "Gora", "not_available": "Not Available" }, "siteMonitor": { "http_status": "HTTP status", "error": "Error", - "response": "Response", - "down": "Down", - "up": "Up", + "response": "Erantzuna", + "down": "Behera", + "up": "Gora", "not_available": "Not Available" }, "emby": { @@ -102,8 +102,8 @@ "transcoding": "Transcoding", "bitrate": "Bit-tasa", "no_active": "No Active Streams", - "movies": "Movies", - "series": "Series", + "movies": "Filmak", + "series": "Serieak", "episodes": "Episodes", "songs": "Abestiak" }, @@ -115,39 +115,39 @@ "unknown": "Ezezaguna" }, "evcc": { - "pv_power": "Production", - "battery_soc": "Battery", - "grid_power": "Grid", - "home_power": "Consumption", - "charge_power": "Charger", + "pv_power": "Produkzioak", + "battery_soc": "Bateria", + "grid_power": "Sarea", + "home_power": "Kontsumoa", + "charge_power": "Kargagailua", "kilowatt": "kW" }, "flood": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, "freshrss": { - "subscriptions": "Subscriptions", - "unread": "Unread" + "subscriptions": "Harpidetzak", + "unread": "Irakurri gabe" }, "fritzbox": { "connectionStatus": "Status", "connectionStatusUnconfigured": "Unconfigured", - "connectionStatusConnecting": "Connecting", + "connectionStatusConnecting": "Konektatzen", "connectionStatusAuthenticating": "Authenticating", "connectionStatusPendingDisconnect": "Pending Disconnect", "connectionStatusDisconnecting": "Disconnecting", - "connectionStatusDisconnected": "Disconnected", - "connectionStatusConnected": "Connected", + "connectionStatusDisconnected": "Deskonektatuta", + "connectionStatusConnected": "Konektatuta", "uptime": "Uptime", "maxDown": "Max. Down", "maxUp": "Max. Up", - "down": "Down", - "up": "Up", + "down": "Behera", + "up": "Gora", "received": "Received", - "sent": "Sent", + "sent": "Bidalita", "externalIPAddress": "Ext. IP", "externalIPv6Address": "Ext. IPv6", "externalIPv6Prefix": "Ext. IPv6-Prefix" @@ -189,7 +189,7 @@ "plex": { "streams": "Active Streams", "albums": "Albums", - "movies": "Movies", + "movies": "Filmak", "tv": "TV Shows" }, "sabnzbd": { @@ -199,18 +199,18 @@ }, "rutorrent": { "active": "Active", - "upload": "Upload", - "download": "Download" + "upload": "Kargatu", + "download": "Jeitsierak" }, "transmission": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, "qbittorrent": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, @@ -223,8 +223,8 @@ "invalid": "Invalid" }, "deluge": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, @@ -233,15 +233,15 @@ "cachemissbytes": "Cache Miss Bytes" }, "downloadstation": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, "sonarr": { "wanted": "Wanted", "queued": "Queued", - "series": "Series", + "series": "Serieak", "queue": "Queue", "unknown": "Ezezaguna" }, @@ -249,7 +249,7 @@ "wanted": "Wanted", "missing": "Missing", "queued": "Queued", - "movies": "Movies", + "movies": "Filmak", "queue": "Queue", "unknown": "Ezezaguna" }, @@ -285,7 +285,7 @@ }, "netalertx": { "total": "Guztira", - "connected": "Connected", + "connected": "Konektatuta", "new_devices": "New Devices", "down_alerts": "Down Alerts" }, @@ -302,8 +302,8 @@ "latency": "Latency" }, "speedtest": { - "upload": "Upload", - "download": "Download", + "upload": "Kargatu", + "download": "Jeitsierak", "ping": "Ping" }, "portainer": { @@ -315,7 +315,7 @@ "download": "Downloaded", "nondownload": "Non-Downloaded", "read": "Read", - "unread": "Unread", + "unread": "Irakurri gabe", "downloadedread": "Downloaded & Read", "downloadedunread": "Downloaded & Unread", "nondownloadedread": "Non-Downloaded & Read", @@ -405,7 +405,7 @@ "medusa": { "wanted": "Wanted", "queued": "Queued", - "series": "Series" + "series": "Serieak" }, "minecraft": { "players": "Jokalariak", @@ -416,7 +416,7 @@ }, "miniflux": { "read": "Read", - "unread": "Unread" + "unread": "Irakurri gabe" }, "authentik": { "users": "Users", @@ -523,15 +523,15 @@ "up_to_date": "Up to Date", "child_bridges": "Child Bridges", "child_bridges_status": "{{ok}}/{{total}}", - "up": "Up", + "up": "Gora", "pending": "Pending", - "down": "Down" + "down": "Behera" }, "healthchecks": { "new": "New", - "up": "Up", + "up": "Gora", "grace": "In Grace Period", - "down": "Down", + "down": "Behera", "paused": "Paused", "status": "Status", "last_ping": "Last Ping", @@ -646,8 +646,8 @@ "load": "Load Avg", "memory": "Mem Usage", "wanStatus": "WAN Status", - "up": "Up", - "down": "Down", + "up": "Gora", + "down": "Behera", "temp": "Temp", "disk": "Disk Usage", "wanIP": "WAN IP" @@ -660,7 +660,7 @@ }, "immich": { "users": "Users", - "photos": "Photos", + "photos": "Argazkiak", "videos": "Videos", "storage": "Storage" }, @@ -672,14 +672,14 @@ "m": "m" }, "atsumeru": { - "series": "Series", + "series": "Serieak", "archives": "Archives", "chapters": "Chapters", "categories": "Categories" }, "komga": { "libraries": "Libraries", - "series": "Series", + "series": "Serieak", "books": "Books" }, "diskstation": { @@ -688,13 +688,13 @@ "volumeAvailable": "Available" }, "mylar": { - "series": "Series", - "issues": "Issues", + "series": "Serieak", + "issues": "Arazoak", "wanted": "Wanted" }, "photoprism": { "albums": "Albums", - "photos": "Photos", + "photos": "Argazkiak", "videos": "Videos", "people": "People" }, @@ -772,7 +772,7 @@ "books": "Books", "authors": "Authors", "categories": "Categories", - "series": "Series" + "series": "Serieak" }, "jdownloader": { "downloadCount": "Queue", @@ -781,7 +781,7 @@ "downloadSpeed": "Speed" }, "kavita": { - "seriesCount": "Series", + "seriesCount": "Serieak", "totalFiles": "Files" }, "azuredevops": { @@ -801,8 +801,8 @@ "status": "Status", "online": "Online", "offline": "Offline", - "name": "Name", - "map": "Map", + "name": "Izena", + "map": "Mapa", "currentPlayers": "Current players", "players": "Jokalariak", "maxPlayers": "Max players", @@ -819,10 +819,10 @@ "recipes": "Recipes", "users": "Users", "categories": "Categories", - "tags": "Tags" + "tags": "Etiketak" }, "openmediavault": { - "downloading": "Downloading", + "downloading": "Deskargatzen", "total": "Guztira", "running": "Running", "stopped": "Stopped", @@ -832,8 +832,8 @@ "openwrt": { "uptime": "Uptime", "cpuLoad": "CPU Load Avg (5m)", - "up": "Up", - "down": "Down", + "up": "Gora", + "down": "Behera", "bytesTx": "Transmitted", "bytesRx": "Received" }, @@ -846,9 +846,9 @@ "sitesDown": "Sites Down", "paused": "Paused", "notyetchecked": "Not Yet Checked", - "up": "Up", + "up": "Gora", "seemsdown": "Seems Down", - "down": "Down", + "down": "Behera", "unknown": "Ezezaguna" }, "calendar": { @@ -856,7 +856,7 @@ "physicalRelease": "Physical release", "digitalRelease": "Digital release", "noEventsToday": "No events for today!", - "noEventsFound": "No events found" + "noEventsFound": "Ez da gertaerarik aurkitu." }, "romm": { "platforms": "Platforms", @@ -868,7 +868,7 @@ }, "mailcow": { "domains": "Domains", - "mailboxes": "Mailboxes", + "mailboxes": "Gutunontziak", "mails": "Mails", "storage": "Storage" }, @@ -877,14 +877,14 @@ "criticals": "Criticals" }, "plantit": { - "events": "Events", - "plants": "Plants", - "photos": "Photos", + "events": "Ekitaldiak", + "plants": "Landareak", + "photos": "Argazkiak", "species": "Species" }, "gitea": { - "notifications": "Notifications", - "issues": "Issues", + "notifications": "Jakinarazpenak", + "issues": "Arazoak", "pulls": "Pull Requests" }, "stash": { @@ -894,34 +894,34 @@ "playDuration": "Time Watched", "sceneSize": "Scenes Size", "sceneDuration": "Scenes Duration", - "images": "Images", - "imageSize": "Images Size", + "images": "Irudia", + "imageSize": "Irudiaren tamaina", "galleries": "Galleries", "performers": "Performers", "studios": "Studios", - "movies": "Movies", - "tags": "Tags", + "movies": "Filmak", + "tags": "Etiketak", "oCount": "O Count" }, "tandoor": { "users": "Users", "recipes": "Recipes", - "keywords": "Keywords" + "keywords": "Hitz gakoak" }, "homebox": { - "items": "Items", + "items": "Elementuak", "totalWithWarranty": "With Warranty", "locations": "Locations", - "labels": "Labels", + "labels": "Etiketak", "users": "Users", - "totalValue": "Total Value" + "totalValue": "Guztira" }, "crowdsec": { "alerts": "Alerts", "bans": "Bans" }, "wgeasy": { - "connected": "Connected", + "connected": "Konektatuta", "enabled": "Enabled", "disabled": "Disabled", "total": "Guztira" @@ -934,8 +934,8 @@ }, "myspeed": { "ping": "Ping", - "download": "Download", - "upload": "Upload" + "download": "Jeitsierak", + "upload": "Kargatu" }, "stocks": { "stocks": "Stocks", @@ -951,23 +951,23 @@ }, "linkwarden": { "links": "Links", - "collections": "Collections", - "tags": "Tags" + "collections": "Bildumak", + "tags": "Etiketak" }, "zabbix": { "unclassified": "Not classified", "information": "Informazioa", - "warning": "Warning", - "average": "Average", - "high": "High", + "warning": "Abisua", + "average": "Batez besteko", + "high": "Altua", "disaster": "Disaster" }, "lubelogger": { "vehicle": "Vehicle", - "vehicles": "Vehicles", + "vehicles": "Ibilgailuak", "serviceRecords": "Service Records", - "reminders": "Reminders", - "nextReminder": "Next Reminder", + "reminders": "Oroigarriak", + "nextReminder": "Hurrengo abisua", "none": "None" }, "vikunja": { @@ -977,7 +977,7 @@ "tasksInProgress": "Tasks In Progress" }, "headscale": { - "name": "Name", + "name": "Izena", "address": "Address", "last_seen": "Last Seen", "status": "Status", @@ -985,10 +985,10 @@ "offline": "Offline" }, "beszel": { - "name": "Name", + "name": "Izena", "systems": "Systems", - "up": "Up", - "down": "Down", + "up": "Gora", + "down": "Behera", "paused": "Paused", "pending": "Pending", "status": "Status", @@ -999,23 +999,23 @@ "network": "NET" }, "argocd": { - "apps": "Apps", - "synced": "Synced", + "apps": "Aplikazioak", + "synced": "Sinkronizatuta", "outOfSync": "Out Of Sync", "healthy": "Osasuntsu", "degraded": "Degraded", "progressing": "Progressing", "missing": "Missing", - "suspended": "Suspended" + "suspended": "Etenda" }, "spoolman": { "loading": "Loading" }, "gitlab": { - "groups": "Groups", - "issues": "Issues", + "groups": "Taldeak", + "issues": "Arazoak", "merges": "Merge Requests", - "projects": "Projects" + "projects": "Proiektuak" }, "apcups": { "status": "Status", @@ -1024,11 +1024,11 @@ "timeleft": "Time Left" }, "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", + "bookmarks": "Laster-markak", + "favorites": "Gogokoak", + "archived": "Artxibatuta", "highlights": "Highlights", - "lists": "Lists", - "tags": "Tags" + "lists": "Zerrendak", + "tags": "Etiketak" } } From 6fbe080b280acfde81c75eb2574a56dcd0fd97d9 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 16 Mar 2025 14:13:12 -0700 Subject: [PATCH 42/89] Bump version to 1.0.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b8bd695..44fc1b35 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.0.3", + "version": "1.0.4", "private": true, "scripts": { "preinstall": "npx only-allow pnpm", From 934ad3a6f1b8630f9752f29a2646242f2cff74f8 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 16 Mar 2025 15:33:38 -0700 Subject: [PATCH 43/89] Fix: remove medusa widget trailing slash (#5007) --- src/widgets/medusa/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/medusa/widget.js b/src/widgets/medusa/widget.js index 3619d16b..fbfd8af2 100644 --- a/src/widgets/medusa/widget.js +++ b/src/widgets/medusa/widget.js @@ -1,7 +1,7 @@ import genericProxyHandler from "utils/proxy/handlers/generic"; const widget = { - api: "{url}/api/v1/{key}/{endpoint}/", + api: "{url}/api/v1/{key}/{endpoint}", proxyHandler: genericProxyHandler, mappings: { From b4dc53c7c0e07ba4eaa59a4b3dd698ae11fa1f32 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 16 Mar 2025 20:09:34 -0700 Subject: [PATCH 44/89] Feature: allow disable ipv6 in proxy, refactor cacheFetch to use proxy (#5011) --- docs/troubleshooting/index.md | 13 ++------- src/pages/api/releases.js | 4 +-- src/pages/api/search/searchSuggestion.js | 4 +-- src/pages/api/widgets/openmeteo.js | 4 +-- src/pages/api/widgets/openweathermap.js | 4 +-- src/pages/api/widgets/stocks.js | 4 +-- src/pages/api/widgets/weather.js | 4 +-- src/utils/config/widget-helpers.js | 29 ++++++++++---------- src/utils/proxy/cached-fetch.js | 25 ----------------- src/utils/proxy/http.js | 35 +++++++++++++++++++++--- 10 files changed, 61 insertions(+), 65 deletions(-) delete mode 100644 src/utils/proxy/cached-fetch.js diff --git a/docs/troubleshooting/index.md b/docs/troubleshooting/index.md index 7f73f2dd..81550439 100644 --- a/docs/troubleshooting/index.md +++ b/docs/troubleshooting/index.md @@ -70,7 +70,9 @@ If, after correctly adding and mapping your custom icons via the [Icons](../conf ## Disabling IPv6 -If you are having issues with certain widgets that are unable to reach public APIs (e.g. weather), you may need to disable IPv6 on your host machine. This can be done by adding the following to your `docker-compose.yml` file (or for docker run, the equivalent flag): +If you are having issues with certain widgets that are unable to reach public APIs (e.g. weather), in certain setups you may need to disable IPv6. You can set the environment variable `HOMEPAGE_PROXY_DISABLE_IPV6` to `true` to disable IPv6 for the homepage proxy. + +Alternatively, you can use the `sysctls` option in your docker-compose file to disable IPv6 for the homepage container completely: ```yaml services: @@ -79,12 +81,3 @@ services: sysctls: - net.ipv6.conf.all.disable_ipv6=1 ``` - -or disable IPv6 for the docker network: - -```yaml -networks: - some_network: - driver: bridge - enable_ipv6: false -``` diff --git a/src/pages/api/releases.js b/src/pages/api/releases.js index f15930c2..372ace9d 100644 --- a/src/pages/api/releases.js +++ b/src/pages/api/releases.js @@ -1,4 +1,4 @@ -import cachedFetch from "utils/proxy/cached-fetch"; +import { cachedRequest } from "utils/proxy/http"; import createLogger from "utils/logger"; const logger = createLogger("releases"); @@ -6,7 +6,7 @@ const logger = createLogger("releases"); export default async function handler(req, res) { const releasesURL = "https://api.github.com/repos/gethomepage/homepage/releases"; try { - return res.send(await cachedFetch(releasesURL, 5)); + return res.send(await cachedRequest(releasesURL, 5)); } catch (e) { logger.error(`Error checking GitHub releases: ${e}`); return res.send([]); diff --git a/src/pages/api/search/searchSuggestion.js b/src/pages/api/search/searchSuggestion.js index dbe072ea..209d1f2c 100644 --- a/src/pages/api/search/searchSuggestion.js +++ b/src/pages/api/search/searchSuggestion.js @@ -1,7 +1,7 @@ import { searchProviders } from "components/widgets/search/search"; import { getSettings } from "utils/config/config"; -import cachedFetch from "utils/proxy/cached-fetch"; +import { cachedRequest } from "utils/proxy/http"; import { widgetsFromConfig } from "utils/config/widget-helpers"; export default async function handler(req, res) { @@ -29,5 +29,5 @@ export default async function handler(req, res) { return res.json([query, []]); // Responde with the same array format but with no suggestions. } - return res.send(await cachedFetch(`${provider.suggestionUrl}${encodeURIComponent(query)}`, 5, "Mozilla/5.0")); + return res.send(await cachedRequest(`${provider.suggestionUrl}${encodeURIComponent(query)}`, 5, "Mozilla/5.0")); } diff --git a/src/pages/api/widgets/openmeteo.js b/src/pages/api/widgets/openmeteo.js index e63847b4..28f2e4f0 100644 --- a/src/pages/api/widgets/openmeteo.js +++ b/src/pages/api/widgets/openmeteo.js @@ -1,9 +1,9 @@ -import cachedFetch from "utils/proxy/cached-fetch"; +import { cachedRequest } from "utils/proxy/http"; export default async function handler(req, res) { const { latitude, longitude, units, cache, timezone } = req.query; const degrees = units === "metric" ? "celsius" : "fahrenheit"; const timezeone = timezone ?? "auto"; const apiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=sunrise,sunset¤t_weather=true&temperature_unit=${degrees}&timezone=${timezeone}`; - return res.send(await cachedFetch(apiUrl, cache)); + return res.send(await cachedRequest(apiUrl, cache)); } diff --git a/src/pages/api/widgets/openweathermap.js b/src/pages/api/widgets/openweathermap.js index 089ee804..3bdc7a82 100644 --- a/src/pages/api/widgets/openweathermap.js +++ b/src/pages/api/widgets/openweathermap.js @@ -1,4 +1,4 @@ -import cachedFetch from "utils/proxy/cached-fetch"; +import { cachedRequest } from "utils/proxy/http"; import { getSettings } from "utils/config/config"; import { getPrivateWidgetOptions } from "utils/config/widget-helpers"; @@ -26,5 +26,5 @@ export default async function handler(req, res) { const apiUrl = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${apiKey}&units=${units}&lang=${lang}`; - return res.send(await cachedFetch(apiUrl, cache)); + return res.send(await cachedRequest(apiUrl, cache)); } diff --git a/src/pages/api/widgets/stocks.js b/src/pages/api/widgets/stocks.js index 3941a773..4e9f3f55 100644 --- a/src/pages/api/widgets/stocks.js +++ b/src/pages/api/widgets/stocks.js @@ -1,4 +1,4 @@ -import cachedFetch from "utils/proxy/cached-fetch"; +import { cachedRequest } from "utils/proxy/http"; import { getSettings } from "utils/config/config"; import createLogger from "utils/logger"; @@ -60,7 +60,7 @@ export default async function handler(req, res) { const apiUrl = `https://finnhub.io/api/v1/quote?symbol=${ticker}&token=${apiKey}`; // Finnhub free accounts allow up to 60 calls/minute // https://finnhub.io/pricing - const { c, dp } = await cachedFetch(apiUrl, cache || 1); + const { c, dp } = await cachedRequest(apiUrl, cache || 1); logger.debug("Finnhub API response for %s: %o", ticker, { c, dp }); // API sometimes returns 200, but values returned are `null` diff --git a/src/pages/api/widgets/weather.js b/src/pages/api/widgets/weather.js index 9d0451ce..9e63e48d 100644 --- a/src/pages/api/widgets/weather.js +++ b/src/pages/api/widgets/weather.js @@ -1,4 +1,4 @@ -import cachedFetch from "utils/proxy/cached-fetch"; +import { cachedRequest } from "utils/proxy/http"; import { getSettings } from "utils/config/config"; import { getPrivateWidgetOptions } from "utils/config/widget-helpers"; @@ -26,5 +26,5 @@ export default async function handler(req, res) { const apiUrl = `http://api.weatherapi.com/v1/current.json?q=${latitude},${longitude}&key=${apiKey}&lang=${lang}`; - return res.send(await cachedFetch(apiUrl, cache)); + return res.send(await cachedRequest(apiUrl, cache)); } diff --git a/src/utils/config/widget-helpers.js b/src/utils/config/widget-helpers.js index 3b1355d6..93f71194 100644 --- a/src/utils/config/widget-helpers.js +++ b/src/utils/config/widget-helpers.js @@ -56,21 +56,22 @@ export async function cleanWidgetGroups(widgets) { export async function getPrivateWidgetOptions(type, widgetIndex) { const widgets = await widgetsFromConfig(); - const privateOptions = widgets.map((widget) => { - const { index, url, username, password, key, apiKey } = widget.options; + const privateOptions = + widgets.map((widget) => { + const { index, url, username, password, key, apiKey } = widget.options; - return { - type: widget.type, - options: { - index, - url, - username, - password, - key, - apiKey, - }, - }; - }); + return { + type: widget.type, + options: { + index, + url, + username, + password, + key, + apiKey, + }, + }; + }) || {}; return type !== undefined && widgetIndex !== undefined ? privateOptions.find((o) => o.type === type && o.options.index === parseInt(widgetIndex, 10))?.options diff --git a/src/utils/proxy/cached-fetch.js b/src/utils/proxy/cached-fetch.js deleted file mode 100644 index ae3c4610..00000000 --- a/src/utils/proxy/cached-fetch.js +++ /dev/null @@ -1,25 +0,0 @@ -import cache from "memory-cache"; - -const defaultDuration = 5; - -export default async function cachedFetch(url, duration, ua) { - const cached = cache.get(url); - - // eslint-disable-next-line no-param-reassign - duration = duration || defaultDuration; - - if (cached) { - return cached; - } - - // wrapping text in JSON.parse to handle utf-8 issues - const options = {}; - if (ua) { - options.headers = { - "User-Agent": ua, - }; - } - const data = await fetch(url, options).then((res) => res.json()); - cache.put(url, data, duration * 1000 * 60); - return data; -} diff --git a/src/utils/proxy/http.js b/src/utils/proxy/http.js index 3743515b..f8d2dcce 100644 --- a/src/utils/proxy/http.js +++ b/src/utils/proxy/http.js @@ -3,6 +3,7 @@ import { createUnzip, constants as zlibConstants } from "node:zlib"; import { http, https } from "follow-redirects"; +import cache from "memory-cache"; import { addCookieToJar, setCookieHeader } from "./cookie-jar"; import { sanitizeErrorURL } from "./api-helpers"; @@ -81,20 +82,46 @@ export function httpRequest(url, params) { return handleRequest(http, url, params); } +export async function cachedRequest(url, duration = 5, ua = "homepage") { + const cached = cache.get(url); + + if (cached) { + return cached; + } + + const options = { + headers: { + "User-Agent": ua, + Accept: "application/json", + }, + }; + let [, , data] = await httpProxy(url, options); + if (Buffer.isBuffer(data)) { + try { + data = JSON.parse(Buffer.from(data).toString()); + } catch (e) { + logger.debug("Error parsing cachedRequest data for %s: %s %s", url, Buffer.from(data).toString(), e); + data = Buffer.from(data).toString(); + } + } + cache.put(url, data, duration * 1000 * 60); + return data; +} + export async function httpProxy(url, params = {}) { const constructedUrl = new URL(url); + const disableIpv6 = process.env.HOMEPAGE_PROXY_DISABLE_IPV6 === "true"; + const agentOptions = disableIpv6 ? { family: 4, autoSelectFamily: false } : {}; let request = null; if (constructedUrl.protocol === "https:") { request = httpsRequest(constructedUrl, { - agent: new https.Agent({ - rejectUnauthorized: false, - }), + agent: new https.Agent({ ...agentOptions, rejectUnauthorized: false }), ...params, }); } else { request = httpRequest(constructedUrl, { - agent: new http.Agent(), + agent: new http.Agent(agentOptions), ...params, }); } From de9c015f7fef10d7cbc9b951b7462982026fe781 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 17 Mar 2025 07:24:12 -0700 Subject: [PATCH 45/89] Fix: fix minecraft players after move to minecraftstatuspinger (#5017) --- src/widgets/minecraft/proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/minecraft/proxy.js b/src/widgets/minecraft/proxy.js index ab01ae12..5f238acb 100644 --- a/src/widgets/minecraft/proxy.js +++ b/src/widgets/minecraft/proxy.js @@ -18,7 +18,7 @@ export default async function minecraftProxyHandler(req, res) { res.status(200).send({ version: pingResponse.status.version.name, online: true, - players: pingResponse.status.players.online, + players: pingResponse.status.players, }); } catch (e) { if (e) logger.error(e); From 071b5275bc848a25492a9ca1e69004c6bc7d84e8 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 17 Mar 2025 11:19:27 -0700 Subject: [PATCH 46/89] Documentation: fix install page buttons --- docs/assets/custom.css | 3 --- docs/installation/index.md | 8 ++++---- docs/stylesheets/extra.css | 10 ++++++++++ 3 files changed, 14 insertions(+), 7 deletions(-) delete mode 100644 docs/assets/custom.css diff --git a/docs/assets/custom.css b/docs/assets/custom.css deleted file mode 100644 index f959128e..00000000 --- a/docs/assets/custom.css +++ /dev/null @@ -1,3 +0,0 @@ -.md-typeset[data-page-id="landing"] .md-header-anchor { - display: none; -} diff --git a/docs/installation/index.md b/docs/installation/index.md index d1f95dbe..f082845b 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -13,16 +13,16 @@ You have a few options for deploying homepage, depending on your needs. We offer
-:simple-docker: [  Install on Docker :octicons-arrow-right-24:](docker.md) +[:simple-docker:   Install on Docker :octicons-arrow-right-24:](docker.md) { .card } -:simple-kubernetes: [  Install on Kubernetes :octicons-arrow-right-24:](k8s.md) +[:simple-kubernetes:   Install on Kubernetes :octicons-arrow-right-24:](k8s.md) { .card } -:simple-unraid: [  Install on UNRAID :octicons-arrow-right-24:](unraid.md) +[:simple-unraid:   Install on UNRAID :octicons-arrow-right-24:](unraid.md) { .card } -:simple-nextdotjs: [  Building from source :octicons-arrow-right-24:](source.md) +[:simple-nextdotjs:   Building from source :octicons-arrow-right-24:](source.md) { .card }
diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index eb1ddd25..7f299d2e 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -286,3 +286,13 @@ body[data-md-color-scheme="default"] { .md-tabs__link { transform: translateZ(0); } + +.grid.cards .card { + padding: 0; +} + +.grid.cards .card a { + display: block; + padding: 0.8rem; + text-decoration: none; +} From 8d20f22932a3e22aec4f8e4baac90c1557317828 Mon Sep 17 00:00:00 2001 From: morliont Date: Mon, 17 Mar 2025 19:30:01 +0100 Subject: [PATCH 47/89] Enhancement: support dynamic list rendering in custom api widget (#5012) Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com> --- docs/widgets/services/customapi.md | 52 +++++++++++++++++++- src/widgets/customapi/component.jsx | 74 +++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/docs/widgets/services/customapi.md b/docs/widgets/services/customapi.md index 0deb8294..79345008 100644 --- a/docs/widgets/services/customapi.md +++ b/docs/widgets/services/customapi.md @@ -138,7 +138,15 @@ You can manipulate data with the following tools `remap`, `scale`, `prefix` and prefix: "$" ``` -## List View +## Display Options + +The widget supports different display modes that can be set using the `display` property. + +### Block View (Default) + +The default display mode is `block`, which shows fields in a block format. + +### List View You can change the default block view to a list view by setting the `display` option to `list`. @@ -169,6 +177,48 @@ The list view can optionally display an additional field next to the primary fie format: date ``` +### Dynamic List View + +To display a list of items from an array in the API response, set the `display` property to `dynamic-list` and configure the `mappings` object with the following properties: + +```yaml +widget: + type: customapi + url: https://example.com/api/servers + display: dynamic-list + mappings: + items: data # optional, the path to the array in the API response. Omit this option if the array is at the root level + name: id # required, field in each item to use as the item name (left side) + label: ip_address # required, field in each item to use as the item label (right side) + limit: 5 # optional, limit the number of items to display + target: https://example.com/server/{id} # optional, makes items clickable with template support +``` + +This configuration would work with an API that returns a response like: + +```json +{ + "data": [ + { "id": "server1", "name": "Server 1", "ip_address": "192.168.0.1" }, + { "id": "server2", "name": "Server 2", "ip_address": "192.168.0.2" } + ] +} +``` + +The widget would display a list with two items: + +- "Server 1" on the left and "192.168.0.1" on the right, clickable to "https://example.com/server/server1" +- "Server 2" on the left and "192.168.0.2" on the right, clickable to "https://example.com/server/server2" + +For nested fields in the items, you can use dot notation: + +```yaml +mappings: + items: data.results.servers + name: details.id + label: details.name +``` + ## Custom Headers Pass custom headers using the `headers` option, for example: diff --git a/src/widgets/customapi/component.jsx b/src/widgets/customapi/component.jsx index 6d0a63cd..3a6ac069 100644 --- a/src/widgets/customapi/component.jsx +++ b/src/widgets/customapi/component.jsx @@ -1,8 +1,10 @@ import { useTranslation } from "next-i18next"; import Container from "components/services/widget/container"; import Block from "components/services/widget/block"; +import classNames from "classnames"; import useWidgetAPI from "utils/proxy/use-widget-api"; +import * as shvl from "utils/config/shvl"; function getValue(field, data) { let value = data; @@ -165,6 +167,16 @@ export default function Component({ service }) { if (!customData) { switch (display) { + case "dynamic-list": + return ( + +
+
+
Loading...
+
+
+
+ ); case "list": return ( @@ -196,6 +208,68 @@ export default function Component({ service }) { } switch (display) { + case "dynamic-list": + let listItems = customData; + if (mappings.items) listItems = shvl.get(customData, mappings.items, null); + let error; + if (!listItems || !Array.isArray(listItems)) { + error = { message: "Unable to find items" }; + } + const name = mappings.name; + const label = mappings.label; + if (!name || !label) { + error = { message: "Name and label properties are required" }; + } + if (error) { + return ; + } + + const target = mappings.target; + if (mappings.limit && parseInt(mappings.limit, 10) > 0) { + listItems.splice(mappings.limit); + } + + return ( + +
+ {listItems.length === 0 ? ( +
+
No items found
+
+ ) : ( + listItems.map((item, index) => { + const itemName = shvl.get(item, name, ""); + const itemLabel = shvl.get(item, label, ""); + const itemUrl = target ? target.replace(/\{([^}]+)\}/g, (_, key) => item[key] || "") : null; + const className = + "bg-theme-200/50 dark:bg-theme-900/20 rounded-sm m-1 flex-1 flex flex-row items-center justify-between p-1 text-xs"; + + return itemUrl ? ( + +
{itemName}
+
+
{itemLabel}
+
+
+ ) : ( +
+
{itemName}
+
+
{itemLabel}
+
+
+ ); + }) + )} +
+
+ ); case "list": return ( From dca23e85478437775842a99a069922d15277ca4d Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 17 Mar 2025 11:47:55 -0700 Subject: [PATCH 48/89] Enhancement: support shvl syntax for customapi fields (#5020) --- docs/widgets/services/customapi.md | 28 +++++++++++++--------------- src/widgets/customapi/component.jsx | 5 +++++ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/docs/widgets/services/customapi.md b/docs/widgets/services/customapi.md index 79345008..f11e21a5 100644 --- a/docs/widgets/services/customapi.md +++ b/docs/widgets/services/customapi.md @@ -22,15 +22,10 @@ widget: - field: key # needs to be YAML string or object label: Field 1 format: text # optional - defaults to text - - field: # needs to be YAML string or object - path: - to: key2 + - field: path.to.key2 format: number # optional - defaults to text label: Field 2 - - field: # needs to be YAML string or object - path: - to: - another: key3 + - field: path.to.another.key3 label: Field 3 format: percent # optional - defaults to text - field: key # needs to be YAML string or object @@ -49,9 +44,7 @@ widget: label: Field 6 format: text additionalField: # optional - field: - hourly: - time: other key + field: hourly.time.key color: theme # optional - defaults to "". Allowed values: `["theme", "adaptive", "black", "white"]`. format: date # optional - field: key @@ -103,9 +96,16 @@ mappings: label: Name - field: status # Alive label: Status - - field: - origin: name # Earth (C-137) + - field: origin.name # Earth (C-137) label: Origin + - field: locations.1.name # Citadel of Ricks + label: Location +``` + +Note that older versions of the widget accepted fields as a yaml object, which is still supported. E.g.: + +```yaml +mappings: - field: locations: 1: name # Citadel of Ricks @@ -170,9 +170,7 @@ The list view can optionally display an additional field next to the primary fie - any: true # will map all other values to: Unknown additionalField: - field: - hourly: - time: key + field: hourly.time.key color: theme format: date ``` diff --git a/src/widgets/customapi/component.jsx b/src/widgets/customapi/component.jsx index 3a6ac069..b8147caa 100644 --- a/src/widgets/customapi/component.jsx +++ b/src/widgets/customapi/component.jsx @@ -16,6 +16,11 @@ function getValue(field, data) { return value; } + // shvl is easier, everything else is kept for backwards compatibility. + if (typeof field === "string") { + return shvl.get(data, field, null); + } + while (typeof lastField === "object") { key = Object.keys(lastField)[0] ?? null; From 42f1ed3c473e0bf6400fd481d472c4aec3ad8697 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 17 Mar 2025 11:49:35 -0700 Subject: [PATCH 49/89] Update customapi.md --- docs/widgets/services/customapi.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/widgets/services/customapi.md b/docs/widgets/services/customapi.md index f11e21a5..70947a10 100644 --- a/docs/widgets/services/customapi.md +++ b/docs/widgets/services/customapi.md @@ -19,7 +19,7 @@ widget: requestBody: # optional, can be string or object, see below display: # optional, default to block, see below mappings: - - field: key # needs to be YAML string or object + - field: key label: Field 1 format: text # optional - defaults to text - field: path.to.key2 @@ -28,13 +28,13 @@ widget: - field: path.to.another.key3 label: Field 3 format: percent # optional - defaults to text - - field: key # needs to be YAML string or object + - field: key label: Field 4 format: date # optional - defaults to text locale: nl # optional dateStyle: long # optional - defaults to "long". Allowed values: `["full", "long", "medium", "short"]`. timeStyle: medium # optional - Allowed values: `["full", "long", "medium", "short"]`. - - field: key # needs to be YAML string or object + - field: key label: Field 5 format: relativeDate # optional - defaults to text locale: nl # optional From ce0102eb6fa9cf2835f221d216ac2a919fcf3ba4 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 17 Mar 2025 12:25:10 -0700 Subject: [PATCH 50/89] Enhancement: support full width container (#5021) --- docs/configs/settings.md | 8 ++++++++ src/pages/index.jsx | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/configs/settings.md b/docs/configs/settings.md index 93aa7f8f..d56d0f75 100644 --- a/docs/configs/settings.md +++ b/docs/configs/settings.md @@ -254,6 +254,14 @@ layout: columns: 4 ``` +### Full Width + +You can make homepage take up the entire window width by adding: + +```yaml +fullWidth: true +``` + ### Five Columns You can add a fifth column to services (when `style: columns` which is default) by adding: diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 5055a22b..51f5ead3 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -417,7 +417,12 @@ function Home({ initialSettings }) {