|
8 | 8 | ## Contents |
9 | 9 |
|
10 | 10 | - [Config not saving](#config-not-saving) |
11 | | -- [Unable to write conf.yml: EACCES: permission denied](#unable-to-write-confyml-eacces-permission-denied) |
| 11 | + - [Permission denied or read-only filesystem](#permission-denied-or-read-only-filesystem-eacces-erofs) |
| 12 | + - [Kubernetes ConfigMap mount is read-only](#kubernetes-configmap-mount-is-read-only) |
| 13 | + - [SELinux or AppArmor blocks the write](#selinux-or-apparmor-blocks-the-write) |
| 14 | + - [Backup step fails so save aborts](#backup-step-fails-so-save-aborts) |
| 15 | + - [Save button is missing or returns 403](#save-button-is-missing-or-returns-403-forbidden) |
| 16 | + - [Save unavailable on Vercel, Netlify or other static hosts](#save-unavailable-on-vercel-netlify-or-other-static-hosts) |
| 17 | + - [/config-manager/save returns 404 or HTML](#config-managersave-returns-404-or-html) |
| 18 | + - ["Invalid filename" when saving a sub-page](#invalid-filename-when-saving-a-sub-page) |
| 19 | + - ["Cannot save to an external URL"](#cannot-save-to-an-external-url) |
| 20 | + - [Saved successfully but the UI shows the old config](#saved-successfully-but-the-ui-shows-the-old-config) |
| 21 | + - [Container crashes or restart loop after saving](#container-crashes-or-restart-loop-after-saving-310-and-311-only) |
| 22 | + - [Intentionally read-only mode](#intentionally-read-only-mode) |
12 | 23 | - [Refused to Connect in Web Content View](#refused-to-connect-in-modal-or-workspace-view) |
13 | 24 | - [404 On Static Hosting](#404-on-static-hosting) |
14 | 25 | - [404 from Mobile Home Screen](#404-after-launch-from-mobile-home-screen) |
|
24 | 35 | - [High CPU or RAM Usage on Startup](#high-cpu-or-ram-usage-on-startup) |
25 | 36 | - [Heap limit Allocation failed](#ineffective-mark-compacts-near-heap-limit-allocation-failed) |
26 | 37 | - [Command failed with signal "SIGKILL"](#command-failed-with-signal-sigkill) |
27 | | -- [Container Crashes or Restart Loop After Saving Config](#container-crashes-or-restart-loop-after-saving-config) |
28 | 38 | - [Auth Validation Error: "should be object"](#auth-validation-error-should-be-object) |
29 | 39 | - [App Not Starting After Update to 2.0.4](#app-not-starting-after-update-to-204) |
30 | 40 | - [Keycloak Redirect Error](#keycloak-redirect-error) |
31 | 41 | - [OIDC or Keycloak failure on numeric client IDs](#oidc-or-keycloak-failure-on-numeric-client-ids) |
32 | 42 | - [Mount Type Mismatch](#mount-type-mismatch) |
33 | | -- [Permission Denied Saving Config](#permission-denied-saving-config) |
34 | | -- [Config not Saving on Vercel / Netlify / CDN](#config-not-saving-on-vercel--netlify--cdn) |
35 | | -- [Config Not Updating](#config-not-updating) |
36 | | -- [Config Still not Updating](#config-still-not-updating) |
37 | 43 | - [Styles and Assets not Updating](#styles-and-assets-not-updating) |
38 | 44 | - [DockerHub toomanyrequests](#dockerhub-toomanyrequests) |
39 | 45 | - [Old image tags fail to pull](#old-image-tags-fail-to-pull) |
|
65 | 71 |
|
66 | 72 | ## Config not saving |
67 | 73 |
|
68 | | -### Possible Issue 1: Unable to call save endpoint from CDN/static server |
69 | | -If you're running Dashy using a static hosting provider (like Vercel), then there is no Node server, and so the save config action will not work via the UI. |
70 | | -You'll instead need to copy the YAML after making your changes, and paste that into your `conf.yml` directly. If you've connected Vercel to git, then these changes will take effect automatically, once you commit your changes. |
71 | | -Look here for more information: [https://dashy.to/docs/deployment#deploy-to-cloud-service](https://dashy.to/docs/deployment#deploy-to-cloud-service) |
| 74 | +There should be an error message, explaining the reason the config save failed. First check [browser console](#how-to-open-browser-console) (<kbd>F12</kbd> --> Console), and then your server-side logs in the terminal. Then, see the following sections for solutions to each possible error. |
72 | 75 |
|
73 | | -If you're running on Netlify, there are some cloud functions which take care of all the server endpoints (like status checking), so these will work as expected. |
| 76 | +<a id="config-not-saving-on-vercel--netlify--cdn"></a> |
| 77 | +<a id="possible-issue-1-unable-to-call-save-endpoint-from-cdnstatic-server"></a> |
| 78 | +<a id="unable-to-write-confyml-eacces-permission-denied"></a> |
| 79 | +<a id="permission-denied-saving-config"></a> |
| 80 | +<a id="possible-issue-2-unable-to-save"></a> |
| 81 | +<a id="config-not-updating"></a> |
| 82 | +<a id="config-still-not-updating"></a> |
| 83 | +<a id="possible-issue-3-saved-but-not-updating"></a> |
74 | 84 |
|
75 | | -See also [#1465](https://github.com/Lissy93/dashy/issues/1465) |
| 85 | +### Permission denied or read-only filesystem (EACCES, EROFS) |
76 | 86 |
|
77 | | -### Possible Issue 2: Unable to save |
78 | | -In Docker, double check that the file isn't read-only, and that the container actually has permissions to modify it. You shouldn't really be running it as a root user, and I'm not sure if it will work if you do- |
| 87 | +The container can't write to your `conf.yml` or its directory. Almost always an ownership mismatch: the host directory belongs to a different uid than the one Dashy runs as inside the container. Less commonly a read-only mount or an over-strict file mode. |
79 | 88 |
|
80 | | -### Possible Issue 3: Saved but not updating |
81 | | -After saving, the frontend will recompile, which may take a couple seconds (or a bit longer on a Pi or low-powered device). If it doesn't recompile, you can manually trigger a re-build. |
| 89 | +Dashy runs as UID=1000 (default non-root node user). You can see this by running `docker exec -it dashy id`. Then, check who owns the user-data directory, with: `docker exec -it dashy ls -la /app/user-data` - if it's not `1000` then that's the issue. And the solution is just to run `sudo chown -R 1000:1000 /path/to/your/user-data` to set the right owner. |
82 | 90 |
|
83 | | ---- |
| 91 | +Fixes: |
| 92 | +1. **Hand the directory to uid 1000** (recommended). Keeps the container running as a non-root user, which is how Dashy is built to run `sudo chown -R 1000:1000 /path/to/your/user-data` |
| 93 | +2. **Run the container as your own user** if `chown` isn't practical (multi-user hosts, NAS appliances, host directories you don't want relabelled). Add `--user $(id -u):$(id -g)` to `docker run`, or set `user: "1000:1000"` (or your host uid:gid) on the service in `docker-compose.yml`. |
| 94 | +3. **Loosen a single-file mount** if its mode is `444`. Narrow case, only fixes that one symptom: `chmod 644 /path/to/conf.yml` |
84 | 95 |
|
85 | | -## Unable to write conf.yml: `EACCES: permission denied` |
| 96 | +**Common mistakes** |
| 97 | +- **Using uid/gid 1001.** A common guess on Synology, Unraid and similar where 1001 is the host's first user. Dashy's container is 1000, not 1001. |
| 98 | +- **`chmod` alone for a UID mismatch.** Loosens permissions but doesn't change who owns the file. You need `chown`. |
| 99 | +- **`chmod -R 777` or `775`.** Works as a workaround, masks the real problem, weakens security. Use `chown` to the right uid instead. |
86 | 100 |
|
87 | | -Most commonly the `conf.yml` file itself is mounted read-only, or its mode is `444`. Make it writable on the host: |
| 101 | +**Other gotchas:** |
| 102 | +- **Named Docker volumes** (created with `docker volume create`) inherit ownership from whatever first writes to them. If an older container set them up as root, the diagnose step will show that. Recreate the volume or `chown` the underlying directory under `/var/lib/docker/volumes/`. |
| 103 | +- **macOS hosts** rarely hit this. Docker Desktop transparently maps host uid to container uid through its VM. If saves are failing on macOS, look elsewhere first. |
| 104 | +- **Storage layers that ignore POSIX permissions** (some NAS app-data folders use FUSE, SMB or overlay mounts where `chmod` and `chgrp` are silent no-ops). Bind-mount user-data from a native filesystem path instead. |
88 | 105 |
|
89 | | -```bash |
90 | | -chmod 644 /path/to/your/conf.yml |
91 | | -``` |
| 106 | +### Kubernetes ConfigMap mount is read-only |
| 107 | + |
| 108 | +If you've mounted your `conf.yml` from a ConfigMap, writes will always fail with `EROFS` regardless of UID. ConfigMap volumes are read-only by design. Either treat the ConfigMap as the source of truth and edit it directly (saves through the UI won't work), or use a writable volume type like a `PersistentVolumeClaim` for `user-data/`. |
| 109 | + |
| 110 | +### SELinux or AppArmor blocks the write |
| 111 | + |
| 112 | +If you're on RHEL/Fedora, or systems with SELinux or AppArmour, and you've confirmed permissions are fine, and container's UID matches the host owner, but you still see `EACCES`. |
| 113 | + |
| 114 | +For SELinux, add the `:Z` flag to your volume mount so Docker relabels it for the container (e.g. `volumes: [ './user-data:/app/user-data:Z' ]`) |
| 115 | + |
| 116 | +For AppArmor, check `dmesg` for `apparmor="DENIED"` lines and adjust the profile. Disabling enforcement is a last resort. |
| 117 | + |
| 118 | +### Backup step fails so save aborts |
| 119 | + |
| 120 | +Before each save, Dashy backs up the current `conf.yml` to `user-data/config-backups/`. If that folder can't be written, the whole save aborts with `Unable to backup conf.yml`. |
| 121 | + |
| 122 | +Two ways out: |
| 123 | +1. Point `BACKUP_DIR` at a writable path |
| 124 | +2. Set `DISABLE_CONFIG_BACKUPS=true` to skip the backup step entirely |
| 125 | + |
| 126 | +### Save button is missing or returns 403 Forbidden |
| 127 | + |
| 128 | +Have you got auth setup? If so, make sure you are logged in as an admin, or set `type: admin` to your user in `conf.yml`. |
| 129 | + |
| 130 | +Beyond that, there's several other config options which prevent saving the config file, so if you didn't mean to add them, just remove from `conf.yml` |
| 131 | +- **`appConfig.preventWriteToDisk: true`** disables disk save and the button |
| 132 | +- **`appConfig.preventLocalSave: true`** disables the "Local" save option |
| 133 | +- **`appConfig.disableConfiguration: true`** hides the editor entirely. `disableConfigurationForNonAdmin: true` does the same just for non-admins. |
| 134 | + |
| 135 | +### Save unavailable on Vercel, Netlify or other static hosts |
| 136 | +Updating source config file on static hosts is not possible, since they have no Node server, nor have write access to modify any files. |
| 137 | +The "Local" save mode will still work (changes are just persisted in your browser), but the real solution is to copy/export the updated YAML and replace it in the source config file in your repo. |
| 138 | + |
| 139 | +Related: [#1465](https://github.com/Lissy93/dashy/issues/1465). |
| 140 | + |
| 141 | +### `/config-manager/save` returns 404 or HTML |
| 142 | +How are you running/serving Dashy? |
| 143 | +If you've got a reverse proxy which only forwards specific path prefixes then maybe you're missing the `/config-manager/*` API endpoints? |
| 144 | +Check the failed request in the browser's Network tab. If the response is HTML (a proxy error page) or a plain 404, your proxy isn't routing the path. Add `/config-manager/` to whatever you're forwarding, or simplify the rules so everything reaches Dashy. |
| 145 | + |
| 146 | +Or if you're serving up the compiled Vue app directly, instead of using the Node server, then the endpoint won't be available. |
92 | 147 |
|
93 | | -As for backups, Dashy creates a timestamped backup of the existing config in `user-data/config-backups/` before writing the new one. If the host filesystem prevents that copy (read-only mount, wrong UID/GID, no execute bit on the parent directory), the save aborts before touching the live config. |
| 148 | +### "Invalid filename" when saving a sub-page |
94 | 149 |
|
95 | | -Check that the user-data volume is writable by the container user: |
| 150 | +The save endpoint rejects sub-page filenames with path separators or non-yaml extensions. Check the `path:` value of the page in your `pages:` block. It needs to be a plain basename like `home.yml`, not `pages/home.yml` or `home.txt`. |
| 151 | + |
| 152 | +### "Cannot save to an external URL" |
| 153 | + |
| 154 | +The sub-page you are editing is loaded from a remote URL. Dashy can't write back to that URL. |
| 155 | +You will need to edit the file at it's origin yourself instead (click the Export to view the YAML). |
| 156 | +Or you could download the config to `user-data/something.yml`, and update `path:` to point to the local version. |
| 157 | + |
| 158 | +### Saved successfully but the UI shows the old config |
| 159 | + |
| 160 | +Two unrelated causes share this symptom: |
| 161 | + |
| 162 | +1. **Local storage overrides the file.** Dashy lets users save settings locally in browser storage, which take priority over `conf.yml`. Open Dashy in incognito to confirm. If the changes appear there, clear local settings via Config menu > "Clear Local Settings". |
| 163 | +2. **Docker isn't picking up file changes.** Some text editors save by replacing the inode, which breaks single-file bind mounts. Edit the file in place, or mount the parent directory rather than the single file. [More background](https://medium.com/@jonsbun/why-need-to-be-careful-when-mounting-single-files-into-a-docker-container-4f929340834). |
| 164 | + |
| 165 | +<a id="container-crashes-or-restart-loop-after-saving-config"></a> |
| 166 | + |
| 167 | +### Container crashes or restart loop after saving (3.1.0 and 3.1.1 only) |
| 168 | + |
| 169 | +If your container crashes or restart-loops right after clicking save, with logs like `ERR_HTTP_HEADERS_SENT` or `ERR_STREAM_WRITE_AFTER_END`, this was a known double-`res.end()` bug in 3.1.0 and 3.1.1. Fixed in v3.2.13 and later. |
96 | 170 |
|
97 | 171 | ```bash |
98 | | -docker exec -it dashy id |
99 | | -docker exec -it dashy ls -la /app/user-data |
| 172 | +docker pull lissy93/dashy:latest |
| 173 | +docker compose up -d --force-recreate |
100 | 174 | ``` |
101 | 175 |
|
102 | | -If you bind-mount from the host, make sure the host directory is owned by the container's UID (or world-writable). You can also override the backup location with the `BACKUP_DIR` env var. |
| 176 | +### Intentionally read-only mode |
103 | 177 |
|
104 | | -And, if you intentionally want a read-only config and don't want users to even attempt saves, set `appConfig.preventWriteToDisk: true` in `conf.yml` - Dashy will then disable both the endpoint, and the save button itself, to make the experience more explicit. |
| 178 | +To stop anyone saving from the UI, set `appConfig.preventWriteToDisk: true` in `conf.yml`. This disables the endpoint and the save button. For Docker users, you can harden things further, by mounting the config and all user-data as read-only. |
105 | 179 |
|
106 | 180 | --- |
107 | 181 |
|
@@ -349,36 +423,6 @@ See also [#624](https://github.com/Lissy93/dashy/issues/624) |
349 | 423 |
|
350 | 424 | --- |
351 | 425 |
|
352 | | -## Container Crashes or Restart Loop After Saving Config |
353 | | - |
354 | | -If your Dashy container crashes or enters a restart loop the moment you click **Save to Disk** in the editor - particularly with logs that include something like: |
355 | | - |
356 | | -```text |
357 | | -node:_http_outgoing:652 |
358 | | - throw new ERR_HTTP_HEADERS_SENT('set'); |
359 | | -``` |
360 | | - |
361 | | -or: |
362 | | - |
363 | | -```text |
364 | | -Error [ERR_STREAM_WRITE_AFTER_END]: write after end |
365 | | -``` |
366 | | - |
367 | | -This was a known crash in Dashy 3.1.0 and 3.1.1 where a partial-failure code path in the save handler would call `res.end()` twice on the same response, causing Node to throw an unhandled rejection and exit the process. Docker would then restart the container, the user would save again, and the loop repeated. Several users also reported it was reliably triggered by entering edit mode while `statusCheck: true` was set, because the periodic background traffic increased the chance of overlapping responses. |
368 | | - |
369 | | -**This is fixed in v3.2.13 and later** |
370 | | - |
371 | | -```bash |
372 | | -docker pull lissy93/dashy:latest |
373 | | -docker compose up -d --force-recreate |
374 | | -``` |
375 | | - |
376 | | -If you can't upgrade right away, the temporary workaround that worked for affected users is to set `statusCheck: false` under `appConfig` in your `conf.yml`. This reduces the trigger frequency without changing the underlying bug. |
377 | | - |
378 | | -See also: [#1945](https://github.com/Lissy93/dashy/issues/1945), [#1935](https://github.com/Lissy93/dashy/issues/1935), [#1494](https://github.com/Lissy93/dashy/issues/1494) |
379 | | - |
380 | | ---- |
381 | | - |
382 | 426 | ## Auth Validation Error: "should be object" |
383 | 427 |
|
384 | 428 | In V 1.6.5 an update was made that in the future will become a breaking change. You will need to update you config to reflect this before V 2.0.0 is released. In the meantime, your previous config will continue to function normally, but you will see a validation warning. The change means that the structure of the `appConfig.auth` object is now an object, which has a `users` property. |
@@ -487,42 +531,6 @@ If you'd rather mount a single file (`-v ~/conf.yml:/app/user-data/conf.yml`), t |
487 | 531 |
|
488 | 532 | --- |
489 | 533 |
|
490 | | -## Permission Denied Saving Config |
491 | | - |
492 | | -If saving config from the UI fails with `EACCES` or `permission denied`, your mounted `user-data` directory is owned by a uid the container can't write to. Inside the container, Dashy runs as uid 1000 (the `node` user), and your host directory probably belongs to a different uid. |
493 | | - |
494 | | -Two fixes, pick whichever's less of a faff: |
495 | | - |
496 | | -1. Run the container as your own user. On `docker run`, add `--user $(id -u):$(id -g)`. In `docker-compose.yml`, uncomment the `user:` line and set it to your uid:gid (run `id -u` and `id -g` to find them). |
497 | | -2. Hand the directory to uid 1000: `sudo chown -R 1000:1000 /path/to/your/user-data`. |
498 | | - |
499 | | -Most people are already uid 1000 on Linux and macOS, so this only tends to bite on NAS boxes, multi-user servers, or anywhere the first user isn't 1000. |
500 | | - |
501 | | ---- |
502 | | - |
503 | | -## Config not Saving on Vercel / Netlify / CDN |
504 | | - |
505 | | -If you're running Dashy using a static hosting provider (like Vercel), then there is no Node server, and so the save config action will not work via the UI. |
506 | | -You'll instead need to copy the YAML after making your changes, and paste that into your `conf.yml` directly. If you've connected Vercel to git, then these changes will take effect automatically, once you commit your changes. |
507 | | - |
508 | | -If you're running on Netlify, there are some cloud functions which take care of all the server endpoints (like status checking), so these will work as expected. |
509 | | - |
510 | | -See also [#1465](https://github.com/Lissy93/dashy/issues/1465) |
511 | | - |
512 | | ---- |
513 | | - |
514 | | -## Config Not Updating |
515 | | - |
516 | | -Dashy has the option to save settings and config locally, in browser storage. Anything here will take precedence over whatever is in your config file, sometimes with unintended consequences. If you've updated the config file manually, and are not seeing changes reflected in the UI, then try visiting the site in Incognito mode. If that works, then the solution is just to clear local storage. This can be done from the config menu, under "Clear Local Settings". |
517 | | - |
518 | | ---- |
519 | | - |
520 | | -## Config Still not Updating |
521 | | - |
522 | | -Sometimes your text editor updates files [inode](https://linuxhandbook.com/inode-linux/), meaning changes will not be picked up by the Docker container. This [article](https://medium.com/@jonsbun/why-need-to-be-careful-when-mounting-single-files-into-a-docker-container-4f929340834) explains things further. |
523 | | - |
524 | | ---- |
525 | | - |
526 | 534 | ## Styles and Assets not Updating |
527 | 535 |
|
528 | 536 | If you find that your styles and other visual assets work when visiting `ip:port` by not `dashy.domain.com`, then this is usually caused by caching. In your browser, do a hard-refresh (<kbd>Ctrl</kbd> + <kbd>F5</kbd>). If you use Cloudflare, then you can clear the cache through the management console, or set the cache level to Bypass for certain files, under the Rules tab. |
|
0 commit comments