diff --git a/Dockerfile b/Dockerfile index 2c15dc6c0..7963407c3 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/README.md b/README.md index fff2dfa4d..090973bd1 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/configs/kubernetes.md b/docs/configs/kubernetes.md index 718095efc..49158e6bb 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/docs/installation/docker.md b/docs/installation/docker.md index f2498fab8..6d9148dde 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/index.md b/docs/installation/index.md index db5968535..3aaa41449 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -27,16 +27,12 @@ You have a few options for deploying homepage, depending on your needs. We offer -## Environment Variables - ### `HOMEPAGE_ALLOWED_HOSTS` -Required. +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 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. +`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. -### `HOMEPAGE_PROXY_DISABLE_IPV6` +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. -Optional. - -In certain environments, you may need to disable IPv6 for the proxy to work correctly. Set this environment variable to `true` to disable IPv6. +This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended. diff --git a/docs/installation/k8s.md b/docs/installation/k8s.md index cd9184ee6..172b9b295 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`. @@ -302,6 +223,9 @@ spec: - name: homepage image: "ghcr.io/gethomepage/homepage:latest" imagePullPolicy: Always + env: + - name: HOMEPAGE_ALLOWED_HOSTS + 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 f0f07140b..6697eb92c 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. diff --git a/docs/troubleshooting/index.md b/docs/troubleshooting/index.md index 91e0dc1b3..908e6ce2c 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). ## Disabling IPv6 @@ -70,3 +71,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 +``` diff --git a/docs/widgets/services/komga.md b/docs/widgets/services/komga.md index fc76127fe..e71ae19a2 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 ``` diff --git a/k3d/k3d-helm-values.yaml b/k3d/k3d-helm-values.yaml index 60b6fe381..13bb9229b 100644 --- a/k3d/k3d-helm-values.yaml +++ b/k3d/k3d-helm-values.yaml @@ -46,6 +46,10 @@ config: docker: settings: +env: + - name: HOMEPAGE_ALLOWED_HOSTS + value: "homepage.k3d.localhost:8080" + serviceAccount: create: true name: homepage diff --git a/package.json b/package.json index 21653f190..2b8bd6957 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", @@ -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 6100111b7..6b5c5910f 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: {} diff --git a/public/locales/eu/common.json b/public/locales/eu/common.json index c122d734c..f935b928d 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" } } diff --git a/src/components/bookmarks/item.jsx b/src/components/bookmarks/item.jsx index 4208f0701..c9b84eac5 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 ? ( diff --git a/src/middleware.js b/src/middleware.js index f20119031..bb9fbea52 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -4,11 +4,12 @@ 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}`]; + 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.`, diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index bf46e3f63..052412d90 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 ( 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 { diff --git a/src/pages/api/search/searchSuggestion.js b/src/pages/api/search/searchSuggestion.js index 7d5d250bb..dbe072ea7 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) { diff --git a/src/utils/kubernetes/ingress-list.js b/src/utils/kubernetes/ingress-list.js index 2e44d4a1f..49b5d6671 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) { diff --git a/src/widgets/emby/component.jsx b/src/widgets/emby/component.jsx index b37b50187..41220e227 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}` : ""}`; diff --git a/src/widgets/speedtest/component.jsx b/src/widgets/speedtest/component.jsx index b4fbeaa6a..e34f53aca 100644 --- a/src/widgets/speedtest/component.jsx +++ b/src/widgets/speedtest/component.jsx @@ -36,14 +36,14 @@ export default function Component({ service }) { diff --git a/tailwind.config.js b/tailwind.config.js index a4fa5b53e..4cc6f130d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -33,48 +33,4 @@ module.exports = { }, }, plugins: [tailwindForms, tailwindScrollbars], - // always include these in build as classes are dynamically constructed - safelist: [ - "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", - { - pattern: /h-([0-96])/, - variants: ["sm", "md", "lg", "xl", "2xl"], - }, - ], };