first commit

This commit is contained in:
2024-05-02 07:42:34 +07:00
commit 61922abab7
405 changed files with 104316 additions and 0 deletions

1
CNAME Normal file
View File

@@ -0,0 +1 @@
dashy.to

53
Dockerfile Normal file
View File

@@ -0,0 +1,53 @@
FROM node:16.13.2-alpine AS BUILD_IMAGE
# Set the platform to build image for
ARG TARGETPLATFORM
ENV TARGETPLATFORM=${TARGETPLATFORM:-linux/amd64}
# Install additional tools needed if on arm64 / armv7
RUN \
case "${TARGETPLATFORM}" in \
'linux/arm64') apk add --no-cache python3 make g++ ;; \
'linux/arm/v7') apk add --no-cache python3 make g++ ;; \
esac
# Create and set the working directory
WORKDIR /app
# Install app dependencies
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile --network-timeout 1000000
# Copy over all project files and folders to the working directory
COPY . ./
# Build initial app for production
RUN yarn build --mode production
# Production stage
FROM node:16.13.2-alpine
# Define some ENV Vars
ENV PORT=80 \
DIRECTORY=/app \
IS_DOCKER=true
# Create and set the working directory
WORKDIR ${DIRECTORY}
# Update tzdata for setting timezone
RUN apk add --no-cache tzdata
# Copy built application from build phase
COPY --from=BUILD_IMAGE /app ./
# Ensure only one version of conf.yml exists
RUN rm dist/conf.yml
# Finally, run start command to serve up the built application
CMD [ "yarn", "start" ]
# Expose the port
EXPOSE ${PORT}
# Run simple healthchecks every 5 mins, to check that everythings still great
HEALTHCHECK --interval=5m --timeout=5s --start-period=30s CMD yarn health-check

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-2022 Alicia Sykes <https://aliciasykes.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1
Procfile Normal file
View File

@@ -0,0 +1 @@
web: npm run build-and-start

799
README.md Normal file
View File

@@ -0,0 +1,799 @@
<h1 align="center">Dashy</h1>
<p align="center">
<i>Dashy helps you organize your self-hosted services by making them accessible from a single place</i>
<br/>
<img width="120" src="https://i.ibb.co/yhbt6CY/dashy.png" />
<br/>
<b><a href="./docs/showcase.md">User Showcase</a></b> | <b><a href="https://demo.dashy.to">Live Demo</a></b> | <b><a href="./docs/quick-start.md">Getting Started</a></b> | <b><a href="https://dashy.to/docs">Documentation</a></b> | <b><a href="https://github.com/Lissy93/dashy">GitHub</a></b>
<br/><br/>
<a href="https://github.com/awesome-selfhosted/awesome-selfhosted#personal-dashboards">
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome Self-Hosted">
</a>
<a href="./LICENSE">
<img src="https://img.shields.io/badge/License-MIT-0aa8d2?logo=opensourceinitiative&logoColor=fff" alt="License MIT">
</a>
<a href="./.github/CHANGELOG.md">
<img src="https://img.shields.io/github/package-json/v/lissy93/dashy?logo=azurepipelines&amp;color=0aa8d2" alt="Current Version">
</a>
<a href="https://hub.docker.com/r/lissy93/dashy">
<img src="https://img.shields.io/docker/pulls/lissy93/dashy?logo=docker&color=0aa8d2&logoColor=fff" alt="Docker Pulls">
</a>
<a href="http://as93.link/dashy-build-status">
<img src="https://badgen.net/github/status/lissy93/dashy?icon=github" alt="GitHub Status">
</a>
<a href="https://snyk.io/test/github/lissy93/dashy">
<img src="https://snyk.io/test/github/lissy93/dashy/badge.svg" alt="Known Vulnerabilities">
</a>
</p>
<details>
<summary><b>Table of Contents</b></summary>
<p>
- **Getting Started**
- [🌈 Features](#features-)
- [⚡Demo](#demo-)
- [🚀 Getting Started](#getting-started-)
- [🔧 Configuring](#configuring-)
- **Feature Overview**
- [🎨 Theming](#theming-)
- [🧸 Icons](#icons-)
- [🚦 Status Indicators](#status-indicators-)
- [📊 Widgets](#widgets-)
- [🔐 Authentication](#authentication-)
- [👓 Alternate Views](#alternate-views-)
- [🖱️ Opening Methods](#opening-methods-)
- [🔎 Searching and Shortcuts](#searching-and-shortcuts-)
- [⚙️ Config Editor](#config-editor-)
- [☁ Cloud Backup & Sync](#cloud-backup--sync-)
- [🌎 Language Switching](#language-switching-)
- [📃 Multi-Page Support](#multi-page-support-)
- **Community**
- [📊 System Requirements](#system-requirements-)
- [🙋‍♀️ Support](#support-)
- [💖 Supporting Dashy](#supporting-dashy-)
- [🏆 Credits](#credits-)
- [🧱 Developing](#developing-)
- [🗞️ Release Schedule](#release-schedule-)
- [📘 Documentation](#documentation-)
- [🛣️ Roadmap](#roadmap-)
- [🙌 Alternatives](#alternatives-)
- [📜 License](#license-)
</p>
</details>
## Features 🌈
- 📃 Support for multiple pages
- 🚦 Real-time status monitoring for each of your apps/links
- 📊 Use widgets to display info and dynamic content from self-hosted services
- 🔎 Instant search by name, domain, or tags + customizable hotkeys & keyboard shortcuts
- 🎨 Many built-in color themes, with UI color editor and support for custom CSS
- 🧸 Many icon options - Font-Awesome, homelab icons, auto-fetching Favicon, images, emojis, etc.
- 💂 Optional authentication with multi-user access, configurable privileges, and SSO support
- 🌎 Multi-language support, with 10+ human-translated languages, and more on the way
- ☁ Optional, encrypted, free off-site cloud backup and restore feature available
- 💼 A workspace view, for easily switching between multiple apps simultaneously
- 🛩️ A minimal view, for use as a fast-loading browser Startpage
- 🖱️ Choose app launch methods: new tab, same tab, clipboard, pop-up modal, or open in workspace view
- 📏 Customizable layout, sizes, text, component visibility, sort order, behavior, etc.
- 🖼️ Options for a full-screen background image, custom nav-bar links, HTML footer, title, etc.
- 🚀 Easy to setup with Docker, or on bare metal, or with 1-Click cloud deployment
- ⚙️ Easy single-file YAML-based configuration, and option to configure app through the UI
- ✨ Under active development with improvements and new features added regularly
- 🤏 Small bundle size, fully responsive UI, and PWA for basic offline access
- 🆓 100% free and open-source
- 🔐 Strong focus on privacy
- 🌈 And loads more...
**[⬆️ Back to Top](#dashy)**
## Demo ⚡
**Live Instances**: [Demo 1](https://demo.dashy.to) (Live Demo) ┆ [Demo 2](https://live.dashy.to) (Dashy Links) ┆ [Demo 3](https://dev.dashy.to) (Dev Preview)
**Screenshots**: Checkout the [Showcase](./docs/showcase.md), to see example dashboards from the community
**Spin up your own demo**: [![One-Click Deploy with PWD](https://img.shields.io/badge/Play--with--Docker-Deploy-2496ed?style=flat-square&logo=docker)](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml) or [`docker run -p 8080:80 lissy93/dashy`](./docs/quick-start.md)
<p align="center">
<img width="800" src="https://i.ibb.co/L8YbNNc/dashy-demo2.gif" alt="Demo" />
</p>
**[⬆️ Back to Top](#dashy)**
---
## Getting Started 🚀
> For full setup instructions, see: [**Deployment**](./docs/deployment.md)
### Deploying from Docker Hub 🐳
You will need [Docker](https://docs.docker.com/get-docker/) installed on your system
```
docker run -p 8080:80 lissy93/dashy
```
Or
```docker
docker run -d \
-p 4000:80 \
-v /root/my-local-conf.yml:/app/public/conf.yml \
--name my-dashboard \
--restart=always \
lissy93/dashy:latest
```
[![Dashy on Docker Hub](https://dockeri.co/image/lissy93/dashy)](https://hub.docker.com/r/lissy93/dashy)
See also: [examples with Docker Compose](./docs/deployment.md#using-docker-compose). Dashy is also available via GHCR, and tags for other architectures (`arm32v7`, `arm64v8`, etc.) and set versions are supported
> Once you've got Dashy running, see [App Management Docs](./docs/management.md) for info on using health checks, updating, backups, web-server configs, logs, performance, security, and more.
### Deploying from Source 🔨
You will need [git](https://git-scm.com/downloads), the latest or LTS version of [Node.js](https://nodejs.org/) and _(optionally)_ [Yarn](https://yarnpkg.com/) installed on your system.
- Clone the Repo: `git clone https://github.com/Lissy93/dashy.git` and `cd dashy`
- Configuration: Fill in your settings in `./public/conf.yml`
- Install dependencies: `yarn`
- Build: `yarn build`
- Run: `yarn start`
> See docs: [Full list of Dashy's commands](./docs/management.md#basic-commands)
### Deploy to the Cloud ☁️
Dashy supports **1-Click deployments** on several popular cloud platforms. To spin up a new instance, just click a link below:
- [<img src="https://i.ibb.co/ZxtzrP3/netlify.png" width="18"/> Deploy to Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/dashy)
- [<img src="https://i.ibb.co/d2P1WZ7/heroku.png" width="18"/> Deploy to Heroku](https://heroku.com/deploy?template=https://github.com/Lissy93/dashy)
- [<img src="https://i.ibb.co/Ld2FZzb/vercel.png" width="18"/> Deploy to Vercel](https://vercel.com/new/project?template=https://github.com/lissy93/dashy)
- [<img src="https://i.ibb.co/xCHtzgh/render.png" width="18"/> Deploy to Render](https://render.com/deploy?repo=https://github.com/lissy93/dashy/tree/deploy_render)
- [<img src="https://i.ibb.co/J7MGymY/googlecloud.png" width="18"/> Deploy to GCP](https://deploy.cloud.run/?git_repo=https://github.com/lissy93/dashy.git)
- [<img src="https://i.ibb.co/HVWVYF7/docker.png" width="18"/> Deploy to PWD](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml)
- [<img src="https://i.ibb.co/7NxnM2P/easypanel.png" width="18"/> Deploy to Easypanel](https://easypanel.io/docs/templates/dashy)
> For more 1-click cloud deployments, see [Cloud Deployment](./docs/deployment.md#deploy-to-cloud-service)
**[⬆️ Back to Top](#dashy)**
---
## Configuring 🔧
> For full configuration documentation, see: [**Configuring**](./docs/configuring.md)
Dashy is configured through a YAML file, located at `./public/conf.yml`. In addition, you can find a complete list of available options in the [Configuring Docs](./docs/configuring.md). The config can also be edited and saved directly through the UI.
**[⬆️ Back to Top](#dashy)**
---
## Theming 🎨
> For full theming documentation, see: [**Theming**](./docs/theming.md)
Dashy comes pre-bundled with several built-in themes, which you can preview, apply and edit through the UI. With the theme configurator and support for custom CSS, everything is in place to quickly develop your own unique-looking dashboard.
<p align="center">
<a href="https://i.ibb.co/BVSHV1v/dashy-themes-slideshow.gif">
<img alt="Example Themes" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/theme-slideshow.gif" width="400" />
</a>
</p>
<p align="center">
<a href="https://i.ibb.co/cLDXj1R/dashy-theme-configurator.gif">
<img alt="Example Themes" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/theme-config-demo.gif" width="400" />
</a>
</p>
**[⬆️ Back to Top](#dashy)**
---
## Icons 🧸
> For full iconography documentation, see: [**Icons**](./docs/icons.md)
Both sections and items can have an icon associated with them, defined under the `icon` attribute. With several different icon packs supported, you'll be able to find the perfect thumbnail for any app or service.
The following icon types are supported:
- **Favicon** - Automatically fetch an apps icon from its Favicon or logo image
- **Icon Packs** - Use any icon from [font-awesome], [simple-icons] or [material icons]
- **Emoji** - Any valid emoji can be used as an icon
- **Generative** - Unique, auto-generated images for easily identifying services
- **URL** - Pass the URL of any valid image in to have it fetched and rendered
- **Local** - Store custom images locally and reference by filename
- **Homelab Icons** - Using [dashboard-icons] for logos of commonly self-hosted services
[font-awesome]: https://fontawesome.com/icons
[simple-icons]: https://simpleicons.org/
[material icons]: https://github.com/Templarian/MaterialDesign
[dashboard-icons]: https://github.com/WalkxCode/dashboard-icons
<p align="center">
<img width="400" src="https://i.ibb.co/GTVmZnc/dashy-example-icons.png" />
</p>
**[⬆️ Back to Top](#dashy)**
---
## Status Indicators 🚦
> For full monitoring documentation, see: [**Status Indicators**](./docs/status-indicators.md)
Dashy has an optional feature to check if each app/ service is up and responding, then display a small status indicator icon. Hovering over it will show additional stats like response time and status code.
Status indicators can be globally enabled by setting `appConfig.statusCheck: true` or enabled/ disabled on a per-item basis. Status is checked on page load, but you can allow continuous polling by specifying a time interval between checks, in seconds under `appConfig.statusCheckInterval`. You can also use a different endpoint for status checking, with `statusCheckUrl`, and if needed, pass in custom headers under `statusCheckHeaders`.
<p align="center">
<img alt="Status Checks demo" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/status-check-demo.gif" width="600" />
</p>
**[⬆️ Back to Top](#dashy)**
---
## Widgets 📊
> For full widget documentation, see: [**Widgets**](./docs/widgets.md)
You can display dynamic content from services in the form of widgets. There are several pre-built widgets availible for showing useful info, and integrations with commonly self-hosted services, but you can also easily create your own for almost any app.
<p align="center">
<img width="600" src="https://i.ibb.co/GFjXVHy/dashy-widgets.png" />
</p>
**[⬆️ Back to Top](#dashy)**
---
## Authentication 🔐
> For full authentication documentation, see: [**Authentication**](./docs/authentication.md)
Dashy has full support for secure single-sign-on using [Keycloak](https://www.keycloak.org/) for secure, easy authentication, see [setup docs](/docs/authentication.md#keycloak) for a full usage guide.
There is also a basic auth feature, which doesn't require additional setup. To enable this, add an `auth` attribute under `appConfig`, containing an array of `users`, each with a username, SHA-256 hashed password and optional user type. Basic auth also supports several access control features, including read-only guest access and granular controls.
```yaml
appConfig:
auth:
users:
- user: alicia
hash: 4D1E58C90B3B94BCAD9848ECCACD6D2A8C9FBC5CA913304BBA5CDEAB36FEEFA3
type: admin
```
Other access control systems are also supported, see the [Alternative Auth Methods](./docs/authentication.md#alternative-authentication-methods) docs.
**[⬆️ Back to Top](#dashy)**
---
## Alternate Views 👓
As well as the default homepage, there is also:
- A minimal view, valid for use as a browser start page
- A workspace view, useful for visiting many apps simultaneously
You can change the view from the UI, using the switch icon in the top-right corner, or select a default view in the config under `appConfig.startingView` attribute.
<p align="center">
<b>Example of Workspace View</b><br>
<img alt="Workspace view demo" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/workspace-demo.gif" width="600" />
</p>
<p align="center">
<b>Example of Minimal View</b><br>
<img alt="Workspace view demo" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/minimal-view-demo.gif" width="600" />
</p>
**[⬆️ Back to Top](#dashy)**
---
## Opening Methods 🖱️
> For full documentation on views and opening methods, see: [**Alternate Views**](./docs/alternate-views.md)
There are several different ways you can launch apps. You can specify the default opening method for any given item under the `target` attribute or set a site-wide default under `appConfig.defaultOpeningMethod`. Right-click on an item to item for all options. The following options are supported:
- `sametab` - The app will be launched in the current tab
- `newtab` - The app will be launched in a new tab (or use Ctrl + Click)
- `modal` - Launch app in a resizable/ movable popup modal on the current page (or use Alt + Click)
- `workspace` - Changes to Workspace view and launches app
- `clipboard` - Copy the app's URL to your system clipboard
- `top` - Opens in the top-most browsing context, useful if you're accessing Dashy through an iframe
**[⬆️ Back to Top](#dashy)**
---
## Searching and Shortcuts 🔎
> For full documentation on searching, see: [**Searching & Shortcuts**](./docs/searching.md)
Quickly finding and launching applications is the primary aim of Dashy. To that end, instant search and customizable keyboard shortcuts are built-in.
To start filtering, start typing—no need to select the search bar or use any special key. Then use either the tab key or arrow keys to select and move between results, and hit enter to launch the currently selected application.
For apps that you use regularly, you can set a custom keybinding. Use the `hotkey` parameter on a certain item to specify a numeric key between `0 - 9`. You can then launch that app by just pressing that key.
You can also add custom tags to a given item to make finding them based on keywords easier. For example, in the following example, searching for 'Movies' will show 'Plex'
```yaml
items:
- title: Plex
hotkey: 8
icon: favicon
description: Media library
url: https://plex.lab.local
tags: [ movies, videos, music ]
```
To search the web directly through Dashy, just press enter after typing your query. Options for web search are set under `appConfig.webSearch`. There is built-in support for [10+ search engines](./docs/searching.md#setting-search-engine), or [use your own custom provider](./docs/searching.md#using-custom-search-engine) or self-hosted instance. With the web search, you can also define your bangs to redirect results to any given app, website, or search engine, when the query is preceded with a certain character sequence (usually beginning in `/`, `!` or `:`).
```yaml
webSearch:
searchEngine: duckduckgo
openingMethod: newtab
searchBangs:
/r: reddit
/w: wikipedia
/s: https://whoogle.local/search?q=
':wolf': wolframalpha
':so': stackoverflow
':git': github
```
Hit `Esc` at any time to close any open apps, clear the search field, or hide any modals.
**[⬆️ Back to Top](#dashy)**
---
## Config Editor ⚙️
> For full config documentation, see: [**Configuring**](./docs/configuring.md)
As well as passing in a YAML config file, you can also configure the app directly through the UI and preview changes live.
To edit any section or item, right-click on it, and select "Edit", or enter the Edit Mode (using the Pen icon in the top-right), then click any part of the page to edit. Changes will be visible immediately but will not be saved until clicking "Save to Disk" or "Save Locally".
Under the config menu, you can export, view, backup, or reset app config and edit the raw config file in a text editor with built-in schema validation. It's recommended to keep a backup of your config.
<p align="center">
<img alt="Interactive Editor demo" src="https://user-images.githubusercontent.com/1862727/139543020-b0576d28-0830-476f-afc8-a815d4de6def.gif" width="600" />
</p>
<p align="center">
<img alt="Config Editor demo" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/config-editor-demo.gif" width="600" />
</p>
**[⬆️ Back to Top](#dashy)**
---
## Cloud Backup & Sync ☁
> For full backup documentation, see: [**Cloud Backup & Sync**](./docs/backup-restore.md)
Dashy has an **optional** built-in feature for securely backing up your config to a hosted cloud service and then restoring it on another instance. This is useful not only for backing up your configuration off-site but also enables Dashy to be used without having to write a YAML config file.
All data is fully E2E encrypted before being sent to the backend (done in [`CloudBackup.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/CloudBackup.js) using [crypto.js](https://github.com/brix/crypto-js) 's AES method). The data is then sent to a [Cloudflare worker](https://developers.cloudflare.com/workers/learning/how-workers-works) and stored in a [KV](https://developers.cloudflare.com/workers/learning/how-kv-works) data store.
**[⬆️ Back to Top](#dashy)**
---
## Language Switching 🌎
> For full internationalization documentation, see: [**Multi-Language Support**](./docs/multi-language-support.md)
Dashy supports multiple languages and locales. When available, your language should be automatically detected and applied on load. But you can also select a language through the UI (under config --> Switch Language) or set `appConfig.language` to your language (specified as a 2-digit [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)), as seen below, e.g. `language: de`.
#### Supported Languages
- 🇬🇧 **English**: `en` - _Default_
- 🇦🇪 **Arabic**: `ar` - _Auto-generated_
- 🇧🇩 **Bengali**: `bn` - Contributed by **[@soaibsafi](https://github.com/soaibsafi)**
- 🇧🇬 **Bulgarian**: `bg` - Contributed by **[@asenov](https://github.com/asenov)**
- 🇨🇳 **Chinese**: `cn` - Contributed by **[@FormatToday](https://github.com/FormatToday)**
- 🇨🇿 **Czech**: `cs` - Contributed by **[@Tuzi555](https://github.com/Tuzi555)**
- 🇩🇰 **Danish**: `da` - Contributed by **[@lordpansar](https://github.com/lordpansar)**
- 🇳🇱 **Dutch**: `nl` - Contributed by **[@evroon](https://github.com/evroon)**
- 🇫🇷 **French**: `fr` - Contributed by **[@EVOTk](https://github.com/EVOTk)**
- 🇩🇪 **German**: `de` - Contributed by **[@Niklashere](https://github.com/Niklashere)**
- 🇬🇷 **Greek**: `el` - Contributed by **[@aviolaris](https://github.com/aviolaris)**
- 🇮🇳 **Hindi**: `hi` - _Auto-generated_
- 🇮🇹 **Italian**: `it` - Contributed by **[@alexdelprete](https://github.com/alexdelprete)**
- 🇯🇵 **Japanese**: `ja` - _Auto-generated_
- 🇰🇷 **Korean**: `ko` - Contributed by **[@boggy-cs](https://github.com/boggy-cs)**
- 🇳🇴 **Norwegian Bokmål**: `nb` - Contributed by **[@rubjo](https://github.com/rubjo)**
- 🇵🇱 **Polish**: `pl` - Contributed by **[@skaarj1989](https://github.com/skaarj1989)**
- 🇵🇹 **Portuguese**: `pt` - Contributed by **[@LeoColman](https://github.com/LeoColman)**
- 🇷🇺 **Russian**: `ru` - _Auto-generated_
- 🇸🇰 **Slovak**: `sk` - Contributed by **[@Smexhy](https://github.com/Smexhy)**
- 🇸🇮 **Slovenian**: `sl` - Contributed by **[@UrekD](https://github.com/UrekD)**
- 🇪🇸 **Spanish**: `es` - Contributed by **[@lu4t](https://github.com/lu4t)**
- 🇸🇪 **Swedish**: `sv` - Contributed by **[@BOZG](https://github.com/BOZG)**
- 🇹🇼 **Traditional Chinese**: `zh-TW` - Contributed by **[@stanly0726](https://github.com/stanly0726)**
- 🇹🇷 **Turkish**: `tr` - Contributed by **[@imsakg](https://github.com/imsakg)**
- 🏴‍☠️ **Pirate**: `pirate` - Contributed by **[@Lissy93](https://github.com/lissy93)**
#### Add your Language
I would love Dashy to be available to everyone without language being a barrier to entry. If you've got a few minutes to spare, consider adding translations for your language. It's a quick task, and all text is in [a single JSON file](https://github.com/Lissy93/dashy/tree/master/src/assets/locales). Since any missing text will fall back to English, you don't need to translate it all.
**[⬆️ Back to Top](#dashy)**
---
## Multi-Page Support 📃
> For full multi-page documentation, see: [**Pages & Sections**](./docs/pages-and-sections.md)
Within your dashboard, you can have as many sub-pages as you require. To load additional pages, specify a name, and path to a config file under `pages`. The config file can be either local (stored in `/public`), or remote (located anywhere accessible).
```yaml
pages:
- name: Networking Services
path: 'networking.yml'
- name: Work Stuff
path: 'work.yml'
```
Or
```yaml
pages:
- name: Getting Started
path: 'https://snippet.host/tvcw/raw'
- name: Homelab
path: 'https://snippet.host/tetp/raw'
- name: Browser Startpage
path: 'https://snippet.host/zcom/raw'
```
---
## System Requirements 📊
If running on bare metal, Dashy requires [Node](https://nodejs.org/en/) V 16.0.0 or later, LTS (16.13.2) is recommended.
If running in Docker container, the recommended base image is Alpine (3.15)
The hardware requirements vary depending on where and how you are running Dashy. Generally speaking, on a bare-metal system or Docker container, 1GB of memory should be more than enough, and depending on whether you are using your own assets, then 1GB of disk space should be sufficient.
If you are using one of the 1-click cloud deployment methods, serving the app through a CDN or using a static hosting provider, then there are no specific requirements, as the built app is just a series of static JS files, and so is very light-weight.
Dashy also wells run on low-powered ARM-based single board computers, such as a Raspberry Pi (tested on Pi 3)
**Browser Support**
![Chrome](https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png) | ![Firefox](https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png) | ![IE](https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png) | ![Opera](https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png) | ![Safari](https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png)
--- | --- | --- | --- | --- |
Latest ✔ | Latest ✔ | 10+ ✔ | Latest ✔ | 6.1+ ❌ |
**[⬆️ Back to Top](#dashy)**
---
## Support 🙋‍♀️
If you're having trouble getting Dashy up and running, or have a question about usage or configuration, feel free to ask. The best place to do this is via [the Discussions](https://github.com/Lissy93/dashy/discussions).
If you've found something which isn't working as it should, please raise a bug by [opening a ticket](https://github.com/Lissy93/dashy/issues/new/choose).
It's best to check the [docs](./docs), [previous issues](https://github.com/Lissy93/dashy/issues?q=label%3A%22%F0%9F%A4%B7%E2%80%8D%E2%99%82%EF%B8%8F+Question%22+) and [troubleshooting guide](./docs/troubleshooting.md) first.
**[⬆️ Back to Top](#dashy)**
---
## Supporting Dashy 💖
> For full details and other ways you can help out, see: [**Contributing**](./docs/contributing.md)
If you're using Dashy and would like to help support its development, then that would be awesome! Contributions of any type, any size, are always very much appreciated, and we will appropriately credit you for your effort.
Several areas that we need a bit of help with at the moment are:
- Translating - Help make Dashy available to non-native English speakers by [adding your language](./docs/multi-language-support.md#adding-a-new-language)
- Donate a small amount by [Sponsoring @Lissy93 on GitHub](https://github.com/sponsors/Lissy93) and receive some extra perks!
- Complete a [short survey](https://survey.typeform.com/to/gl0L68ou) to have your say about future features
- Share your dashboard in the [Showcase](https://github.com/Lissy93/dashy/blob/master/docs/showcase.md#dashy-showcase-), to inspire others
- Spread the word by sharing Dashy or a screenshot of your dashboard to help new users discover it
- Submit a PR to add a new feature, fix a bug, update the docs, add a theme, widget or something else
- Star Dashy on GitHub/ DockerHub or leave an upvote / review on [these platforms](https://github.com/Lissy93/dashy/blob/master/docs/contributing.md#star-upvote-or-leave-a-review)
[![Sponsor Lissy93 on GitHub](./docs/assets/sponsor-button.svg)](https://github.com/sponsors/Lissy93)
**[⬆️ Back to Top](#dashy)**
## Credits 🏆
> For a complete list of credits, and attributions to packages used within Dashy, see: [**Credits**](./docs/credits.md)
Thank you so much to everyone who has helped with Dashy so far; every contribution is very much appreciated.
#### Sponsors
Huge thanks to the sponsors helping to support Dashy's development!
<!-- readme: sponsors -start -->
<table>
<tr>
<td align="center">
<a href="https://github.com/emlazzarin">
<img src="https://avatars.githubusercontent.com/u/1141361?u=714e3487a3f2e0df721b01a0133945f075d3ff68&v=4" width="80;" alt="emlazzarin"/>
<br />
<sub><b>Eddy Lazzarin</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/AnandChowdhary">
<img src="https://avatars.githubusercontent.com/u/2841780?u=ca8e292b15abcc6cddaeae0abded0115c51b4789&v=4" width="80;" alt="AnandChowdhary"/>
<br />
<sub><b>Anand Chowdhary</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/shrippen">
<img src="https://avatars.githubusercontent.com/u/2873570?v=4" width="80;" alt="shrippen"/>
<br />
<sub><b>Shrippen</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/davidpaulyoung">
<img src="https://avatars.githubusercontent.com/u/3418369?v=4" width="80;" alt="davidpaulyoung"/>
<br />
<sub><b>David Young</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/bile0026">
<img src="https://avatars.githubusercontent.com/u/5022496?u=aec96ad173c0ea9baaba93807efa8a848af6595c&v=4" width="80;" alt="bile0026"/>
<br />
<sub><b>Zach Biles</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/UlisesGascon">
<img src="https://avatars.githubusercontent.com/u/5110813?u=3c41facd8aa26154b9451de237c34b0f78d672a5&v=4" width="80;" alt="UlisesGascon"/>
<br />
<sub><b>Ulises Gascón</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/digitalarche">
<img src="https://avatars.githubusercontent.com/u/6546135?u=a1a724d38ee1eba2d2d315495d482256312affe8&v=4" width="80;" alt="digitalarche"/>
<br />
<sub><b>Digital Archeology</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/bmcgonag">
<img src="https://avatars.githubusercontent.com/u/7346620?u=2a0f9284f3e12ac1cc15288c254d1ec68a5081e8&v=4" width="80;" alt="bmcgonag"/>
<br />
<sub><b>Brian McGonagill</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/vlad-timofeev">
<img src="https://avatars.githubusercontent.com/u/11474041?u=eee43705b54d2ec9f51fc4fcce5ad18dd17c87e4&v=4" width="80;" alt="vlad-timofeev"/>
<br />
<sub><b>Vlad Timofeev</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/iJasonWade">
<img src="https://avatars.githubusercontent.com/u/12824479?u=5446c46f50a3197b9cd970e1669ed42e654c66b1&v=4" width="80;" alt="iJasonWade"/>
<br />
<sub><b>Jason Ash</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/DRXAquosus">
<img src="https://avatars.githubusercontent.com/u/45409262?v=4" width="80;" alt="DRXAquosus"/>
<br />
<sub><b>DRXAquosus</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Bastii717">
<img src="https://avatars.githubusercontent.com/u/53431819?u=dff9e241e6dbecbc283ee13486a2312cb3dd9784&v=4" width="80;" alt="Bastii717"/>
<br />
<sub><b>Bastii717</b></sub>
</a>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/ratty222">
<img src="https://avatars.githubusercontent.com/u/92832598?u=137b65530cbd5f5af9c24cde51baa6cc77cc934b&v=4" width="80;" alt="ratty222"/>
<br />
<sub><b>Ratty222</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jtfinley72">
<img src="https://avatars.githubusercontent.com/u/96497997?v=4" width="80;" alt="jtfinley72"/>
<br />
<sub><b>Jtfinley72</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/aldrich8">
<img src="https://avatars.githubusercontent.com/u/106362981?u=af356e9c6e32f58fa9e9f19a846da8fd1611dbb0&v=4" width="80;" alt="aldrich8"/>
<br />
<sub><b>Aldrich</b></sub>
</a>
</td></tr>
</table>
<!-- readme: sponsors -end -->
#### Contributors
[![Auto-generated contributors](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/CONTRIBUTORS.svg)](./docs/credits.md)
#### Stats
[![Stats](https://repobeats.axiom.co/api/embed/48546e3c768d38c450ba136e32c0992bcf58ad73.svg "Repobeats analytics image")](https://github.com/Lissy93/dashy/blob/master/docs/credits.md)
**[⬆️ Back to Top](#dashy)**
---
## Developing 🧱
> For full development documentation, see: [**Developing**](./docs/developing.md)
[![Open Project in VS Code](https://img.shields.io/badge/Open_in-VS_Code-863cfc?style=flat-square&logo=visualstudiocode)](https://open.vscode.dev/Lissy93/Dashy)
[![Open in GitPod](https://img.shields.io/badge/Open_in-GitPod-ffae33?style=flat-square&logo=gitpod)](https://gitpod.io/#github.com/lissy93/dashy.git)
[![Open in GitHub Code Spaces](https://img.shields.io/badge/Open_in-Code%20Spaces-131313?style=flat-square&logo=github)](https://github.dev/Lissy93/dashy)
Before getting started, you'll need [Git](https://git-scm.com/downloads), [Node](https://nodejs.org/en/download/) and optionally [Yarn](https://yarnpkg.com/) (run `npm i -g yarn`) installed.
To set up the development environment:
1. Get Code: `git clone https://github.com/Lissy93/dashy.git` and `cd dashy`
2. Install dependencies: `yarn`
3. Start dev server: `yarn dev`
4. Open the browser: `http://localhost:8080`
When you're ready, you can build the production app with `yarn build`, and then run it with `yarn start`
If you're new to web development, I've put together a short [list of resources](https://github.com/Lissy93/dashy/blob/master/docs/developing.md#resources-for-beginners) to help beginners get started
**Repo Status**:
[![Open PRs](https://flat.badgen.net/github/open-prs/lissy93/dashy?icon=github)](https://github.com/Lissy93/dashy/pulls)
[![Total PRs](https://flat.badgen.net/github/prs/lissy93/dashy?icon=github)](https://github.com/Lissy93/dashy/pulls?q=)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/lissy93/dashy?style=flat-square)](https://github.com/Lissy93/dashy/commits/master)
[![Last Commit](https://flat.badgen.net/github/last-commit/lissy93/dashy?icon=github)](https://github.com/Lissy93/dashy/commits/master)
[![Contributors](https://flat.badgen.net/github/contributors/lissy93/dashy?icon=github)](https://github.com/Lissy93/dashy/graphs/contributors)
**[⬆️ Back to Top](#dashy)**
---
## Documentation 📘
> For full docs, see: **[Documentation Contents](./docs/readme.md)**
#### Running Dashy
- 💨 [Quick Start](/docs/quick-start.md) - TDLR guide on getting Dashy up and running in under 5 minutes
- 🚀 [Deployment](/docs/deployment.md) - Full guide on setting up Dashy on various different environments
- 🔧 [Configuring](/docs/configuring.md) - Complete list of all available options in the config file
- 💻 [Management](/docs/management.md) - Managing your app, updating, security, web server configuration, etc
- 🚒 [Troubleshooting](/docs/troubleshooting.md) - Common errors and problems, and how to fix them
#### Feature Docs
- 🛡️ [Authentication](/docs/authentication.md) - Guide to setting up authentication to protect your dashboard
- 🌈 [Alternate Views](/docs/alternate-views.md) - Outline of available pages / views and item opening methods
- 💾 [Backup & Restore](/docs/backup-restore.md) - Guide to backing up config with Dashy's cloud sync feature
- 🧸 [Icons](/docs/icons.md) - Outline of all available icon types for sections and items, with examples
- 🌐 [Multi-Language Support](/docs/multi-language-support.md) - Switching languages, and adding a new locales
- 🚦 [Status Indicators](/docs/status-indicators.md) - Using Dashy to monitor uptime and status of your apps
- 🔍 [Searching & Shortcuts](/docs/searching.md) - Searching, launching methods + keyboard shortcuts
- 🎨 [Theming](/docs/theming.md) - Complete guide to applying, writing and modifying themes + styles
- 📊 [Widgets](/docs/widgets.md) - List of all dynamic content widgets, with usage guides and examples
#### Development and Contributing
- 🧱 [Developing](/docs/developing.md) - Running Dashy development server locally, and general workflow
- 🛎️ [Development Guides](/docs/development-guides.md) - Common development tasks, to help new contributors
- 💖 [Contributing](/docs/contributing.md) - How to contribute to Dashy
- 🌟 [Showcase](/docs/showcase.md) - See how others are using Dashy, and share your dashboard
- 🏆 [Credits](/docs/credits.md) - Shout out to the amazing people who have contributed so far
- 🗞️ [Release Workflow](/docs/release-workflow.md) - Info about releases, CI and automated tasks
#### Misc
- 🔐 [Privacy & Security](/docs/privacy.md) - List of requests, potential issues, and security resources
- 📄 [License](/LICENSE) - Copy of the MIT License
- ⚖️ [Legal](/.github/LEGAL.md) - Licenses of direct dependencies
- 📏 [Code of Conduct](/.github/CODE_OF_CONDUCT.md) - Contributor Covenant Code of Conduct
- 🌳 [Changelog](/.github/CHANGELOG.md) - Details of recent changes, and historical versions
**[⬆️ Back to Top](#dashy)**
---
## Roadmap 🛣️
For upcoming features that will be released in the near future, see the [**Current Roadmap**](https://github.com/Lissy93/dashy/discussions/405)
For past updates, see the [**Changelog**](/.github/CHANGELOG.md)
**[⬆️ Back to Top](#dashy)**
---
## Alternatives 🙌
A few self-hosted web apps serve a similar purpose to Dashy. If you're looking for a dashboard, and Dashy doesn't meet your needs, I highly recommend you check these projects out!
- [Flame](https://github.com/pawelmalak/flame) by @pawelmalak (`MIT`)
- [HomeDash2](https://lamarios.github.io/Homedash2)
- [Homer](https://github.com/bastienwirtz/homer) (`Apache License 2.0`)
- [Organizr](https://organizr.app/) (`GPL-3.0 License`)
- [Heimdall](https://github.com/linuxserver/Heimdall) (`MIT`)
- [Smashing](https://github.com/Smashing/smashing) (`MIT`)
- See more 👉 [Awesome Self-Hosted](https://github.com/awesome-selfhosted/awesome-selfhosted#personal-dashboards)
**[⬆️ Back to Top](#dashy)**
---
## License 📜
Dashy is Licensed under [MIT X11](https://en.wikipedia.org/wiki/MIT_License)
```
Copyright © 2021-2022 Alicia Sykes <https://aliciasykes.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, Dashy shall not be used in advertising or otherwise
to promote the sale, use, or other dealings in this Software without prior written
authorization from the repo owner.
```
**TDLR;** _You can do whatever you like with Dashy: use it in private or commercial settings,_
_redistribute and modify it. But you must display this license and credit the author._
_There is no warranty that this app will work as expected, and the author cannot be held_
_liable for anything that goes wrong._
For more info, see TLDR Legal's [Explanation of MIT](https://tldrlegal.com/license/mit-license)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FLissy93%2Fdashy.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FLissy93%2Fdashy?ref=badge_large)
**[⬆️ Back to Top](#dashy)**
---
<p align="center">
<br>
<a href="https://dashboard.trackgit.com/token/ks0bx7bb14lsvbwoc3ik">
<img src="https://us-central1-trackgit-analytics.cloudfunctions.net/token/ping/ks0bx7bb14lsvbwoc3ik?style=flat-square" />
</a>
<br><br>
<a href="https://github.com/Lissy93/dashy">
<img src="https://github.githubassets.com/images/icons/emoji/octocat.png" />
</a>
<br><br>
<i>Thank you for Visiting</i>
</p>

17
app.json Normal file
View File

@@ -0,0 +1,17 @@
{
"name": "Dashy",
"website": "https://dashy.to/",
"description": "A Dashboard for your Homelab 🚀",
"repository": "https://github.com/lissy93/dashy",
"logo": "https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/logo.png",
"keywords": [
"node",
"vue",
"static",
"dashboard",
"self-hosted",
"home-lab",
"lissy93"
],
"stack": "heroku-20"
}

50
docker-compose.yml Normal file
View File

@@ -0,0 +1,50 @@
---
# Welcome to Dashy! To get started, run `docker compose up -d`
# You can configure your container here, by modifying this file
version: "3.8"
services:
dashy:
container_name: Dashy
# Pull latest image from DockerHub
# image: lissy93/dashy
# To build from source, replace 'image: lissy93/dashy' with 'build: .'
build: .
# Or, to use a Dockerfile for your archtecture, uncomment the following
# context: .
# dockerfile: ./docker/Dockerfile-arm32v7
# You can also use an image with a different tag, or pull from a different registry, e.g:
# image: ghcr.io/lissy93/dashy or image: lissy93/dashy:arm64v8
# Pass in your config file below, by specifying the path on your host machine
volumes:
- .:/app
# - /path/to/my-config.yml:/app/public/conf.yml
# - /path/to/item-icons:/app/public/item-icons
# Set port that web service will be served on. Keep container port as 80
ports:
- 4000:4000
# Set any environmental variables
environment:
- NODE_ENV=development
# Specify your user ID and group ID. You can find this by running `id -u` and `id -g`
# - UID=1000
# - GID=1000
# Specify restart policy
restart: unless-stopped
# Configure healthchecks
# healthcheck:
# test: ['CMD', 'node', '/app/services/healthcheck']
# interval: 1m30s
# timeout: 10s
# retries: 3
# start_period: 40s
# entrypoint: ["yarn", "dev"]

22
docker-push.sh Normal file
View File

@@ -0,0 +1,22 @@
!/bin/bash
image="git.rssa.top/kanzi/dashy"
#get timestamp for the tag
timestamp=$(date +%Y%m%d%H%M%S)
tag=$image:$timestamp
latest=$image:latest
#build image
docker build -t $tag .
docker tag $tag $latest
#push to dockerhub
docker login git.rssa.top
#sudo docker login -u username -p password
docker push $tag
docker push $latest
#remove dangling images
docker system prune -f

43
docker/Dockerfile-arm32v7 Normal file
View File

@@ -0,0 +1,43 @@
FROM alpine:3.12 AS builder
# Download QEMU, see https://github.com/docker/hub-feedback/issues/1261
RUN QEMU_URL=https://github.com/balena-io/qemu/releases/download/v5.2.0%2Bbalena4/qemu-5.2.0.balena4-arm.tar.gz \
&& apk add curl && curl -L $QEMU_URL | tar zxvf - -C . --strip-components 1
# Start second (arm32v7) stage
FROM arm32v7/alpine:3.12
# Add QEMU from build stage
COPY --from=builder qemu-arm-static /usr/bin
# Install Node and Yarn
RUN apk add --update --no-cache nodejs npm yarn
# Define some ENV Vars
ENV PORT=80 \
DIRECTORY=/app \
IS_DOCKER=true
# Create and set the working directory
WORKDIR ${DIRECTORY}
# Copy over both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./
# Install project dependencies
RUN yarn
# Copy over all project files and folders to the working directory
COPY . .
# Build initial app for production
RUN yarn build
# Expose given port
EXPOSE ${PORT}
# Finally, run start command to serve up the built application
CMD [ "yarn", "build-and-start"]
# Run simple healthchecks every 5 mins, to check the Dashy's everythings great
HEALTHCHECK --interval=5m --timeout=2s --start-period=30s CMD yarn health-check

43
docker/Dockerfile-arm64v8 Normal file
View File

@@ -0,0 +1,43 @@
FROM alpine:3.12 AS builder
# Download QEMU, see https://github.com/docker/hub-feedback/issues/1261
RUN QEMU_URL=https://github.com/balena-io/qemu/releases/download/v5.2.0%2Bbalena4/qemu-5.2.0.balena4-aarch64.tar.gz \
&& apk add curl && curl -L $QEMU_URL | tar zxvf - -C . --strip-components 1
# Start second (arm64v8) stage
FROM arm64v8/alpine:3.12
# Add QEMU from build stage
COPY --from=builder qemu-aarch64-static /usr/bin
# Install Node and Yarn
RUN apk add --update --no-cache nodejs npm yarn
# Define some ENV Vars
ENV PORT=80 \
DIRECTORY=/app \
IS_DOCKER=true
# Create and set the working directory
WORKDIR ${DIRECTORY}
# Copy over both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./
# Install project dependencies
RUN yarn
# Copy over all project files and folders to the working directory
COPY . .
# Build initial app for production
RUN yarn build
# Expose given port
EXPOSE ${PORT}
# Finally, run start command to serve up the built application
CMD [ "yarn", "build-and-start"]
# Run simple healthchecks every 5 mins, to check the Dashy's everythings great
HEALTHCHECK --interval=5m --timeout=2s --start-period=30s CMD yarn health-check

22
docker/Dockerfile-lite Normal file
View File

@@ -0,0 +1,22 @@
# -----------------------------------------------------------------------------------------
# A light-weight alternative Docker image, using NGINX rather than Node.js to serve the app
# This means that certain features that require server-side endpoints will not be available
# -----------------------------------------------------------------------------------------
# Build Stage - Install dependencies + build the app
FROM node:lts-alpine3.14 as build
WORKDIR /dashy
COPY package*.json .
COPY yarn.lock .
RUN yarn
COPY . .
RUN yarn build
# Production Stage - Serve up built files with NGINX
FROM nginx:alpine as production
COPY ./docker/nginx.conf /etc/nginx/nginx.conf
COPY --from=build /dashy/dist /usr/share/nginx/html
EXPOSE 80
ENTRYPOINT ["nginx", "-g", "daemon off;"]
LABEL maintainer="Alicia Sykes <alicia@omg.lol>"

31
docker/Dockerfile-old Normal file
View File

@@ -0,0 +1,31 @@
FROM node:lts-alpine3.14
# Define some ENV Vars
ENV PORT=80 \
DIRECTORY=/app \
IS_DOCKER=true
# Create and set the working directory
WORKDIR ${DIRECTORY}
# Copy over both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./
COPY yarn.lock ./
# Install project dependencies
RUN yarn
# Copy over all project files and folders to the working directory
COPY . .
# Build initial app for production
RUN yarn build
# Expose given port
EXPOSE ${PORT}
# Finally, run start command to serve up the built application
CMD [ "yarn", "build-and-start"]
# Run simple healthchecks every 5 mins, to check the Dashy's everythings great
HEALTHCHECK --interval=5m --timeout=2s --start-period=30s CMD yarn health-check

136
docker/docker-readme.md Normal file
View File

@@ -0,0 +1,136 @@
<h1 align="center">Dashy</h1>
<p align="center">
<i>Dashy helps you organize your self-hosted services by making them accessible from a single place</i>
<br/>
<img width="120" src="https://i.ibb.co/yhbt6CY/dashy.png" />
<br/>
<b><a href="https://github.com/Lissy93/dashy/blob/master/docs/showcase.md">User Showcase</a></b> | <b><a href="https://demo.dashy.to">Live Demo</a></b> | <b><a href="https://github.com/Lissy93/dashy/blob/master/docs/quick-start.md">Getting Started</a></b> | <b><a href="https://dashy.to/docs">Documentation</a></b> | <b><a href="https://github.com/Lissy93/dashy">GitHub</a></b>
<br/><br/>
<a href="https://github.com/awesome-selfhosted/awesome-selfhosted#personal-dashboards">
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome Self-Hosted">
</a>
<a href="https://github.com/Lissy93/dashy/blob/master/LICENSE">
<img src="https://img.shields.io/badge/License-MIT-0aa8d2?logo=opensourceinitiative&logoColor=fff" alt="License MIT">
</a>
<a href="https://github.com/Lissy93/dashy/blob/master/.github/CHANGELOG.md">
<img src="https://img.shields.io/github/package-json/v/lissy93/dashy?logo=azurepipelines&amp;color=0aa8d2" alt="Current Version">
</a>
<a href="https://hub.docker.com/r/lissy93/dashy">
<img src="https://img.shields.io/docker/pulls/lissy93/dashy?logo=docker&color=0aa8d2&logoColor=fff" alt="Docker Pulls">
</a>
<a href="http://as93.link/dashy-build-status">
<img src="https://badgen.net/github/status/lissy93/dashy?icon=github" alt="GitHub Status">
</a>
<a href="https://snyk.io/test/github/lissy93/dashy">
<img src="https://snyk.io/test/github/lissy93/dashy/badge.svg" alt="Known Vulnerabilities">
</a>
</p>
## Features 🌈
- 🔎 Instant search by name, domain, or tags + customizable hotkeys & keyboard shortcuts
- 🎨 Multiple built-in color themes, with UI color editor and support for custom CSS
- 🧸 Many icon options - Font-Awesome, homelab icons, auto-fetching Favicon, images, emojis, etc.
- 🚦 Status monitoring for each of your apps/links for basic availability and uptime checking
- 📊 Widgets for displaying info and dynamic content from your self-hosted services
- 💂 Optional authentication with multi-user access, configurable privileges, and SSO support
- 🌎 Multi-language support, with 10+ human-translated languages, and more on the way
- ☁ Optional, encrypted, free off-site cloud backup and restore feature available
- 💼 A workspace view, for easily switching between multiple apps simultaneously
- 🛩️ A minimal view, for use as a fast-loading browser Startpage
- 🖱️ Choose app launch method, either new tab, same tab, a pop-up modal, or in the workspace view
- 📏 Customizable layout, sizes, text, component visibility, sort order, behavior, etc.
- 🖼️ Options for a full-screen background image, custom nav-bar links, HTML footer, title, etc.
- 🚀 Easy to setup with Docker, or on bare metal, or with 1-Click cloud deployment
- ⚙️ Easy configuration, either through the UI, or using a YAML file
- ✨ Under active development with improvements and new features added regularly
- 🤏 Small bundle size, fully responsive UI, and PWA for basic offline access
- 🆓 100% free and open-source
- 🔐 Strong focus on privacy
- 🌈 And loads more...
## Demo ⚡
**Live Instances**: [Demo 1](https://demo.dashy.to) (Live Demo) ┆ [Demo 2](https://live.dashy.to) (Dashy Links) ┆ [Demo 3](https://dev.dashy.to) (Dev Preview)
**Screenshots**: Checkout the [Showcase](https://github.com/Lissy93/dashy/blob/master/docs/showcase.md), to see example dashboards from the community
**Spin up your own demo**: [![One-Click Deploy with PWD](https://img.shields.io/badge/Play--with--Docker-Deploy-2496ed?style=flat-square&logo=docker)](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml) or [`docker run -p 8080:80 lissy93/dashy`](./docs/quick-start.md)
<p align="center">
<img width="800" src="https://i.ibb.co/L8YbNNc/dashy-demo2.gif" alt="Demo" />
</p>
**[⬆️ Back to Top](#dashy)**
---
## Getting Started 🛫
To deploy Dashy with Docker, just run `docker run -p 8080:80 lissy93/dashy`, then open `http://localhost:8080`
For full list of options and a Docker compose file, see the [Deployment Docs](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md).
Dashy can also be run on bare metal using Node.js, or deployed to a cloud service, using the 1-Click deploy script.
---
## Documentation 📝
#### Running Dashy
- **[Quick Start](https://github.com/Lissy93/dashy/blob/master/docs/quick-start.md)** - TDLR guide on getting Dashy up and running
- **[Deployment](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md)** - Full guide on deploying Dashy either locally or online
- **[Configuring](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md)** - Complete list of all available options in the config file
- **[App Management](https://github.com/Lissy93/dashy/blob/master/docs/management.md)** - Managing your app, updating, security, web server configuration, etc
- **[Troubleshooting](https://github.com/Lissy93/dashy/blob/master/docs/troubleshooting.md)** - Common errors and problems, and how to fix them
#### Feature Docs
- **[Authentication](https://github.com/Lissy93/dashy/blob/master/docs/authentication.md)** - Guide to setting up authentication to protect your dashboard
- **[Alternate Views](https://github.com/Lissy93/dashy/blob/master/docs/alternate-views.md)** - Outline of available pages / views and item opening methods
- **[Backup & Restore](https://github.com/Lissy93/dashy/blob/master/docs/backup-restore.md)** - Guide to backing up config with Dashy's cloud sync feature
- **[Icons](https://github.com/Lissy93/dashy/blob/master/docs/icons.md)** - Outline of all available icon types for sections and items, with examples
- **[Language Switching](https://github.com/Lissy93/dashy/blob/master/docs/multi-language-support.md)** - Details on how to switch language, or add a new locale
- **[Status Indicators](https://github.com/Lissy93/dashy/blob/master/docs/status-indicators.md)** - Using Dashy to monitor uptime and status of your apps
- **[Searching & Shortcuts](https://github.com/Lissy93/dashy/blob/master/docs/searching.md)** - Searching, launching methods + keyboard shortcuts
- **[Theming](https://github.com/Lissy93/dashy/blob/master/docs/theming.md)** - Complete guide to applying, writing and modifying themes + styles
- **[Widgets](https://github.com/Lissy93/dashy/blob/master/docs/widgets.md)** - List of all dynamic content widgets, with usage guides and examples
#### Development and Contributing
- **[Developing](https://github.com/Lissy93/dashy/blob/master/docs/developing.md)** - Running Dashy development server locally, and general workflow
- **[Development Guides](https://github.com/Lissy93/dashy/blob/master/docs/development-guides.md)** - Common development tasks, to help new contributors
- **[Contributing](https://github.com/Lissy93/dashy/blob/master/docs/contributing.md)** - How you can help keep Dashy alive
- **[Showcase](https://github.com/Lissy93/dashy/blob/master/docs/showcase.md)** - See how others are using Dashy, and share your dashboard
- **[Credits](https://github.com/Lissy93/dashy/blob/master/docs/credits.md)** - List of people and projects that have made Dashy possible
- **[Release Workflow](https://github.com/Lissy93/dashy/blob/master/docs/release-workflow.md)** - Info about releases, CI and automated tasks
---
## License 📜
Dashy is Licensed under [MIT X11](https://en.wikipedia.org/wiki/MIT_License)
```
Copyright © 2021 Alicia Sykes <https://aliciasykes.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, Dashy shall not be used in advertising or otherwise
to promote the sale, use, or other dealings in this Software without prior written
authorization from the repo owner.
```

8
docker/hooks/pre_build Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
# Used to setup QEMU to build arm images on amd64 processors.
# Source: https://git.io/J0ezo
# Register qemu-*-static for all supported processors except the
# current one, but also remove all registered binfmt_misc before
docker run --rm --privileged multiarch/qemu-user-static:register --reset

15
docker/nginx.conf Normal file
View File

@@ -0,0 +1,15 @@
worker_processes 4;
events { worker_connections 1024; }
http {
server {
listen 80;
root /usr/share/nginx/html;
include /etc/nginx/mime.types;
location /appui {
try_files $uri /index.html;
}
}
}

64
docs/alternate-views.md Normal file
View File

@@ -0,0 +1,64 @@
# Alternate Views & Opening Methods
## Views
Dashy has three different views:
- Default View - This is the main homepage with sections in a grid layout
- Workspace View - Items displayed on the side, and are launched within Dashy
- Minimal View - A clean + simple tabbed view
You can switch between views using the dropdown in the top-right corner. Set your chosen Starting View with `appConfig.startingView`. Click the page title at any time to go back to your selected starting view.
### Default
This is the main page that you will land on when you first launch the application. Here all of your sections (with items + widgets) are visible in a grid layout.
<p align="center">
<b>Example of Default View</b><br>
<img width="800" src="https://i.ibb.co/L8YbNNc/dashy-demo2.gif" alt="Demo" />
</p>
### Workspace
The workspace view displays your links in a sidebar on the left-hand side, and apps are launched inside an iframe without having to leave Dashy. This enables you to use all of your self-hosted apps from one place, and makes multi-tasking easy.
You can specify a default app to be opened when you land on the workspace, by setting `appConfig.workspaceLandingUrl: https://app-to-open/`. If this app exists within your sections.items, then the corresponding section will also be expanded.
You can also opt to keep previously opened websites/ apps open in the background, by setting `appConfig.enableMultiTasking: true`. This comes at the cost of performance, but does mean that your session with each app is preserved, enabling you to quickly switch between them.
<p align="center">
<b>Example of Workspace View</b><br>
<img alt="Workspace view demo" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/workspace-demo.gif" width="800" />
</p>
### Minimal View
The minimal view aims to be super fast and simple, and can be used as a browser startpage. Items are grouped into a tab view, and the last opened tab will be remembered. Similar to the main view, you can search and launch items just by typing, and right-clicking will show more options (like open in modal, workspace or new tab).
<p align="center">
<b>Example of Minimal View</b><br>
<img alt="Workspace view demo" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/minimal-view-demo.gif" width="800" />
</p>
## Opening Methods
Dashy supports several different ways to launch your apps. The primary opening method for each app can be specified using the `target` attribute, with a value of one of the following:
- `sametab` - The app will be launched in the current tab
- `newtab` - The app will be launched in a new tab
- `top` - Opens in the top-most browsing context, useful if you're accessing Dashy through an iframe
- `modal` - Launch app in a resizable/ movable popup modal on the current page
- `workspace` - Changes to Workspace view, and launches app
You can also set a default opening method, which will be applied to all items that don't have a specified target, using `appConfig.defaultOpeningMethod`, to one of the above values.
Even if the target is not set (or is set to `sametab`), you can still launch any given app in an alternative method. Either right-click to see all options, or use one of the keyboard shortcuts: Alt + Click will open the modal, and Ctrl + Click will open in a new tab.
<p align="center">
<img width="500" src="https://i.ibb.co/vmZdSRt/dashy-context-menu-2.png" />
</p>
If you don't like the custom context menu, it can be disabled by setting `appConfig.disableContextMenu: true`.
If you get a 'Refused to Connect' error in the modal or workspace views, then the target app has it's X-Frame-Options HTTP set to block requests from embedded content. You can easily fix this by setting this header to ALLOW, for instructions on how to do so, see the [Troubleshooting Docs](/docs/troubleshooting.md#refused-to-connect-in-modal-or-workspace-view).

View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
docs/assets/logo.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 93 KiB

View File

@@ -0,0 +1,7 @@
<svg width="223px" height="30px" version="1.1" viewBox="0 0 223 30" xmlns="http://www.w3.org/2000/svg">
<title>Artboard</title>
<desc>Created with Sketch.</desc>
<rect id="Rectangle" width="223" height="30" rx="8" fill="#ff5e5b" style="fill-rule:evenodd;fill:#ff8eff"/>
<path d="m19.011 10.912c0.57462-1.6874 1.9364-2.531 4.0853-2.531 3.2234 0 4.4184 4.0247 2.7288 6.6559-1.1264 1.7541-3.3978 3.9728-6.8141 6.6559-3.4163-2.6832-5.6877-4.9018-6.8141-6.6559-1.6896-2.6312-0.49462-6.6559 2.7288-6.6559 2.1489 0 3.5107 0.84368 4.0853 2.531z" fill="#ff5e5b" style="fill:none;stroke-width:1.5;stroke:#fff"/>
<text x="55" y="20" style="fill:#ffffff;font-family:sans-serif;font-size:16px;letter-spacing:0px;line-height:1.25;word-spacing:0px" xml:space="preserve"><tspan x="31.423412" y="20.493532" style="fill:#ffffff;font-size:16px">Sponsor me on Github</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 873 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

350
docs/authentication.md Normal file
View File

@@ -0,0 +1,350 @@
# Authentication
- [Basic Auth](#built-in-auth)
- [Setting Up Authentication](#setting-up-authentication)
- [Hash Password](#hash-password)
- [Logging In and Out](#logging-in-and-out)
- [Guest Access](#enabling-guest-access)
- [Per-User Access](#granular-access)
- [Security Considerations](#security)
- [Keycloak Auth](#keycloak)
- [Deploying Keycloak](#1-deploy-keycloak)
- [Setting up Keycloak](#2-setup-keycloak-users)
- [Configuring Dashy for Keycloak](#3-enable-keycloak-in-dashy-config-file)
- [Alternative Authentication Methods](#alternative-authentication-methods)
- [VPN](#vpn)
- [IP-Based Access](#ip-based-access)
- [Web Server Authentication](#web-server-authentication)
- [OAuth Services](#oauth-services)
- [Auth on Cloud Hosting Services](#static-site-hosting-providers)
## Built-In Auth
Dashy has a basic login page included, and frontend authentication. You can enable this by adding users to the `auth` section under `appConfig` in your `conf.yml`. If this section is not specified, then no authentication will be required to access the app, and the homepage will resolve to your dashboard.
### Setting Up Authentication
The `auth` property takes an array of users. Each user needs to include a username, hash and optional user type (`admin` or `normal`). The hash property is a [SHA-256 Hash](https://en.wikipedia.org/wiki/SHA-2) of your desired password.
For example:
```yaml
appConfig:
auth:
users:
- user: alicia
hash: 4D1E58C90B3B94BCAD9848ECCACD6D2A8C9FBC5CA913304BBA5CDEAB36FEEFA3
type: admin
- user: bob
hash: 5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8
```
### Hash Password
Dashy uses [SHA-256 Hash](https://en.wikipedia.org/wiki/Sha-256), a 64-character string, which you can generate using an online tool, such as [this one](https://passwordsgenerator.net/sha256-hash-generator/) or [CyberChef](https://gchq.github.io/CyberChef/) (which can be self-hosted/ ran locally).
A hash is a one-way cryptographic function, meaning that it is easy to generate a hash for a given password, but very hard to determine the original password for a given hash. This means, that so long as your password is long, strong and unique, it is safe to store its hash in the clear. Having said that, you should never reuse passwords, hashes can be cracked by iterating over known password lists, generating a hash of each.
### Logging In and Out
Once authentication is enabled, so long as there is no valid token in cookie storage, the application will redirect the user to the login page. When the user enters credentials in the login page, they will be checked, and if valid, then a token will be generated, and they can be redirected to the home page. If credentials are invalid, then an error message will be shown, and they will remain on the login page. Once in the application, to log out: the user can click the logout button (in the top-right), which will clear cookie storage, causing them to be redirected back to the login page.
### Enabling Guest Access
With authentication set up, by default no access is allowed to your dashboard without first logging in with valid credentials. Guest mode can be enabled to allow for read-only access to a secured dashboard by any user, without the need to log in. A guest user cannot write any changes to the config file, but can apply modifications locally (stored in their browser). You can enable guest access, by setting `appConfig.auth.enableGuestAccess: true`.
### Granular Access
You can use the following properties to make certain sections or items only visible to some users, or hide sections and items from guests.
- `hideForUsers` - Section or Item will be visible to all users, except for those specified in this list
- `showForUsers` - Section or Item will be hidden from all users, except for those specified in this list
- `hideForGuests` - Section or Item will be visible for logged in users, but not for guests
For Example:
```yaml
- name: Code Analysis & Monitoring
icon: fas fa-code
displayData:
cols: 2
hideForUsers: [alicia, bob]
items:
...
```
```yaml
- name: Deployment Pipelines
icon: fas fa-rocket
displayData:
hideForGuests: true
items:
- title: Hide Me
displayData:
hideForUsers: [alicia, bob]
```
### Permissions
Any user who is not an admin (with `type: admin`) will not be able to write changes to disk.
You can also prevent any user from writing changes to disk, using `preventWriteToDisk`. Or prevent any changes from being saved locally in browser storage, using `preventLocalSave`. Both properties can be found under [`appConfig`](./docs/configuring.md#appconfig-optional).
To disable all UI config features, including View Config, set `disableConfiguration`. Alternatively you can disable UI config features for all non admin users by setting `disableConfigurationForNonAdmin` to true.
### Security
With basic auth, all logic is happening on the client-side, which could mean a skilled user could manipulate the code to view parts of your configuration, including the hash. If the SHA-256 hash is of a common password, it may be possible to determine it, using a lookup table, in order to find the original password. Which can be used to manually generate the auth token, that can then be inserted into session storage, to become a valid logged in user. Therefore, you should always use a long, strong and unique password, and if you instance contains security-critical info and/ or is exposed directly to the internet, and alternative authentication method may be better. The purpose of the login page is merely to prevent immediate unauthorized access to your homepage.
**[⬆️ Back to Top](#authentication)**
---
## Keycloak
Dashy also supports using a [Keycloak](https://www.keycloak.org/) authentication server. The setup for this is a bit more involved, but it gives you greater security overall, useful for if your instance is exposed to the internet.
[Keycloak](https://www.keycloak.org/about.html) is a Java-based [open source](https://github.com/keycloak/keycloak), high-performance, secure authentication system, supported by [RedHat](https://www.redhat.com/en). It is easy to setup ([with Docker](https://quay.io/repository/keycloak/keycloak)), and enables you to secure multiple self-hosted applications with single-sign-on using standard protocols (OpenID Connect, OAuth 2.0, SAML 2.0 and social login). It's also very customizable, you can write or use custom [themes](https://wjw465150.gitbooks.io/keycloak-documentation/content/server_development/topics/themes.html), [plugins](https://www.keycloak.org/extensions.html), [password policies](https://wjw465150.gitbooks.io/keycloak-documentation/content/server_admin/topics/authentication/password-policies.html) and more.
The following guide will walk you through setting up Keycloak with Dashy. If you already have a Keycloak instance configured, then skip to Step 3.
### 1. Deploy Keycloak
First thing to do is to spin up a new instance of Keycloak. You will need [Docker installed](https://docs.docker.com/engine/install/), and can then choose a tag, and pull the container from [quay.io/keycloak/keycloak](https://quay.io/repository/keycloak/keycloak)
Use the following run command, replacing the attributes (default credentials, port and name), or incorporate this into your docker-compose file.
```bash
docker run -d \
-p 8081:8080 \
--name auth-server \
-e KEYCLOAK_USER=admin \
-e KEYCLOAK_PASSWORD=admin \
quay.io/keycloak/keycloak:15.0.2
```
If you need to pull from DockerHub, a non-official image is available [here](https://registry.hub.docker.com/r/jboss/keycloak). Or if you would prefer not to use Docker, you can also directly install Keycloak from source, following [this guide](https://www.keycloak.org/docs/latest/getting_started/index.html).
You should now be able to access the Keycloak web interface, using the port specified above (e.g. `http://127.0.0.1:8081`), login with the default credentials, and when prompted create a new password.
### 2. Setup Keycloak Users
Before we can use Keycloak, we must first set it up with some users. Keycloak uses Realms (similar to tenants) to create isolated groups of users. You must create a Realm before you will be able to add your first user.
1. Head over to the admin console
2. In the top-left corner there is a dropdown called 'Master', hover over it and then click 'Add Realm'
3. Give your realm a name, and hit 'Create'
You can now create your first user.
1. In the left-hand menu, click 'Users', then 'Add User'
2. Fill in the form, including username and hit 'Save'
3. Under the 'Credentials' tab, give the new user an initial password. They will be prompted to change this after first login
The last thing we need to do in the Keycloak admin console is to create a new client
1. Within your new realm, navigate to 'Clients' on the left-hand side, then click 'Create' in the top-right
2. Choose a 'Client ID', set 'Client Protocol' to 'openid-connect', and for 'Valid Redirect URIs' put a URL pattern to where you're hosting Dashy (if you're just testing locally, then * is fine), and do the same for the 'Web Origins' field
3. Make note of your client-id, and click 'Save'
### 3. Enable Keycloak in Dashy Config File
Now that your Keycloak instance is up and running, all that's left to do is to configure Dashy to use it. Under `appConfig`, set `auth.enableKeycloak: true`, then fill in the details in `auth.keycloak`, including: `serverUrl` - the URL where your Keycloak instance is hosted, `realm` - the name you gave your Realm, and `clientId` - the Client ID you chose.
For example:
```yaml
appConfig:
...
auth:
enableKeycloak: true
keycloak:
serverUrl: 'http://localhost:8081'
realm: 'alicia-homelab'
clientId: 'dashy'
```
Note that if you are using Keycloak V 17 or older, you will also need to set `legacySupport: true` (also under `appConfig.auth.keycloak`). This is because the API endpoint was updated in later versions.
If you use Keycloak with an external Identity Provier, you can set the `idpHint: 'alias-of-kc-idp'` option to allow the IdP Hint to be passed to Keycloak. This will cause Keycloak to skip its login page and redirect the user directly to the specified IdP's login page. Set to the value of the 'Alias' field of the desired IdP as defined in Keycloak under 'Identity Providers'.
### 4. Add groups and roles (Optional)
Keycloak allows you to assign users roles and groups. You can use these values to configure who can access various sections or items in Dashy.
Keycloak server administration and configuration is a deep topic; please refer to the [server admin guide](https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-and-access-using-roles-and-groups) to see details about creating and assigning roles and groups.
Once you have groups or roles assigned to users you can configure access under each section or item `displayData.showForKeycloakUser` and `displayData.hideForKeycloakUser`.
Both show and hide configurations accept a list of `groups` and `roles` that limit access. If a users data matches one or more items in these lists they will be allowed or excluded as defined.
```yaml
sections:
- name: DeveloperResources
displayData:
showForKeycloakUsers:
roles: ['canViewDevResources']
hideForKeycloakUsers:
groups: ['ProductTeam']
items:
- title: Not Visible for developers
displayData:
hideForKeycloakUsers:
groups: ['DevelopmentTeam']
```
Depending on how you're hosting Dashy and Keycloak, you may also need to set some HTTP headers, to prevent a CORS error. This would typically be the `Access-Control-Allow-Origin [URL-of Dashy]` on your Keycloak instance. See the [Setting Headers](https://github.com/Lissy93/dashy/blob/master/docs/management.md#setting-headers) guide in the management docs for more info.
Your app is now secured :) When you load Dashy, it will redirect to your Keycloak login page, and any user without valid credentials will be prevented from accessing your dashboard.
From within the Keycloak console, you can then configure things like time-outs, password policies, etc. You can also backup your full Keycloak config, and it is recommended to do this, along with your Dashy config. You can spin up both Dashy and Keycloak simultaneously and restore both applications configs using a `docker-compose.yml` file, and this is recommended.
---
## Alternative Authentication Methods
If you are self-hosting Dashy, and require secure authentication to prevent unauthorized access, then you can either use Keycloak, or one of the following options:
- [Authentication Server](#authentication-server) - Put Dashy behind a self-hosted auth server
- [VPN](#vpn) - Use a VPN to tunnel into the network where Dashy is running
- [IP-Based Access](#ip-based-access) - Disallow access from all IP addresses, except your own
- [Web Server Authentication](#web-server-authentication) - Enable user control within your web server or proxy
- [OAuth Services](#oauth-services) - Implement a user management system using a cloud provider
- [Password Protection (for cloud providers)](#static-site-hosting-providers) - Enable password-protection on your site
### Authentication Server
#### Authelia
[Authelia](https://www.authelia.com/) is an open-source full-featured authentication server, which can be self-hosted and either on bare metal, in a Docker container or in a Kubernetes cluster. It allows for fine-grained access control rules based on IP, path, users etc, and supports 2FA, simple password access or bypass policies for your domains.
- `git clone https://github.com/authelia/authelia.git`
- `cd authelia/examples/compose/lite`
- Modify the `users_database.yml` the default username and password is authelia
- Modify the `configuration.yml` and `docker-compose.yml` with your respective domains and secrets
- `docker-compose up -d`
For more information, see the [Authelia docs](https://www.authelia.com/docs/)
### VPN
A catch-all solution to accessing services running from your home network remotely is to use a VPN. It means you do not need to worry about implementing complex authentication rules, or trusting the login implementation of individual applications. However it can be inconvenient to use on a day-to-day basis, and some public and corporate WiFi block VPN connections. Two popular VPN protocols are [OpenVPN](https://openvpn.net/) and [WireGuard](https://www.wireguard.com/)
### IP-Based Access
If you have a static IP or use a VPN to access your running services, then you can use conditional access to block access to Dashy from everyone except users of your pre-defined IP address. This feature is offered by most cloud providers, and supported by most web servers.
#### Apache
In Apache, this is configured in your `.htaccess` file in Dashy's root folder, and should look something like:
```text
Order Deny,Allow
Deny from all
Allow from [your-ip]
```
#### NGINX
In NGINX you can specify [control access](https://docs.nginx.com/nginx/admin-guide/security-controls/controlling-access-proxied-http/) rules for a given site in your `nginx.conf` or hosts file. For example:
```text
server {
listen 80;
server_name www.dashy.example.com;
location / {
root /path/to/dashy/;
passenger_enabled on;
allow [your-ip];
deny all;
}
}
```
#### Caddy
In Caddy, [Request Matchers](https://caddyserver.com/docs/caddyfile/matchers) can be used to filter requests
```text
dashy.site {
@public_networks not remote_ip [your-ip]
respond @public_networks "Access denied" 403
}
```
### Web Server Authentication
Most web servers make password protecting certain apps very easy. Note that you should also set up HTTPS and have a valid certificate in order for this to be secure.
#### Apache
First crate a `.htaccess` file in Dashy's route directory. Specify the auth type and path to where you want to store the password file (usually the same folder). For example:
```text
AuthType Basic
AuthName "Please Sign into Dashy"
AuthUserFile /path/dashy/.htpasswd
require valid-user
```
Then create a `.htpasswd` file in the same directory. List users and their hashed passwords here, with one user on each line, and a colon between username and password (e.g. `[username]:[hashed-password]`). You will need to generate an MD5 hash of your desired password, this can be done with an [online tool](https://www.web2generators.com/apache-tools/htpasswd-generator). Your file will look something like:
```text
alicia:$apr1$jv0spemw$RzOX5/GgY69JMkgV6u16l0
```
#### NGINX
NGINX has an [authentication module](https://nginx.org/en/docs/http/ngx_http_auth_basic_module.html) which can be used to add passwords to given sites, and is fairly simple to set up. Similar to above, you will need to create a `.htpasswd` file. Then just enable auth and specify the path to that file, for example:
```text
location / {
auth_basic "closed site";
auth_basic_user_file conf/htpasswd;
}
```
#### Caddy
Caddy has a [basic-auth](https://caddyserver.com/docs/caddyfile/directives/basicauth) directive, where you specify a username and hash. The password hash needs to be base-64 encoded, the [`caddy hash-password`](https://caddyserver.com/docs/command-line#caddy-hash-password) command can help with this. For example:
```text
basicauth /secret/* {
alicia JDJhJDEwJEVCNmdaNEg2Ti5iejRMYkF3MFZhZ3VtV3E1SzBWZEZ5Q3VWc0tzOEJwZE9TaFlZdEVkZDhX
}
```
For more info about implementing a single sign on for all your apps with Caddy, see [this tutorial](https://joshstrange.com/securing-your-self-hosted-apps-with-single-signon/)
#### Lighttpd
You can use the [mod_auth](https://doc.lighttpd.net/lighttpd2/mod_auth.html) module to secure your site with Lighttpd. Like with Apache, you need to first create a password file listing your usernames and hashed passwords, but in Lighttpd, it's usually called `.lighttpdpassword`.
Then in your `lighttpd.conf` file (usually in the `/etc/lighttpd/` directory), load in the mod_auth module, and configure it's directives. For example:
```text
server.modules += ( "mod_auth" )
auth.debug = 2
auth.backend = "plain"
auth.backend.plain.userfile = "/home/lighttpd/.lighttpdpassword"
$HTTP["host"] == "dashy.my-domain.net" {
server.document-root = "/home/lighttpd/dashy.my-domain.net/http"
server.errorlog = "/var/log/lighttpd/dashy.my-domain.net/error.log"
accesslog.filename = "/var/log/lighttpd/dashy.my-domain.net/access.log"
auth.require = (
"/docs/" => (
"method" => "basic",
"realm" => "Password protected area",
"require" => "user=alicia"
)
)
}
```
Restart your web server for changes to take effect.
### OAuth Services
There are also authentication services, such as [Ory.sh](https://www.ory.sh/), [Okta](https://developer.okta.com/), [Auth0](https://auth0.com/), [Firebase](https://firebase.google.com/docs/auth/). Implementing one of these solutions would involve some changes to the [`Auth.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/Auth.js) file, but should be fairly straightforward.
### Static Site Hosting Providers
If you are hosting Dashy on a cloud platform, you will probably find that it has built-in support for password protected access to web apps. For more info, see the relevant docs for your provider, for example: [Netlify Password Protection](https://docs.netlify.com/visitor-access/password-protection/), [Cloudflare Access](https://www.cloudflare.com/teams/access/), [AWS Cognito](https://aws.amazon.com/cognito/), [Azure Authentication](https://docs.microsoft.com/en-us/azure/app-service/scenario-secure-app-authentication-app-service) and [Vercel Password Protection](https://vercel.com/docs/platform/projects#password-protection).
**[⬆️ Back to Top](#authentication)**

111
docs/backup-restore.md Normal file
View File

@@ -0,0 +1,111 @@
# Cloud Backup and Restore
Dashy has a built-in feature for securely backing up your config to a hosted cloud service, and then restoring it on another instance. This feature is totally optional, and if you do not enable it, then Dashy will not make any external network requests.
This is useful not only for backing up your configuration off-site, but it also enables Dashy to be used without having write a YAML config file, and makes it possible to use a public hosted instance, without the need to self-host.
<p align="center">
<img src="https://i.ibb.co/p4pxSqX/dashy-backup-restore.png" width="600" />
</p>
## How it Works
All data is encrypted before being sent to the backend. In Dashy, this is done in [`CloudBackup.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/CloudBackup.js), using [crypto.js](https://github.com/brix/crypto-js)'s AES method, using the users chosen password as the key. The data is then sent to a [Cloudflare worker](https://developers.cloudflare.com/workers/learning/how-workers-works) (a platform for running serverless functions), and stored in a [KV](https://developers.cloudflare.com/workers/learning/how-kv-works) data store.
## Creating a Backup
Once you've got Dashy configured to your preference, open the Backup & Restore menu (click the Cloud icon in the top-right corner). Here you will be prompted to choose a password, which will be used to encrypt your data. If you forget this password, there will be no way to recover your config. After clicking 'Backup' your data will be encrypted, compressed and sent to the hosted cloud service. A backup ID will be returned (in the format of xxxx-xxxx-xxxx-xxxx), this is what you use, along with your password to restore the backup on another system, so take note of it. To update a backup, return to this menu, enter your password, and click 'Update Backup'.
## Restoring a Backup
To restore a backup, navigate to the Backup & Restore menu, and under restore, enter your backup ID, and the password you chose. Your config file will be downloaded, decrypted and applied to local storage.
## Privacy & Security
Data is only ever sent to the cloud when the user actively triggers a backup. All transmitted data is first encrypted using [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard). Your selected password never leaves your device, and is hashed before being compared. It is only possible to restore a configuration if you have both the backup ID and decryption password.
Because the data is encrypted on the client-side (before being sent to the cloud), it is not possible for a man-in-the-middle, government entity, website owner, or even Cloudflare to be able read any of your data. The biggest risk to your data, would be a weak password, or a compromised system.
Having said that, although the code uses robust security libraries and is open source- it was never intended to be a security product, and has not been audited, and therefore cannot be considered totally secure - please keep that in mind.
## Fair Use Policy
Maximum of 24mb of storage per user. Please do not repeatedly hit the endpoint, as if the quota is exceeded the service may become less available to other users. Abuse may result in your IP being temporarily banned by Cloudflare.
---
## Self-Hosting the Backup Server
### Quick Start
- Install Wrangler CLI Tool: `npm i -g @cloudflare/wrangler`
- Log into Cloudflare account: `wrangler login`
- Create a new project: `wrangler generate my-project`
- Install dependencies: `cd my-project` && `npm i`
### Populate `wrangler.toml`
- Add your `account_id` (found on the right sidebar of the Workers or Overview Dashboard)
- Add your `zone_id` (found in the Overview tab of your desired domain on Cloudflare)
- Add your `route`, which should be a domain or host, supporting a wildcard
```toml
name = "dashy-worker"
type = "javascript"
workers_dev = true
route = "example.com/*"
zone_id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
account_id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
kv_namespaces = [
{ binding = "DASHY_CLOUD_BACKUP", id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
]
```
### Complete `index.js`
- Write code to handle your requests, and interact with any other data sources in this file
- Generally, this is done within an event listener for 'fetch', and returns a promise
- For Example:
```javascript
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
return new Response('Hello World!', {
headers: { 'content-type': 'text/plain' },
})
}
```
- For the code used for Dashy's cloud service, see [here](https://gist.github.com/Lissy93/d19b43d50f30e02fa25f349cf5cb5ed8#file-index-js)
### Commands
- `wrangler dev` - To start the wrangler development server
- `wrangler publish` - To publish to your cloudflare account (first run `wrangler login`)
## API
There are four endpoints, and to keep things simple, they all use the same base URL/ route.
- **`GET`** - Get config for a given user
- `backupId` - The ID of the desired encrypted object
- `subHash` - The latter half of the password hash, to verify ownership
- **`POST`** - Save a new config object, and returns `backupId`
- `userData` - The encrypted, compressed and stringified user config
- `subHash` - The latter half of the password hash, to verify ownership
- **`PUT`** - Update an existing config object
- `backupId` - The ID of the object to update
- `subHash` - Part of the hash, to verify ownership of said object
- `userData` - The new data to store
- **`DELETE`** - Delete a specified config object
- `backupId` - The ID of the object to be deleted
- `subHash` - Part of the password hash, to verify ownership of the object
For more info, see the [API Docs](https://documenter.getpostman.com/view/2142819/TzXumzce).
If you are using Postman, you may find this pre-made [collection](https://www.getpostman.com/collections/58f79ddb150223f67b35) helpful in getting things setup.

379
docs/configuring.md Normal file
View File

@@ -0,0 +1,379 @@
# Configuring
All app configuration is specified in [`/public/conf.yml`](https://github.com/Lissy93/dashy/blob/master/public/conf.yml) which is in [YAML Format](https://yaml.org/) format. If you're using Docker, this file can be passed in as a volume. Changes can either be made directly to this file, or done [through the UI](#editing-config-through-the-ui). From the UI you can also export, backup, reset, validate and download your configuration file.
## There are three ways to edit the config
- **Directly in the YAML file** _(5/5 reliability, 3/5 usability)_
- Write changes directly to the conf.yml file, optionally using one of the templates provided. This can be done in your favorite editor and uploading to your server, or directly editing the file via SSH, but the easiest method would be to use [Code Server](https://github.com/coder/code-server)
- **UI JSON Editor** _(4/5 reliability, 4/5 usability)_
- From the UI, under the config menu there is a JSON editor, with built-in validation, documentation and advanced options
- **UI Visual Editor** _(3/5 reliability, 5/5 usability)_
- From the UI, enter the Interactive Edit Mode, then click any part of the page to edit. Changes are previewed live, and then saved to disk
- **REST API** _(Coming soon)_
- Programmatically edit config either through the command line, using a script or a third-party application
## Tips
- You may find it helpful to look at some sample config files to get you started, a collection of which can be found [here](https://gist.github.com/Lissy93/000f712a5ce98f212817d20bc16bab10)
- You can check that your config file fits the schema, by running `yarn validate-config`
- After modifying your config, the app needs to be recompiled, by running `yarn build` - this happens automatically if you're using Docker
- It is recommended to keep a backup of your config file. You can download it under Config menu, or use the [Cloud Backup](./docs/backup-restore.md) feature.
- You can make use of YAML features, like anchors, comments, multi-line strings, etc to reuse attributes and keep your config file readable
- Once you have finished configuring your dashboard, you can choose to [disable UI config](#preventing-changes) if you wish
- All fields are optional, unless otherwise stated.
The following file provides a reference of all supported configuration options.
## Contents
- [**`pageInfo`**](#pageinfo) - Header text, footer, title, navigation, etc
- [`navLinks`](#pageinfonavlinks-optional) - Links to display in the navigation bar
- [**`pages`**](#pages-optional) - List of additional config files, for multi-page dashboards
- [**`appConfig`**](#appconfig-optional) - Main application settings
- [`webSearch`](#appconfigwebsearch-optional) - Configure web search engine options
- [`hideComponents`](#appconfighidecomponents-optional) - Show/ hide page components
- [`auth`](#appconfigauth-optional) - Built-in authentication setup
- [`users`](#appconfigauthusers-optional) - List or users (for simple auth)
- [`keycloak`](#appconfigauthkeycloak-optional) - Auth config for Keycloak
- [**`sections`**](#section) - List of sections
- [`displayData`](#sectiondisplaydata-optional) - Section display settings
- [`show/hideForKeycloakUsers`](#sectiondisplaydatahideforkeycloakusers-sectiondisplaydatashowforkeycloakusers-itemdisplaydatahideforkeycloakusers-and-itemdisplaydatashowforkeycloakusers) - Set user controls
- [`icon`](#sectionicon-and-sectionitemicon) - Icon for a section
- [`items`](#sectionitem) - List of items
- [`icon`](#sectionicon-and-sectionitemicon) - Icon for an item
- [`displayData`](#itemdisplaydata-optional) - Item display settings
- [`show/hideForKeycloakUsers`](#sectiondisplaydatahideforkeycloakusers-sectiondisplaydatashowforkeycloakusers-itemdisplaydatahideforkeycloakusers-and-itemdisplaydatashowforkeycloakusers) - Set user controls
- [`widgets`](#sectionwidget-optional) - List of widgets
- [**Notes**](#notes)
- [Editing Config through the UI](#editing-config-through-the-ui)
- [About YAML](#about-yaml)
- [Config Saving Methods](#config-saving-methods)
- [Preventing Changes](#preventing-changes)
- [Example](#example)
---
## Top-Level Fields
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`pageInfo`** | `object` | Required | Basic meta data like title, description, nav bar links, footer text. See [`pageInfo`](#pageinfo)
**`appConfig`** | `object` | _Optional_ | Settings related to how the app functions, including API keys and global styles. See [`appConfig`](#appconfig-optional)
**`sections`** | `array` | Required | An array of sections, each containing an array of items, which will be displayed as links. See [`section`](#section)
**`pages`** | `array` | _Optional_ | An array additional config files, used for multi-page dashboards. See [`pages`](#pages-optional)
**[⬆️ Back to Top](#configuring)**
## `PageInfo`
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`title`** | `string` | Required | Your dashboard title, displayed in the header and browser tab
**`description`** | `string` | _Optional_ | Description of your dashboard, also displayed as a subtitle
**`navLinks`** | `array` | _Optional_ | Optional list of a maximum of 6 links, which will be displayed in the navigation bar. See [`navLinks`](#pageinfonavlinks-optional)
**`footerText`** | `string` | _Optional_ | Text to display in the footer (note that this will override the default footer content). This can also include HTML and inline CSS
**`logo`** | `string` | _Optional_ | The path to an image to display in the header (to the right of the title). This can be either local, where `/` is the root of `./public`, or any remote image, such as `https://i.ibb.co/yhbt6CY/dashy.png`. It's recommended to scale your image down, so that it doesn't impact load times
**[⬆️ Back to Top](#configuring)**
## `pageInfo.navLinks` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`title`** | `string` | Required | The text to display on the link button
**`path`** | `string` | Required | The URL to navigate to when clicked. Can be relative (e.g. `/about`) or absolute (e.g. `https://example.com` or `http://192.168.1.1`)
**`target`** | `string` | _Optional_ | The opening method (external links only). Can be either `newtab`, `sametab`, `top` or `parent`. Defaults to `newtab`
**[⬆️ Back to Top](#configuring)**
## `pages[]` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`name`** | `string` | Required | A unique name for that page
**`path`** | `string` | Required | The path (local or remote) to the config file to use.<br>For files located within `/public`, you only need to specify filename, for externally hosted files you must include the full URL
**[⬆️ Back to Top](#configuring)**
## `appConfig` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`language`** | `string` | _Optional_ | The 2 (or 4-digit) [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for your language, e.g. `en` or `en-GB`. This must be a language that the app has already been [translated](https://github.com/Lissy93/dashy/tree/master/src/assets/locales) into. If your language is unavailable, Dashy will fallback to English. By default Dashy will attempt to auto-detect your language, although this may not work on some privacy browsers.
**`startingView`** | `enum` | _Optional_ | Which page to load by default, and on the base page or domain root. You can still switch to different views from within the UI. Can be either `default`, `minimal` or `workspace`. Defaults to `default`
**`defaultOpeningMethod`** | `enum` | _Optional_ | The default opening method for items, if no `target` is specified for a given item. Can be either `newtab`, `sametab`, `modal`, `workspace`, `clipboard`, `top` or `parent`. Defaults to `newtab`
**`statusCheck`** | `boolean` | _Optional_ | When set to `true`, Dashy will ping each of your services and display their status as a dot next to each item. This can be overridden by setting `statusCheck` under each item. Defaults to `false`
**`statusCheckInterval`** | `boolean` | _Optional_ | The number of seconds between checks. If set to `0` then service will only be checked on initial page load, which is usually the desired functionality. If value is less than `10` you may experience a hit in performance. Defaults to `0`
**`webSearch`** | `object` | _Optional_ | Configuration options for the web search feature, set your default search engine, opening method or disable web search. See [`webSearch`](#appconfigwebsearch-optional)
**`backgroundImg`** | `string` | _Optional_ | Path to an optional full-screen app background image. This can be either remote (http) or local (/). Note that this will slow down initial load
**`enableFontAwesome`** | `boolean` | _Optional_ | If set to `true` font-awesome will be loaded, if set to `false` they will not be. if left blank font-awesome will be enabled only if required by 1 or more icons
**`enableMaterialDesignIcons`** | `boolean` | _Optional_ | If set to `true` mdi icons will be loaded, if set to `false` they will not be. Where `true` is enabled, if left blank material design icons will be enabled only if required by 1 or more icons
**`fontAwesomeKey`** | `string` | _Optional_ | If you have a font-awesome key, then you can use it here and make use of premium icons. It is a 10-digit alpha-numeric string from you're FA kit URL (e.g. `13014ae648`)
**`faviconApi`** | `enum` | _Optional_ | Only applicable if you are using favicons for item icons. Specifies which service to use to resolve favicons. Set to `local` to do this locally, without using an API. Services running locally will use this option always. Available options are: `local`, `faviconkit`, `iconhorse`, `google`, `clearbit`, `webmasterapi` and `allesedv`. Defaults to `faviconkit`. See [Icons](/docs/icons.md#favicons) for more info
**`auth`** | `object` | _Optional_ | All settings relating to user authentication. See [`auth`](#appconfigauth-optional)
**`defaultIcon`** | `string` | _Optional_ | An icon to be applied to any items, which don't already have an icon set. See [Icon Docs](/docs/icons.md#default-icon) for more info
**`layout`** | `enum` | _Optional_ | Layout for homepage, either `horizontal`, `vertical` or `auto`. Defaults to `auto`. This specifies the layout and direction of how sections are positioned on the home screen. This can also be modified and overridden from the UI.
**`iconSize`** | `enum` | _Optional_ | The size of link items / icons. Can be either `small`, `medium,` or `large`. Defaults to `medium`. This can also be set directly from the UI.
**`colCount`** | `number` | _Optional_ | The number of columns of sections displayed on the homepage, using the default view. Should be in integer between `1` and `8`. Note that by default this is applied responsively, based on current screen size, and specifying a value here will override this behavior, which may not be desirable.
**`theme`** | `string` | _Optional_ | The default theme for first load (you can change this later from the UI)
**`cssThemes`** | `string[]` | _Optional_ | An array of custom theme names which can be used in the theme switcher dropdown
**`customColors`** | `object`| _Optional_ | Enables you to apply a custom color palette to any given theme. Use the theme name (lowercase) as the key, for an object including key-value-pairs, with the color variable name as keys, and 6-digit hex code as value. See [Theming](/docs/theming.md#modifying-theme-colors) for more info
**`externalStyleSheet`** | `string` or `string[]` | _Optional_ | Either a URL to an external stylesheet or an array or URLs, which can be applied as themes within the UI
**`customCss`** | `string` | _Optional_ | Raw CSS that will be applied to the page. This can also be set from the UI. Please minify it first.
**`hideComponents`** | `object` | _Optional_ | A list of key page components (header, footer, search, settings, etc) that are present by default, but can be removed using this option. See [`appConfig.hideComponents`](#appconfighideComponents-optional)
**`routingMode`** | `string` | _Optional_ | Can be either `hash` or `history`. Determines the URL format for sub-pages, hash mode will look like `/#/home` whereas with history mode available you have nice clean URLs, like `/home`. For more info, see the [Vue docs](https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations). If you're hosting Dashy with a custom BASE_URL, you will find that a bit of extra server config is necessary to get history mode working, so here you may want to instead use `hash` mode.Defaults to `history`.
**`enableMultiTasking`** | `boolean` | _Optional_ | If set to true, will keep apps open in the background when in the workspace view. Useful for quickly switching between multiple sites, and preserving their state, but comes at the cost of performance.
**`workspaceLandingUrl`** | `string` | _Optional_ | The URL or an app, service or website to launch when the workspace view is opened, before another service has been launched
**`preventWriteToDisk`** | `boolean` | _Optional_ | If set to `true`, users will be prevented from saving config changes to disk through the UI
**`preventLocalSave`** | `boolean` | _Optional_ | If set to `true`, users will be prevented from applying config changes to local storage
**`disableConfiguration`** | `boolean` | _Optional_ | If set to true, no users will be able to view or edit the config through the UI
**`disableConfigurationForNonAdmin`** | `boolean` | _Optional_ | If set to true, only admin users will be able to view or edit the config through the UI. disableConfiguration must not be set to true.
**`widgetsAlwaysUseProxy`** | `boolean` | _Optional_ | If set to `true`, requests made by widgets will always be proxied, same as setting `useProxy: true` on each widget. Note that this may break some widgets.
**`showSplashScreen`** | `boolean` | _Optional_ | If set to `true`, a loading screen will be shown. Defaults to `false`.
**`enableErrorReporting`** | `boolean` | _Optional_ | Enable reporting of unexpected errors and crashes. This is off by default, and **no data will ever be captured unless you explicitly enable it**. Turning on error reporting helps previously unknown bugs get discovered and fixed. Dashy uses [Sentry](https://github.com/getsentry/sentry) for error reporting. Defaults to `false`.
**`sentryDsn`** | `boolean` | _Optional_ | If you need to monitor errors in your instance, then you can use Sentry to collect and process bug reports. Sentry can be self-hosted, or used as SaaS, once your instance is setup, then all you need to do is pass in the DSN here, and enable error reporting. You can learn more on the [Sentry DSN Docs](https://docs.sentry.io/product/sentry-basics/dsn-explainer/). Note that this will only ever be used if `enableErrorReporting` is explicitly enabled.
**`disableSmartSort`** | `boolean` | _Optional_ | For the most-used and last-used app sort functions to work, a basic open-count is stored in local storage. If you do not want this to happen, then disable smart sort here, but you wil no longer be able to use these sort options. Defaults to `false`.
**`disableUpdateChecks`** | `boolean` | _Optional_ | If set to true, Dashy will not check for updates. Defaults to `false`.
**`enableServiceWorker`** | `boolean` | _Optional_ | Service workers cache web applications to improve load times and offer basic offline functionality, and are enabled by default in Dashy. The service worker can sometimes cause older content to be cached, requiring the app to be hard-refreshed. If you do not want SW functionality, or are having issues with caching, set this property to `false` to disable all service workers.
**`disableContextMenu`** | `boolean` | _Optional_ | If set to `true`, the custom right-click context menu will be disabled. Defaults to `false`.
**[⬆️ Back to Top](#configuring)**
## `appConfig.auth` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`users`** | `array` | _Optional_ | An array of objects containing usernames and hashed passwords. If this is not provided, then authentication will be off by default, and you will not need any credentials to access the app. See [`appConfig.auth.users`](#appconfigauthusers-optional). <br>**Note** this method of authentication is handled on the client side, so for security critical situations, it is recommended to use an [alternate authentication method](/docs/authentication.md#alternative-authentication-methods).
**`enableKeycloak`** | `boolean` | _Optional_ | If set to `true`, then authentication using Keycloak will be enabled. Note that you need to have an instance running, and have also configured `auth.keycloak`. Defaults to `false`
**`keycloak`** | `object` | _Optional_ | Config options to point Dashy to your Keycloak server. Requires `enableKeycloak: true`. See [`auth.keycloak`](#appconfigauthkeycloak-optional) for more info
**`enableGuestAccess`** | `boolean` | _Optional_ | When set to `true`, an unauthenticated user will be able to access the dashboard, with read-only access, without having to login. Requires `auth.users` to be configured. Defaults to `false`.
For more info, see the **[Authentication Docs](/docs/authentication.md)**
**[⬆️ Back to Top](#configuring)**
## `appConfig.auth.users` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`user`** | `string` | Required | Username to log in with
**`hash`** | `string` | Required | A SHA-256 hashed password
**`type`** | `string` | _Optional_ | The user type, either admin or normal
**[⬆️ Back to Top](#configuring)**
## `appConfig.auth.keycloak` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`serverUrl`** | `string` | Required | The URL (or URL/ IP + Port) where your keycloak server is running
**`realm`** | `string` | Required | The name of the realm (must already be created) that you want to use
**`clientId`** | `string` | Required | The Client ID of the client you created for use with Dashy
**`legacySupport`** | `boolean` | _Optional_ | If using Keycloak 17 or older, then set this to `true`
**[⬆️ Back to Top](#configuring)**
## `appConfig.webSearch` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`disableWebSearch`** | `string` | _Optional_ | Web search is enabled by default, but can be disabled by setting this property to `true`
**`searchEngine`** | `string` | _Optional_ | Set the key name for your search engine. Can also use a custom engine by setting this property to `custom`. Currently supported: `duckduckgo`, `google`, `whoogle`, `qwant`, `startpage`, `searx-bar` and `searx-info`. Defaults to `duckduckgo`
**`customSearchEngine`** | `string` | _Optional_ | You can also use a custom search engine, or your own self-hosted instance. This requires `searchEngine: custom` to be set. Then add the URL of your service, with GET query string included here
**`openingMethod`** | `string` | _Optional_ | Set your preferred opening method for search results: `newtab`, `sametab`, `workspace`. Defaults to `newtab`
**`searchBangs`** | `object` | _Optional_ | A key-value-pair set of custom search _bangs_ for redirecting query to a specific app or search engine. The key of each should be the bang you will type (typically starting with `/`, `!` or `:`), and value is the destination, either as a search engine key (e.g. `reddit`) or a URL with search parameters (e.g. `https://en.wikipedia.org/w/?search=`)
**[⬆️ Back to Top](#configuring)**
## `appConfig.hideComponents` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`hideHeading`** | `boolean` | _Optional_ | If set to `true`, the page title & sub-title will not be visible. Defaults to `false`
**`hideNav`** | `boolean` | _Optional_ | If set to `true`, the navigation menu will not be visible. Defaults to `false`
**`hideSearch`** | `boolean` | _Optional_ | If set to `true`, the search bar will not be visible. Defaults to `false`
**`hideSettings`** | `boolean` | _Optional_ | If set to `true`, the settings menu will be initially collapsed. Defaults to `false`
**`hideFooter`** | `boolean` | _Optional_ | If set to `true`, the footer will not be visible. Defaults to `false`
**[⬆️ Back to Top](#configuring)**
## `section`
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`name`** | `string` | Required | The title for the section
**`icon`** | `string` | _Optional_ | An single icon to be displayed next to the title. See [`section.icon`](#sectionicon-and-sectionitemicon)
**`items`** | `array` | _Optional_ | An array of items to be displayed within the section. See [`item`](#sectionitem). Sections must include either 1 or more items, or 1 or more widgets.
**`widgets`** | `array` | _Optional_ | An array of widgets to be displayed within the section. See [`widget`](#sectionwidget-optional)
**`displayData`** | `object` | _Optional_ | Meta-data to optionally override display settings for a given section. See [`displayData`](#sectiondisplaydata-optional)
**[⬆️ Back to Top](#configuring)**
## `section.item`
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`title`** | `string` | Required | The text to display/ title of a given item. Max length `18`
**`description`** | `string` | _Optional_ | Additional info about an item, which is shown in the tooltip on hover, or visible on large tiles
**`url`** | `string` | Required | The URL / location of web address for when the item is clicked
**`icon`** | `string` | _Optional_ | The icon for a given item. Can be a font-awesome icon, favicon, remote URL or local URL. See [`item.icon`](#sectionicon-and-sectionitemicon)
**`target`** | `string` | _Optional_ | The opening method for when the item is clicked, either `newtab`, `sametab`, `modal`, `workspace`, `clipboard`, `top` or `parent`. Where `newtab` will open the link in a new tab, `sametab` will open it in the current tab, and `modal` will open a pop-up modal, `workspace` will open in the Workspace view and `clipboard` will copy the URL to system clipboard (but not launch app). Defaults to `newtab`
**`hotkey`** | `number` | _Optional_ | Give frequently opened applications a numeric hotkey, between `0 - 9`. You can then just press that key to launch that application.
**`tags`** | `string[]` | _Optional_ | A list of tags, which can be used for improved search
**`statusCheck`** | `boolean` | _Optional_ | When set to `true`, Dashy will ping the URL associated with the current service, and display its status as a dot next to the item. The value here will override `appConfig.statusCheck` so you can turn off or on checks for a given service. Defaults to `appConfig.statusCheck`, falls back to `false`
**`statusCheckUrl`** | `string` | _Optional_ | If you've enabled `statusCheck`, and want to use a different URL to what is defined under the item, then specify it here
**`statusCheckHeaders`** | `object` | _Optional_ | If you're endpoint requires any specific headers for the status checking, then define them here
**`statusCheckAllowInsecure`** | `boolean` | _Optional_ | By default, any request to insecure content will be blocked. Setting this option to `true` will disable the `rejectUnauthorized` option, enabling you to ping non-HTTPS services for the current item. Defaults to `false`
**`statusCheckAcceptCodes`** | `string` | _Optional_ | If your service's response code is anything other than 2xx, then you can opt to specify an alternative success code. E.g. if you expect your server to return 403, but still want the status indicator to be green, set this value to `403`
**`statusCheckMaxRedirects`** | `number` | _Optional_ | If your service redirects to another page, and you would like status checks to follow redirects, then specify the maximum number of redirects here. Defaults to `0` / will not follow redirects
**`color`** | `string` | _Optional_ | An optional color for the text and font-awesome icon to be displayed in. Note that this will override the current theme and so may not display well
**`backgroundColor`** | `string` | _Optional_ | An optional background fill color for the that given item. Again, this will override the current theme and so might not display well against the background
**`provider`** | `string` | _Optional_ | The name of the provider for a given service, useful for when including hosted apps. In some themes, this is visible under the item name
**`displayData`** | `object` | _Optional_ | Meta-data to optionally override display settings for a given item. See [`displayData`](#itemdisplaydata-optional)
**[⬆️ Back to Top](#configuring)**
## `item.displayData` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`hideForUsers`** | `string[]` | _Optional_ | Current item will be visible to all users, except for those specified in this list
**`showForUsers`** | `string[]` | _Optional_ | Current item will be hidden from all users, except for those specified in this list
**`hideForGuests`** | `boolean` | _Optional_ | Current item will be visible for logged in users, but not for guests (see `appConfig.enableGuestAccess`). Defaults to `false`
**`hideForKeycloakUsers`** | `object` | _Optional_ | Current item will be visible to all keycloak users, except for those configured via these groups and roles. See `hideForKeycloakUsers`
**`showForKeycloakUsers`** | `object` | _Optional_ | Current item will be hidden from all keycloak users, except for those configured via these groups and roles. See `showForKeycloakUsers`
**[⬆️ Back to Top](#configuring)**
## `section.widget` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`type`** | `string` | Required | The widget type. See [Widget Docs](/docs/widgets.md) for full list of supported widgets
**`options`** | `object` | _Optional_ | Some widgets accept either optional or required additional options. Again, see the [Widget Docs](/docs/widgets.md) for full list of options
**`updateInterval`** | `number` | _Optional_ | You can keep a widget constantly updated by specifying an update interval, in seconds. See [Continuous Updates Docs](/docs/widgets.md#continuous-updates) for more info
**`useProxy`** | `boolean` | _Optional_ | Some widgets make API requests to services that are not CORS-enabled. For these instances, you will need to route requests through a proxy, Dashy has a built in CORS-proxy, which you can use by setting this option to `true`. Defaults to `false`. See the [Proxying Requests Docs](/docs/widgets.md#proxying-requests) for more info
**`timeout`** | `number` | _Optional_ | Request timeout in milliseconds, defaults to ½ a second (`500`)
**`ignoreErrors`** | `boolean` | _Optional_ | Prevent an error message being displayed, if a network request or something else fails. Useful for false-positives
**`label`** | `string` | _Optional_ | Add custom label to a given widget. Useful for identification, if there are multiple of the same type of widget in a single section
**[⬆️ Back to Top](#configuring)**
## `section.displayData` _(optional)_
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`sortBy`** | `string` | _Optional_ | The sort order for items within the current section. By default items are displayed in the order in which they are listed in within the config. The following sort options are supported: `most-used` (most opened apps first), `last-used` (the most recently used apps), `alphabetical`, `reverse-alphabetical`, `random` and `default`
**`collapsed`** | `boolean` | _Optional_ | If true, the section will be collapsed initially, and will need to be clicked to open. Useful for less regularly used, or very long sections. Defaults to `false`
**`cutToHeight`** | `boolean` | _Optional_ | By default, sections will fill available space. Set this option to true to match section height with content height
**`rows`** | `number` | _Optional_ | Height of the section, specified as the number of rows it should span vertically, e.g. `2`. Defaults to `1`. Max is `5`.
**`cols`** | `number` | _Optional_ | Width of the section, specified as the number of columns the section should span horizontally, e.g. `2`. Defaults to `1`. Max is `5`.
**`itemSize`** | `string` | _Optional_ | Specify the size for items within this group, either `small`, `medium` or `large`. Note that this will override any settings specified through the UI
**`color`** | `string` | _Optional_ | A custom accent color for the section, as a hex code or HTML color (e.g. `#fff`)
**`customStyles`** | `string` | _Optional_ | Custom CSS properties that should be applied to that section, e.g. `border: 2px dashed #ff0000;`
**`sectionLayout`** | `string` | _Optional_ | Specify which CSS layout will be used to responsively place items. Can be either `auto` (which uses flex layout), or `grid`. If `grid` is selected, then `itemCountX` and `itemCountY` may also be set. Defaults to `auto`
**`itemCountX`** | `number` | _Optional_ | The number of items to display per row / horizontally. If not set, it will be calculated automatically based on available space. Can only be set if `sectionLayout` is set to `grid`. Must be a whole number between `1` and `12`
**`itemCountY`** | `number` | _Optional_ | The number of items to display per column / vertically. If not set, it will be calculated automatically based on available space. If `itemCountX` is set, then `itemCountY` can be calculated automatically. Can only be set if `sectionLayout` is set to `grid`. Must be a whole number between `1` and `12`
**`hideForUsers`** | `string[]` | _Optional_ | Current section will be visible to all users, except for those specified in this list
**`showForUsers`** | `string[]` | _Optional_ | Current section will be hidden from all users, except for those specified in this list
**`hideForGuests`** | `boolean` | _Optional_ | Current section will be visible for logged in users, but not for guests (see `appConfig.enableGuestAccess`). Defaults to `false`
**`hideForKeycloakUsers`** | `object` | _Optional_ | Current section will be visible to all keycloak users, except for those configured via these groups and roles. See `hideForKeycloakUsers`
**`showForKeycloakUsers`** | `object` | _Optional_ | Current section will be hidden from all keycloak users, except for those configured via these groups and roles. See `showForKeycloakUsers`
**[⬆️ Back to Top](#configuring)**
## `section.icon` and `section.item.icon`
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`icon`** | `string` | _Optional_ | The icon for a given item or section. <br>See [Icon Docs](/docs/icons.md) for all available supported icon types, including: auto-fetched favicons, generative icons, emoji icons, home-lab service logos, font-awesome, simple-icons, material icons, and icons specified by URL
**[⬆️ Back to Top](#configuring)**
## `section.displayData.hideForKeycloakUsers`, `section.displayData.showForKeycloakUsers`, `item.displayData.hideForKeycloakUsers` and `item.displayData.showForKeycloakUsers`
**Field** | **Type** | **Required**| **Description**
--- |------------| --- | ---
**`groups`** | `string[]` | _Optional_ | Current Section or Item will be hidden or shown based on the user having any of the groups in this list
**`roles`** | `string[]` | _Optional_ | Current Section or Item will be hidden or shown based on the user having any of the roles in this list
**[⬆️ Back to Top](#configuring)**
---
## Notes
### Editing Config through the UI
Config can be modified directly through the UI, and then written to disk, or applied locally. This can be done wither with the raw config editor (introduced in V 0.6.5 / [#3](https://github.com/Lissy93/dashy/pull/3)), or the interactive editor (introduced in V 1.8.9 / [#298](https://github.com/Lissy93/dashy/pull/298)).
<p align="center">
<a href="https://ibb.co/CzkyMNb">
<b>Interactive Editor</b><br>
<img alt="Interactive Editor demo" src="https://user-images.githubusercontent.com/1862727/139543020-b0576d28-0830-476f-afc8-a815d4de6def.gif" width="600" />
</a>
<br>
<a href="https://ibb.co/zRv542H">
<b>JSON Editor</b><br>
<img alt="Config Editor demo" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/config-editor-demo.gif" width="600" />
</a>
</p>
### About YAML
If you're new to YAML, it's pretty straight-forward. The format is exactly the same as that of JSON, but instead of using curly braces, structure is denoted using whitespace. This [quick guide](https://linuxhandbook.com/yaml-basics/) should get you up to speed in a few minutes, for more advanced topics take a look at this [Wikipedia article](https://en.wikipedia.org/wiki/YAML).
### Config Saving Methods
When updating the config through the JSON editor in the UI, you have two save options: **Local** or **Write to Disk**.
- Changes saved locally will only be applied to the current user through the browser, and will not apply to other instances - you either need to use the cloud sync feature, or manually update the conf.yml file.
- On the other-hand, if you choose to write changes to disk, then your main `conf.yml` file will be updated, and changes will be applied to all users, and visible across all devices. For this functionality to work, you must be running Dashy with using the Docker container, or the Node server. A backup of your current configuration will also be saved in the same directory.
### Preventing Changes
If you have authentication set up, then any user who is not an admin (with `type: admin`) will not be able to write changes to disk.
You can also prevent changes from any user being written to disk, using `preventWriteToDisk`. Or prevent any changes from being saved locally in browser storage, using `preventLocalSave`.
To disable all UI config features, set `disableConfiguration`. Alternatively you can disable UI config features for all non Admin users by setting `disableConfigurationForNonAdmin` to true.
### Example
```yaml
---
pageInfo:
title: Home Lab
sections: # An array of sections
- name: Section 1 - Getting Started
items: # An array of items
- title: GitHub
description: Source code and documentation on GitHub
icon: fab fa-github
url: https://github.com/Lissy93/dashy
- title: Issues
description: View currently open issues, or raise a new one
icon: fas fa-bug
url: https://github.com/Lissy93/dashy/issues
- title: Demo
description: A live demo
icon: far fa-rocket
url: https://dashy-demo-1.netlify.app
- name: Section 2 - Local Services
items:
- title: Firewall
icon: favicon
url: http://192.168.1.1/
- title: Game Server
icon: https://i.ibb.co/710B3Yc/space-invader-x256.png
url: http://192.168.130.1/
```
For more example config files, see: [this gist](https://gist.github.com/Lissy93/000f712a5ce98f212817d20bc16bab10)
If you need any help, feel free to [Raise an Issue](https://github.com/Lissy93/dashy/issues/new?assignees=Lissy93&labels=%F0%9F%A4%B7%E2%80%8D%E2%99%82%EF%B8%8F+Question&template=question.md&title=%5BQUESTION%5D) or [Start a Discussion](https://github.com/Lissy93/dashy/discussions)
Happy Configuring 🤓🔧
**[⬆️ Back to Top](#configuring)**

137
docs/contributing.md Normal file
View File

@@ -0,0 +1,137 @@
# Contributing
First off, thank you for considering contributing towards Dashy! 🙌
There are several ways that you can help out, and any contributions, however small will always be very much appreciated.
You will be appropriately credited in the readme - huge thank you to [everyone who has helped](/docs/credits.md) so far 💞
## Take a 2-minute survey
Help improve Dashy by taking a very short, 6-question survey. This will give me a better understanding of what is important to you, so that I can make Dashy better in the future :)
[![Take the Survey](https://img.shields.io/badge/Take_the-Survey-%231a86fd?style=for-the-badge&logo=buddy)](https://survey.typeform.com/to/gl0L68ou)
## Share your dashboard
Dashy now has a [Showcase](https://github.com/Lissy93/dashy/blob/master/docs/showcase.md#dashy-showcase-) where you can show off a screenshot of your dashboard, and get inspiration from other users (and I really love seeing how people are using Dashy). To [submit your dashboard](https://github.com/Lissy93/dashy/blob/master/docs/showcase.md#submitting-your-dashboard), either open a PR or raise an issue.
[![Add your Dashboard to the Showcase](https://img.shields.io/badge/Add_your_Dashboard-Showcase-%238616ee?style=for-the-badge&logo=feathub&logoColor=8616ee)](https://github.com/Lissy93/dashy/issues/new?assignees=&labels=%F0%9F%92%AF+Showcase&template=showcase-addition.yml&title=%5BSHOWCASE%5D+%3Ctitle%3E)
## Make a small donation
Donations help to cover server costs, development time and caffeine ;)
Don't feel any pressure to donate anything, as Dashy and my other projects will always be 100% free, for everyone, for ever.
[![Sponsor Lissy93 on GitHub](https://img.shields.io/badge/Sponsor_on_GitHub-Lissy93-%23ff4dda?style=for-the-badge&logo=githubsponsors&logoColor=ff4dda)](https://github.com/sponsors/Lissy93)
Sponsoring will give you several perks - for $1 / £0.75 per month, you'll get a sponsor badge on your profile, be credited on the Dashy's readme, with a link to your website/ profile/ socials, get priority support, have your feature ideas implemented, plus lots more. For more info, see [@Lissy93's Sponsor Page](https://github.com/sponsors/Lissy93).
<details>
<summary>You can also send a one-off small contribution using crypto</summary>
<p>
[![Donate with BTC](https://en.cryptobadges.io/badge/big/3853bSxupMjvxEYfwGDGAaLZhTKxB2vEVC)](https://en.cryptobadges.io/donate/3853bSxupMjvxEYfwGDGAaLZhTKxB2vEVC)[![Donate with Ethereum](https://en.cryptobadges.io/badge/big/0x0fc98cBf8bea932B4470C46C0FbE1ed1f6765017)](https://en.cryptobadges.io/donate/0x0fc98cBf8bea932B4470C46C0FbE1ed1f6765017)
- **BTC**: `3853bSxupMjvxEYfwGDGAaLZhTKxB2vEVC`
- **ETH**: `0x0fc98cBf8bea932B4470C46C0FbE1ed1f6765017` / `aliciasykes.eth`
- **XMR**: `471KZdxb6N63aABR4WYwMRjTVkc1p1x7wGsUTEF7AMYzL8L94A5pCuYWkosgJQ5Ze8Y2PscVCGZFJa3hDPg6MaDq47GUm8r`
- **LTC**: `MAuck6Ea1qaNihwKfXutkR1R6BorMth86H`
- **ZEC**: `t1bw1SefijsXRDQVxC9w64XsRK8hBhtQohQ`
</p>
</details>
## Enable Anonymous Bug Reports
Bug reports helps me to discover bugs I was unaware of, and then fix them, in order to make Dashy more reliable long term. This is a simple, yet really helpful step you can take to help improve Dashy. [Sentry](https://github.com/getsentry/sentry) is an open source error tracking and performance monitoring tool, which enables the identification any errors which occur in the production app (only if you enable it).
To enable error reporting:
```yaml
appConfig:
enableErrorReporting: true
```
All reporting is **disabled** by default, and no data will ever be sent to any external endpoint without your explicit consent. All statistics are anonymized and stored securely. For more about privacy and security, see the [Sentry Security Docs](https://sentry.io/security/).
## Add Translations
If you speak another language, then adding translations will help make Dashy available to non-native English speakers. This is a very quick and easy task, as all application text is located in [`locales/en.json`](https://github.com/Lissy93/dashy/blob/master/src/assets/locales/en.json), so adding a new language is as simple as copying this file and translating the values. You don't have to translate it all, as any missing attributes will just fallback to English. For a full tutorial, see the [Multi-Language Support Docs](https://github.com/Lissy93/dashy/blob/master/docs/multi-language-support.md).
## Submit a PR
Contributing to the code or docs is super helpful. You can fix a bug, add a new feature or improve an existing one. If you've built your own custom widget, theme or view, consider sharing it in a PR. I've written [several guides](/docs/development-guides.md) to help you get started, and the steps for setting up the development environment are outlined in the [Development Docs](/docs/developing.md). Feel free to ask if you have any questions.
## Improve the Docs
Found a typo, or something that isn't as clear as it could be? Maybe I've missed something off altogether, or you hit a roadblock that took you a while to figure out. Submitting a pull request to add to or improve the documentation will help future users get Dashy up and running more easily.
All content is located either in the [`./README.md`](/README.md) or [`/docs/`](/docs) directory, and synced to the Wiki and website using a GH [action](/actions/workflows/wiki-sync.yml).
## Raise a bug
If you've found a bug, then please do raise it as an issue. This will help me know if there's something that needs fixing. Try and include as much detail as possible, such as your environment, steps to reproduce, any console output and maybe an example screenshot or recording if necessary.
[![Raise a Bug](https://img.shields.io/badge/Raise_a-Bug-%23dc2d76?style=for-the-badge&logo=dependabot)](https://github.com/Lissy93/dashy/issues/new?assignees=lissy93&labels=%F0%9F%90%9B+Bug&template=bug.yml&title=%5BBUG%5D+%3Ctitle%3E)
## Join the discussion
I've enabled the discussion feature on GitHub, here you can share tips and tricks, useful information, or your dashboard. You can also ask questions, and offer basic support to other users.
[![Join the Discussion on GitHub](https://img.shields.io/badge/Join_the-Discussion-%23ffd000?style=for-the-badge&logo=livechat)](https://github.com/Lissy93/dashy/discussions)
## Request a feature via BountySource
BountySource is a platform for sponsoring the development of certain features on open source projects. If there is a feature you'd like implemented into Dashy, but either isn't high enough priority or is deemed to be more work than it's worth, then you can instead contribute a bounty towards it's development. You won't pay a penny until your proposal is fully built, and you are satisfied with the result. This helps support the developers, and makes Dashy better for everyone.
[![Request a Feature on BountySource](https://img.shields.io/badge/BountySource-Dashy-%23F67909?style=for-the-badge&logo=openbugbounty)](https://www.bountysource.com/teams/dashy)
## Spread the word
Dashy is still a relatively young project, and as such not many people know of it. It would be great to see more users, and so it would be awesome if you could consider sharing with your friends or on social platforms.
[![Share Dashy on Mastodon](https://img.shields.io/badge/Share-Mastodon-%232b90d9?style=flat-square&logo=mastodon)](https://mastodon.social/?text=Check%20out%20Dashy%2C%20the%20privacy-friendly%2C%20self-hosted%20startpage%20for%20organizing%20your%20life%3A%20https%3A%2F%2Fgithub.com%2FLissy93%2Fdashy%20-%20By%20%40lissy93%40mastodon.social)
[![Share Dashy on Reddit](https://img.shields.io/badge/Share-Reddit-%23FF5700?style=flat-square&logo=reddit)](http://www.reddit.com/submit?url=https://github.com/Lissy93/dashy&title=Dashy%20-%20The%20self-hosted%20dashboard%20for%20your%20homelab%20%F0%9F%9A%80)
[![Share Dashy on Twitter](https://img.shields.io/badge/Share-Twitter-%231DA1F2?style=flat-square&logo=twitter)](https://twitter.com/intent/tweet?url=https://github.com/lissy93/dashy&text=Check%20out%20Dashy%20by%20@Lissy_Sykes,%20the%20self-hosted%20dashboard%20for%20your%20homelab%20%F0%9F%9A%80)
[![Share Dashy on Facebook](https://img.shields.io/badge/Share-Facebook-%234267B2?style=flat-square&logo=facebook)](https://www.facebook.com/sharer/sharer.php?u=https://github.com/lissy93/dashy)
[![Share Dashy on LinkedIn](https://img.shields.io/badge/Share-LinkedIn-%230077b5?style=flat-square&logo=linkedin)](https://www.linkedin.com/shareArticle?mini=true&url=https://github.com/lissy93/dashy)
[![Share Dashy on Pinterest](https://img.shields.io/badge/Share-Pinterest-%23E60023?style=flat-square&logo=pinterest)](https://pinterest.com/pin/create/button/?url=https://github.com/lissy93/dashy&media=https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/1-home-lab-material.png&description=Check%20out%20Dashy,%20the%20self-hosted%20dashboard%20for%20your%20homelab%20%F0%9F%9A%80)
[![Share Dashy on VK](https://img.shields.io/badge/Share-VK-%234C75A3?style=flat-square&logo=vk)](https://vk.com/share.php?url=https%3A%2F%2Fgithub.com%2Flissy93%2Fdashy%2F&title=Check%20out%20Dashy%20-%20The%20Self-Hosted%20Dashboard%20for%20your%20Homelab%20%F0%9F%9A%80)
[![Share Dashy via Viber](https://img.shields.io/badge/Share-Viber-%238176d6?style=flat-square&logo=viber)](viber://forward?text=https%3A%2F%2Fgithub.com%2Flissy93%2Fdashy%0ACheck%20out%20Dashy%2C%20the%20self-hosted%20dashboard%20for%20your%20homelab%20%F0%9F%9A%80)
[![Share Dashy via Telegram](https://img.shields.io/badge/Share-Telegram-%230088cc?style=flat-square&logo=telegram)](https://t.me/share/url?url=https%3A%2F%2Fgithub.com%2Flissy93%2Fdashy&text=Check%20out%20Dashy%2C%20the%20self-hosted%20dashboard%20for%20your%20homelab%20%F0%9F%9A%80)
[![Share Dashy via Email](https://img.shields.io/badge/Share-Email-%238A90C7?style=flat-square&logo=protonmail)](mailto:info@example.com?&subject=Check%20out%20Dashy%20-%20The%20self-hosted%20dashboard%20for%20your%20homelab%20%F0%9F%9A%80&cc=&bcc=&body=https://github.com/lissy93/dashy)
## Star, Upvote or Leave a Review
Dashy is on the following platforms, and if you could spare a few seconds to give it an upvote or review, this will also help new users discover Dashy
[![ProductHunt](https://img.shields.io/badge/Review-ProductHunt-%23b74424?style=flat-square&logo=producthunt)](https://www.producthunt.com/posts/dashy)
[![AlternativeTo](https://img.shields.io/badge/Review-AlternativeTo-%235581a6?style=flat-square&logo=abletonlive)](https://alternativeto.net/software/dashy/about/)
[![Slant](https://img.shields.io/badge/Review-Slant-%2346a1df?style=flat-square&logo=capacitor)](https://www.slant.co/improve/topics/27783/viewpoints/1/~self-hosted-homelab-startpage~dashy)
[![Star on GitHub](https://img.shields.io/github/stars/Lissy93/Dashy?color=ba96d6&label=Star%20-%20GitHub&logo=github&style=flat-square)](https://github.com/Lissy93/dashy/stargazers)
[![Star on DockerHub](https://img.shields.io/docker/stars/lissy93/dashy?color=4cb6e0&label=Star%20-%20Docker&logo=docker&style=flat-square)](https://hub.docker.com/r/lissy93/dashy)
## Follow for More
If you've enjoyed Dashy, you can follow the me to get updates about other projects that I am working on.
[![Alicia Sykes on Twitter](https://img.shields.io/twitter/follow/Lissy_Sykes?style=social&logo=twitter)](https://twitter.com/Lissy_Sykes)
[![Alicia Sykes on GitHub](https://img.shields.io/github/followers/lissy93?label=Lissy93&style=social)](https://github.com/Lissy93)
[![Alicia Sykes on Mastodon](https://img.shields.io/mastodon/follow/1032965?domain=https%3A%2F%2Fmastodon.social)](https://mastodon.social/web/accounts/1032965)
[![Alicia Sykes on Keybase](https://img.shields.io/badge/aliciasykes--lightgrey?style=social&logo=Keybase)](https://keybase.io/aliciasykes)
[![Alicia Sykes's Website](https://img.shields.io/badge/aliciasykes.com--lightgrey?style=social&logo=Tencent%20QQ)](https://aliciasykes.com)
[![Alicia Sykes's Blog](https://img.shields.io/badge/Blog--lightgrey?style=social&logo=micro.blog)](https://notes.aliciasykes.com/)
[![Alicia Sykes's PGP](https://img.shields.io/badge/PGP--lightgrey?style=social&logo=Let%E2%80%99s%20Encrypt)](https://keybase.io/aliciasykes/pgp_keys.asc)
If you like, you could also consider [subscribing to my mailing list](https://notes.aliciasykes.com/subscribe) for occasional blog post updates.
---
### Contributors
For a full list of Dashy's contributors, see the [Credits Page](/docs/credits.md)
[![Auto-generated contributors](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/CONTRIBUTORS.svg)](/docs/credits.md)
### Star-Gazers Over Time
[![Stargazers](https://starchart.cc/Lissy93/dashy.svg)](https://seladb.github.io/StarTrack-js/#/preload?r=Lissy93,dashy)

1058
docs/credits.md Normal file
View File

File diff suppressed because it is too large Load Diff

361
docs/deployment.md Normal file
View File

@@ -0,0 +1,361 @@
# Deployment
Welcome to Dashy, so glad you're here :) Deployment is super easy, and there are several methods available depending on what type of system you're using. If you're self-hosting, then deploying with Docker (or similar container engine) is the recommended approach.
## Quick Start
If you want to skip the fuss, and [get straight down to it](/docs/quick-start.md), then you can spin up a new instance of Dashy by running:
```bash
docker run -p 8080:80 lissy93/dashy
```
See [Management Docs](/docs/management.md) for info about securing, monitoring, updating, health checks, auto starting, web server configuration, etc
Once you've got Dashy up and running, you'll want to configure it with your own content, for this you can reference the [configuring docs](/docs/configuring.md).
## Deployment Methods
- [Deployment](#deployment)
- [Quick Start](#quick-start)
- [Deployment Methods](#deployment-methods)
- [Deploy with Docker](#deploy-with-docker)
- [Using Docker Compose](#using-docker-compose)
- [Unraid](#unraid)
- [Synology NAS](#synology-nas)
- [Build from Source](#build-from-source)
- [Deploy to cloud service](#deploy-to-cloud-service)
- [Netlify](#netlify)
- [Heroku](#heroku)
- [Vercel](#vercel)
- [DigitalOcean](#digitalocean)
- [Google Cloud Platform](#google-cloud-platform)
- [Platform.sh](#platformsh)
- [Render](#render)
- [Scalingo](#scalingo)
- [Play-with-Docker](#play-with-docker)
- [Surge.sh](#surgesh)
- [Easypanel](#easypanel)
- [Hosting with CDN](#hosting-with-cdn)
- [Requirements](#requirements)
- [System Requirements](#system-requirements)
- [Docker](#docker)
- [Bare Metal](#bare-metal)
- [CDN / Cloud Deploy](#cdn--cloud-deploy)
- [Browser Support](#browser-support)
---
## Deploy with Docker
**Container Info**: [
![Docker Supported Architecture](https://img.shields.io/badge/Architectures-amd64%20|%20arm32v7%20|%20arm64v8-6ba6e5)
![Docker Base Image](https://img.shields.io/badge/Base_Image-Alpine_3.14-6ba6e5)
![Docker Hosted on](https://img.shields.io/badge/Hosted_on-DockerHub-6ba6e5)
](https://hub.docker.com/r/lissy93/dashy)<br>
**Status**: [
![Docker Build Status](https://img.shields.io/docker/cloud/build/lissy93/dashy?label=Docker%20Build)
![Docker Pulls](https://img.shields.io/docker/pulls/lissy93/dashy?color=ecb2f7)
![Docker Stars](https://img.shields.io/docker/stars/lissy93/dashy?color=f7f754&label=Docker%20Stars)
![Docker Image Size](https://img.shields.io/docker/image-size/lissy93/dashy/latest?color=1eea76)
![Docker Cloud Build](https://img.shields.io/docker/cloud/automated/lissy93/dashy?color=f4a966&label=Docker%20Build)
](https://hub.docker.com/r/lissy93/dashy)
Dashy has a built container image hosted on [Docker Hub](https://hub.docker.com/r/lissy93/dashy). You will need [Docker](https://docs.docker.com/get-docker/) installed on your system.
```bash
docker run -d \
-p 8080:80 \
-v /root/my-local-conf.yml:/app/public/conf.yml \
--name my-dashboard \
--restart=always \
lissy93/dashy:latest
```
Explanation of the above options:
- `-d` Detached mode (not running in the foreground of your terminal)
- `-p` The port that should be exposed, and the port it should be mapped to in your host system `[host-port][container-port]`, leave the container port as is
- `-v` Specify volumes, to pass data from your host system to the container, in the format of `[host-path]:[container-path]`, you can use this to pass your config file, directory of assets (like icons), custom CSS or web assets (like favicon.ico, manifest.json etc)
- `--name` Give your container a human-readable name
- `--restart=always` Spin up the container when the daemon starts, or after it has been stopped
- `lissy93/dashy:latest` This last option is the image the container should be built from, you can also use a specific version or architecture type, by replacing `:latest` with one of the [tags](https://hub.docker.com/r/lissy93/dashy/tags)
For all available options, and to learn more, see the [Docker Run Docs](https://docs.docker.com/engine/reference/commandline/run/)
Dashy is also available through GHCR: `docker pull ghcr.io/lissy93/dashy:latest`
If you're deploying Dashy on a modern ARM-based board, such as a Raspberry Pi (2+), then you'll need to use one of Dashy's ARM images. Set the base image + tag to either `lissy93/dashy:arm64v8` or `lissy93/dashy:arm32v7`, depending on your system architecture. You can also use the `multi-arch` image, which should work on all system architectures.
The image defaults to `:latest`, but you can instead specify a specific version, e.g. `docker pull lissy93/dashy:release-1.5.0`
---
## Using Docker Compose
Using Docker Compose can be useful for saving your specific config in files, without having to type out a long run command each time. Save compose config as a YAML file, and then run `docker compose up -d` (optionally use the `-f` flag to specify file location, if it isn't located at `./docker-compose.yml`), `-d` is detached mode (not running in the foreground of your terminal). Compose is also useful if you are using clusters, as the format is very similar to stack files, used with Docker Swarm.
The following is a complete example of a [`docker-compose.yml`](https://github.com/Lissy93/dashy/blob/master/docker-compose.yml) for Dashy. Run it as is, or uncomment the additional options you need.
```yaml
---
version: "3.8"
services:
dashy:
# To build from source, replace 'image: lissy93/dashy' with 'build: .'
# build: .
image: lissy93/dashy
container_name: Dashy
# Pass in your config file below, by specifying the path on your host machine
# volumes:
# - /root/my-config.yml:/app/public/conf.yml
ports:
- 4000:80
# Set any environmental variables
environment:
- NODE_ENV=production
# Specify your user ID and group ID. You can find this by running `id -u` and `id -g`
# - UID=1000
# - GID=1000
# Specify restart policy
restart: unless-stopped
# Configure healthchecks
healthcheck:
test: ['CMD', 'node', '/app/services/healthcheck']
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
```
You can use a different tag, by for example setting `image: lissy93/dashy:arm64v8`, or pull from GHCR instead by setting `image: ghcr.io/lissy93/dashy`.
If you are building from source, and would like to use one of the [other Dockerfiles](https://github.com/Lissy93/dashy/tree/master/docker), then under `services.dashy` first set `context: .`, then specify the the path to the dockerfile, e.g. `dockerfile: ./docker/Dockerfile-arm32v7`
---
## Unraid
// TODO
---
## Synology NAS
Installing dashy is really simply and fast:
1. Install Docker via Synology ```Package Center```.
2. Go to ```File Station``` and open the ```docker``` folder. Inside the docker folder, create one new folder and name it ```dashy```.
> Note: Be careful to enter only lowercase, not uppercase letters.
3. Go to Control Panel / Task Scheduler / Create / Scheduled Task / User-defined script.
4. Once you click on ```User-defined``` script a new window will open.
5. Follow the instructions below:
6. General: In the Task field type in Install dashy. Uncheck "Enabled" option. Select root User.
7. Schedule: Select Run on the following date then select "Do not repeat".
8. Task Settings: Check "Send run details by email", add your email then copy paste the code below in the Run command area. After that click OK.
```bash
docker run -d \
-p 4000:80 \
-v /volume1/docker/dashy/my-local-conf.yml:/app/public/conf.yml \
--name dashy \
--restart=always \
lissy93/dashy:latest
```
dashy should be up within 1-2min after you've started the install task procedure
---
## Build from Source
If you do not want to use Docker, you can run Dashy directly on your host system. For this, you will need both [git](https://git-scm.com/downloads) and the latest or LTS version of [Node.js](https://nodejs.org/) installed, and optionally [yarn](https://yarnpkg.com/)
1. Get Code: `git clone https://github.com/Lissy93/dashy.git` and `cd dashy`
2. Configuration: Fill in you're settings in `./public/conf.yml`
3. Install dependencies: `yarn`
4. Build: `yarn build`
5. Run: `yarn start`
---
## Deploy to cloud service
If you don't have a home server, then fear not - Dashy can be deployed to pretty much any cloud provider. The above Docker and NPM guides will work exactly the same on a VPS, but I've also setup some 1-Click deploy links for 10+ of the most common cloud providers, to make things easier. Note that if your instance is exposed to the internet, it will be your responsibility to adequately secure it.
Some hosting providers required a bit of extra configuration, which was why I've made separate branches for deploying to those services (named: [`deploy_cloudflare`](https://github.com/Lissy93/dashy/tree/deploy_cloudflare), [`deploy_digital-ocean`](https://github.com/Lissy93/dashy/tree/deploy_digital-ocean), [`deploy_platform-sh`](https://github.com/Lissy93/dashy/tree/deploy_platform-sh) and [`deploy_render`](https://github.com/Lissy93/dashy/tree/deploy_render)). If there's another cloud service which you'd like 1-click deployment to be supported for, feel free to raise an issue.
**Note** If you use a static hosting provider, then status checks, writing new config changes to disk from the UI, and triggering a rebuild through the UI will not be available. This is because these features need endpoints provided by Dashy's local Node server. Everything else should work just the same though.
### Netlify
[![Deploy to Netlify](https://i.ibb.co/GtKMysT/deploy-netlify-button.png)](https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/dashy)
[Netlify](https://www.netlify.com/) offers Git-based serverless cloud hosting for web applications. Their services are free to use for personal use, and they support deployment from both public and private repos, as well as direct file upload. The free plan also allows you to use your own custom domain or sub-domain, and is easy to setup.
To deploy Dashy to Netlify, use the following link
```text
https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/dashy
```
### Heroku
[![Deploy to Heroku](https://i.ibb.co/GdMFzBP/deploy-heroku-button.png)](https://heroku.com/deploy?template=https://github.com/Lissy93/dashy)
[Heroku](https://www.heroku.com/) is a fully managed cloud platform as a service. You define app settings in a Procfile and app.json, which specifying how the app should be build and how the server should be started. Heroku costs a minimum of $5 for 1,000 dyno hours per month (there are around 720 hours in a month), and supports custom domains. Heroku's single-dyno service is not as quite performant as some other providers, and the app will have a short wake-up time when not visited for a while
To deploy Dashy to Heroku, use the following link
```text
https://heroku.com/deploy?template=https://github.com/Lissy93/dashy
```
### Vercel
[![Deploy with Vercel](https://i.ibb.co/mJF3R7m/deploy-vercel-button.png)](https://vercel.com/new/project?template=https://github.com/lissy93/dashy)
[Vercel](https://vercel.com/) is a performance-focused platform for hosting static frontend apps. It comes bundled with some useful tools for monitoring and analyzing application performance and other metrics. Vercel is free for personal use, allows for custom domains and has very reasonable limits.
To deploy Dashy to Vercel, use the following link
```text
https://vercel.com/new/project?template=https://github.com/lissy93/dashy
```
### DigitalOcean
[![Deploy to DO](https://i.ibb.co/PFt0PkB/deploy-digital-ocean-button.png)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/lissy93/dashy/tree/deploy_digital-ocean&refcode=3838338e7f79)
[DigitalOcean](https://www.digitalocean.com/) is a cloud service providing affordable developer-friendly virtual machines from $5/month. But they also have an app platform, where you can run web apps, static sites, APIs and background workers. CDN-backed static sites are free for personal use.
```text
https://cloud.digitalocean.com/apps/new?repo=https://github.com/lissy93/dashy/tree/deploy_digital-ocean
```
### Google Cloud Platform
[![Run on Google Cloud](https://i.ibb.co/LkvHttd/deploy-google-cloud-button.png)](https://deploy.cloud.run/?git_repo=https://github.com/lissy93/dashy.git)
[Cloud Run](https://cloud.google.com/run/) is a service offered by [Google Cloud](https://cloud.google.com/). It's a fully managed serverless platform, for developing and deploying highly scalable containerized applications. Similar to AWS and Azure, GCP offers a wide range of cloud services, which are billed on a payperuse basis, but Cloud Run has a [free tier](https://cloud.google.com/run/pricing) offering 180,000 vCPU-seconds, 360,000 GiB-seconds, and 2 million requests per month.
To deploy Dashy to GCP, use the following link
```text
https://deploy.cloud.run/?git_repo=https://github.com/lissy93/dashy.git
```
### Platform.sh
[![Deploy to Platform.sh](https://i.ibb.co/nPnJgJP/deploy-platform-sh-button.png)](https://console.platform.sh/projects/create-project/?template=https://github.com/lissy93/dashy&utm_campaign=deploy_on_platform?utm_medium=button&utm_source=affiliate_links&utm_content=https://github.com/lissy93/dashy)
[Platform.sh](https://platform.sh) is an end-to-end solution for developing and deploying applications. It is geared towards enterprise users with large teams, and focuses on allowing applications to scale up and down. Unlike the above providers, Platform.sh is not free, although you can deploy a test app to it without needing a payment method
To deploy Dashy to Platform.sh, use the following link
```text
https://console.platform.sh/projects/create-project/?template=https://github.com/lissy93/dashy
```
### Render
[![Deploy to Render](https://i.ibb.co/QXNCbxT/deploy-render-button.png)](https://render.com/deploy?repo=https://github.com/lissy93/dashy/tree/deploy_render)
[Render](https://render.com) is cloud provider that provides easy deployments for static sites, Docker apps, web services, databases and background workers. Render is great for developing applications, and very easy to use. Static sites are free, and services start at $7/month. Currently there are only 2 server locations - Oregon, USA and Frankfurt, Germany. For more info, see the [Render Docs](https://render.com/docs)
To deploy Dashy to Render, use the following link
```text
https://render.com/deploy?repo=https://github.com/lissy93/dashy/tree/deploy_render
```
### Scalingo
[![Deploy on Scalingo](https://i.ibb.co/nj0KxyH/deploy-scalingo-button.png)](https://my.scalingo.com/deploy?source=https://github.com/lissy93/dashy#master)
[Scalingo](https://scalingo.com/) is a scalable container-based cloud platform as a service. It's focus is on compliance and uptime, and is geared towards enterprise users. Scalingo is also not free, although they do have a 3-day free trial that does not require a payment method.
To deploy Dashy to Scalingo, use the following link
```text
https://my.scalingo.com/deploy?source=https://github.com/lissy93/dashy#master
```
### Play-with-Docker
[![Try in PWD](https://i.ibb.co/SfbH7Zy/deploy-pwd-button.png)](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml)
[Play with Docker](https://labs.play-with-docker.com/) is a community project by Marcos Liljedhal and Jonathan Leibiusky and sponsored by Docker, intended to provide a hands-on learning environment. Their labs let you quickly spin up a Docker container or stack, and test out the image in a temporary, sandboxed environment. There's no need to sign up, and it's completely free.
To run Dashy in PWD, use the following URL:
```text
https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml
```
### Surge.sh
![Follow instructions below](https://i.ibb.co/XkcKzKz/deploy-surge-button.png)
[Surge.sh](http://surge.sh/) is quick and easy static web publishing platform for frontend-apps.
Surge supports [password-protected projects](https://surge.sh/help/adding-password-protection-to-a-project). You can also [add a custom domain](https://surge.sh/help/adding-a-custom-domain) and then [force HTTPS by default](https://surge.sh/help/using-https-by-default) and optionally [set a custom SSL certificate](https://surge.sh/help/securing-your-custom-domain-with-ssl)
To deploy Dashy to Surge.sh, first clone and cd into Dashy, install dependencies, and then use the following commands
```bash
yarn add -g surge
yarn build
surge ./dist
```
### Easypanel
[![Deploy to Easypanel](https://i.ibb.co/ZNPwQX3/deploy-easypanel-button.png)](https://easypanel.io/docs/templates/dashy)
[Easypanel](https://easypanel.io) it's a modern server control panel. You can use it to deploy Dashy on your own server.
To deploy Dashy to Easypanel, use the following link
```text
https://easypanel.io/docs/templates/dashy
```
---
## Hosting with CDN
Once Dashy has been built, it is effectively just a static web app. This means that it can be served up with pretty much any static host, CDN or web server. To host Dashy through a CDN, the steps are very similar to building from source: clone the project, cd into it, install dependencies, write your config file and build the app. Once build is complete you will have a `./dist` directory within Dashy's root, and this is the build application which is ready to be served up.
However without Dashy's node server, there are a couple of features that will be unavailable to you, including: Writing config changes to disk through the UI, triggering a rebuild through the UI and application status checks. Everything else will work fine.
---
## Requirements
### System Requirements
Dashy works well on a Raspberry Pi (tested on Pi 3 and later), but should also run well on any system.
### Docker
Initial app build causes a spike in resource usage, but once the built app is running it is fairly steady. For this reason, Dashy works best with a minimum of 1GB of memory, and 1GB of disk space.
### Bare Metal
Minimum 526mb mem, 2GB disk space.
### CDN / Cloud Deploy
No specific requirements. The built application alone (without the Node server) is very light-weight, and can be handled smoothly by pretty much any CDN or cloud deployment service (see [this list](/docs/deployment.md#deploy-to-cloud-service) or natively supported cloud providers).
If you're using your own icons, or other assets, additional disk space will be required for those resources.
### Browser Support
JavaScript is required to run Dashy.
In terms of browser support, pretty much any browser released since 2018 should render content just fine. However, for Internet Explorer, only IE11+ is supported, yet performance here is still not optimal. The recommended browser is either a Chromium-based / Webkit browser (Chrome, Brave, Vivaldi, Edge, Yandex, etc), or Firefox or one of it's forks (FF-ESR, Tor, LibreWolf, etc). Recent versions of Safari and Opera are also supported, but with limited continuous testing.
<p align="center"><img width="500" src="https://i.ibb.co/pjnmbw9/browser-compatibility.png" /></p>

380
docs/developing.md Normal file
View File

@@ -0,0 +1,380 @@
# Developing
This article outlines how to get Dashy running in a development environment, and outlines the basics of the architecture.
If you're adding new features, you may want to check out the [Development Guides](./docs/development-guides.md) docs, for tutorials covering basic tasks.
- [Setting up the Development Environment](#setting-up-the-dev-environment)
- [Prerequisites](#prerequisites)
- [Running the App](#running-the-project)
- [Project Commands](#project-commands)
- [Environmental Variables](#environmental-variables)
- [Git Strategy](#git-strategy)
- [Flow](#git-flow)
- [Branches](#git-branch-naming)
- [Commit emojis](#commit-emojis)
- [PR Guidelines](#pr-guidelines)
- [Resources for Beginners](#resources-for-beginners)
- [App Info](#app-info)
- [Code Style Guide](#style-guide)
- [Application Structure](#application-structure)
- [Development Tools](#development-tools)
- [Misc / Notes](#notes)
## Setting up the Dev Environment
### Prerequisites
You will need either the latest or LTS version of **[Node.js](https://nodejs.org/)** to build and serve the application and **[Git](https://git-scm.com/downloads)** to easily fetch the code, and push any changes. If you plan on running or deploying the container, you'll also need **[Docker](https://docs.docker.com/get-docker/)**. To avoid any unexpected issues, ensure you've got at least **[NPM](https://www.npmjs.com/get-npm)** V 7.5 or **[Yarn](https://classic.yarnpkg.com/en/docs/install/#windows-stable)** 1.22 (you may find [NVM](https://github.com/nvm-sh/nvm) helpful for switching/ managing versions).
### Running the Project
1. Get Code: `git clone https://github.com/Lissy93/dashy.git`
2. Navigate into the directory: `cd dashy`
3. Install dependencies: `yarn`
4. Start dev server: `yarn dev`
Dashy should now be being served on <http://localhost:8080/>. Hot reload is enabled, so making changes to any of the files will trigger them to be rebuilt and the page refreshed.
### Project Commands
#### Basics
- **`yarn build`** - In the interest of speed, the application is pre-compiled, this means that the config file is read during build-time, and therefore the app needs to rebuilt for any new changes to take effect. Luckily this is very straight forward. Just run `yarn build` or `docker exec -it [container-id] yarn build`
- **`yarn start`** - Starts a web server, and serves up the production site from `./dist` (must run build command first)
#### Development
- **`yarn dev`** - Starts the development server with hot reloading
- **`yarn lint`** - Lints code to ensure it follows a consistent, neat style
- **`yarn test`** - Runs tests, and outputs results
#### Utils and Checks
- **`yarn validate-config`** - If you have quite a long configuration file, you may wish to check that it's all good to go, before deploying the app. This can be done with `yarn validate-config` or `docker exec -it [container-id] yarn validate-config`. Your config file needs to be in `/public/conf.yml` (or within your Docker container at `/app/public/conf.yml`). This will first check that your YAML is valid, and then validates it against Dashy's [schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.js).
- **`yarn health-check`** - Checks that the application is up and running on it's specified port, and outputs current status and response times. Useful for integrating into your monitoring service, if you need to maintain high system availability
#### Alternate Start Commands
- **`yarn build-and-start`** - Builds the app, runs checks and starts the production server. Commands are run in parallel, and so is faster than running them in independently. Uses the `yarn build` and `yarn start` commands
- **`yarn build-watch`** - If you find yourself making frequent changes to your configuration, and do not want to have to keep manually rebuilding, then this option is for you. It will watch for changes to any files within the projects root, and then trigger a rebuild. Note that if you are developing new features, then `yarn dev` would be more appropriate, as it's significantly faster at recompiling (under 1 second), and has hot reloading, linting and testing integrated
- **`yarn pm2-start`** - Starts the Node server using [PM2](https://pm2.keymetrics.io/), a process manager for Node.js applications, that helps them stay alive. PM2 has some built-in basic monitoring features, and an optional [management solution](https://pm2.io/). If you are running the app on bare metal, it is recommended to use this start command
#### Notes
- If you are using NPM, replace `yarn` with `npm run`
- If you are using Docker, precede each command with `docker exec -it [container-id]`. Container ID can be found by running `docker ps`
- You can manage the app using the [Vue-CLI Service](https://cli.vuejs.org/guide/cli-service.html), with `npx vue-cli-service [command]`. Or to start the Vue Management UI, run `npx vue ui`, and open `http://localhost:8000`
### Environmental Variables
All environmental variables are optional. Currently there are not many environmental variables used, as most of the user preferences are stored under `appConfig` in the `conf.yml` file.
You can set variables either in your environment, or using the [`.env`](https://github.com/Lissy93/dashy/blob/master/.env) file.
- `NODE_ENV` - Current environment, can be either development, production or test
- `PORT` - The port to expose the running application on
- `HOST` - The host that Dashy is running on, domain or IP
- `BASE_URL` - The default base path for serving up static assets
- `VUE_APP_DOMAIN` - Usually the same as BASE_URL, but accessible in frontend
- `INTEGRITY` - Should enable SRI for build script and link resources
- `IS_DOCKER` - Computed automatically on build. Indicates if running in container
- `VUE_APP_VERSION` - Again, set automatically using package.json during build time
- `BACKUP_DIR` - Directory for conf.yml backups
### Environment Modes
You can set the environment using the `NODE_ENV` variable. By default, the correct environment should be selected based on the script you run to start the app. The following environments are supported: `production`, `development` and `test`. For more info, see [Vue CLI Environment Modes](https://cli.vuejs.org/guide/mode-and-env.html#modes).
---
## Git Strategy
### Git Flow
Like most Git repos, we are following the [Github Flow](https://guides.github.com/introduction/flow) standard.
1. Create a branch (or fork if you don'd have write access)
2. Code some awesome stuff 🧑‍💻
3. Add, commit and push your changes to your branch/ fork
4. Head over to GitHub and create a Pull Request
5. Fill in the required sections in the template, and hit submit
6. Follow up with any reviews on your code
7. Merge 🎉
### Git Branch Naming
The format of your branch name should be something similar to: `[TYPE]/[TICKET]_[TITLE]`
For example, `FEATURE/420_Awesome-feature` or `FIX/690_login-server-error`
### Commit Emojis
Using a single emoji at the start of each commit message, to indicate the type task, makes the commit ledger easier to understand, plus it looks cool.
- 🎨 `:art:` - Improve structure / format of the code.
- ⚡️ `:zap:` - Improve performance.
- 🔥 `:fire:` - Remove code or files.
- 🐛 `:bug:` - Fix a bug.
- 🚑️ `:ambulance:` - Critical hotfix
-`:sparkles:` - Introduce new features.
- 📝 `:memo:` - Add or update documentation.
- 🚀 `:rocket:` - Deploy stuff.
- 💄 `:lipstick:` - Add or update the UI and style files.
- 🎉 `:tada:` - Begin a project.
-`:white_check_mark:` - Add, update, or pass tests.
- 🔒️ `:lock:` - Fix security issues.
- 🔖 `:bookmark:` - Make a Release or Version tag.
- 🚨 `:rotating_light:` - Fix compiler / linter warnings.
- 🚧 `:construction:` - Work in progress.
- ⬆️ `:arrow_up:` - Upgrade dependencies.
- 👷 `:construction_worker:` - Add or update CI build system.
- ♻️ `:recycle:` - Refactor code.
- 🩹 `:adhesive_bandage:` - Simple fix for a non-critical issue.
- 🔧 `:wrench:` - Add or update configuration files.
- 🍱 `:bento:` - Add or update assets.
- 🗃️ `:card_file_box:` - Perform database schema related changes.
- ✏️ `:pencil2:` - Fix typos.
- 🌐 `:globe_with_meridians:` - Internationalization and translations.
For a full list of options, see [gitmoji.dev](https://gitmoji.dev/)
### PR Guidelines
Once you've made your changes, and pushed them to your fork or branch, you're ready to open a pull request!
For a pull request to be merged, it must:
- Must be backwards compatible
- The build, lint and tests (run by GH actions) must pass
- There must not be any merge conflicts
When you submit your PR, include the required info, by filling out the PR template. Including:
- A brief description of your changes
- The issue, ticket or discussion number (if applicable)
- For UI relate updates include a screenshot
- If any dependencies were added, explain why it was needed, state the cost associated, and confirm it does not introduce any security issues
- Finally, check the checkboxes, to confirm that the standards are met, and hit submit!
---
## Resources for Beginners
New to Web Development? Glad you're here! Dashy is a pretty simple app, so it should make a good candidate for your first PR. Presuming that you already have a basic knowledge of JavaScript, the following articles should point you in the right direction for getting up to speed with the technologies used in this project:
- [Open Source for Beginners](https://opensource.guide/how-to-contribute/)
- [Introduction to Vue.js](https://v3.vuejs.org/guide/introduction.html)
- [Vue.js Walkthrough](https://www.taniarascia.com/getting-started-with-vue/)
- [ES6 Features](https://github.com/lukehoban/es6features)
- [Definitive guide to SCSS](https://blog.logrocket.com/the-definitive-guide-to-scss/)
- [Complete beginners guide to Docker](https://docker-curriculum.com/)
- [Docker Classroom - Interactive Tutorials](https://training.play-with-docker.com/)
- [Quick start TypeScript guide](https://www.freecodecamp.org/news/learn-typescript-in-5-minutes-13eda868daeb/)
- [Complete TypeScript tutorial series](https://www.typescripttutorial.net/)
- [Using TypeScript with Vue.js](https://blog.logrocket.com/vue-typescript-tutorial-examples/)
- [Git cheat sheet](http://git-cheatsheet.com/)
- [Basics of using NPM](https://www.freecodecamp.org/news/what-is-npm-a-node-package-manager-tutorial-for-beginners/)
As well as Node, Git and Docker- you'll also need an IDE (e.g. [VS Code](https://code.visualstudio.com/) or [Vim](https://www.vim.org/)) and a terminal (Windows users may find [WSL](https://docs.microsoft.com/en-us/windows/wsl/) more convenient).
---
## App Info
### Style Guide
Linting is done using [ESLint](https://eslint.org/), and using the [Vue.js Styleguide](https://github.com/vuejs/eslint-config-standard), which is very similar to the [AirBnB Styleguide](https://github.com/airbnb/javascript). You can run `yarn lint` to report and fix issues. While the dev server is running, issues will be reported to the console automatically, and any lint errors will trigger the build to fail. Note that all lint checks must pass before any PR can be merged. Linting is also run as a git pre-commit hook
The most significant things to note are:
- Indentation should be done with two spaces
- Strings should use single quotes
- All statements must end in a semi-colon
- The final element in all objects must be preceded with a comma
- Maximum line length is 100
- There must be exactly one blank line between sections, before function names, and at the end of the file
- With conditionals, put else on the same line as your if block's closing brace
- All multiline blocks must use braces
- Avoid console statements in the frontend
Styleguides:
- Vue: [Vue styleguide](https://vuejs.org/v2/style-guide/)
- JavaScript: [github.com/airbnb/javascript](https://github.com/airbnb/javascript)
---
### Application Structure
#### Files in the Root: `./`
```text
├── package.json # Project meta-data, dependencies and paths to scripts
├── src/ # Project front-end source code
├── server.js # A Node.js server to serve up the /dist directory
├── services/ # All server-side endpoints and utilities
├── vue.config.js # Vue.js configuration
├── Dockerfile # The blueprint for building the Docker container
├── docker-compose.yml # A Docker run command
├── .env # Location for any environmental variables
├── yarn.lock # Auto-generated list of current packages and version numbers
├── docs/ # Markdown documentation
├── README.md # Readme, basic info for getting started
├── LICENSE.md # License for use
```
#### Frontend Source: `./src/`
```text
./src
├── App.vue # Vue.js starting file
├── assets # Static non-compiled assets
│ ├── fonts # .ttf font files
│ ├── locales # All app text, each language in a separate JSON file
│ ╰── interface-icons # SVG icons used in the app
├── components # All front-end Vue web components
│ ├── Charts # Charting components for dynamically displaying widget data
│ │ ├── Gauge.vue # A speed-dial style chart for showing 0 - 100 values
│ │ ╰── PercentageChart.vue # A horizontal bar for showing percentage breakdowns
│ ├── Configuration # Components relating to the user config pop-up
│ │ ├── AppInfoModal.vue # A modal showing core app info, like version, language, etc
│ │ ├── AppVersion.vue # Shows current version from package.json, compares with GitHub
│ │ ├── CloudBackupRestore.vue # Form where the user manages cloud sync options
│ │ ├── ConfigContainer.vue # Main container, wrapping all other config components
│ │ ├── CustomCss.vue # Form where the user can input custom CSS
│ │ ├── EditSiteMeta.vue # Form where the user can edit site meta data
│ │ ├── JsonEditor.vue # JSON editor, where the user can modify the main config file
│ │ ╰── RebuildApp.vue # A component allowing user to trigger a rebuild through the UI
│ ├── FormElements # Basic form elements used throughout the app
│ │ ├── Button.vue # Standard button component
│ │ ├── Radio.vue # Standard radio button input
│ │ ├── Select.vue # Standard dropdown input selector
│ │ ├── Input.vue # Standard text field input component
│ │ ╰── Toggle.vue # Standard on / off toggle switch
│ ├── InteractiveEditor # Components for the interactive UI config editor
│ │ ├── AddNewSectionLauncher # Button that launches the EditSection form, used for adding new section
│ │ ├── EditAppConfig.vue # Form for editing appConfig
│ │ ├── EditPageInfo.vue # Form for editing pageInfo
│ │ ├── EditSection.vue # Form for adding / editing sections
│ │ ├── EditItem.vue # Form for adding or editing items
│ │ ├── EditModeSaveMenu.vue # The bar at the bottom of screen in edit mode, containing save buttons
│ │ ├── EditModeTopBanner.vue # The bar at the top of screen in edit mode
│ │ ├── ExportConfigMenu.vue # Modal for viewing / exporting edited config
│ │ ├── MoveItemTo.vue # Form for moving / copying items to other sections
│ │ ╰── SaveCancelButtons.vue # Buttons visible in all the edit menus, to save or cancel changes
│ ├── LinkItems # Components for Sections and Link Items
│ │ ├── Collapsable.vue # The collapsible functionality of sections
│ │ ├── IframeModal.vue # Pop-up iframe modal, for viewing websites within the app
│ │ ├── Item.vue # Main link item, which is displayed within an item group
│ │ ├── ItemGroup.vue # Item group is a section containing icons
│ │ ├── ItemIcon.vue # The icon used by both items and sections
│ │ ├── ItemOpenMethodIcon.vue # A small icon, visible on hover, indicating opening method
│ │ ├── ItemContextMenu.vue # The right-click menu, for showing Item opening methods and info
│ │ ├── SectionContextMenu.vue # The right-click menu, for showing Section edit/ open options
│ │ ╰── StatusIndicator.vue # Traffic light dot, showing if app is online or down
│ ├── Minimal View # Components used for the startpage / minimal alternative view
│ │ ├── MinimalHeading.vue # Title part of minimal view
│ │ ├── MinimalSearch.vue # Search bar for minimal view
│ │ ╰── MinimalSection.vue # Tabbed-Item section for minimal view
│ ├── PageStrcture # Components relating the main structure of the page
│ │ ├── Footer.vue # Footer, visible at the bottom of all pages
│ │ ├── Header.vue # Header, visible at the top of pages, and includes title and nav
│ │ ├── LoadingScreen.vue # Splash screen shown on first load
│ │ ├── Nav.vue # Navigation bar, includes a list of links
│ │ ╰── PageTitle.vue # Page title and sub-title, visible within the Header
│ ├── Workspace # Components used for the multi-tasking/ Workspace view
│ │ ├── MultiTaskingWeb.vue # When multi-tasking enabled, generates new iframe
│ │ ├── SideBar.vue # The left sidebar for the workspace view
│ │ ├── SideBarItem.vue # App item for the sidebar view
│ │ ├── SideBarSection.vue # Collapsible collection of items within workspace sidebar
│ │ ├── WebContent.vue # Workspace iframe view, displays content of current app
│ │ ╰── WidgetView.vue # Workspace container for displaying widgets in main content
│ ├── Widgets # Directory contains all custom widget components
│ │ ╰── .... # Too many to list, see widget docs instead
│ ╰── Settings # Components relating to the quick-settings, in the top-right
│ ├── AuthButtons.vue # Logout button and other app info
│ ├── ConfigLauncher.vue # Icon that when clicked will launch the Configuration component
│ ├── CustomThemeMaker.vue # Color pickers for letting user build their own theme
│ ├── ItemSizeSelector.vue # Set of buttons used to set and save item size
│ ├── KeyboardShortcutInfo.vue# Small pop-up displaying the available keyboard shortcuts
│ ├── LanguageSwitcher.vue # Dropdown in a modal for changing app language
│ ├── LayoutSelector.vue # Set of buttons, letting the user select their desired layout
│ ├── SearchBar.vue # The input field in the header, used for searching the app
│ ├── SettingsContainer.vue # Container that wraps all the quick-settings components
│ ╰── ThemeSelector.vue # Drop-down menu enabling the user to select and change themes
├── main.js # Main front-end entry point
├── registerServiceWorker.js # Registers and manages service workers, for PWA apps
├── router.js # Defines all available application routes
├── styles # Directory of all globally used common SCSS styles
│ ├── color-palette.scss # All color variable names and default values
│ ├── color-themes.scss # All variable values for built-in themes
│ ├── dimensions.scss # Dimensions and sizes as variables
│ ├── global-styles.scss # Basics and style resets used globally
│ ├── media-queries.scss # Screen sizes and media queries
│ ├── style-helpers.scss # SCSS functions used for modifying values
│ ├── typography.scss # Font and text styles used globally
│ ╰── user-defined-themes.scss # Empty, put any custom styles or themes here
├── mixins # Reusable component bases, extended by other views / components
│ ├── ChartingMixin.js # Functions for rendering charts in widget components
│ ├── GlancesMixin.js # Functions for fetching system info from Glances for widgets
│ ├── HomeMixin.js # Functions for homepage, used by default, minimal and workspace views
│ ╰── WidgetMixin.js # Functions for all widgets, like data fetching, updating and error handling
├── utils # Directory of re-used helper functions
│ ├── ArrowKeyNavigation.js # Functionality for arrow-key navigation
│ ├── Auth.js # Handles all authentication related actions
│ ├── CheckSectionVisibility.js # Checks which parts of the page should be visible/ hidden based on config
│ ├── ClickOutside.js # A directive for detecting click, used to hide dropdown, modal or context menu
│ ├── ConfigHelpers.js # Helper functions for managing configuration
│ ├── CloudBackup.js # Functionality for encrypting, processing and network calls
│ ├── ConfigSchema.json # The schema, used to validate the users conf.yml file
│ ├── ConfigAccumulator.js # Central place for managing and combining config
│ ├── ConfigHelpers.json # Collection of helper functions to process config using accumulator
│ ├── ConfigValidator.js # A helper script that validates the config file against schema
│ ├── CoolConsole.js # Prints info, warning and error messages to browser console, with a cool style
│ ├── defaults.js # Global constants and their default values
│ ├── emojis.json # List of emojis with unicode and shortcode, used for emoji icon feature
│ ├── EmojiUnicodeRegex.js # Regular expression to validate emoji unicode format, for emoji icons
│ ├── ErrorHandler.js # Helper function called when an error is returned
│ ├── InitServiceWorker.js # Initializes and manages service worker, if enabled
│ ├── Search.js # Helper functions for searching/ filtering items in all views
│ ├── JsonToYaml.js # Function that parses and converts raw JSON into valid YAML
│ ├── KeycloakAuth.js # Singleton class to manage Keycloak authentication
│ ├── languages.js # Handles fetching, switching and validating languages
│ ╰── ThemeHelper.js # Function that handles the fetching and setting of user themes
╰── views # Directory of available pages, corresponding to available routes
├── Home.vue # The home page container
├── About.vue # About page
├── Login.vue # TAuthentication page
├── Minimal.vue # The minimal view
╰── Workspace.vue # The workspace view with apps in sidebar
```
#### Visualisation of Source Directory
![File Breakdown](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/repo-visualization.svg)
---
## Development Tools
### Performance - Lighthouse
The easiest method of checking performance is to use Chromium's build in auditing tool, Lighthouse. To run the test, open Developer Tools (usually F12) --> Lighthouse and click on the 'Generate Report' button at the bottom.
### Dependencies - BundlePhobia
[BundlePhobia](https://bundlephobia.com/) is a really useful app that lets you analyze the cost of adding any particular dependency to an application
---
## Notes
### Known Warnings
When running the build command, several warnings appear. These are not errors, and do not affect the security or performance of the application. They will be addressed in a future update
`WARN A new version of sass-loader is available. Please upgrade for best experience.` - Currently we're using an older version of SASS loader, since the more recent releases do not seem to be compatible with the Vue CLI's webpack configuration.
`WARN asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).` - For the PWA to support Windows 10, a splash screen asset is required, and is quite large. This throws a warning, however PWA assets are not loaded until needed, so shouldn't have any impact on application performance. A similar warning is thrown for the Raleway font, and that is looking to be addressed.

473
docs/development-guides.md Normal file
View File

@@ -0,0 +1,473 @@
# Development Guides
A series of short tutorials, to guide you through the most common development tasks.
Sections:
- [Creating a new theme](#creating-a-new-theme)
- [Writing Translations](#writing-translations)
- [Adding a new option in the config file](#adding-a-new-option-in-the-config-file)
- [Updating Dependencies](#updating-dependencies)
- [Writing Netlify Cloud Functions](#developing-netlify-cloud-functions)
- [Hiding Page Furniture](#hiding-page-furniture-on-certain-routes)
- [Adding / Using Environmental Variables](#adding--using-environmental-variables)
- [Building a Widget](#building-a-widget)
- [Respecting Config Permissions](#respecting-config-permissions)
## Creating a new theme
Adding a new theme is really easy. There's two things you need to do: Pass the theme name to Dashy, so that it can be added to the theme selector dropdown menu, and then write some styles!
### 1. Add Theme Name
Choose a snappy name for you're theme, and add it to the `builtInThemes` array inside [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js#L27).
### 2. Write some Styles
Put your theme's styles inside [`color-themes.scss`](https://github.com/Lissy93/dashy/blob/master/src/styles/color-themes.scss).
Create a new block, and make sure that `data-theme` matches the theme name you chose above. For example:
```css
html[data-theme='tiger'] {
--primary: #f58233;
--background: #0b1021;
}
```
Then you can go ahead and write you're own custom CSS. Although all CSS is supported here, the best way to define you're theme is by setting the CSS variables. You can find a [list of all CSS variables, here](https://github.com/Lissy93/dashy/blob/master/docs/theming.md#css-variables).
For a full guide on styling, see [Theming Docs](./theming.md).
Note that if you're theme is just for yourself, and you're not submitting a PR, then you can instead just pass it under `appConfig.cssThemes` inside your config file. And then put your theme in your own stylesheet, and pass it into the Docker container - [see how](https://github.com/Lissy93/dashy/blob/master/docs/theming.md#adding-your-own-theme).
## Writing Translations
For full docs about Dashy's multi-language support, see [Multi-Language Support](./multi-language-support.md)
Dashy is using [vue-i18n](https://vue-i18n.intlify.dev/guide/) to manage multi-language support.
Adding a new language is pretty straightforward, with just three steps:
### 1. Create a new Language File
Create a new JSON file in `./src/assets/locales` name is a 2-digit [ISO-639 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for your language, E.g. for German `de.json`, French `fr.json` or Spanish `es.json` - You can find a list of all ISO codes at [iso.org](https://www.iso.org/obp/ui).
### 2. Translate
Using [`en.json`](https://github.com/Lissy93/dashy/tree/master/src/assets/locales/en.json) as an example, translate the JSON values to your language, while leaving the keys as they are. It's fine to leave out certain items, as if they're missing they will fall-back to English. If you see any attribute which include curly braces (`{xxx}`), then leave the inner value of these braces as is, as this is for variables.
```json
{
"theme-maker": {
"export-button": "Benutzerdefinierte Variablen exportieren",
"reset-button": "Stile zurücksetzen für",
"show-all-button": "Alle Variablen anzeigen",
"save-button": "Speichern",
"cancel-button": "Abbrechen",
"saved-toast": "{theme} Erfolgreich aktualisiert",
"reset-toast": "Benutzerdefinierte Farben für {theme} entfernt"
},
}
```
### 3. Add your file to the app
In [`./src/utils/languages.js`](https://github.com/Lissy93/dashy/tree/master/src/utils/languages.js), you need to do 2 small things:
First import your new translation file, do this at the top of the page.
E.g. `import de from '@/assets/locales/de.json';`
Second, add it to the array of languages, e.g:
```javascript
export const languages = [
{
name: 'English',
code: 'en',
locale: en,
flag: '🇬🇧',
},
{
name: 'German', // The name of your language
code: 'de', // The ISO code of your language
locale: de, // The name of the file you imported (no quotes)
flag: '🇩🇪', // An optional flag emoji
},
];
```
You can also add your new language to the readme, under the [Language Switching](https://github.com/Lissy93/dashy#language-switching-) section, and optionally include your name/ username if you'd like to be credited for your work. Done!
If you are not comfortable with making pull requests, or do not want to modify the code, then feel free to instead send the translated file to me, and I can add it into the application. I will be sure to credit you appropriately.
## Adding a new option in the config file
This section is for, adding a new setting to the config file.
All of the users config is specified in `./public/conf.yml` - see [Configuring Docs](./configuring.md) for info.
It's important to first ensure that there isn't a similar option already available, the new option is definitely necessary, and most importantly that it is fully backwards compatible.
Next choose the appropriate section to place it under
- Application settings should be located under `appConfig`
- Page info (such as text and metadata) should be under `pageInfo`
- Data relating to specific sections should be under `section[n].displayData`
- Settings applied to specific items or widgets, should be under `item[n]` or `widget[n]`
For example, if your option is added under `appConfig`, you can access it within your component using the `$store`, this is typically placed in a computed property, e.g:
```javascript
computed: {
appConfig() {
return this.$store.getters.appConfig;
},
...
},
```
Then, where you want get the users value within your component, use something like: `this.appConfig.myProperty`. Don't forget to have a fallback or default for then the user hasn't specified it.
If you have a default fallback value, then this would typically be specified in the [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js) file.
You will now need to add the definition of your new attribute into the [ConfigSchema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.js). This will make it available in the UI config editor, and also ensure that the config validation check doesn't fail.
For example:
```json
"fontAwesomeKey": {
"type": "string",
"pattern": "^[a-z0-9]{10}$",
"description": "API key for font-awesome",
"example": "0821c65656"
}
```
or
```json
"iconSize": {
"enum": [ "small", "medium", "large" ],
"default": "medium",
"description": "The size of each link item / icon"
}
```
Finally, add your new property to the [`configuring.md`](./configuring.md) API docs. Put it under the relevant section, and be sure to include field name, data type, a description and mention that it is optional. If your new feature needs more explaining, then you can also document it under the relevant section elsewhere in the documentation.
Checklist:
- [ ] Ensure the new attribute is actually necessary, and nothing similar already exists
- [ ] Update the [Schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.js) with the parameters for your new option
- [ ] If required, set a default or fallback value (usually in [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js))
- [ ] Document the new value in [`configuring.md`](./configuring.md), and if required under the relevant section in the docs
- [ ] Ensure your changes are backwards compatible, and that nothing breaks if the attribute isn't specified
---
## Updating Dependencies
Running `yarn upgrade` will updated all dependencies based on the ranges specified in the `package.json`. The `yarn.lock` file will be updated, as will the contents of `./node_modules`, for more info, see the [yarn upgrade documentation](https://classic.yarnpkg.com/en/docs/cli/upgrade/). [`npm-check-updates`](https://github.com/raineorshine/npm-check-updates) is a useful tool to help with this.
It is important to thoroughly test after any big dependency updates.
---
## Developing Netlify Cloud Functions
When Dashy is deployed to Netlify, it is effectively running as a static app, and therefore the server-side code for the Node.js endpoints is not available. However Netlify now supports serverless cloud lambda functions, which can be used to replace most functionality.
### 1. Run Netlify Dev Server
First off, install the Netlify CLI: `npm install netlify-cli -g`
Then, from within the root of Dashy's directory, start the server, by running: `netlify dev`
### 2. Create a lambda function
This should be saved it in the [`./services/serverless-functions`](https://github.com/Lissy93/dashy/tree/master/services/serverless-functions) directory
```javascript
exports.handler = async () => ({
statusCode: 200,
body: 'Return some data here...',
});
```
### 3. Redirect the Node endpoint to the function
In the [`netlify.toml`](https://github.com/Lissy93/dashy/blob/FEATURE/serverless-functions/netlify.toml) file, add a 301 redirect, with the path to the original Node.js endpoint, and the name of your cloud function
```toml
[[redirects]]
from = "/status-check"
to = "/.netlify/functions/cloud-status-check"
status = 301
force = true
```
---
## Hiding Page Furniture on Certain Routes
For some pages (such as the login page, the minimal start page, etc) the basic page furniture, (like header, footer, nav, etc) is not needed. This section explains how you can hide furniture on a new view (step 1), or add a component that should be hidden on certain views (step 2).
### 1. Add the route name to the should hide array
In [`./src/utils/defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js), there's an array called `hideFurnitureOn`. Append the name of the route (the same as it appears in [`router.js`](https://github.com/Lissy93/dashy/blob/master/src/router.js)) here.
### 2. Add the conditional to the structural component to hide
First, import the helper function:
```javascript
import { shouldBeVisible } from '@/utils/SectionHelpers';
```
Then you can create a computed value, that calls this function, passing in the route name:
```javascript
export default {
...
computed: {
...
isVisible() {
return shouldBeVisible(this.$route.name);
},
},
};
```
Finally, in the markup of your component, just add a `v-if` statement, referencing your computed value
```vue
<header v-if="isVisible">
...
</header>
```
---
## Adding / Using Environmental Variables
All environmental variables are optional. Currently there are not many environmental variables used, as most of the user preferences are stored under `appConfig` in the `conf.yml` file.
You can set variables either in your environment, or using the [`.env`](https://github.com/Lissy93/dashy/blob/master/.env) file.
Any environmental variables used by the frontend are preceded with `VUE_APP_`. Vue will merge the contents of your `.env` file into the app in a similar way to the ['dotenv'](https://github.com/motdotla/dotenv) package, where any variables that you set on your system will always take preference over the contents of any `.env` file.
If add any new variables, ensure that there is always a fallback (define it in [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js)), so as to not cause breaking changes. Don't commit the contents of your `.env` file to git, but instead take a few moments to document what you've added under the appropriate section. Try and follow the concepts outlined in the [12 factor app](https://12factor.net/config).
---
## Building a Widget
### Step 0 - Prerequisites
If this is your first time working on Dashy, then the [Developing Docs](https://github.com/Lissy93/dashy/blob/master/docs/developing.md) instructions for project setup and running. In short, you just need to clone the project, cd into it, install dependencies (`yarn`) and then start the development server (`yarn dev`).
To build a widget, you'll also need some basic knowledge of Vue.js. The [official Vue docs](https://vuejs.org/v2/guide/) provides a good starting point, as does [this guide](https://www.taniarascia.com/getting-started-with-vue/) by Tania Rascia
If you just want to jump straight in, then [here](https://github.com/Lissy93/dashy/commit/3da76ce2999f57f76a97454c0276301e39957b8e) is a complete implementation of a new example widget, or take a look at the [`XkcdComic.vue`](https://github.com/Lissy93/dashy/blob/master/src/components/Widgets/XkcdComic.vue) widget, which is pretty simple.
### Step 1 - Create Widget
Firstly, create a new `.vue` file under [`./src/components/Widgets`](https://github.com/Lissy93/dashy/tree/master/src/components/Widgets).
```vue
<template>
<div class="example-wrapper">
</div>
</template>
<script>
import axios from 'axios';
import WidgetMixin from '@/mixins/WidgetMixin';
import { widgetApiEndpoints } from '@/utils/defaults';
export default {
mixins: [WidgetMixin],
data() {
return {
results: null,
};
},
computed: {
endpoint() {
return `${widgetApiEndpoints.myApi}/something`;
},
},
methods: {
fetchData() {
this.makeRequest(this.endpoint).then(this.processData);
},
processData(data) {
// Do processing any here, and set component data
this.results = data;
},
},
};
</script>
<style scoped lang="scss">
</style>
```
All widgets extend from the [Widget](https://github.com/Lissy93/dashy/blob/master/src/mixins/WidgetMixin.js) mixin. This provides some basic functionality that is shared by all widgets. The mixin includes the following `options`, `startLoading()`, `finishLoading()`, `error()` and `update()`.
- **Getting user options: `options`**
- Any user-specific config can be accessed with `this.options.something` (where something is the data key you're accessing)
- **Loading state: `startLoading()` and `finishLoading()`**
- You can show the loader with `this.startLoading()`, then when your data request completes, hide it again with `this.finishLoading()`
- **Error handling: `error()`**
- If something goes wrong (such as API error, or missing user parameters), then call `this.error()` to show message to user
- **Updating data: `update()`**
- When the user clicks the update button, or if continuous updates are enabled, then the `update()` method within your widget will be called
### Step 2 - Adding Functionality
#### **Accessing User Options**
If your widget is going to accept any parameters from the user, then we can access these with `this.options.[parmName]`. It's best to put these as computed properties, which will enable us to check it exists, is valid, and if needed format it. For example, if we have an optional property called `count` (to determine number of results), we can do the following, and then reference it within our component with `this.count`
```javascript
computed: {
count() {
if (!this.options.count) {
return 5;
}
return this.options.count;
},
...
},
```
#### **Adding an API Endpoint**
If your widget makes a data request, then add the URL for the API endpoint to the `widgetApiEndpoints` array in [`defaults.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/defaults.js#L207)
```javascript
widgetApiEndpoints: {
...
exampleEndpoint: 'https://hub.dummyapis.com/ImagesList',
},
```
Then in your widget file:
```javascript
import { widgetApiEndpoints } from '@/utils/defaults';
```
For GET requests, you may need to add some parameters onto the end of the URL. We can use another computed property for this, for example:
```javascript
endpoint() {
return `${widgetApiEndpoints.exampleEndpoint}?count=${this.count}`;
},
```
#### **Making an API Request**
Axios is used for making data requests, so import it into your component: `import axios from 'axios';`
Under the `methods` block, we'll create a function called `fetchData`, here we can use Axios to make a call to our endpoint.
```javascript
fetchData() {
this.makeRequest(this.endpoint, this.headers).then(this.processData);
},
```
There are three things happening here:
- If the response completes successfully, we'll pass the results to another function that will handle them
- If there's an error, then we call `this.error()`, which will show a message to the user
- Whatever the result, once the request has completed, we call `this.finishLoading()`, which will hide the loader
#### **Processing Response**
In the above example, we call the `processData()` method with the result from the API, so we need to create that under the `methods` section. How you handle this data will vary depending on what's returned by the API, and what you want to render to the user. But however you do it, you will likely need to create a data variable to store the response, so that it can be easily displayed in the HTML.
```javascript
data() {
return {
myResults: null,
};
},
```
And then, inside your `processData()` method, you can set the value of this, with:
```javascript
`this.myResults = 'whatever'`
```
#### **Rendering Response**
Now that the results are in the correct format, and stored as data variables, we can use them within the `<template>` to render results to the user. Again, how you do this will depend on the structure of your data, and what you want to display, but at it's simplest, it might look something like this:
```vue
<p class="results">{{ myResults }}</p>
```
#### **Styling**
Styles can be written for your widget within the `<style>` block.
There are several color variables used by widgets, which extend from the base palette. Using these enables users to override colors to theme their dashboard, if they wish. The variables are: `--widget-text-color`, `--widget-background-color` and `--widget-accent-color`
```vue
<style scoped lang="scss">
p.results {
color: var(--widget-text-color);
}
</style>
```
For examples of finished widget components, see the [Widgets](https://github.com/Lissy93/dashy/tree/master/src/components/Widgets) directory. Specifically, the [`XkcdComic.vue`](https://github.com/Lissy93/dashy/blob/master/src/components/Widgets/XkcdComic.vue) widget is quite minimal, so would make a good example, as will [this example implementation](https://github.com/Lissy93/dashy/commit/3da76ce2999f57f76a97454c0276301e39957b8e).
### Step 3 - Register
Next, register your new widget in [`WidgetBase.vue`](https://github.com/Lissy93/dashy/blob/master/src/components/Widgets/WidgetBase.vue). In this file, you'll need to add the following:
```javascript
const COMPAT = {
...
'example-widget': 'ExampleWidget',
};
```
Here, the `example-widget` property name will be used to identify the widget when parsing the `type` property in a configuration file. The `ExampleWidget` string is used to dynamically import the widget, and therefore must match the widget's filename as it exists in the `components/widgets` folder.
### Step 4 - Docs
Finally, add some documentation for your widget in the [Widget Docs](https://github.com/Lissy93/dashy/blob/master/docs/widgets.md), so that others know how to use it. Include the following information: Title, short description, screenshot, config options and some example YAML.
**Summary**: For a complete example of everything discussed here, see: [`3da76ce`](https://github.com/Lissy93/dashy/commit/3da76ce2999f57f76a97454c0276301e39957b8e)
---
## Respecting Config Permissions
Any screen that displays part or all of the users config, must not be shown when the user has disabled viewing config.
This can be done by checking the `allowViewConfig` attribute of the `permissions` getter, in the store.
First create a new `computed` property, like:
```javascript
allowViewConfig() {
return this.$store.getters.permissions.allowViewConfig;
},
```
Then wrap the part of your UI which displays config with: `v-if="allowViewConfig"`
If required, add a message showing that the component isn't available, using the `AccessError` component. E.g.
```javascript
import AccessError from '@/components/Configuration/AccessError';
```
```vue
<AccessError v-else />
```
The `$store.getters.permissions` object also returns options for when and where config can be saved, using: `allowWriteToDisk`, and `allowSaveLocally` - both are booleans.

210
docs/icons.md Normal file
View File

@@ -0,0 +1,210 @@
# Icons
Both sections and items can have an icon, which is specified using the `icon` attribute. Using icons improves the aesthetics of your UI and makes the app more intuitive to use. Dashy supports multiple different icon providers, usage instructions for which are explained here.
- [Auto-Fetched Favicons](#favicons)
- [Font Awesome Icons](#font-awesome)
- [Simple Icons](#simple-icons)
- [Generative Icons](#generative-icons)
- [Emoji Icons](#emoji-icons)
- [Home-Lab Icons](#home-lab-icons)
- [Material Icons](#material-design-icons)
- [Icons by URL](#icons-by-url)
- [Local Icons](#local-icons)
- [Using a Default Icon](#default-icon)
- [No Icon](#no-icon)
<p align="center">
<img width="500" src="https://i.ibb.co/GTVmZnc/dashy-example-icons.png" />
</p>
---
## Favicons
Dashy can auto-fetch an icon for a given service, using it's favicon. Just set `icon: favicon` to use this feature.
<p align="center">
<img width="580" src="https://i.ibb.co/k6wyhnB/favicon-icons.png" />
</p>
Since different websites host their favicons at different paths, for the best results Dashy can use an API to resolve a websites icon.
The default favicon API is [allesedv.com](https://favicon.allesedv.com/), but you can change this under `appConfig.faviconApi`. If you'd prefer not to use an API, just set this value to `local`. You can also use different APIs for individual items, by setting `icon: favicon-[api]`, e.g. `favicon-clearbit`.
The following favicon APIs are supported:
- `allesedv` - [allesedv.com](https://favicon.allesedv.com/) is a highly efficient IPv6-enabled service
- `iconhorse` - [Icon.Horse](https://icon.horse/) returns quality icons for any site, with caching for speed and fallbacks for sites without an icon
- `clearbit` - [Clearbit](https://clearbit.com/logo) returns high-quality square logos from mainstream websites
- `faviconkit` - [faviconkit.com](https://faviconkit.com/) good quality icons and most sites supported (Note: down as of Nov '21)
- `besticon` - [BestIcon](https://github.com/mat/besticon) fetches websites icons from manifest
- `mcapi` - [MC-API](https://eu.mc-api.net/) fetches default website favicon, originally a Minecraft util
- `duckduckgo` - Returns decent quality website icons, from DuckDuckGo search
- `google` - Official Google favicon API service, good support for all sites, but poor quality
- `yandex` - Lower quality icons, but useful in some regions where other services are blocked
- `local` - Set to local to fetch the default icon at /favicon.ico instead of using an API
If for a given service none of the APIs work in your situation, and nor does local, then the best option is to find the path of the services logo or favicon, and set the icon to the URL of the raw image. For example, `icon: https://monitoring.local/faviconx128.png`- you can find this path using the browser dev tools.
---
## Font Awesome
You can use any [Font Awesome Icon](https://fontawesome.com/icons) simply by specifying it's identifier. This is in the format of `[category] [name]` and can be found on the page for that icon on the Font Awesome site. For example: `fas fa-rocket`, `fab fa-monero` or `fas fa-unicorn`.
Font-Awesome has a wide variety of free icons, but you can also use their pro icons if you have a membership. To do so, you need to specify your license key under: `appConfig.fontAwesomeKey`. This is usually a 10-digit string, for example `13014ae648`.
<p align="center">
<img width="500" src="https://i.ibb.co/tMtwNYZ/fontawesome-icons3.png" />
</p>
---
## Simple Icons
[SimpleIcons.org](https://simpleicons.org/) is a collection of 2000+ high quality, free and open source brand and logo SVG icons. Usage of which is very similar to font-awesome icons. First find the glyph you want to use on the [website](https://simpleicons.org/), then just set your icon the the simple icon slug, prefixed with `si-`.
<p align="center">
<img width="580" src="https://i.ibb.co/MVhkXfC/simple-icons-example.png" />
</p>
For example:
```yaml
sections:
- name: Simple Icons Example
items:
- title: Portainer
icon: si-portainer
- title: FreeNAS
icon: si-freenas
- title: NextCloud
icon: si-nextcloud
- title: Home Assistant
icon: si-homeassistant
```
---
## Generative Icons
To uses a unique and programmatically generated icon for a given service just set `icon: generative`. This is particularly useful when you have a lot of similar services with a different IP or port, and no specific icon. These icons are generated with [DiceBear](https://avatars.dicebear.com/) (or [Evatar](https://evatar.io/) for fallback), and use a hash of the services domain/ ip for entropy, so each domain will have a unique icon.
<p align="center">
<img width="500" src="https://i.ibb.co/b2pC2CL/generative-icons-2.png" />
</p>
---
## Emoji Icons
You can use almost any emoji as an icon for items or sections. You can specify the emoji either by pasting it directly, using it's unicode ( e.g. `'U+1F680'`) or shortcode (e.g. `':rocket:'`). You can find these codes for any emoji using [Emojipedia](https://emojipedia.org/) (near the bottom of emoji each page), or for a quick reference to emoji shortcodes, check out [emojis.ninja](https://emojis.ninja/) by @nomanoff.
<p align="center">
<img width="580" src="https://i.ibb.co/YLwgTf9/emoji-icons-1.png" />
</p>
For example, these will all render the same rocket (🚀) emoji: `icon: ':rocket:'` or `icon: 'U+1F680'` or `icon: 🚀`
---
## Home-Lab Icons
The [dashboard-icons](https://github.com/walkxcode/Dashboard-Icons) repo by [@WalkxCode](https://github.com/WalkxCode) provides a comprehensive collection of 360+ high-quality PNG icons for commonly self-hosted services. Dashy natively supports these icons, and you can use them just by specifying the icon name (without extension) preceded by `hl-`. See [here](https://github.com/walkxcode/Dashboard-Icons/tree/main/png) for a full list of all available icons. Note that these are fetched and cached strait from GitHub, so if you require offline access, the [Local Icons](#local-icons) method may be a better option for you.
For example:
```yaml
sections:
- name: Home Lab Icons Example
items:
- title: AdGuard Home
icon: hl-adguardhome
- title: Long Horn
icon: hl-longhorn
- title: Nagios
icon: hl-nagios
- title: Whoogle Search
icon: hl-whooglesearch
```
<p align="center">
<img width="580" src="https://i.ibb.co/PQzYHmD/homelab-icons-2.png" />
</p>
---
## Material Design Icons
Dashy also supports 5000+ [material-design-icons](https://github.com/Templarian/MaterialDesign). To use these, first find the name/ slug for your icon [here](https://dev.materialdesignicons.com/icons), and then prefix is with `mdi-`.
For example:
```yaml
sections:
- name: Material Design Icons Example
items:
- title: Alien Icon
icon: mdi-alien
- title: Fire Icon
icon: mdi-fire
- title: Dino Icon
icon: mdi-google-downasaur
```
<p align="center">
<img width="500" src="https://i.ibb.co/fC9B4mq/icons-mdi-example.png" />
</p>
---
## Icons by URL
You can also set an icon by passing in a valid URL pointing to the icons location. For example `icon: https://i.ibb.co/710B3Yc/space-invader-x256.png`, this can be in .png, .jpg or .svg format, and hosted anywhere (local or remote) - so long as it's accessible from where you are hosting Dashy. The icon will be automatically scaled to fit, however loading in a lot of large icons may have a negative impact on performance, especially if you visit Dashy from new devices often.
---
## Local Icons
You may also want to store your icons locally, bundled within Dashy so that there is no reliance on outside services. This can be done by putting the icons within Dashy's `./public/item-icons/` directory. If you are using Docker, then the easiest option is to map a volume from your host system, for example: `-v /local/image/directory:/app/public/item-icons/`. To reference an icon stored locally, just specify it's name and extension. For example, if my icon was stored in `/app/public/item-icons/maltrail.png`, then I would just set `icon: maltrail.png`.
You can also use sub-folders within the `item-icons` directory to keep things organized. You would then specify an icon with it's folder name slash image name. For example: `networking/monit.png`
---
## Default Icon
If you'd like to set a default icon, to be applied to any items which don't have an icon already set, then this can be done under `appConfig.defaultIcon`.
---
## No Icon
If you don't wish for a given item or section to have an icon, just leave out the `icon` attribute.
---
## Icon Collections and Resources
The following websites provide good-quality, free icon sets. To use any of these icons, either copy the link to the raw icon (it should end in `.svg` or `.png`) and paste it as your `icon`, or download and save the icons in `/public/item-icons` / mapped Docker volume. Full credit to the authors, please see the licenses for each service for usage and copyright information.
- [Icons for Self-Hosted Apps](https://thehomelab.wiki/books/helpful-tools-resources/page/icons-for-self-hosted-dashboards) - 350+ high-quality icons for commonly self-hosted services
- [SVG Box](https://svgbox.net/iconsets/) - Cryptocurrency, social media apps and flag icons
- [Simple Icons](https://simpleicons.org/) - Free SVG brand icons, with easy API access
- [Material Design Icons](https://github.com/google/material-design-icons/) - Hundreds of Open source PNG + SVG icons by Google
- [Icons8](https://icons8.com/icons) - Thousands of icons, all with free versions at 64x64
- [Flat Icon](https://www.flaticon.com/) - Wide variety of icon sets, most of which are free to use
- [SVG Repo](https://www.svgrepo.com/) - 300,000+ Vector Icons
If you are a student, then you can get free access to premium icons on [Icon Scout](https://education.github.com/pack/redeem/iconscout-student) or [Icons8](https://icons8.com/github-students) using the [GitHub Student Pack](https://education.github.com/pack).
---
## Notes
If you are using icons from an external source, these will be fetched on initial page load automatically, if and when needed. But combining icons from multiple services may have a negative impact on performance.
You can improve load speeds, by downloading your required icons, and serving them locally. Scaling icons to the minimum required dimensions (e.g. 128x128 or 64x64) will also greatly improve application load times.
For icons from external sources, please see the Privacy Policies and Licenses for that provider.

910
docs/management.md Normal file
View File

@@ -0,0 +1,910 @@
# App Management
_The following article is a primer on managing self-hosted apps. It covers everything from keeping the Dashy (or any other app) up-to-date, secure, backed up, to other topics like auto-starting, monitoring, log management, web server configuration and using custom domains._
## Contents
- [Providing Assets](#providing-assets)
- [Running Commands](#running-commands)
- [Healthchecks](#healthchecks)
- [Logs and Performance](#logs-and-performance)
- [Auto-Starting at Boot](#auto-starting-at-system-boot)
- [Updating](#updating)
- [Backing Up](#backing-up)
- [Scheduling](#scheduling)
- [SSL Certificates](#ssl-certificates)
- [Authentication](#authentication)
- [Managing with Compose](#managing-containers-with-docker-compose)
- [Environmental Variables](#passing-in-environmental-variables)
- [Setting Headers](#setting-headers)
- [Remote Access](#remote-access)
- [Custom Domain](#custom-domain)
- [Securing Containers](#container-security)
- [Web Server Configuration](#web-server-configuration)
- [Running a Modified App](#running-a-modified-version-of-the-app)
- [Building your Own Container](#building-your-own-container)
---
## Providing Assets
Although not essential, you will most likely want to provide several assets to your running app.
This is easy to do using [Docker Volumes](https://docs.docker.com/storage/volumes/), which lets you share a file or directory between your host system, and the container. Volumes are specified in the Docker run command, or Docker compose file, using the `--volume` or `-v` flags. The value of which consists of the path to the file / directory on your host system, followed by the destination path within the container. Fields are separated by a colon (`:`), and must be in the correct order. For example: `-v ~/alicia/my-local-conf.yml:/app/public/conf.yml`
In Dashy, commonly configured resources include:
- `./public/conf.yml` - Your main application config file
- `./public/item-icons` - A directory containing your own icons. This allows for offline access, and better performance than fetching from a CDN
- Also within `./public` you'll find standard website assets, including `favicon.ico`, `manifest.json`, `robots.txt`, etc. There's no need to pass these in, but you can do so if you wish
- `/src/styles/user-defined-themes.scss` - A stylesheet for applying custom CSS to your app. You can also write your own themes here.
**[⬆️ Back to Top](#management)**
---
## Running Commands
If you're running an app in Docker, then commands will need to be passed to the container to be executed. This can be done by preceding each command with `docker exec -it [container-id]`, where container ID can be found by running `docker ps`. For example `docker exec -it 26c156c467b4 yarn build`. You can also enter the container, with `docker exec -it [container-id] /bin/ash`, and navigate around it with normal Linux commands.
Dashy has several commands that can be used for various tasks, you can find a list of these either in the [Developing Docs](/docs/developing.md#project-commands), or by looking at the [`package.json`](https://github.com/Lissy93/dashy/blob/master/package.json#L5). These can be used by running `yarn [command-name]`.
**[⬆️ Back to Top](#management)**
---
## Healthchecks
Healthchecks are configured to periodically check that Dashy is up and running correctly on the specified port. By default, the health script is called every 5 minutes, but this can be modified with the `--health-interval` option. You can check the current container health with: `docker inspect --format "{{json .State.Health }}" [container-id]`, and a summary of health status will show up under `docker ps`. You can also manually request the current application status by running `docker exec -it [container-id] yarn health-check`. You can disable healthchecks altogether by adding the `--no-healthcheck` flag to your Docker run command.
To restart unhealthy containers automatically, check out [Autoheal](https://hub.docker.com/r/willfarrell/autoheal/). This image watches for unhealthy containers, and automatically triggers a restart. (This is a stand in for Docker's `--exit-on-unhealthy` that was proposed, but [not merged](https://github.com/moby/moby/pull/22719)). There's also [Deunhealth](https://github.com/qdm12/deunhealth), which is super light-weight, and doesn't require network access.
```bash
docker run -d \
--name autoheal \
--restart=always \
-e AUTOHEAL_CONTAINER_LABEL=all \
-v /var/run/docker.sock:/var/run/docker.sock \
willfarrell/autoheal
```
**[⬆️ Back to Top](#management)**
---
## Logs and Performance
### Container Logs
You can view logs for a given Docker container with `docker logs [container-id]`, add the `--follow` flag to stream the logs. For more info, see the [Logging Documentation](https://docs.docker.com/config/containers/logging/). There's also [Dozzle](https://dozzle.dev/), a useful tool, that provides a web interface where you can stream and query logs from all your running containers from a single web app.
### Container Performance
You can check the resource usage for your running Docker containers with `docker stats` or `docker stats [container-id]`. For more info, see the [Stats Documentation](https://docs.docker.com/engine/reference/commandline/stats/). There's also [cAdvisor](https://github.com/google/cadvisor), a useful web app for viewing and analyzing resource usage and performance of all your running containers.
### Management Apps
You can also view logs, resource usage and other info as well as manage your entire Docker workflow in third-party Docker management apps. For example [Portainer](https://github.com/portainer/portainer) an all-in-one open source management web UI for Docker and Kubernetes, or [LazyDocker](https://github.com/jesseduffield/lazydocker) a terminal UI for Docker container management and monitoring.
### Advanced Logging and Monitoring
Docker supports using [Prometheus](https://prometheus.io/) to collect logs, which can then be visualized using a platform like [Grafana](https://grafana.com/). For more info, see [this guide](https://docs.docker.com/config/daemon/prometheus/). If you need to route your logs to a remote syslog, then consider using [logspout](https://github.com/gliderlabs/logspout). For enterprise-grade instances, there are managed services, that make monitoring container logs and metrics very easy, such as [Sematext](https://sematext.com/blog/docker-container-monitoring-with-sematext/) with [Logagent](https://github.com/sematext/logagent-js).
**[⬆️ Back to Top](#management)**
---
## Auto-Starting at System Boot
You can use Docker's [restart policies](https://docs.docker.com/engine/reference/run/#restart-policies---restart) to instruct the container to start after a system reboot, or restart after a crash. Just add the `--restart=always` flag to your Docker compose script or Docker run command. For more information, see the docs on [Starting Containers Automatically](https://docs.docker.com/config/containers/start-containers-automatically/).
For Podman, you can use `systemd` to create a service that launches your container, [the docs](https://podman.io/blogs/2018/09/13/systemd.html) explains things further. A similar approach can be used with Docker, if you need to start containers after a reboot, but before any user interaction.
To restart the container after something within it has crashed, consider using [`docker-autoheal`](https://github.com/willfarrell/docker-autoheal) by @willfarrell, a service that monitors and restarts unhealthy containers. For more info, see the [Healthchecks](#healthchecks) section above.
**[⬆️ Back to Top](#management)**
---
## Updating
Dashy is under active development, so to take advantage of the latest features, you may need to update your instance every now and again.
### Updating Docker Container
1. Pull latest image: `docker pull lissy93/dashy:latest`
2. Kill off existing container
- Find container ID: `docker ps`
- Stop container: `docker stop [container_id]`
- Remove container: `docker rm [container_id]`
3. Spin up new container: `docker run [params] lissy93/dashy`
### Automatic Docker Updates
You can automate the above process using [Watchtower](https://github.com/containrrr/watchtower).
Watchtower will watch for new versions of a given image on Docker Hub, pull down your new image, gracefully shut down your existing container and restart it with the same options that were used when it was deployed initially.
To get started, spin up the watchtower container:
```bash
docker run -d \
--name watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower
```
For more information, see the [Watchtower Docs](https://containrrr.dev/watchtower/)
### Updating Dashy from Source
Stop your current instance of Dashy, then navigate into the source directory. Pull down the latest code, with `git pull origin master`, then update dependencies with `yarn`, rebuild with `yarn build`, and start the server again with `yarn start`.
**[⬆️ Back to Top](#management)**
---
## Backing Up
### Backing Up Containers
You can make a backup of any running container really easily, using [`docker commit`](https://docs.docker.com/engine/reference/commandline/commit/) and save it with [`docker export`](https://docs.docker.com/engine/reference/commandline/export/), to do so:
- First find the container ID, you can do this with `docker container ls`
- Now to create the snapshot, just run `docker commit -p [container-id] my-backup`
- Finally, to save the backup locally, run `docker save -o ~/dashy-backup.tar my-backup`
- If you want to push this to a container registry, run `docker push my-backup:latest`
Note that this will not include any data in docker volumes, and the process here is a bit different. Since these files exist on your host system, if you have an existing backup solution implemented, you can incorporate and volume files within that system.
### Backing Up Volumes
[offen/docker-volume-backup](https://github.com/offen/docker-volume-backup) is a useful tool for periodic Docker volume backups, to any S3-compatible storage provider. It's run as a light-weight Docker container, and is easy to setup, and also supports GPG-encryption, email notification, and routing away older backups.
To get started, create a docker-compose similar to the example below, and then start the container. For more info, check out their [documentation](https://github.com/offen/docker-volume-backup), which is very clear.
```yaml
version: '3'
services:
backup:
image: offen/docker-volume-backup:latest
environment:
BACKUP_CRON_EXPRESSION: "0 * * * *"
BACKUP_PRUNING_PREFIX: backup-
BACKUP_RETENTION_DAYS: 7
AWS_BUCKET_NAME: backup-bucket
AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
volumes:
- data:/backup/my-app-backup:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes:
data:
```
It's worth noting that this process can also be done manually, using the following commands:
Backup:
```bash
docker run --rm -v some_volume:/volume -v /tmp:/backup alpine tar -cjf /backup/some_archive.tar.bz2 -C /volume ./
```
Restore:
```bash
docker run --rm -v some_volume:/volume -v /tmp:/backup alpine sh -c "rm -rf /volume/* /volume/..?* /volume/.[!.]* ; tar -C /volume/ -xjf /backup/some_archive.tar.bz2"
```
### Dashy-Specific Backup
Since Dashy is open source, and freely available, providing you're configuration data is passed in as volumes, there shouldn't be any need to backup the main container. Your main config file, and any assets you're using should be kept backed up, preferably in at least two places, and you should ensure that you can easily restore from backup, if needed.
Dashy also has a built-in cloud backup feature, which is free for personal users, and will let you make and restore fully encrypted backups of your config directly through the UI. To learn more, see the [Cloud Backup Docs](/docs/backup-restore.md)
**[⬆️ Back to Top](#management)**
---
## Scheduling
If you need to periodically schedule the running of a given command on Dashy (or any other container), then a useful tool for doing so it [ofelia](https://github.com/mcuadros/ofelia). This runs as a Docker container and is really useful for things like backups, logging, updating, notifications, etc. Crons are specified using Go's crontab format, and a useful tool for visualizing this is [crontab.guru](https://crontab.guru/). This can also be done natively with Alpine: `docker run -it alpine ls /etc/periodic`.
I recommend combining this with [healthchecks](https://github.com/healthchecks/healthchecks) for easy monitoring of jobs, and failure notifications.
**[⬆️ Back to Top](#management)**
---
## SSL Certificates
Enabling HTTPS with an SSL certificate is recommended, especially if you are hosting Dashy anywhere other than your home. This will ensure that all traffic is encrypted in transit.
### Auto-SSL
If you are using [NGINX Proxy Manager](https://nginxproxymanager.com/), then SSL is supported out of the box. Once you've added your proxy host and web address, then set the scheme to HTTPS, then under the SSL Tab select "Request a new SSL certificate" and follow the on-screen instructions.
If you're hosting Dashy behind Cloudflare, then they offer [free and easy SSL](https://www.cloudflare.com/en-gb/learning/ssl/what-is-an-ssl-certificate/)- all you need to do is enable it under the SSL/TLS tab. Or if you are using shared hosting, you may find [this tutorial](https://www.sitepoint.com/a-guide-to-setting-up-lets-encrypt-ssl-on-shared-hosting/) helpful.
### Getting a Self-Signed SSL Certificate
[Let's Encrypt](https://letsencrypt.org/docs/) is a global Certificate Authority, providing free SSL/TLS Domain Validation certificates in order to enable secure HTTPS access to your website. They have good browser/ OS [compatibility](https://letsencrypt.org/docs/certificate-compatibility/) with their ISRG X1 and DST CA X3 root certificates, support [Wildcard issuance](https://community.letsencrypt.org/t/acme-v2-production-environment-wildcards/55578) done via ACMEv2 using the DNS-01 and have [Multi-Perspective Validation](https://letsencrypt.org/2020/02/19/multi-perspective-validation.html). Let's Encrypt provide [CertBot](https://certbot.eff.org/) an easy app for generating and setting up an SSL certificate.
This process can be automated, using something like the [Docker-NGINX-Auto-SSL Container](https://github.com/Valian/docker-nginx-auto-ssl) to generate and renew certificates when needed.
If you're not so comfortable on the command line, then you can use a tool like [SSL For Free](https://www.sslforfree.com/) or [ZeroSSL](https://zerossl.com/) to generate your cert. They also provide step-by-step setup instructions for most platforms.
### Passing a Self-Signed Certificate to Dashy
Once you've generated your SSL cert, you'll need to pass it to Dashy. This can be done by specifying the paths to your public and private keys using the `SSL_PRIV_KEY_PATH` and `SSL_PUB_KEY_PATH` environmental variables. Or if you're using Docker, then just pass public + private SSL keys in under `/etc/ssl/certs/dashy-pub.pem` and `/etc/ssl/certs/dashy-priv.key` respectively, e.g:
```bash
docker run -d \
-p 8080:80 \
-v ~/my-private-key.key:/etc/ssl/certs/dashy-priv.key:ro \
-v ~/my-public-key.pem:/etc/ssl/certs/dashy-pub.pem:ro \
lissy93/dashy:latest
```
By default the SSL port is `443` within a Docker container, or `4001` if running on bare metal, but you can override this with the `SSL_PORT` environmental variable.
Once everything is setup, you can verify your site is secured using a tool like [SSL Checker](https://www.sslchecker.com/sslchecker).
**[⬆️ Back to Top](#management)**
---
## Authentication
Dashy natively supports secure authentication using KeyCloak. There is also a Simple Auth feature that doesn't require any additional setup. Usage instructions for both, as well as alternative auth methods, has now moved to the **[Authentication Docs](/docs/authentication.md)** page.
**[⬆️ Back to Top](#management)**
---
## Managing Containers with Docker Compose
When you have a lot of containers, it quickly becomes hard to manage with `docker run` commands. The solution to this is [docker compose](https://docs.docker.com/compose/), a handy tool for defining all a containers run settings in a single YAML file, and then spinning up that container with a single short command - `docker compose up`. A good example of which can be seen in [@abhilesh's docker compose collection](https://github.com/abhilesh/self-hosted_docker_setups).
You can use Dashy's default [`docker-compose.yml`](https://github.com/Lissy93/dashy/blob/master/docker-compose.yml) file as a template, and modify it according to your needs.
An example Docker compose, using the default base image from DockerHub, might look something like this:
```yaml
---
version: "3.8"
services:
dashy:
container_name: Dashy
image: lissy93/dashy
volumes:
- /root/my-config.yml:/app/public/conf.yml
ports:
- 4000:80
environment:
- BASE_URL=/my-dashboard
restart: unless-stopped
healthcheck:
test: ['CMD', 'node', '/app/services/healthcheck']
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
```
**[⬆️ Back to Top](#management)**
---
## Passing in Environmental Variables
With Docker, you can define environmental variables under the `environment` section of your Docker compose file. Environmental variables are used to configure high-level settings, usually before the config file has been read. For a list of all supported env vars in Dashy, see [the developing docs](/docs/developing.md#environmental-variables), or the default [`.env`](https://github.com/Lissy93/dashy/blob/master/.env) file.
A common use case, is to run Dashy under a sub-page, instead of at the root of a URL (e.g. `https://my-homelab.local/dashy` instead of `https://dashy.my-homelab.local`). In this use-case, you'd specify the `BASE_URL` variable in your compose file.
```yaml
environment:
- BASE_URL=/dashy
```
You can also do the same thing with the docker run command, using the [`--env`](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file) flag.
If you've got many environmental variables, you might find it useful to put them in a [`.env` file](https://docs.docker.com/compose/env-file/). Similarly, for Docker run you can use [`--env-file`](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file) if you'd like to pass in a file containing all your environmental variables.
**[⬆️ Back to Top](#management)**
---
## Setting Headers
Any external requests made to a different origin (app/ service under a different domain) will be blocked if the correct headers are not specified. This is known as [Cross-Origin Resource Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) (CORS) and is a security feature built into modern browsers.
If you see a CORS error in your console, this can be easily fixed by setting the correct headers. This is not a bug with Dashy, so please don't raise it as a bug!
### Example Headers
- [Caddy](#caddy)
- [NGINX](#nginx)
- [Træfɪk](#traefik)
- [HAProxy](#haproxy)
- [Apache](#apache)
_The following section briefly outlines how you can set headers for common web proxies/ servers. More info can be found in the documentation for the proxy that you are using, or in the [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)._
These examples are using:
- `Access-Control-Allow-Origin` header, but depending on what type of content you are enabling, this will vary. For example, to allow a site to be loaded in an iframe (for the modal or workspace views) you would use `X-Frame-Options`.
- The domain root (`/`), if your're hosting from a sub-page, replace that with your path.
- A wildcard (`*`), which would allow access from traffic on any domain, this is discouraged, and you should replace it with the URL where you are hosting Dashy. Note that for requests that transport sensitive info, like credentials (e.g. Keycloak login), the wildcard is [disallowed all together](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#requests_with_credentials) and will be blocked.
#### Caddy
> See [Caddy `header` docs](https://caddyserver.com/docs/caddyfile/directives/header) for more info.
```text
headers / {
Access-Control-Allow-Origin *
}
```
#### NGINX
> See [NGINX `ngx_http_headers_module` docs](https://nginx.org/en/docs/http/ngx_http_headers_module.html) for more info.
```text
location / {
add_header Access-Control-Allow-Origin *;
}
```
Note this can also be done through the UI, using NGINX Proxy Manager.
#### Traefik
> See [Træfɪk CORS headers docs](https://doc.traefik.io/traefik/middlewares/http/headers/#cors-headers) for more info.
```text
labels:
- "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
- "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org"
- "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.testheader.headers.addvaryheader=true"
```
#### HAProxy
> See [HAProxy Rewrite Response Docs](https://www.haproxy.com/documentation/hapee/latest/traffic-routing/rewrites/rewrite-responses/) for more info.
```text
/
http-response add-header Access-Control-Allow-Origin *
```
#### Apache
> See [Apache `mode_headers` docs](https://httpd.apache.org/docs/current/mod/mod_headers.html) for more info.
```text
Header always set Access-Control-Allow-Origin "*"
```
#### Squid
> See [Squid `request_header_access` docs](http://www2.gr.squid-cache.org/Doc/config/request_header_access/) for more info.
```text
request_header_access Authorization allow all
```
**[⬆️ Back to Top](#management)**
---
## Remote Access
- [WireGuard](#wireguard)
- [Reverse SSH Tunnel](#reverse-ssh-tunnel)
- [TCP Tunnel](#tcp-tunnel)
### WireGuard
Using a VPN is one of the easiest ways to provide secure, full access to your local network from remote locations. [WireGuard](https://www.wireguard.com/) is a reasonably new open source VPN protocol, that was designed with ease of use, performance and security in mind. Unlike OpenVPN, it doesn't need to recreate the tunnel whenever connection is dropped, and it's also much easier to setup, using shared keys instead.
- **Install Wireguard** - See the [Install Docs](https://www.wireguard.com/install/) for download links + instructions
- On Debian-based systems, it's `sudo apt install wireguard`
- **Generate a Private Key** - Run `wg genkey` on the Wireguard server, and copy it to somewhere safe for later
- **Create Server Config** - Open or create a file at `/etc/wireguard/wg0.conf` and under `[Interface]` add the following (see example below):
- `Address` - as a subnet of all desired IPs
- `PrivateKey` - that you just generated
- `ListenPort` - Default is `51820`, but can be anything
- **Get Client App** - Download the [WG client app](https://www.wireguard.com/install/) for your platform (Linux, Windows, MacOS, Android or iOS are all supported)
- **Create new Client Tunnel** - On your client app, there should be an option to create a new tunnel, when doing so a client private key will be generated (but if not, use the `wg genkey` command again), and keep it somewhere safe. A public key will also be generated, and this will go in our saver config
- **Add Clients to Server Config** - Head back to your `wg0.conf` file on the server, create a `[Peer]` section, and populate the following info
- `AllowedIPs` - List of IP address inside the subnet, the client should have access to
- `PublicKey` - The public key for the client you just generated
- **Start the Server** - You can now start the WG server, using: `wg-quick up wg0` on your server
- **Finish Client Setup** - Head back to your client device, and edit the config file, leave the private key as is, and add the following fields:
- `PublicKey` - The public key of the server
- `Address` - This should match the `AllowedIPs` section on the servers config file
- `DNS` - The DNS server that'll be used when accessing the network through the VPN
- `Endpoint` - The hostname or IP + Port where your WG server is running (you may need to forward this in your firewall's settings)
- **Done** - Your clients should now be able to connect to your WG server :) Depending on your networks firewall rules, you may need to port forward the address of your WG server
#### **Example Server Config**
```ini
# Server file
[Interface]
# Which networks does my interface belong to? Notice: /24 and /64
Address = 10.5.0.1/24, 2001:470:xxxx:xxxx::1/64
PrivateKey = xxx
ListenPort = 51820
# Peer 1
[Peer]
PublicKey = xxx
# Which source IPs can I expect from that peer? Notice: /32 and /128
AllowedIps = 10.5.0.35/32, 2001:470:xxxx:xxxx::746f:786f/128
# Peer 2
[Peer]
PublicKey = xxx
# Which source IPs can I expect from that peer? This one has a LAN which can
# access hosts/jails without NAT.
# Peer 2 has a single IP address inside the VPN: it's 10.5.0.25/32
AllowedIps = 10.5.0.25/32,10.21.10.0/24,10.21.20.0/24,10.21.30.0/24,10.31.0.0/24,2001:470:xxxx:xxxx::ca:571e/128
```
#### **Example Client Config**
```ini
[Interface]
# Which networks does my interface belong to? Notice: /24 and /64
Address = 10.5.0.35/24, 2001:470:xxxx:xxxx::746f:786f/64
PrivateKey = xxx
# Server
[Peer]
PublicKey = xxx
# I want to route everything through the server, both IPv4 and IPv6. All IPs are
# thus available through the Server, and I can expect packets from any IP to
# come from that peer.
AllowedIPs = 0.0.0.0/0, ::0/0
# Where is the server on the internet? This is a public address. The port
# (:51820) is the same as ListenPort in the [Interface] of the Server file above
Endpoint = 1.2.3.4:51820
# Usually, clients are behind NAT. to keep the connection running, keep alive.
PersistentKeepalive = 15
```
A useful tool for getting WG setup is [Algo](https://github.com/trailofbits/algo). It includes scripts and docs which cover almost all devices, platforms and clients, and has best practices implemented, and security features enabled. All of this is better explained in [this blog post](https://blog.trailofbits.com/2016/12/12/meet-algo-the-vpn-that-works/).
### Reverse SSH Tunnel
SSH (or [Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell)) is a secure tunnel that allows you to connect to a remote host. Unlike the VPN methods, an SSH connection does not require an intermediary, and will not be affected by your IP changing. However it only allows you to access a single service at a time. SSH was really designed for terminal access, but because of the latter mentioned benefits it's useful to setup, as a fallback option.
Directly SSH'ing into your home, would require you to open a port (usually 22), which would be terrible for security, and is not recommended. However a reverse SSH connection is initiated from inside your network. Once the connection is established, the port is redirected, allowing you to use the established connection to SSH into your home network.
The issue you've probably spotted, is that most public, corporate, and institutional networks will block SSH connections. To overcome this, you'd have to establish a server outside of your homelab that your homelab's device could SSH into to establish the reverse SSH connection. You can then connect to that remote server (the _mothership_), which in turn connects to your home network.
Now all of this is starting to sound like quite a lot of work, but this is where services like [remot3.it](https://remote.it/) come in. They maintain the intermediary mothership server, and create the tunnel service for you. It's free for personal use, secure and easy. There are several similar services, such as [RemoteIoT](https://remoteiot.com/), or you could create your own on a cloud VPS (see [this tutorial](https://gist.github.com/nileshtrivedi/4c615e8d3c1bf053b0d31176b9e69e42) for more info on that).
Before getting started, you'll need to head over to [Remote.it](https://app.remote.it/auth/#/sign-up) and create an account.
Then setup your local device:
1. If you haven't already done so, you'll need to enable and configure SSH.
- This is out-of-scope of this article, but I've explained it in detail in [this post](https://notes.aliciasykes.com/22798/my-server-setup#configure-ssh).
2. Download the Remote.it install script from their [GitHub](https://github.com/remoteit/installer)
- `curl -LkO https://raw.githubusercontent.com/remoteit/installer/master/scripts/auto-install.sh`
3. Make it executable, with `chmod +x ./auto-install.sh`, and then run it with `sudo ./auto-install.sh`
4. Finally, configure your device, by running `sudo connectd_installer` and following the on-screen instructions
And when you're ready to connect to it:
1. Login to [app.remote.it](https://app.remote.it/), and select the name of your device
2. You should see a list of running services, click SSH
3. You'll then be presented with some SSH credentials that you can now use to securely connect to your home, via the Remote.it servers
Done :)
### TCP Tunnel
If you're running Dashy on your local network, behind a firewall, but need to temporarily share it with someone external, this can be achieved quickly and securely using [Ngrok](https://ngrok.com/). It's basically a super slick, encrypted TCP tunnel that provides an internet-accessible address that anyone use to access your local service, from anywhere.
To get started, [Download](https://ngrok.com/download) and install Ngrok for your system, then just run `ngrok http [port]` (replace the port with the http port where Dashy is running, e.g. 8080). When [using https](https://ngrok.com/docs#http-local-https), specify the full local url/ ip including the protocol.
Some Ngrok features require you to be authenticated, you can [create a free account](https://dashboard.ngrok.com/signup) and generate a token in [your dashboard](https://dashboard.ngrok.com/auth/your-authtoken), then run `ngrok authtoken [token]`.
It's recommended to use authentication for any publicly accessible service. Dashy has an [Auth](/docs/authentication.md) feature built in, but an even easier method it to use the [`-auth`](https://ngrok.com/docs#http-auth) switch. E.g. `ngrok http -auth="username:password123" 8080`
By default, your web app is assigned a randomly generated ngrok domain, but you can also use your own custom domain. Under the [Domains Tab](https://dashboard.ngrok.com/endpoints/domains) of your Ngrok dashboard, add your domain, and follow the CNAME instructions. You can now use your domain, with the [`-hostname`](https://ngrok.com/docs#http-custom-domains) switch, e.g. `ngrok http -region=us -hostname=dashy.example.com 8080`. If you don't have your own domain name, you can instead use a custom sub-domain (e.g. `alicia-dashy.ngrok.io`), using the [`-subdomain`](https://ngrok.com/docs#custom-subdomain-names) switch.
To integrate this into your docker-compose, take a look at the [gtriggiano/ngrok-tunnel](https://github.com/gtriggiano/ngrok-tunnel) container.
There's so much more you can do with Ngrok, such as exposing a directory as a file browser, using websockets, relaying requests, rewriting headers, inspecting traffic, TLS and TCP tunnels and lots more. All or which is explained in [the Documentation](https://ngrok.com/docs).
It's worth noting that Ngrok isn't the only option here, other options include: [FRP](https://github.com/fatedier/frp), [Inlets](https://inlets.dev), [Local Tunnel](https://localtunnel.me/), [TailScale](https://tailscale.com/), etc. Check out [Awesome Tunneling](https://github.com/anderspitman/awesome-tunneling) for a list of alternatives.
**[⬆️ Back to Top](#management)**
---
## Custom Domain
- [Using DNS](#using-nginx)
- [Using NGINX](#using-dns)
### Using DNS
For locally running services, a domain can be set up directly in the DNS records. This method is really quick and easy, and doesn't require you to purchase an actual domain. Just update your networks DNS resolver, to point your desired URL to the local IP where Dashy (or any other app) is running. For example, a line in your hosts file might look something like: `192.168.0.2 dashy.homelab.local`.
If you're using Pi-Hole, a similar thing can be done in the `/etc/dnsmasq.d/03-custom-dns.conf` file, add a line like: `address=/dashy.example.com/192.168.2.0` for each of your services.
If you're running OPNSense/ PfSense, then this can be done through the UI with Unbound, it's explained nicely in [this article](https://homenetworkguy.com/how-to/use-custom-domain-name-in-internal-network/), by Dustin Casto.
### Using NGINX
If you're using NGINX, then you can use your own domain name, with a config similar to the below example.
```text
upstream dashy {
server 127.0.0.1:32400;
}
server {
listen 80;
server_name dashy.mydomain.com;
# Setup SSL
ssl_certificate /var/www/mydomain/sslcert.pem;
ssl_certificate_key /var/www/mydomain/sslkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_session_timeout 5m;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://dashy;
proxy_redirect off;
proxy_buffering off;
proxy_set_header host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
}
```
Similarly, a basic `Caddyfile` might look like:
```text
dashy.example.com {
reverse_proxy / nginx:80
}
```
For more info, [this guide](https://thehomelab.wiki/books/dns-reverse-proxy/page/create-domain-records-to-point-to-your-home-server-on-cloudflare-using-nginx-progy-manager) on Setting up Domains with NGINX Proxy Manager and CloudFlare may be useful.
**[⬆️ Back to Top](#management)**
---
## Container Security
- [Keep Docker Up-To-Date](#keep-docker-up-to-date)
- [Set Resource Quotas](#set-resource-quotas)
- [Don't Run as Root](#dont-run-as-root)
- [Specify a User](#specify-a-user)
- [Limit Capabilities](#limit-capabilities)
- [Prevent new Privileges being Added](#prevent-new-privileges-being-added)
- [Disable Inter-Container Communication](#disable-inter-container-communication)
- [Don't Expose the Docker Daemon Socket](#dont-expose-the-docker-daemon-socket)
- [Use Read-Only Volumes](#use-read-only-volumes)
- [Set the Logging Level](#set-the-logging-level)
- [Verify Image before Pulling](#verify-image-before-pulling)
- [Specify the Tag](#specify-the-tag)
- [Container Security Scanning](#container-security-scanning)
- [Registry Security](#registry-security)
- [Security Modules](#security-modules)
### Keep Docker Up-To-Date
To prevent known container escape vulnerabilities, which typically end in escalating to root/administrator privileges, patching Docker Engine and Docker Machine is crucial. For more info, see the [Docker Installation Docs](https://docs.docker.com/engine/install/).
### Set Resource Quotas
Docker enables you to limit resource consumption (CPU, memory, disk) on a per-container basis. This not only enhances system performance, but also prevents a compromised container from consuming a large amount of resources, in order to disrupt service or perform malicious activities. To learn more, see the [Resource Constraints Docs](https://docs.docker.com/config/containers/resource_constraints/)
For example, to run Dashy with max of 1GB ram, and max of 50% of 1 CP core:
`docker run -d -p 8080:80 --cpus=".5" --memory="1024m" lissy93/dashy:latest`
### Don't Run as Root
Running a container with admin privileges gives it more power than it needs, and can be abused. Dashy does not need any root privileges, and Docker by default doesn't run containers as root, so providing you don't specifically type sudo, you should be all good here.
Note that if you're facing permission issues on Debian-based systems, you may need to add your user to the Docker group. First create the group: `sudo groupadd docker`, then add your (non-root) user: `sudo usermod aG docker [my-username]`, finally `newgrp docker` to refresh.
### Specify a User
One of the best ways to prevent privilege escalation attacks, is to configure the container to use an unprivileged user. This also means that any files created by the container and mounted, will be owned by the specified user (and not root), which makes things much easier.
You can specify a user, using the [`--user` param](https://docs.docker.com/engine/reference/run/#user), and should include the user ID (`UID`), which can be found by running `id -u`, and the and the group ID (`GID`), using `id -g`.
With Docker run, you specify it like:
`docker run --user 1000:1000 -p 8080:80 lissy93/dashy`
Of if you're using Docker-compose, you could use an environmental variable
```yaml
version: "3.8"
services:
dashy:
image: lissy93/dashy
user: ${CURRENT_UID}
ports: [ 4000:80 ]
```
And then to set the variable, and start the container, run: `CURRENT_UID=$(id -u):$(id -g) docker-compose up`
### Limit capabilities
Docker containers run with a subset of [Linux Kernal's Capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html) by default. It's good practice to drop privilege permissions that are not needed for any given container.
With Docker run, you can use the `--cap-drop` flag to remove capabilities, you can also use `--cap-drop=all` and then define just the required permissions using the `--cap-add` option. For a list of available capabilities, see the [Privilege Capabilities Docs](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities).
Note that dropping privileges and capabilities on runtime is not fool-proof, and often any leftover privileges can be used to re-escalate, see [POS36-C](https://wiki.sei.cmu.edu/confluence/display/c/POS36-C.+Observe+correct+revocation+order+while+relinquishing+privileges).
Here's an example using docker-compose, removing privileges that are not required for Dashy to run:
```yaml
version: "3.8"
services:
dashy:
image: lissy93/dashy
ports: [ 4000:80 ]
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
- DAC_OVERRIDE
- NET_BIND_SERVICE
```
### Prevent new Privileges being Added
To prevent processes inside the container from getting additional privileges, pass in the `--security-opt=no-new-privileges:true` option to the Docker run command (see [docs](https://docs.docker.com/engine/reference/run/#security-configuration)).
Run Command:
`docker run --security-opt=no-new-privileges:true -p 8080:80 lissy93/dashy`
Docker Compose
```yaml
security_opt:
- no-new-privileges:true
```
### Disable Inter-Container Communication
By default Docker containers can talk to each other (using [`docker0` bridged network](https://docs.docker.com/config/containers/container-networking/)). If you don't need this capability, then it should be disabled. This can be done with the `--icc=false` in your run command. You can learn more about how to facilitate secure communication between containers in the [Compose Networking docs](https://docs.docker.com/compose/networking/).
### Don't Expose the Docker Daemon Socket
Docker socket `/var/run/docker.sock` is the UNIX socket that Docker is listening to. This is the primary entry point for the Docker API. The owner of this socket is root. Giving someone access to it is equivalent to giving unrestricted root access to your host.
You should **not** enable TCP Docker daemon socket (`-H tcp://0.0.0.0:XXX`), as doing so exposes un-encrypted and unauthenticated direct access to the Docker daemon, and if the host is connected to the internet, the daemon on your computer can be used by anyone from the public internet- which is bad. If you need TCP, you should [see the docs](https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-socket-option) to understand how to do this more securely.
Similarly, never expose `/var/run/docker.sock` to other containers as a volume, as it can be exploited.
### Use Read-Only Volumes
You can specify that a specific volume should be read-only by appending `:ro` to the `-v` switch. For example, while running Dashy, if we want our config to be writable, but keep all other assets protected, we would do:
```bash
docker run -d \
-p 8080:80 \
-v ~/dashy-conf.yml:/app/public/conf.yml \
-v ~/dashy-icons:/app/public/item-icons:ro \
-v ~/dashy-theme.scss:/app/src/styles/user-defined-themes.scss:ro \
lissy93/dashy:latest
```
You can also prevent a container from writing any changes to volumes on your host's disk, using the `--read-only` flag. Although, for Dashy, you will not be able to write config changes to disk, when edited through the UI with this method. You could make this work, by specifying the config directory as a temp write location, with `--tmpfs /app/public/conf.yml` - but that this will not write the volume back to your host.
### Set the Logging Level
Logging is important, as it enables you to review events in the future, and in the case of a compromise this will let get an idea of what may have happened. The default log level is `INFO`, and this is also the recommendation, use `--log-level info` to ensure this is set.
### Verify Image before Pulling
Only use trusted images, from verified/ official sources. If an app is open source, it is more likely to be safe, as anyone can verify the code. There are also tools available for scanning containers,
Unless otherwise configured, containers can communicate among each other, so running one bad image may lead to other areas of your setup being compromised. Docker images typically contain both original code, as well as up-stream packages, and even if that image has come from a trusted source, the up-stream packages it includes may not have.
### Specify the Tag
Using fixed tags (as opposed to `:latest` ) will ensure immutability, meaning the base image will not change between builds. Note that for Dashy, the app is being actively developed, new features, bug fixes and general improvements are merged each week, and if you use a fixed version you will not enjoy these benefits. So it's up to you weather you would prefer a stable and reproducible environment, or the latest features and enhancements.
### Container Security Scanning
It's helpful to be aware of any potential security issues in any of the Docker images you are using. You can run a quick scan using Snyk on any image to output known vulnerabilities using [Docker scan](https://docs.docker.com/engine/scan/), e.g: `docker scan lissy93/dashy:latest`.
A similar product is [Trivy](https://github.com/aquasecurity/trivy), which is free an open source. First install it (with your package manager), then to scan an image, just run: `trivy image lissy93/dashy:latest`
For larger systems, RedHat [Clair](https://www.redhat.com/en/topics/containers/what-is-clair) is an app for parsing image contents and reporting on any found vulnerabilities. You run it locally in a container, and configure it with YAML. It can be integrated with Red Hat Quay, to show results on a dashboard. Most of these use static analysis to find potential issues, and scan included packages for any known security vulnerabilities.
### Registry Security
Although over-kill for most users, you could run your own registry locally which would give you ultimate control over all images, see the [Deploying a Registry Docs](https://docs.docker.com/registry/deploying/) for more info. Another option is [Docker Trusted Registry](https://docker-docs.netlify.app/ee/dtr/), it's great for enterprise applications, it sits behind your firewall, running on a swarm managed by Docker Universal Control Plane, and lets you securely store and manage your Docker images, mitigating the risk of breaches from the internet.
### Security Modules
Docker supports several modules that let you write your own security profiles.
[AppArmor](https://www.apparmor.net/)is a kernel module that proactively protects the operating system and applications from external or internal threats, by enabling you to restrict programs' capabilities with per-program profiles. You can specify either a security policy by name, or by file path with the `apparmor` flag in docker run. Learn more about writing profiles, [here](https://gitlab.com/apparmor/apparmor/-/wikis/QuickProfileLanguage).
[Seccomp](https://en.wikipedia.org/wiki/Seccomp) (Secure Computing Mode) is a sandboxing facility in the Linux kernel that acts like a firewall for system calls (syscalls). It uses Berkeley Packet Filter (BPF) rules to filter syscalls and control how they are handled. These filters can significantly limit a containers access to the Docker Host's Linux kernel - especially for simple containers/applications. It requires a Linux-based Docker host, with secomp enabled, and you can check for this by running `docker info | grep seccomp`. A great resource for learning more about this is [DockerLabs](https://training.play-with-docker.com/security-seccomp/).
**[⬆️ Back to Top](#management)**
---
## Web Server Configuration
> _The following section only applies if you are not using Docker, and would like to use your own web server_
Dashy ships with a pre-configured Node.js server, in [`server.js`](https://github.com/Lissy93/dashy/blob/master/server.js) which serves up the contents of the `./dist` directory on a given port. You can start the server by running `node server`. Note that the app must have been build (run `yarn build`), and you need [Node.js](https://nodejs.org) installed.
If you wish to run Dashy from a sub page (e.g. `example.com/dashy`), then just set the `BASE_URL` environmental variable to that page name (in this example, `/dashy`), before building the app, and the path to all assets will then resolve to the new path, instead of `./`.
However, since Dashy is just a static web application, it can be served with whatever server you like. The following section outlines how you can configure a web server.
Note, that if you choose not to use `server.js` to serve up the app, you will loose access to the following features:
- Loading page, while the app is building
- Writing config file to disk from the UI
- Website status indicators, and ping checks
Example Configs
- [NGINX](#nginx)
- [Apache](#apache)
- [Caddy](#caddy)
- [Firebase](#firebase-hosting)
- [cPanel](#cpanel)
### NGINX
Create a new file in `/etc/nginx/sites-enabled/dashy`
```text
server {
listen 80;
listen [::]:80;
root /var/www/dashy/html;
index index.html;
server_name your-domain.com www.your-domain.com;
location / {
try_files $uri $uri/ =404;
}
}
```
To use HTML5 history mode (`appConfig.routingMode: history`), replace the inside of the location block with: `try_files $uri $uri/ /index.html;`.
Then upload the build contents of Dashy's dist directory to that location.
For example: `scp -r ./dist/* [username]@[server_ip]:/var/www/dashy/html`
### Apache
Copy Dashy's dist folder to your apache server, `sudo cp -r ./dashy/dist /var/www/html/dashy`.
In your Apache config, `/etc/apche2/apache2.conf` add:
```text
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
```
Add a `.htaccess` file within `/var/www/html/dashy/.htaccess`, and add:
```text
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]
```
Then restart Apache, with `sudo systemctl restart apache2`
### Caddy
Caddy v2
```text
try_files {path} /
```
Caddy v1
```text
rewrite {
regexp .*
to {path} /
}
```
### Firebase Hosting
Create a file names `firebase.json`, and populate it with something similar to:
```text
{
"hosting": {
"public": "dist",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
```
### cPanel
1. Login to your WHM
2. Open 'Feature Manager' on the left sidebar
3. Under 'Manage feature list', click 'Edit'
4. Find 'Application manager' in the list, enable it and hit 'Save'
5. Log into your users cPanel account, and under 'Software' find 'Application Manager'
6. Click 'Register Application', fill in the form using the path that Dashy is located, and choose a domain, and hit 'Save'
7. The application should now show up in the list, click 'Ensure dependencies', and move the toggle switch to 'Enabled'
8. If you need to change the port, click 'Add environmental variable', give it the name 'PORT', choose a port number and press 'Save'.
9. Dashy should now be running at your selected path an on a given port
**[⬆️ Back to Top](#management)**
---
## Running a Modified Version of the App
If you'd like to make any code changes to the app, and deploy your modified version, this section briefly explains how.
The first step is to fork the project on GitHub, and clone it to your local system. Next, install the dependencies (`yarn`), and start the development server (`yarn dev`) and visit `localhost:8080` in your browser. You can then make changes to the codebase, and see the live app update in real-time. Once you've finished, running `yarn build` will build the app for production, and output the assets into `./dist` which can then be deployed using a web server, CDN or the built-in Node server with `yarn start`. For more info on all of this, take a look at the [Developing Docs](/docs/developing.md). To build your own Docker container from the modified app, see [Building your Own Container](#building-your-own-container)
**[⬆️ Back to Top](#management)**
---
## Building your Own Container
Similar to above, you'll first need to fork and clone Dashy to your local system, and then install dependencies.
Then, either use Dashy's default [`Dockerfile`](https://github.com/Lissy93/dashy/blob/master/Dockerfile) as is, or modify it according to your needs.
To build and deploy locally, first build the app with: `docker build -t dashy .`, and then start the app with `docker run -p 8080:80 --name my-dashboard dashy`. Or modify the `docker-compose.yml` file, replacing `image: lissy93/dashy` with `build: .` and run `docker compose up`.
Your container should now be running, and will appear in the list when you run `docker container ls a`. If you'd like to enter the container, run `docker exec -it [container-id] /bin/ash`.
You may wish to upload your image to a container registry for easier access. Note that if you choose to do this on a public registry, please name your container something other than just 'dashy', to avoid confusion with the official image.
You can push your build image, by running: `docker push ghcr.io/OWNER/IMAGE_NAME:latest`. You will first need to authenticate, this can be done by running `echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin`, where `CR_PAT` is an environmental variable containing a token generated from your GitHub account. For more info, see the [Container Registry Docs](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry).
**[⬆️ Back to Top](#management)**
---

View File

@@ -0,0 +1,179 @@
# Internationalization
Internationalization is the process of making an application available in other languages. This is important, as not everyone is a native English speaker. This page explains how you can switch languages, how to add a new language, and how to make text translatable when writing a new component.
- [Setting your Language](#setting-language)
- [Adding a new Language](#adding-a-new-language)
- [Adding New Text to a Component](#adding-new-text-to-a-component)
---
## Setting Language
By default, Dashy will attempt to use the language of your browser or system. If a translation for your language does not yet exist, it will fallback to English.
### In the UI
You can manually select your language in the UI. Under the Config Menu, click the Language button, and select your language from the dropdown menu. Your preference will be saved in local storage.
### Config File
You can also set your language in the config file. Specify the ISO code of one of the supported languages, under `appConfig.lang`. For example:
```yaml
appConfig:
language: de
```
### Available Languages
At the time of writing the following languages are supported: `en`, `zh-CN`, `nl`, `fr`, `de`, `es`, `sl`, `it`, `pt`, `ru`, `ar`, `hi`, `ja`, but an up-to-date list of all implemented translations can be found in [`./src/utils/languages.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/languages.js). Languages are specified by their 2-digit [ISO-639 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes), or sometimes a 4-digit code if it's a regional dialect.
---
## Adding a new Language
Dashy is using [vue-i18n](https://vue-i18n.intlify.dev/guide/) to manage multi-language support.
Adding a new language is pretty straightforward, with just three steps:
### 1. Create a new Language File
Create a new JSON file in `./src/assets/locales` for your language.
You should name it with the 2-digit [ISO-639 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for your locale (e.g. for German `de.json`, French `fr.json` or Spanish `es.json`) - You can find a list of all ISO codes at [iso.org](https://www.iso.org/obp/ui).
If your language is a specific dialect or regional translation, then use the Posfix [CLDR](http://cldr.unicode.org/) format, where, e.g. `en-GB.json` (British English), `es-MX.json` (Spanish, in Mexico) or `zh-CN.json` (Chinese, simplified) - A list of which can be found [here](https://github.com/unicode-org/cldr-json/blob/master/cldr-json/cldr-core/availableLocales.json)
### 2. Translate
Using [`en.json`](https://github.com/Lissy93/dashy/tree/master/src/assets/locales/en.json) as an example, translate the JSON values to your language, while leaving the keys as they are. It's fine to leave out certain items, as if they're missing they will fall-back to English. If you see any attribute which include curly braces (`{xxx}`), then leave the inner value of these braces as is, as this is for variables.
```json
{
"theme-maker": {
"export-button": "Benutzerdefinierte Variablen exportieren",
"reset-button": "Stile zurücksetzen für",
"show-all-button": "Alle Variablen anzeigen",
"save-button": "Speichern",
"cancel-button": "Abbrechen",
"saved-toast": "{theme} Erfolgreich aktualisiert",
"reset-toast": "Benutzerdefinierte Farben für {theme} entfernt"
},
}
```
### 3. Add your file to the app
In [`./src/utils/languages.js`](https://github.com/Lissy93/dashy/tree/master/src/utils/languages.js), you need to do 2 small things:
First import your new translation file, do this at the top of the page.
E.g. `import de from '@/assets/locales/de.json';`
Second, add it to the array of languages, e.g:
```javascript
export const languages = [
{
name: 'English',
code: 'en',
locale: en,
flag: '🇬🇧',
},
{
name: 'German', // The name of your language
code: 'de', // The ISO code of your language
locale: de, // The name of the file you imported (no quotes)
flag: '🇩🇪', // An optional flag emoji
},
];
```
You can also add your new language to the readme, under the [Language Switching](https://github.com/Lissy93/dashy#language-switching-) section and optionally include your name/ username if you'd like to be credited for your work. Done!
If you are not comfortable with making pull requests, or do not want to modify the code, then feel free to instead send the translated file to me, and I can add it into the application. I will be sure to credit you appropriately.
---
## Adding New Text to a Component
If you're working on a new component, then any text that is displayed to the user should be extracted out of the component, and stored in the file. This also applies to any existing components, that might have been forgotten to be translated. Thankfully, everything is already setup, so this is a pretty easy job.
### 1. Add Translated Text
Firstly, go to [`./src/assets/locales/en.json`](https://github.com/Lissy93/dashy/blob/master/src/assets/locales/en.json), and either find the appropriate section, or create a new section. Lets say you're new component is called `my-widget`, you could add `"my-widget": {}` to store all your text as key-value-pairs. E.g.
```json
"my-widget": {
"awesome-text": "I am some text, that will be seen by the user"
}
```
Note that you **must** add English translations for all text. Missing languages are not a problem, as they will always fallback to English, but if the English is missing, then nothing can be displayed.
### 2. Use Text within Component
Once your text is in the translation file, you can now use it within your component. There is a global `$t` function, with takes the key of your new translation, and returns the value. For example:
```vue
<p>{{ $t('my-widget.awesome-text') }}</p>
```
Note that the `{{ }}` just tells Vue that this is JavaScript/ dynamic.
This will render: `<p>I am some text, that will be seen by the user</p>`
If you need to display text programmatically, from within the components JavaScript (e.g. in a toast popup), then use `this.$t`.
For example: `alert(this.$t('my-widget.awesome-text'))`.
You may also need to pass a variable to be displayed within a translation. Vue I18n supports [Interpolations](https://vue-i18n.intlify.dev/guide/essentials/syntax.html#interpolations) using mustache-like syntax.
For example, you would set your translation to:
```json
{
"welcome-message": "Hello {name}!"
}
```
And then pass that variable (`name`) within a JSON object as the second parameter on `$t`, like:
```javascript
$t('welcome-message', { name: 'Alicia' })
```
Which will render:
```text
Hello Alicia!
```
There are many other advanced features, including Pluralization, Datetime & Number Formatting, Message Support and more, all of which are outlined in the [Vue-i18n Docs](https://vue-i18n.intlify.dev/guide/).
### Basic Example
Using the search bar as an example, this would look something like:
In [`./src/components/Settings/SearchBar.vue`](https://github.com/Lissy93/dashy/blob/master/src/components/Settings/SearchBar.vue):
```vue
<template>
<form>
<label for="search-input">{{ $t('search.search-label') }}</label>
<input
v-model="searchValue"
:placeholder="$t('search.search-placeholder')"
/>
</form>
</template>
```
Then in [`./src/assets/locales/en.json`](https://github.com/Lissy93/dashy/blob/master/src/assets/locales/en.json):
```json
{
"search": {
"search-label": "Search",
"search-placeholder": "Start typing to filter",
},
...
}
```

View File

@@ -0,0 +1,97 @@
# Pages and Sections
## Multi-Page Support
You can have additional pages within your dashboard, with each having it's own config file. The config files for sub-pages can either be stored locally, or hosted separately. A link to each additional page will be displayed in the navigation bar.
You can edit additional pages using the interactive editor, exactly the same was as your primary page (so long as it's local). But please save changes to one page, before you start editing the next.
### Using Local Sub-Pages
To get started, create a new `.yml` config file for your sub-page, placing it within `/app/public`. Then within your primary `conf.yml`, choose a name, and specify the path to the new file.
For example:
```yaml
pages:
- name: Networking Services
path: 'networking.yml'
- name: Work Stuff
path: 'work.yml'
```
If you're sub-page is located within `/app/public`, then you only need to specify the filename, but if it's anywhere else, then the full path is required.
### Using Remote Sub-Pages
Config files don't need to be local, you can store them anywhere, and data will be imported as sub-pages on page load.
For example:
```yaml
pages:
- name: Getting Started
path: 'https://snippet.host/tvcw/raw'
- name: Homelab
path: 'https://snippet.host/tetp/raw'
- name: Browser Startpage
path: 'https://snippet.host/zcom/raw'
```
There are many options of how this can be used. You could store your config within a Git repository, in order to easily track and rollback changes. Or host your config on your NAS, to have it backed up with the rest of your files. Or use a hosted paste service, for example [snippet.host](https://snippet.host/), which supports never-expiring CORS-enabled pastes, which can also be edited later.
You will obviously not be able to write updates to remote configs directly through the UI editor, but you can still make and preview changes, then use the export menu to get a copy of the new config, which can then be pasted to the remote source manually.
The config file must, of course be accessible from within Dashy. If your config contains sensitive info (like API keys, credentials, secret URLs, etc), take care not to expose it to the internet.
The following example shows creating a config, publishing it as a [Gist](https://gist.github.com/), copying the URL to the raw file, and using it within your dashboard.
<p align="center">
<img width="700" alt="Public config in a gist demo"
src="https://i.ibb.co/55jm3LG/how-to-use-remote-config-sub-page.gif"
/>
</p>
### Restrictions
Only top-level fields supported by sub-pages are `pageInfo` and `sections`. The `appConfig` and `pages` will always be inherited from your main `conf.yml` file. Other than that, sub-pages behave exactly the same as your default view, and can contain sections, items, widgets and page info like nav links, title and logo.
Note that since page paths are required by the router, they are set at build-time, not run-time, and so a rebuild (happens automatically) is required for changes to page paths to take effect (this only applies to changes to the `pages` array, rebuild isn't required for editing page content).
## Sub-Items
A normal section will contain zero or more items, for example:
```yaml
- name: Coding
icon: far fa-code
items:
- title: GitHub
url: https://github.com/
- title: StackOverflow
url: http://stackoverflow.com/
```
But items can also be grouped together, referred to as sub-items. This is useful for a group of less frequently used items, which you don't want to take up too much space, or for action buttons (_coming soon_).
Item groups may also have an optional title.
```yaml
- name: Coding
icon: far fa-code
items:
- title: Normal Item 1
- title: Normal Item 2
- subItems:
- title: JavaScript
url: https://developer.mozilla.org
icon: si-javascript
- title: TypeScript
url: https://www.typescriptlang.org/docs
icon: si-typescript
- title: Svelt
url: https://svelte.dev/docs
icon: si-svelte
- title: Go
url: https://go.dev/doc
icon: si-go
```

295
docs/privacy.md Normal file
View File

@@ -0,0 +1,295 @@
# Privacy & Security
Dashy was built with privacy in mind.
Self-hosting your own apps and services is a great way to protect yourself from the mass data collection employed by big tech companies, and Dashy was designed to make self-hosting easier, by keeping your local services organized and accessible from a single place. The [management docs](https://github.com/Lissy93/dashy/blob/master/docs/management.md) contains a though guide on the steps you can take to secure your homelab.
Dashy operates on the premise, that no external data requests should ever be made, unless explicitly enabled by the user. In the interest of transparency, the code is 100% open source and clearly documented throughout.
| 🔐 For privacy and security tips, check out another project of mine: **[Personal Security Checklist](https://github.com/Lissy93/personal-security-checklist)** |
|-|
## Contents
- [External Requests](#external-requests)
- [Icons](#icons)
- [Themes](#themes)
- [Widgets](#widgets)
- [Features](#features)
- [Status Checking](#status-checking)
- [Update Checks](#update-checks)
- [Cloud Backup](#cloud-backup)
- [Web Search](#web-search)
- [Error Reporting](#anonymous-error-reporting)
- [Browser Storage](#browser-storage)
- [App Dependencies](#dependencies)
- [Security Features](#security-features)
- [Securing your Environment](#securing-your-environment)
- [Reporting a Security Issue](#reporting-a-security-issue)
---
## External Requests
By default, Dashy will not make any external requests, unless you configure it to. Some features (which are off by default) do require internat access, and this section outlines those features, the services used, and links to their privacy policies.
The following section outlines all network requests that are made when certain features are enabled.
### Icons
#### Font Awesome
If either any of your sections, items or themes are using icons from font-awesome, then it will be automatically enabled. But you can also manually enable or disable it by setting `appConfig.enableFontAwesome` to `true` / `false`. Requests are made directly to Font-Awesome CDN, for more info, see the [Font Awesome Privacy Policy](https://fontawesome.com/privacy).
#### Material Design Icons
If either any of your sections, items or themes are mdi icons, then it will be automatically enabled. But you can also manually enable or disable it by setting `appConfig.enableMaterialDesignIcons` to `true` / `false`. Requests are made directly to Material-Design-Icons CDN, for more info, see the [Material Design Icons Website](https://materialdesignicons.com/).
#### Favicon Fetching
If an item's icon is set to `favicon`, then it will be auto-fetched from the corresponding URL. Since not all websites have their icon located at `/favicon.ico`, and if they do, it's often very low resolution (like `16 x 16 px`). Therefore, the default behavior is for Dashy to check if the URL is public, and if so will use an API to fetch the favicon. For self-hosted services, the favicon will be fetched from the default path, and no external requests will be made.
The default favicon API is [allesedv.com](https://favicon.allesedv.com/), but this can be changed by setting `appConfig.faviconApi` to an alternate source (`iconhorse`, `clearbit`, `faviconkit`, `besticon`, `duckduckgo`, `google` and `allesedv` are supported). If you do not want to use any API, then you can set this property to `local`, and the favicon will be fetched from the default path. For hosted services, this will still incur an external request.
#### Generative Icons
If an item has the icon set to `generative`, then an external request it made to [Dice Bear](https://dicebear.com/) to fetch the uniquely generated icon. The URL of a given service is used as the key for generating the icon, but it is first hashed and encoded for basic privacy. For more info, please reference the [Dicebear Privacy Policy](https://avatars.dicebear.com/legal/privacy-policy)
As a fallback, if Dicebear fails, then [Evatar](https://evatar.io/) is used.
#### Other Icons
Section icons, item icons and app icons are able to accept a URL to a raw image, if the image is hosted online then an external request will be made. To avoid the need to make external requests for icon assets, you can either use a self-hosted CDN, or store your images within `./public/item-icons` (which can be mounted as a volume if you're using Docker).
#### Web Assets
By default, all assets required by Dashy come bundled within the source, and so no external requests are made. If you add an additional font, which is imported from a CDN, then that will incur an external request. The same applies for other web assets, like external images, scripts or styles.
---
### Features
#### Status Checking
The status checking feature allows you to ping your apps/ services to check if they are currently operational.
Dashy will ping your services directly, and does not rely on any third party. If you are checking the uptime status of a public/ hosted application, then please refer to that services privacy policy. For all self-hosted services, requests happen locally within your network, and are not external.
#### Update Checks
When the application loads, it checks for updates. The results of which are displayed in the config menu of the UI. This was implemented because using a very outdated version of Dashy may have unfixed issues. Your version is fetched from the source (local request), but the latest version is fetched from GitHub, which is an external request. This can be disabled by setting `appConfig.disableUpdateChecks: true`
#### Cloud Backup
Dashy has an optional End-to-End encrypted [cloud backup feature](https://github.com/Lissy93/dashy/blob/master/docs/backup-restore.md). No data is ever transmitted unless you actively enable this feature through the UI.
All data is encrypted before being sent to the backend. This is done in [`CloudBackup.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/CloudBackup.js), using [crypto.js](https://github.com/brix/crypto-js)'s AES method, using the users chosen password as the key. The data is then sent to a [Cloudflare worker](https://developers.cloudflare.com/workers/learning/how-workers-works) (a platform for running serverless functions), and stored in a [KV](https://developers.cloudflare.com/workers/learning/how-kv-works) data store.
Your selected password never leaves your device, and is hashed before being compared. It is only possible to restore a configuration if you have both the backup ID and decryption password. Because the data is encrypted on the client-side (before being sent to the cloud), it is not possible for a man-in-the-middle, government entity, website owner, or even Cloudflare to be able read any of your data.
#### Web Search
Dashy has a primitive [web search feature](https://github.com/Lissy93/dashy/blob/master/docs/searching.md#web-search). No external requests are made, instead you are redirected to your chosen search engine (defaults to DuckDuckGo), using your chosen opening method.
This feature can be disabled under appConfig, with `webSearch: { disableWebSearch: true }`
#### Anonymous Error Reporting
Error reporting is disabled by default, and no data will ever be sent without your explicit consent. In fact, the error tracking code isn't even imported unless you have actively enabled it. [Sentry](https://github.com/getsentry/sentry) is used for this, it's an open source error tracking and performance monitoring tool, used to identify any issues which occur in the production app (if you enable it).
The crash report includes the file or line of code that triggered the error, and a 2-layer deep stack trace. Reoccurring errors will also include the following user information: OS type (Mac, Windows, Linux, Android or iOS) and browser type (Firefox, Chrome, IE, Safari). Data scrubbing is enabled. IP address will not be stored. If any potentially identifiable data ever finds its way into a crash report, it will be automatically and permanently erased. All statistics collected are anonymized and stored securely, and ae automatically deleted after 14 days. For more about privacy and security, see the [Sentry Docs](https://sentry.io/security/).
Enabling anonymous error reporting helps me to discover bugs I was unaware of, and then fix them, in order to make Dashy more reliable long term. Error reporting is activated by setting `appConfig.enableErrorReporting: true`.
If you need to monitor bugs yourself, then you can [self-host your own Sentry Server](https://develop.sentry.dev/self-hosted/), and use it by setting `appConfig.sentryDsn` to your Sentry instances [Data Source Name](https://docs.sentry.io/product/sentry-basics/dsn-explainer/), then just enable error reporting in Dashy.
---
### Themes
Certain themes may use external assets (such as fonts or images). Currently, this only applies the Adventure theme.
---
### Widgets
Dashy supports [Widgets](/docs/widgets.md) for displaying dynamic content. Below is a list of all widgets that make external data requests, along with the endpoint they call and a link to the Privacy Policy of that service.
- **[Weather](/docs/widgets.md#weather)** and **[Weather Forecast](/docs/widgets.md#weather-forecast)**: `https://api.openweathermap.org`
- [OWM Privacy Policy](https://openweather.co.uk/privacy-policy)
- **[RSS Feed](/docs/widgets.md#rss-feed)**: `https://api.rss2json.com/v1/api.json`
- [Rss2Json Privacy Policy](https://rss2json.com/privacy-policy)
- **[IP Address](/docs/widgets.md#public-ip)**: `https://ipapi.co/json` or `http://ip-api.com/json`
- [IPGeoLocation Privacy Policy](https://ipgeolocation.io/privacy.html)
- [IP-API Privacy Policy](https://ip-api.com/docs/legal)
- **[IP Blacklist](/docs/widgets.md#ip-blacklist)**: `https://api.blacklistchecker.com`
- [Blacklist Checker Privacy Policy](https://blacklistchecker.com/privacy)
- **[Domain Monitor](/docs/widgets.md#domain-monitor)**: `http://api.whoapi.com`
- [WhoAPI Privacy Policy](https://whoapi.com/privacy-policy/)
- **[Crypto Watch List](/docs/widgets.md#crypto-watch-list)** and **[Token Price History](/docs/widgets.md#crypto-token-price-history)**: `https://api.coingecko.com`
- [CoinGecko Privacy Policy](https://www.coingecko.com/en/privacy)
- **[Wallet Balance](/docs/widgets.md#wallet-balance)**: `https://api.blockcypher.com/`
- [BlockCypher Privacy Policy](https://www.blockcypher.com/privacy.html)
- **[Code::Stats](/docs/widgets.md#code-stats)**: `https://codestats.net`
- [Code::Stats Privacy Policy](https://codestats.net/tos#privacy)
- **[AnonAddy](/docs/widgets.md#anonaddy)**: `https://app.anonaddy.com`
- [AnonAddy Privacy Policy](https://anonaddy.com/privacy/)
- **[Vulnerability Feed](/docs/widgets.md#vulnerability-feed)**: `https://www.cvedetails.com`
- [CVE Details Privacy Policy](https://www.cvedetails.com/privacy.php)
- **[Exchange Rate](/docs/widgets.md#exchange-rates)**: `https://v6.exchangerate-api.com`
- [ExchangeRateAPI Privacy Policy](https://www.exchangerate-api.com/terms)
- **[Public Holidays](/docs/widgets.md#public-holidays)**: `https://kayaposoft.com`
- [jurajmajer/enrico](https://github.com/jurajmajer/enrico)
- **[Covid-19 Status](/docs/widgets.md#covid-19-status)**: `https://codestats.net`
- [disease-sh/api](https://github.com/disease-sh/api)
- **[Sports Scores](/docs/widgets.md#sports-scores)**: `https://thesportsdb.com`
- No Policy Available
- **[News Headlines](/docs/widgets.md#news-headlines)**: `https://api.currentsapi.services`
- [CurrentsAPI Privacy Policy](https://currentsapi.services/privacy)
- **[Mullvad Status](/docs/widgets.md#mullvad-status)**: `https://am.i.mullvad.net`
- [Mullvad Privacy Policy](https://mullvad.net/en/help/privacy-policy/)
- **[TFL Status](/docs/widgets.md#tfl-status)**: `https://api.tfl.gov.uk`
- [TFL Privacy Policy](https://tfl.gov.uk/corporate/privacy-and-cookies/)
- **[Stock Price History](/docs/widgets.md#stock-price-history)**: `https://alphavantage.co`
- [AlphaVantage Privacy Policy](https://www.alphavantage.co/privacy/)
- **[ETH Gas Prices](/docs/widgets.md#eth-gas-prices)**: `https://ethgas.watch`
- [wslyvh/ethgaswatch](https://github.com/wslyvh/ethgaswatch)
- **[Joke](/docs/widgets.md#joke)**: `https://v2.jokeapi.dev`
- [SV443's Privacy Policy](https://sv443.net/privacypolicy/en)
- **[Flight Data](/docs/widgets.md#flight-data)**: `https://aerodatabox.p.rapidapi.com`
- [AeroDataBox Privacy Policy](https://www.aerodatabox.com/#h.p_CXtIYZWF_WQd)
- **[Astronomy Picture of the Day](/docs/widgets.md#astronomy-picture-of-the-day)**: `https://apodapi.herokuapp.com`
- [NASA's Privacy Policy](https://www.nasa.gov/about/highlights/HP_Privacy.html)
- **[GitHub Trending](/docs/widgets.md#github-trending)** and **[GitHub Profile Stats](/docs/widgets.md#github-profile-stats)**: `https://api.github.com`
- [GitHub's Privacy Policy](https://docs.github.com/en/github/site-policy/github-privacy-statement)
- **[Cron Monitoring (Health Checks)](/docs/widgets.md#cron-monitoring-health-checks)**: `https://healthchecks.io`
- [Health-Checks Privacy Policy](https://healthchecks.io/privacy/)
---
## Browser Storage
In order for user preferences to be persisted between sessions, certain data needs to be stored in the browsers local storage. No personal info is kept here, none of this data can be accessed by other domains, and no data is ever sent to any server without your prior consent.
You can view and delete stored data by opening up the dev tools: <kbd>F12</kbd> --> `Application` --> `Storage`.
The following section outlines all data that is stored in the browsers, as cookies, session storage or local storage.
### Cookies
> [Cookies](https://en.wikipedia.org/wiki/HTTP_cookie) will expire after their pre-defined lifetime
- `AUTH_TOKEN` - A unique token, generated from a hash of users credentials, to verify they are authenticated. Only used when auth is enabled.
### Session Storage
> [Session storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) is deleted when the current session ends (tab / window is closed)
- `SW_STATUS` - The current status of any service workers
- `ERROR_LOG` - List of recent errors
### Local Storage
> [Local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) is persisted between sessions, and only deleted when manually removed
- `LANGUAGE` - The locale to show app text in
- `HIDE_WELCOME_BANNER` - Set to true once user dismissed welcome message, so that it's not shown again
- `LAYOUT_ORIENTATION` - Preferred section layout, either horizontal, vertical or auto
- `COLLAPSE_STATE` - Remembers which sections are collapsed
- `ICON_SIZE` - Size of items, either small, medium or large
- `THEME` - Users applied theme
- `CUSTOM_COLORS` - Any color modifications made to a given theme
- `BACKUP_ID` - If a backup has been made, the ID is stored here
- `BACKUP_HASH` - A unique hash of the previous backups meta data
- `HIDE_SETTINGS` - Lets user hide or show the settings menu
- `USERNAME` - If user logged in, store username. Only used to show welcome message, not used for auth
- `CONF_SECTIONS` - Array of sections, only used when user applies changes locally
- `PAGE_INFO` - Config page info, only used when user applies changes locally
- `APP_CONFIG` - App config, only used when user applies changes locally
- `MOST_USED` - If smart sort is used to order items by most used, store open count
- `LAST_USED` - If smart sort is used to order items by last used, store timestamps
### Deleting Stored Data
You can manually view and delete session storage, local storage and cookies at anytime. Fist [open](/docs/troubleshooting.md#how-to-open-browser-console) your browsers developer tools (usually <kbd>F12</kbd>), then under the Application tab select the storage category. Here you will see a list of stored data, and you can select any item and delete it.
---
## Dependencies
As with most web projects, Dashy relies on several [dependencies](https://github.com/Lissy93/dashy/blob/master/docs/credits.md#dependencies-). For links to each, and a breakdown of their licenses, please see [Legal](https://github.com/Lissy93/dashy/blob/master/.github/LEGAL.md).
Dependencies can introduce security vulnerabilities, but since all these packages are open source any issues are usually very quickly spotted. Dashy is using Snyk for dependency security monitoring, and you can see [the latest report here](https://snyk.io/test/github/lissy93/dashy). If any issue is detected by Snyk, a note about it will appear at the top of the Readme, and will usually be fixed within 48 hours.
Note that packages listed under `devDependencies` section are only used for building the project, and are not included in the production environment.
---
## Securing your Environment
Running your self-hosted applications in individual, containerized environments (such as containers or VMs) helps keep them isolated, and prevent an exploit in one service effecting another.
If you're running Dashy in a container, see [Management Docs --> Container Security](https://github.com/Lissy93/dashy/blob/master/docs/management.md#container-security) for step-by-step security guide.
There is very little complexity involved with Dashy, and therefore the attack surface is reasonably small, but it is still important to follow best practices and employ monitoring for all your self-hosted apps. A couple of things that you should look at include:
- Use SSL for securing traffic in transit
- Configure [authentication](/docs/authentication.md#alternative-authentication-methods) to prevent unauthorized access
- Keep your system, software and Dashy up-to-date
- Ensure your server is appropriately secured
- Manage users and SSH correctly
- Enable and configure firewall rules
- Implement security, malware and traffic scanning
- Setup malicious traffic detection
- Understand the [Docker attack fronts](https://docs.docker.com/engine/security/), and follow [Docker Security Best Practices](https://snyk.io/blog/10-docker-image-security-best-practices/)
This is covered in more detail in [App Management](/docs/management.md).
---
## Security Features
### Subresource Integrity
[Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) or SRI is a security feature that enables browsers to verify that resources they fetch are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched resource must match. This prevents the app from loading any resources that have been manipulated, by verifying the files hashes. It safeguards against the risk of an attacker injecting arbitrary malicious content into any files served up via a CDN.
Dashy supports SRI, and it is recommended to enable this if you are hosting your dashboard via a public CDN. To enable SRI, set the `INTEGRITY` environmental variable to `true`.
### SSL
Native SSL support is enabled, for setup instructions, see the [Management Docs](/docs/management.md#ssl-certificates)
### Authentication
Dashy supports both basic auth, as well as server-based SSO using Keycloak. Full details of which, along with alternate authentication methods can be found in the [Authentication Docs](/docs/authentication.md). If your dashboard is exposed to the internet and/ or contains any sensitive info it is strongly recommended to configure access control with Keycloak or another server-side method.
---
## Disabling Features
You may wish to disable features that you don't want to use, if they involve storing data in the browser or making network requests.
- To disable smart-sort (uses local storage), set `appConfig.disableSmartSort: true`
- To disable update checks (makes external request to GH), set `appConfig.disableUpdateChecks: true`
- To disable web search (redirect to external / internal content), set `appConfig.disableWebSearch: true`
- To keep status checks disabled (external/ internal requests), set `appConfig.statusCheck: false`
- To keep font-awesome icons disabled (external requests), set `appConfig.enableFontAwesome: false`
- To keep error reporting disabled (external requests and data collection), set `appConfig.enableErrorReporting: false`
- To keep the service worker disabled (stores cache of app in browser data), set `appConfig.enableServiceWorker: false`
---
## Reporting a Security Issue
If you think you've found a critical issue with Dashy, please send an email to `security@mail.alicia.omg.lol`. You can encrypt it, using [`0688 F8D3 4587 D954 E9E5 1FB8 FEDB 68F5 5C02 83A7`](https://keybase.io/aliciasykes/pgp_keys.asc?fingerprint=0688f8d34587d954e9e51fb8fedb68f55c0283a7). You should receive a response within 48 hours. For more information, see [SECURITY.md](https://github.com/Lissy93/dashy/blob/master/.github/SECURITY.md).
All non-critical issues can be raised as a ticket.
Please include the following information:
- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
- Full paths of source file(s) related to the manifestation of the issue
- The location of the affected source code (tag/branch/commit or direct URL)
- Any special configuration required to reproduce the issue
- Step-by-step instructions to reproduce the issue
- Proof-of-concept or exploit code (if possible)
- Impact of the issue, including how an attacker might exploit the issue

146
docs/quick-start.md Normal file
View File

@@ -0,0 +1,146 @@
# Quick Start
Welcome to Dashy! So glad you're here 😊 In a couple of minutes, you'll have your new dashboard up and running 🚀
**TLDR;** Run `docker run -p 8080:80 lissy93/dashy`, then open `http://localhost:8080`
---
## 1. Prerequisites
The quickest and easiest method of running Dashy is using Docker (or another container engine). You can find installation instructions for your system in the [Docker Documentation](https://docs.docker.com/get-docker/).
If you don't want to use Docker, then you can use one of Dashy's other supported installation methods instead, all of which are outlined in the [Deployment Docs](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md).
---
## 2. Installation
To pull the latest image, and build and start the app run:
```bash
docker run -d \
-p 8080:80 \
-v ~/my-conf.yml:/app/public/conf.yml \
--name my-dashboard \
--restart=always \
lissy93/dashy:latest
```
Either replace the -v path to point to your config file, or leave it out. For a full list of available options, then see [Dashy with Docker](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md#deploy-with-docker) Docs. If you'd prefer to use Docker Compose, then see [Dashy with Docker Compose](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md#using-docker-compose) Docs. Alternate registries, architectures and pinned versions are also supported.
Your dashboard should now be up and running at `http://localhost:8080` (or your servers IP address/ domain, and the port that you chose). The first time you build, it may take a few minutes.
---
## 3. Configure
Now that you've got Dashy running, you are going to want to set it up with your own content.
Config is written in [YAML Format](https://yaml.org/), and saved in [`/public/conf.yml`](https://github.com/Lissy93/dashy/blob/master/public/conf.yml).
The format on the config file is pretty straight forward. There are three root attributes:
- [`pageInfo`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#pageinfo) - Dashboard meta data, like title, description, nav bar links and footer text
- [`appConfig`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#appconfig-optional) - Dashboard settings, like themes, authentication, language and customization
- [`sections`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#section) - An array of sections, each including an array of items
You can view a full list of all available config options in the [Configuring Docs](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md).
```yaml
pageInfo:
title: Home Lab
sections: # An array of sections
- name: Example Section
icon: far fa-rocket
items:
- title: GitHub
description: Dashy source code and docs
icon: fab fa-github
url: https://github.com/Lissy93/dashy
- title: Issues
description: View open issues, or raise a new one
icon: fas fa-bug
url: https://github.com/Lissy93/dashy/issues
- name: Local Services
items:
- title: Firewall
icon: favicon
url: http://192.168.1.1/
- title: Game Server
icon: https://i.ibb.co/710B3Yc/space-invader-x256.png
url: http://192.168.130.1/
```
Notes:
- You can use a Docker volume to pass a config file from your host system to the container
- E.g. `-v ./host-system/my-local-conf.yml:/app/public/conf.yml`
- It's also possible to edit your config directly through the UI, and changes will be saved in this file
- Check your config against Dashy's schema, with `docker exec -it [container-id] yarn validate-config`
- You might find it helpful to look at some examples, a collection of which can be [found here](https://gist.github.com/Lissy93/000f712a5ce98f212817d20bc16bab10)
- After editing your config, the app will rebuild in the background, which may take a minute
---
## 4. Further Customisation
Once you've got Dashy setup, you'll want to ensure the container is properly healthy, secured, backed up and kept up-to-date. All this is covered in the [Management Docs](https://github.com/Lissy93/dashy/blob/master/docs/management.md).
You might also want to check out the docs for specific features you'd like to use:
- [Authentication](/docs/authentication.md) - Setting up authentication to protect your dashboard
- [Alternate Views](/docs/alternate-views.md) - Using the startpage and workspace view
- [Backup & Restore](/docs/backup-restore.md) - Guide to Dashy's cloud sync feature
- [Icons](/docs/icons.md) - Outline of all available icon types for sections and items
- [Localisation](/docs/multi-language-support.md) - How to change language, or add your own
- [Status Indicators](/docs/status-indicators.md) - Using Dashy to monitor uptime and status of your apps
- [Search & Shortcuts](/docs/searching.md) - Using instant filter, web search and custom hotkeys
- [Theming](/docs/theming.md) - Complete guide to applying, writing and modifying themes and styles
---
## 5. Final Note
If you need any help or support in getting Dashy running, head over to the [Discussions](https://github.com/Lissy93/dashy/discussions) page. If you think you've found a bug, please do [raise it](https://github.com/Lissy93/dashy/issues/new/choose) so it can be fixed. For contact options, see the [Support Page](https://github.com/Lissy93/dashy/blob/master/.github/SUPPORT.md).
If you're enjoying Dashy, and have a few minutes to spare, please do take a moment to look at the [Contributing Page](https://github.com/Lissy93/dashy/blob/master/docs/contributing.md). Huge thanks to [everyone](https://github.com/Lissy93/dashy/blob/master/docs/credits.md) who has already helped out!
Enjoy your dashboard :)
---
## Alternative Deployment Method 1 - From Source
You can also easily run the app on your system without Docker. For this [Git](https://git-scm.com/downloads), [Node.js](https://nodejs.org/), and [Yarn](https://yarnpkg.com/) are required.
```bash
git clone https://github.com/Lissy93/dashy.git && cd dashy
yarn # Install dependencies
yarn build # Build the app
yarn start # Start the app
```
Then edit `./public/conf.yml` and rebuild the app with `yarn build`
---
## Alternative Deployment Method 2 - Netlify
Don't have a server? No problem! You can run Dashy for free on Netlify (as well as many [other cloud providers](./docs/deployment.md#deploy-to-cloud-service)). All you need it a GitHub account.
1. Fork Dashy's repository on GitHub
2. [Log in](app.netlify.com/login/) to Netlify with GitHub
3. Click "New site from Git" and select your forked repo, then click **Deploy**!
4. You can then edit the config in `./public/conf.yml` in your repo, and Netlify will rebuild the app
---
## Alternative Deployment Method 3 - Cloud Services
Dashy supports 1-Click deployments on several popular cloud platforms. To spin up a new instance, just click a link below:
- [<img src="https://i.ibb.co/ZxtzrP3/netlify.png" width="18"/> Deploy to Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/dashy)
- [<img src="https://i.ibb.co/d2P1WZ7/heroku.png" width="18"/> Deploy to Heroku](https://heroku.com/deploy?template=https://github.com/Lissy93/dashy)
- [<img src="https://i.ibb.co/Ld2FZzb/vercel.png" width="18"/> Deploy to Vercel](https://vercel.com/new/project?template=https://github.com/lissy93/dashy)
- [<img src="https://i.ibb.co/xCHtzgh/render.png" width="18"/> Deploy to Render](https://render.com/deploy?repo=https://github.com/lissy93/dashy/tree/deploy_render)
- [<img src="https://i.ibb.co/J7MGymY/googlecloud.png" width="18"/> Deploy to GCP](https://deploy.cloud.run/?git_repo=https://github.com/lissy93/dashy.git)
- [<img src="https://i.ibb.co/HVWVYF7/docker.png" width="18"/> Deploy to PWD](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml)
- [<img src="https://i.ibb.co/7NxnM2P/easypanel.png" width="18"/> Deploy to Easypanel](https://easypanel.io/docs/templates/dashy)

39
docs/readme.md Normal file
View File

@@ -0,0 +1,39 @@
# ![Dashy Docs](https://i.ibb.co/4mdNf7M/heading-docs.png)
## Running Dashy
- [Quick Start](/docs/quick-start.md) - TLDR guide on getting Dashy up and running
- [Deployment](/docs/deployment.md) - Full guide on deploying Dashy either locally or online
- [Configuring](/docs/configuring.md) - Complete list of all available options in the config file
- [App Management](/docs/management.md) - Managing your app, updating, security, web server configuration, etc
- [Troubleshooting](/docs/troubleshooting.md) - Common errors and problems, and how to fix them
## Development and Contributing
- [Developing](/docs/developing.md) - Running Dashy development server locally, and general workflow
- [Development Guides](/docs/development-guides.md) - Common development tasks, to help new contributors
- [Contributing](/docs/contributing.md) - How you can help keep Dashy alive
- [Showcase](/docs/showcase.md) - See how others are using Dashy, and share your dashboard
- [Credits](/docs/credits.md) - List of people and projects that have made Dashy possible
- [Release Workflow](/docs/release-workflow.md) - Info about releases, CI and automated tasks
## Feature Docs
- [Authentication](/docs/authentication.md) - Guide to setting up authentication to protect your dashboard
- [Alternate Views](/docs/alternate-views.md) - Outline of available pages / views and item opening methods
- [Backup & Restore](/docs/backup-restore.md) - Guide to backing up config with Dashy's cloud sync feature
- [Icons](/docs/icons.md) - Outline of all available icon types for sections and items, with examples
- [Language Switching](/docs/multi-language-support.md) - Details on how to switch language, or add a new locale
- [Pages and Sections](/docs/pages-and-sections.md) - Multi-page support, sections, items and sub-items
- [Status Indicators](/docs/status-indicators.md) - Using Dashy to monitor uptime and status of your apps
- [Searching & Shortcuts](/docs/searching.md) - Searching, launching methods + keyboard shortcuts
- [Theming](/docs/theming.md) - Complete guide to applying, writing and modifying themes + styles
- [Widgets](/docs/widgets.md) - List of all dynamic content widgets, with usage guides and examples
## Misc
- [Privacy & Security](/docs/privacy.md) - List of requests, potential issues, and security resources
- [License](/LICENSE) - Copy of the MIT License
- [Legal](/.github/LEGAL.md) - Licenses of direct dependencies
- [Code of Conduct](/.github/CODE_OF_CONDUCT.md) - Contributor Covenant Code of Conduct
- [Changelog](/.github/CHANGELOG.md) - Details of recent changes, and historical versions

166
docs/release-workflow.md Normal file
View File

@@ -0,0 +1,166 @@
# Releases and Workflows
- [Release Schedule](#release-schedule)
- [Deployment Process](#deployment-process)
- [Git Strategy](#git-strategy)
- [Automated Workflows](#automated-workflows)
## Release Schedule
We're using [Semantic Versioning](https://semver.org/), to indicate major, minor and patch versions. You can find the current version number in the readme, and check your apps version under the config menu. The version number is pulled from the [package.json](https://github.com/Lissy93/dashy/blob/master/package.json#L3) file.
Typically there is a new major release every 2 weeks, usually on Sunday, and you can view these under the [Releases Page](https://github.com/Lissy93/dashy/releases). Each new version will also have a corresponding [tag on GitHub](https://github.com/Lissy93/dashy/tags), and each major release will also result in the creation of a new [tag on DockerHub](https://hub.docker.com/r/lissy93/dashy/tags), so that you can fix your container to a certain version.
For a full breakdown of each change, you can view the [Changelog](https://github.com/Lissy93/dashy/blob/master/.github/CHANGELOG.md). Each new feature or significant change needs to be submitted through a pull request, which makes it easy to review and track these changes, and roll back if needed.
---
## Deployment Process
All changes and new features are submitted as pull requests, which can then be tested, reviewed and (hopefully) merged into the master branch. Every time there is a change in the major version number, a new release is published. This usually happens every 2 weeks, on a Sunday.
When a PR is opened:
- The feature branch is built, and deployed as a Netlify instance. This can be accessed at: `https://deploy-preview-[pr-number]--dashy-dev.netlify.app`, and this URL as well as a link to the build logs are added as a comment on the PR by Netlify bot
- Depending on what files were modified, the bot may also add a comment to remind the author of useful info
- A series of checks will run on the new code, using GH Actions, and prevent merging if they fail. This includes: linting, testing, code quality and complexity checking, security scanning and a spell check
- If a new dependency was added, liss-bot will comment with a summary of those changes, as well as the cost of the module, version, and any security concerns. If the bundle size has increased, this will also be added as a comment
After the PR is merged:
- The app is build, and deployed to: <https://dev.dashy.to>
- A new tag in GitHub is created, using the apps version number (from the package.json)
- The Docker container is built, and published under the `:latest` tag on DockerHub and GHCR
When a new major version is released:
- A new GitHub release is created and published, under new versions tag, with info from the changelog
- The container is built and published under a new tag will be created on DockerHub, called `:release-[version]`
- An announcement is opened in GitHub discussions, outlining the main changes, where users can comment and ask questions
[![Netlify Status](https://api.netlify.com/api/v1/badges/3a0216c3-1ed0-40f5-ad90-ff68b1c96c09/deploy-status)](https://app.netlify.com/sites/dashy-dev/deploys)
---
## Git Strategy
### Git Flow
Like most Git repos, we are following the [Github Flow](https://guides.github.com/introduction/flow) standard.
1. Create a branch (or fork if you don'd have write access)
2. Code some awesome stuff, then add and commit your changes
3. Create a Pull Request, complete the checklist and ensure the build succeeds
4. Follow up with any reviews on your code
5. Merge 🎉
### Git Branch Naming
The format of your branch name should be something similar to: `[TYPE]/[TICKET]_[TITLE]`
For example, `FEATURE/420_Awesome-feature` or `FIX/690_login-server-error`
### Commit Emojis
Using a single emoji at the start of each commit message, to indicate the type task, makes the commit ledger easier to understand, plus it looks cool.
- 🎨 `:art:` - Improve structure / format of the code.
- ⚡️ `:zap:` - Improve performance.
- 🔥 `:fire:` - Remove code or files.
- 🐛 `:bug:` - Fix a bug.
- 🚑️ `:ambulance:` - Critical hotfix
-`:sparkles:` - Introduce new features.
- 📝 `:memo:` - Add or update documentation.
- 🚀 `:rocket:` - Deploy stuff.
- 💄 `:lipstick:` - Add or update the UI and style files.
- 🎉 `:tada:` - Begin a project.
-`:white_check_mark:` - Add, update, or pass tests.
- 🔒️ `:lock:` - Fix security issues.
- 🔖 `:bookmark:` - Make a Release or Version tag.
- 🚨 `:rotating_light:` - Fix compiler / linter warnings.
- 🚧 `:construction:` - Work in progress.
- ⬆️ `:arrow_up:` - Upgrade dependencies.
- 👷 `:construction_worker:` - Add or update CI build system.
- ♻️ `:recycle:` - Refactor code.
- 🩹 `:adhesive_bandage:` - Simple fix for a non-critical issue.
- 🔧 `:wrench:` - Add or update configuration files.
- 🍱 `:bento:` - Add or update assets.
- 🗃️ `:card_file_box:` - Perform database schema related changes.
- ✏️ `:pencil2:` - Fix typos.
- 🌐 `:globe_with_meridians:` - Internationalization and translations.
For a full list of options, see [gitmoji.dev](https://gitmoji.dev/)
### PR Guidelines
Once you've made your changes, and pushed them to your fork or branch, you're ready to open a pull request!
For a pull request to be merged, it must:
- Must be backwards compatible
- The build, lint and tests (run by GH actions) must pass
- There must not be any merge conflicts
When you submit your PR, include the required info, by filling out the PR template. Including:
- A brief description of your changes
- The issue, ticket or discussion number (if applicable)
- For UI relate updates include a screenshot
- If any dependencies were added, explain why it was needed, state the cost associated, and confirm it does not introduce any security issues
- Finally, check the checkboxes, to confirm that the standards are met, and hit submit!
---
## Automated Workflows
Dashy makes heavy use of [GitHub Actions](https://github.com/features/actions) to fully automate the checking, testing, building, deploying of the project, as well as administration tasks like management of issues, tags, releases and documentation. The following section outlines each workflow, along with a link the the action file, current status and short description. A lot of these automations were made possible using community actions contributed to GH marketplace by some amazing people.
### Code Processing
Action | Description
--- | ---
**Code Linter**<br/>[![code-linter.yml](https://github.com/Lissy93/dashy/actions/workflows/code-linter.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/code-linter.yml) | After a pull request is created, all new code changes will be linted, and the CI will fail with a helpful message if the code has any formatting inconsistencies
**Code Spell Check**<br/>[![code-spell-check.yml](https://github.com/Lissy93/dashy/actions/workflows/code-spell-check.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/code-spell-check.yml) | After a PR submitted, all auto-fixable spelling errors will be detected, then Liss-Bot will create a separate PR to propose the fixes
**Dependency Update Summary** <br/>[![dependency-updates-summary.yml](https://github.com/Lissy93/dashy/actions/workflows/dependency-updates-summary.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/dependency-updates-summary.yml) | After a PR is submitted, if any of the dependencies are modified, then Liss-Bot will add a comment, explaining which packages have been added, removed, updated or downgraded, as well as other helpful info
**Get Size** <br/>[![get-size.yml](https://github.com/Lissy93/dashy/actions/workflows/get-size.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/get-size.yml) | Adds comment to PR if the size of the built + bundled application has changed compared to the previous version
**Security Scan** <br/>[![security-scanning.yml](https://github.com/Lissy93/dashy/actions/workflows/security-scanning.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/security-scanning.yml) | Uses Snyk to scan the code and dependencies after a PR. Will add a comment and cause the build to fail if a new vulnerability or potential issue is present
### Releases
Action | Description
--- | ---
**Create Tag** <br/>[![auto-tag-pr.yml](https://github.com/Lissy93/dashy/actions/workflows/auto-tag-pr.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/auto-tag-pr.yml) | Whenever the version indicated in package.json is updates, a new GitHub tag will be created for that point in time
**Build App** <br/>[![build-app.yml](https://github.com/Lissy93/dashy/actions/workflows/build-app.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/build-app.yml) | After changes are merged into the master branch, the app will be build, with output pushed to the `dev-demo` branch
**Cache Artifacts** <br/>[![cache-artifacts.yml](https://github.com/Lissy93/dashy/actions/workflows/cache-artifacts.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/cache-artifacts.yml) | After build, returned files will be cached for future actions for that commit
**Docker Publish** <br/>[![docker-publish.yml](https://github.com/Lissy93/dashy/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/docker-publish.yml) | After PR is merged, the multi-architecture Docker container will be built, and then published to GHCR
### Issue Management
Action | Description
--- | ---
**Close Incomplete Issues** <br/>[![close-incomplete-issues.yml](https://github.com/Lissy93/dashy/actions/workflows/close-incomplete-issues.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/close-incomplete-issues.yml) | Issues which do not match any of the issue templates will be closed, and a comment posted explaining why
**Close Stale Issues** <br/>[![close-stale-issues.yml](https://github.com/Lissy93/dashy/actions/workflows/close-stale-issues.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/close-stale-issues.yml) | Issues which have not been updated for 6 weeks will have a comment posted to them. If the author does not reply within the next week, then the issue will be marked as stale and closed. The original author may still reopen the issue at any time
**Close Potential Spam Issues** <br/>[![issue-spam-control.yml](https://github.com/Lissy93/dashy/actions/workflows/issue-spam-control.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/issue-spam-control.yml) | Auto-closes issues, and adds a comment if it was submitted by a user who hasn't yet interacted with the repo, is new to GitHub and has not starred the repository. The comment will advise them to check their issue is complete, and then allow them to reopen it
**Issue Translator** <br/>[![issue-translator.yml](https://github.com/Lissy93/dashy/actions/workflows/issue-translator.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/issue-translator.yml) | Auto-translates any comments and issues that were written in any language other than English, and posts the translation as a comment below
**Label Sponsors** <br/>[![label-sponsors.yml](https://github.com/Lissy93/dashy/actions/workflows/label-sponsors.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/label-sponsors.yml) | Adds a special label to any issues or pull requests raised by users who are sponsoring the project via GitHub, so that they can get priority support
**LGTM Comment**<br/>[![lgtm-comment.yml](https://github.com/Lissy93/dashy/actions/workflows/lgtm-comment.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/lgtm-comment.yml) | When a PR review contains the words LGTM (looks good to me), the Liss-Bot will reply with a random celebratory or thumbs up GIF, just as a bit of fun
**Mind your Language** <br/>[![mind-your-language.yml](https://github.com/Lissy93/dashy/actions/workflows/mind-your-language.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/mind-your-language.yml) | Replies to any comment (on issue or PR) that contains profanities, offensive or inappropriate language with a polite note reminding the user of the code of conduct
**Release Notifier** <br/>[![release-commenter.yml](https://github.com/Lissy93/dashy/actions/workflows/release-commenter.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/release-commenter.yml) | Once a release has been published which fixes an issue, a comment will be added to the relevant issues informing the user who raised it that it was fixed in the current release
**Update Issue after Merge** <br/>[![update-issue-after-pr.yml](https://github.com/Lissy93/dashy/actions/workflows/update-issue-after-pr.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/update-issue-after-pr.yml) | After a PR which fixes an issue is merged, Liss-Bot will add a comment to said issue based on the git commit message
**Auto Add Comment Based on Tag** <br/>[![add-comment-from-tag.yml](https://github.com/Lissy93/dashy/actions/workflows/add-comment-from-tag.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/add-comment-from-tag.yml) | Will add comment with useful info to certain issues, based on the tag applied
### PR Management
Action | Description
--- | ---
**PR Commenter** <br/>[![pr-commenter.yml](https://github.com/Lissy93/dashy/actions/workflows/pr-commenter.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/pr-commenter.yml) | Adds comment with helpful info to pull requests, based on which files have been changes
**Issue from Todo Code** <br/>[![raise-issue-from-todo.yml](https://github.com/Lissy93/dashy/actions/workflows/raise-issue-from-todo.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/raise-issue-from-todo.yml) | When a `todo` note is found in the code after a PR, then Liss-Bot will automatically raise an issue, so that the todo can be addressed/ implemented. The issue will be closed once the todo has been implemented or removed
### Documentation & Reports
Action | Description
--- | ---
**Generate Credits** <br/>[![generate-credits.yml](https://github.com/Lissy93/dashy/actions/workflows/generate-credits.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/generate-credits.yml) | Generates a report, including contributors, collaborators, sponsors, bots and helpful users. Will then insert a markdown table with thanks to these GitHub users and links to their profiles into the Credits page, as well as a summary of sponsors and top contributors into the main readme
**Wiki Sync** <br/>[![wiki-sync.yml](https://github.com/Lissy93/dashy/actions/workflows/wiki-sync.yml/badge.svg)](https://github.com/Lissy93/dashy/actions/workflows/wiki-sync.yml) | Generates and publishes the repositories wiki page using the markdown files within the docs directory
---

120
docs/searching.md Normal file
View File

@@ -0,0 +1,120 @@
# Keyboard Shortcuts
## Searching
One of the primary purposes of Dashy is to allow you to quickly find and launch a given app. To make this as quick as possible, there is no need to touch the mouse, or press a certain key to begin searching - just start typing. Results will be filtered in real-time. No need to worry about case, special characters or small typos, these are taken care of, and your results should appear.
## Navigating
You can navigate through your items or search results using the keyboard. You can use <kbd>Tab</kbd> to cycle through results, and <kbd>Shift</kbd> + <kbd>Tab</kbd> to go backwards. Or use the arrow keys, <kbd>↑</kbd>, <kbd>→</kbd>, <kbd>↓</kbd> and <kbd>←</kbd>.
## Launching Apps
You can launch a elected app by hitting <kbd>Enter</kbd>. This will open the app using your default opening method, specified in `target` (either `newtab`, `sametab`, `modal`, `top` or `workspace`). You can also use <kbd>Alt</kbd> + <kbd>Enter</kbd> to open the app in a pop-up modal, or <kbd>Ctrl</kbd> + <kbd>Enter</kbd> to open it in a new tab. For all available opening methods, just right-click on an item, to bring up the context menu.
## Tags
By default, items are filtered by the `title` attribute, as well as the hostname (extracted from `url`), the `provider` and `description`. If you need to find results based on text which isn't included in these attributes, then you can add `tags` to a given item.
```yaml
items:
- title: Plex
description: Media library
icon: favicon
url: https://plex.lab.local
tags: [ movies, videos, music ]
- title: FreshRSS
description: RSS Reader
icon: favicon
url: https://freshrss.lab.local
tags: [ news, updates, blogs ]
```
In the above example, Plex will be visible when searching for 'movies', and FreshRSS with 'news'
## Custom Hotkeys
For apps that you use regularly, you can set a custom keybinding. Use the `hotkey` parameter on a certain item to specify a numeric key, between `0 - 9`. You can then launch that app, by just pressing that key, which is much quicker than searching for it, if it's an app you use frequently.
```yaml
- title: Bookstack
icon: far fa-books
url: https://bookstack.lab.local/
hotkey: 2
- title: Git Tea
icon: fab fa-git
url: https://git.lab.local/
target: workspace
hotkey: 3
```
In the above example, pressing <kbd>2</kbd> will launch Bookstack. Or hitting <kbd>3</kbd> will open Git in the workspace view.
## Web Search
It's possible to search the web directly from Dashy, which might be useful if you're using Dashy as your start page. This can be done by typing your query as normal, and then pressing <kbd>⏎</kbd>. Web search options are configured under `appConfig.webSearch`.
### Setting Search Engine
Set your default search engine using the `webSearch.searchEngine` property. This defaults to DuckDuckGo. Search engine must be referenced by their key, the following providers are supported:
- [`duckduckgo`](https://duckduckgo.com), [`google`](https://google.com), [`whoogle`](https://whoogle.sdf.org), [`qwant`](https://www.qwant.com), [`startpage`](https://www.startpage.com), [`searx-bar`](https://searx.bar), [`searx-info`](https://searx.info)
- [`searx-tiekoetter`](https://searx.tiekoetter.com), [`searx-bissisoft`](https://searx.bissisoft.com), [`ecosia`](https://www.ecosia.org), [`metager`](https://metager.org/meta), [`swisscows`](https://swisscows.com), [`mojeek`](https://www.mojeek.com)
- [`wikipedia`](https://en.wikipedia.org), [`wolframalpha`](https://www.wolframalpha.com), [`stackoverflow`](https://stackoverflow.com), [`github`](https://github.com), [`reddit`](https://www.reddit.com), [`youtube`](https://youtube.com), [`bbc`](https://www.bbc.co.uk)
### Using Custom Search Engine
You can also use a custom search engine, that isn't included in the above list (like a self-hosted instance of [Whoogle](https://github.com/benbusby/whoogle-search) or [Searx](https://searx.github.io/searx/)). Set `searchEngine: custom`, and then specify the URL (plus query params) to you're search engine under `customSearchEngine`.
For example:
```yaml
appConfig:
webSearch:
searchEngine: custom
customSearchEngine: 'https://searx.local/search?q='
```
### Setting Opening Method
In a similar way to opening apps, you can specify where you would like search results to be opened. This is done under the `openingMethod` attribute, and can be set to either `newtab`, `sametab` or `workspace`. By default results are opened in a new tab.
### Using Bangs
An insanely useful feature of DDG is [Bangs](https://duckduckgo.com/bang), where you type a specific character combination at the start of your search query, and it will be redirected the that website, such as '!w Docker' will display the Docker wikipedia page. Dashy has a similar feature, enabling you to define your own custom bangs to redirect search results to a specific app, website or search engine.
This is done under the `searchBangs` property, with a list of key value pairs. The key is what you will type, and the value is the destination, either as an identifier or a URL with query parameters.
For example:
```yaml
appConfig:
webSearch:
searchEngine: 'duckduckgo'
openingMethod: 'newtab'
searchBangs:
/r: reddit
/w: wikipedia
/s: https://whoogle.local/search?q=
/a: https://www.amazon.co.uk/s?k=
':wolf': wolframalpha
':so': stackoverflow
':git': github
```
Note that bangs begging with `!` or `:` must be surrounded them in quotes
### Disabling Web Search
Web search can be disabled, by setting `disableWebSearch`, for example:
```yaml
appConfig:
webSearch: { disableWebSearch: true }
```
## Clearing Search
You can clear your search term at any time, resting the UI to it's initial state, by pressing <kbd>Esc</kbd>.
This can also be used to close any open pop-up modals.

252
docs/showcase.md Normal file
View File

@@ -0,0 +1,252 @@
# *Dashy Showcase* 🌟
| 💗 Got a sweet dashboard? Submit it to the showcase! 👉 [See How](#submitting-your-dashboard) |
|-|
## Home Lab 2.0
![screenshot-homelab](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/1-home-lab-material.png)
---
## Dipan's Dash
> By [@Dipanghosh](https://github.com/dipanghosh) - [dipan.de](https://dipan.de/) <sup>Re: [#777](https://github.com/Lissy93/dashy/discussions/777)</sup>
> With the option of embedding iframes, it becomes possible to combine and conquer. I have set up Dashy to include graphs from grafana, and set them so that they update automatically. I also have uptime monitors from uptime Kuma, panels from homeassistant are also possible to be included.<br>
> Dashy is awesome!
![screenshot-dipanghosh-dashboard](https://i.ibb.co/bPC6w2n/dipanghosh-dashboard.png)
---
## Ratty222
> By [@ratty222](https://github.com/ratty222) <sup>Re: [#384](https://github.com/Lissy93/dashy/discussions/384)</sup>
![screenshot-ratty222-dashy](https://user-images.githubusercontent.com/1862727/147582551-4c655d37-8bcc-4f95-ab41-164a9d0d6a07.png)
---
## Hugalafutro Dashy
> By [@hugalafutro](https://github.com/hugalafutro) <sup>Re: [#505](https://github.com/Lissy93/dashy/discussions/505)</sup>
[![hugalafutro-dashy-screenshot](https://i.ibb.co/PDpLDKS/hugalafutro-dashy.gif)](https://i.ibb.co/PDpLDKS/hugalafutro-dashy.gif)
---
## NAS Home Dashboard
> By [@cerealconyogurt](https://github.com/cerealconyogurt) <sup>Re: [#74](https://github.com/Lissy93/dashy/issues/74)</sup>
![screenshot-networking-services](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/6-nas-home-dashboard.png)
---
## Brewhack
> By [@brpeterso](https://github.com/brpeterso) <sup>Re: [#680](https://github.com/Lissy93/dashy/issues/680)</sup>
![screenshot-brewhack-dashboard](https://i.ibb.co/cNjzPT4/brewhack.png)
---
## The Dragons Lair
> By [dr460nf1r3](https://github.com/dr460nf1r3) <sup>via [#684](https://github.com/Lissy93/dashy/issues/684)</sup>
> My new startpage featuring the stuff I use most. And of course dragons!
![screenshot-dragons-lair](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/13-dragons-lair.png)
---
## Homelab & VPS dashboard
> By [@shadowking001](https://github.com/shadowking001) <sup>Re: [#86](https://github.com/Lissy93/dashy/issues/86)</sup>
![screenshot-shadowking001-dashy](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/8-shadowking001s-dashy.png)
---
## Raspberry PI Docker Dashboard
> By [@henkiewie](https://github.com/henkiewie) <sup>Re: [#622](https://github.com/Lissy93/dashy/issues/622)</sup>
> I use this dashboard every day. It now even includes a player for a radio stream which I configured with Logitech media server and icecast. I made an smaller version of the grafana dashboard to fit an iframe in kiosk mode, so it monitors the most important values of my RPI. The PI is in Argon m2 case and used as a NAS. The dashboard is a copy of the adventure theme with some changes saved in `/app/src/styles/user-defined-themes.scss`
![screenshot-henkiewie-dashy](https://i.ibb.co/jGzPm6b/henkiewie-dashy-showcase.png)
---
## First Week of Self-Hosting
> By [u//RickyCZ](https://www.reddit.com/user/RickyCZ) <sup>via [Reddit](https://www.reddit.com/r/selfhosted/comments/pose15/just_got_started_a_week_ago_selfhosting_is_very/)</sup>
![screenshot-week-of-self-hosting](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/11-ricky-cz.png)
---
## EVO Dashboard
> By [@EVOTk](https://github.com/EVOTk) <sup>Re: [#316](https://github.com/Lissy93/dashy/pull/316)</sup>
![screenshot-evo-dashboard](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/12-evo-dashboard.png)
---
## The Private Dashboard
> By [@DylanBeMe](https://github.com/DylanBeMe) <sup>Re: [#419](https://github.com/Lissy93/dashy/issues/419)</sup>
![screenshot-private-dashboard](https://i.ibb.co/hKS483T/private-dashboard-Dylan-Be-Me.png)
---
## Networking Services
> By [@Lissy93](https://github.com/lissy93)
![screenshot-networking-services](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/2-networking-services-minimal-dark.png)
---
## Dashy Live
> By [@Lissy93](https://github.com/lissy93)
> A dashboard I made to manage all project development links from one place. View demo at [live.dashy.to](https://live.dashy.to/).
![screenshot-dashy-live](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/10-dashy-live.png)
---
## System Monitor
> An aggregated board for monitoring system resource usage from a single view
![screenshot-monitor](https://i.ibb.co/xfK6BGb/system-monitor-board.png)
---
## Browser Startpage
![screenshot-startpage](https://i.ibb.co/rs07dS1/startpage.png)
---
## CFT Toolbox
![screenshot-cft-toolbox](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/3-cft-toolbox.png)
---
## Bookmarks
![screenshot-bookmarks](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/4-bookmarks-colourful.png)
---
## Project Management
![screenshot-project-management](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/5-project-management.png)
---
## Dashy Example
> An example dashboard, by [@Lissy93](https://github.com/lissy93). View live at [demo.dashy.to](https://demo.dashy.to/).
![screenshot-dashy-example](https://i.ibb.co/YbzqPK7/demo-dashy.png)
---
## HomeLAb 3.0
> By [@skoogee](https://github.com/skoogee) (<http://zhrn.cc>) <sup>[#279](https://github.com/Lissy93/dashy/issues/279)</sup>
> Dashy, is the most complete dashboard I ever tried, has all the features, and it sets itself apart from the rest. It is my default homepage now. I am thankful to the developer @Lissy93 for sharing such a wonderful creation.
[![screenshot-12-skoogee-homelab-3](https://i.ibb.co/F5yBTsT/12-skoogee-homelab-3.png?)](https://ibb.co/album/ynSwzm)
---
## Ground Control
> By [@dtctek](https://github.com/dtctek) <sup>Re: [#83](https://github.com/Lissy93/dashy/issues/83)</sup>
![screenshot-ground-control](https://user-images.githubusercontent.com/1862727/149821995-e9b41dab-186c-42e6-b5b3-e233259b241d.png)
---
## Croco_Grievous
> By [u/Croco_Grievous](https://www.reddit.com/user/Croco_Grievous/) <sup>via [reddit](https://www.reddit.com/r/selfhosted/comments/t4xk3z/everything_started_with_pihole_on_a_raspberry_pi/)</sup>
![screenshot-croco-grievous-dashy](https://i.ibb.co/59XR8KL/dashy-Croco-Grievous.png)
---
## Crypto Dash
> Example usage of widgets to monitor cryptocurrencies news, prices and data. Config is [available here](https://gist.github.com/Lissy93/000f712a5ce98f212817d20bc16bab10#file-example-8-dashy-crypto-widgets-conf-yml)
![screenshot-crypto-dash](https://user-images.githubusercontent.com/1862727/147394584-352fe3bf-740d-4624-a01b-9003a97bc832.png)
---
## Stefantigro
> By [u/stefantigro](https://www.reddit.com/user/stefantigro/) <sup>via [reddit](https://www.reddit.com/r/selfhosted/comments/t5oril/been_selfhosting_close_to_half_a_year_now_all/)</sup>
![screenshot-stefantigro-dashy](https://i.ibb.co/1Kb43Yy/dashy-stefantigro.png)
---
## Morning Dashboard
> Displayed on my smart screen between 05:00 - 08:00, and includes all the info that I usually check before leaving for work
![screenshot-morning-dash](https://i.ibb.co/4Wx8zb7/morning-dashboard.png)
---
## Yet Another Homelab
![screenshot-yet-another-homelab](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/showcase/9-home-lab-oblivion.png)
---
## Submitting your Dashboard
### How to Submit
- [Open an Issue](https://git.io/JEtgM)
- [Open a PR](https://github.com/Lissy93/dashy/compare)
### What to Include
Please include the following information:
- A single high-quality screenshot of your Dashboard
- A short title (it doesn't have to be particularly imaginative)
- An optional description, you could include details on anything interesting or unique about your dashboard, or say how you use it, and why it's awesome
- Optionally leave your name or username, with a link to your GitHub, Twitter or Website
### Template
If you're submitting a pull request, please use a format similar to this:
```text
### [Dashboard Name] (required)
> Submitted by [@username](https://github.com/user) (optional)
[An optional text description, or any interesting details] (optional)
![dashboard-screenshot](https://example.com/url-to-screenshot.png) (required)
---
```

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

2
docs/showcase/readme.md Normal file
View File

@@ -0,0 +1,2 @@
See: [Showcase](/docs/showcase.md).

109
docs/status-indicators.md Normal file
View File

@@ -0,0 +1,109 @@
# Status Indicators
Dashy has an optional feature that can display a small icon next to each of your running services, indicating it's current status. This can be useful if you are using Dashy as your homelab's start page, as it gives you an overview of the health of each of your running services. The status feature will show response time, response code, online/ offline check and if applicable, a relevant error message.
<p align="center">
<img width="800" src="/docs/assets/status-check-demo.gif" />
</p>
## Enabling Status Indicators
By default, this feature is off. If you do not want this feature, just don't add the `statusCheck` to your conf.yml file, then no requests will be made.
To enable status checks, you can either turn it on for all items, by setting `appConfig.statusCheck: true`, like:
```yaml
appConfig:
statusCheck: true
```
Or you can enable/ disable it on a per-item basis, with the `item[n].statusCheck` attribute
```yaml
sections:
- name: Firewall
items:
- title: OPNsense
description: Firewall Central Management
icon: networking/opnsense.png
url: https://192.168.1.1
statusCheck: false
- title: MalTrail
description: Malicious traffic detection system
icon: networking/maltrail.png
url: http://192.168.1.1:8338
statusCheck: true
- title: Ntopng
description: Network traffic probe and network use monitor
icon: networking/ntop.png
url: http://192.168.1.1:3001
statusCheck: true
```
## Continuous Checking
By default, with status indicators enabled Dashy will check an applications status on page load, and will not keep indicators updated. This is usually desirable behavior. However, if you do want the status indicators to continue to poll your running services, this can be enabled by setting the `statusCheckInterval` attribute. Here you define an interval as an integer in seconds, and Dashy will poll your apps every x seconds. Note that if this number is very low (below 5 seconds), you may notice the app running slightly slower.
The following example, will instruct Dashy to continuously check the status of your services every 20 seconds.
```text
appConfig:
statusCheck: true
statusCheckInterval: 20
```
## Using a Different Endpoint
By default, the status checker will use the URL of each application being checked. In some situations, you may want to use a different endpoint for status checking. Similarly, some services provide a dedicated path for uptime monitoring.
You can set the `statusCheckUrl` property on any given item in order to do this. The status checker will then ping that endpoint, instead of the apps main `url` property.
## Setting Custom Headers
If your service is responding with an error, despite being up and running, it is most likely because custom headers for authentication, authorization or encoding are required. You can define these headers under the `statusCheckHeaders` property for any service. It should be defined as an object format, with the name of header as the key, and header content as the value.
For example, `statusCheckHeaders: { 'X-Custom-Header': 'foobar' }`
## Disabling Security
By default, (if you're using HTTPS) any requests to insecure or non-HTTPS content will be blocked. This will cause the status check to fail. If you trust the endpoint (e.g. you're self-hosting it), then you can disable this security measure for an individual item. This is done by setting `statusCheckAllowInsecure: true`
## Allowing Alternative Status Codes
If you expect your service to return a status code that is not in the 2XX range, and still want the indicator to be green, then you can specify an expected status code under `statusCheckAcceptCodes` for a given item. For example, `statusCheckAcceptCodes: '403,418'`
## Troubleshooting Failing Status Checks
If you're using status checks, and despite a given service being online, the check is displaying an error, there are a couple of things you can look at:
If your service requires requests to include any authorization in the headers, then use the `statusCheckHeaders` property, as described [above](#setting-custom-headers).
If you are still having issues, it may be because your target application is blocking requests from Dashy's IP. This is a [CORS error](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), and can be fixed by setting the headers on your target app, to include:
```text
Access-Control-Allow-Origin: https://location-of-dashy/
Vary: Origin
```
If the URL you are checking has an unsigned certificate, or is not using HTTPS, then you may need to disable the rejection of insecure requests. This can be done by setting `statusCheckAllowInsecure` to true for a given item.
If your service is online, but responds with a status code that is not in the 2xx range, then you can use `statusCheckAcceptCodes` to set an accepted status code.
If you get an error, like `Service Unavailable: Server resulted in a fatal error`, even when it's definitely online, this is most likely caused by missing the protocol. Don't forget to include `https://` (or whatever protocol) before the URL, and ensure that if needed, you've specified the port.
Running Dashy in HOST network mode, instead of BRIDGE will allow status check access to other services in HOST mode. For more info, see [#445](https://github.com/Lissy93/dashy/discussions/445).
If you have firewall rules configured, then ensure that they don't prevent Dashy from making requests to the other services you are trying to access.
Currently, the status check needs a page to be rendered, so if this URL in your browser does not return anything, then status checks will not work. This may be modified in the future, but in the meantime, a fix would be to make your own status service, which just checks if your app responds with whatever code you'd like, and then return a 200 plus renders an arbitrary message. Then just point `statusCheckUrl` to your custom page.
For further troubleshooting, use an application like [Postman](https://postman.com) to diagnose the issue. Set the parameter to `GET`, and then make a call to: `https://[url-of-dashy]/status-check/?&url=[service-url]`. Where the service URL must have first been encoded (e.g. with `encodeURIComponent()` or [urlencoder.io](https://www.urlencoder.io/))
If you're serving Dashy though a CDN, instead of using the Node server or Docker image, then the Node endpoint that makes requests will not be available to you, and all requests will fail. A workaround for this may be implemented in the future, but in the meantime, your only option is to use the Docker or Node deployment method.
## How it Works
When the app is loaded, if `appConfig.statusCheck: true` is set, or if any items have the `statusCheck: true` enabled, then Dashy will make a request, to `https://[your-host-name]/status-check?url=[address-or-servce]` (may al include GET params for headers and the secure flag), which in turn will ping that running service, and respond with a status code. Response time is calculated from the difference between start and end time of the request.
When the response completes, an indicator will display next to each item. The color denotes the status: Yellow while waiting for the response to return, green if request was successful, red if it failed, and grey if it was unable to make the request all together.
All requests are made straight from your server, there is no intermediary. So providing you are hosting Dashy yourself, and are checking the status of other self-hosted services, there shouldn't be any privacy concerns. Requests are made asynchronously, so this won't have any significant impact on page load speeds. However recurring requests (using `statusCheckInterval`) may run more slowly if the interval between requests is very short.

199
docs/theming.md Normal file
View File

@@ -0,0 +1,199 @@
# Theming
By default Dashy comes with 25+ built-in themes, which can be applied from the dropdown menu in the UI.
![Built-in Themes](https://i.ibb.co/GV3wRss/Dashy-Themes.png)
You can also add your own themes, apply custom styles, and modify colors.
You can customize Dashy by writing your own CSS, which can be loaded either as an external stylesheet, set directly through the UI, or specified in the config file. Most styling options can be set through CSS variables, which are outlined below.
The following content requires that you have a basic understanding of CSS. If you're just beginning, you may find [this article](https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps) helpful.
## How Theme-Switching Works
The theme switching is done by simply changing the `data-theme` attribute on the root DOM element, which can then be targeted by CSS. First off, in order for the theme to show up in the theme switcher, it needs to be added to the config file, under `appConfig.cssThemes`, either as a string, or an array of strings for multiple themes. For example:
```yaml
appConfig:
cssThemes: ['tiger', 'another-theme']
```
You can now create a block to target you're theme with `html[data-theme='my-theme']{}` and set some styles. The easiest method is by setting CSS variables, but you can also directly override elements by their selector. As an example, see the [built-in CSS themes](https://github.com/Lissy93/dashy/blob/master/src/styles/color-themes.scss).
```css
html[data-theme='tiger'] {
--primary: #f58233;
--background: #0b1021;
}
```
Finally, from the UI use the theme dropdown menu to select your new theme, and your styles will be applied.
You can also set `appConfig.theme` to pre-select a default theme, which will be applied immediately after deployment.
## Modifying Theme Colors
Themes can be modified either through the UI, using the color picker menu (to the right of the theme dropdown), or directly in the config file, under `appConfig.customColors`. Here you can specify the value for any of the [available CSS variables](#css-variables).
<p align="center">
<a href="https://i.ibb.co/cLDXj1R/dashy-theme-configurator.gif">
<img alt="Example Themes" src="https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/theme-config-demo.gif" width="400" />
</a>
</p>
By default, any color modifications made to the current theme through the UI will only be applied locally. If you need these settings to be set globally, then click the 'Export' button, to get the color codes and variable names, which can then be backed up, or saved in your config file.
Custom colors are saved relative the the base theme selected. So if you switch themes after setting custom colors, then you're settings will no longer be applied. You're changes are not lost though, and switching back to the original theme will see your styles reapplied.
If these values are specified in your `conf.yml` file, then it will look something like the below example. Note that in YAML, values or keys which contain special characters, must be wrapped in quotes.
```yaml
appConfig:
customColors:
oblivion:
primary: '#75efff'
background: '#2a3647'
dracula:
primary: '#8be9fd'
```
## Adding your own Theme
User-defined styles and custom themes should be defined in `./src/styles/user-defined-themes.scss`. If you're using Docker, you can pass your own stylesheet in using the `--volume` flag. E.g. `v ./my-themes.scss:/app/src/styles/user-defined-themes.scss`. Don't forget to pass your theme name into `appConfig.cssThemes` so that it shows up on the theme-switcher dropdown.
## Setting Custom CSS in the UI
Custom CSS can be developed, tested and applied directly through the UI. Although you will need to make note of your changes to apply them across instances.
This can be done from the Config menu (spanner icon in the top-right), under the Custom Styles tab. This is then associated with `appConfig.customCss` in local storage. Styles can also be directly applied to this attribute in the config file, but this may get messy very quickly if you have a lot of CSS.
## Page-Specific Styles
If you've got multiple pages within your dashboard, you can choose to target certain styles to specific pages. The top-most element within `<body>` will have a class name specific to the current sub-page. This is usually the page's name, all lowercase, with dashes instead of spaces, but you can easily check this yourself within the dev tools.
For example, if the pages name was "CFT Toolbox", and you wanted to target `.item`s, you would do:
```css
.cft-toolbox .item { border: 4px solid yellow; }
```
## Loading External Stylesheets
The URI of a stylesheet, either local or hosted on a remote CDN can be passed into the config file. The attribute `appConfig.externalStyleSheet` accepts either a string, or an array of strings. You can also pass custom font stylesheets here, they must be in a CSS format (for example, `https://fonts.googleapis.com/css2?family=Cutive+Mono`).
This is handled in [`ThemeHelper.js`](https://github.com/Lissy93/dashy/blob/master/src/utils/ThemeHelper.js).
For example:
```yaml
appConfig:
externalStyleSheet: 'https://example.com/my-stylesheet.css'
```
```yaml
appConfig:
externalStyleSheet: ['/themes/my-theme-1.css', '/themes/my-theme-2.css']
```
## Hard-Coding Section or Item Colors
Some UI components have a color option, that can be set in the config file, to force the color of a given item or section no matter what theme is selected. These colors should be expressed as hex codes (e.g. `#fff`) or HTML colors (e.g. `red`). The following attributes are supported:
- `section.color` - Custom color for a given section
- `item.color` - Font and icon color for a given item
- `item.backgroundColor` - Background color for a given icon
## Typography
Essential fonts bundled within the app are located within `./src/assets/fonts/`. All optional fonts that are used by themes are stored in `./public/fonts/`, if you want to add your own font, this is where you should put it. As with assets, if you're using Docker then using a volume to link a directory on your host system with this path within the container will make management much easier.
Fonts which are not being used by the current theme are **not** fetched on page load. They are instead only loaded into the application if and when they are required. So having multiple themes with various typefaces shouldn't have any negative impact on performance.
Full credit to the typographers behind each of the included fonts. Specifically: Matt McInerney, Christian Robertson, Haley Fiege, Peter Hull, Cyreal and the legendary Vernon Adams
## CSS Variables
All colors as well as other variable values (such as borders, border-radius, shadows) are specified as CSS variables. This makes theming the application easy, as you only need to change a given color or value in one place. You can find all variables in [`color-palette.scss`](https://github.com/Lissy93/dashy/blob/master/src/styles/color-palette.scss) and the themes which make use of these color variables are specified in [`color-themes.scss`](https://github.com/Lissy93/dashy/blob/master/src/styles/color-themes.scss)
CSS variables are simple to use. You define them like: `--background: #fff;` and use them like: `body { background-color: var(--background); }`. For more information, see this guide on using [CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties).
You can determine the variable used by any given element, and visualize changes using the browser developer tools (Usually opened with `F12`, or Options --> More --> Developer Tools). Under the elements tab, click the Element Selector icon (usually top-left corner), you will then be able to select any DOM element on the page by hovering and clicking it. In the CSS panel you will see all styles assigned to that given element, including CSS variables. Click a variable to see it's parent value, and for color attributes, click the color square to modify the color. For more information, see this [getting started guide](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools), and these articles on [selecting elements](https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Select_an_element) and [inspecting and modifying colors](https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Inspect_and_select_colors).
### Top-Level Variables
These are all that are required to create a theme. All other variables inherit their values from these variables, and can optionally be overridden.
- `--primary` - Application primary color. Used for title, text, accents, and other features
- `--background` - Application background color
- `--background-darker` - Secondary background color (usually darker), used for navigation bar, section fill, footer etc
- `--curve-factor` - The border radius used globally throughout the application. Specified in `px`, defaults to `5px`
- `--dimming-factor` - Inactive elements have slight transparency. This can be between `0` (invisible) and `1` (normal), defaults to `0.7`
### Targeted Color Variables
You can target specific elements on the UI with these variables. All are optional, since by default, they inherit their values from above
- `--heading-text-color` - Text color for web page heading and sub-heading. Defaults to `--primary`
- `--nav-link-text-color` - The text color for links displayed in the navigation bar. Defaults to `--primary`
- `--nav-link-background-color` - The background color for links displayed in the navigation bar
- `--nav-link-text-color-hover` - The text color when a navigation bar link is hovered over. Defaults to `--primary`
- `--nav-link-background-color-hover` - The background color for nav bar links when hovered over
- `--nav-link-border-color` - The border color for nav bar links. Defaults to `transparent`
- `--nav-link-border-color-hover` - The border color for nav bar links when hovered over. Defaults to `--primary`
- `--search-container-background` - Background for the container containing the search bar. Defaults to `--background-darker`
- `--search-field-background` - Fill color for the search bar. Defaults to `--background`
- `--settings-background` - The background for the quick settings. Defaults to `--background`
- `--settings-text-color` - The text and icon color for quick settings. Defaults to `--primary`
- `--footer-text-color` - Color for text within the footer. Defaults to `--medium-grey`
- `--footer-text-color-link` - Color for any hyperlinks within the footer. Defaults to `--primary`
- `--item-text-color` - The text and icon color for items. Defaults to `--primary`
- `--item-group-outer-background` - The background color for the outer part of a section (including section head). Defaults to `--primary`
- `--item-group-background` - The background color for the inner part of item groups. Defaults to `#0b1021cc` (semi-transparent black)
- `--item-group-heading-text-color` - The text color for section headings. Defaults to `--item-group-background`;
- `--item-group-heading-text-color-hover` - The text color for section headings, when hovered. Defaults to `--background`
- `--config-code-background` - Background color for the JSON editor in the config menu. Defaults to `#fff` (white)
- `--config-code-color` - Text color for the non-highlighted code within the JSON editor. Defaults to `--background`
- `--config-settings-color` - The background for the config/ settings pop-up modal. Defaults to `--primary`
- `--config-settings-background` - The text color for text within the settings container. Defaults to `--background-darker`
- `--scroll-bar-color` - Color of the scroll bar thumb. Defaults to `--primary`
- `--scroll-bar-background` Color of the scroll bar blank space. Defaults to `--background-darker`
- `--highlight-background` Fill color for text highlighting. Defaults to `--primary`
- `--highlight-color` Text color for selected/ highlighted text. Defaults to `--background`
- `--toast-background` - Background color for the toast info popup. Defaults to `--primary`
- `--toast-color` - Text, icon and border color in the toast info popup. Defaults to `--background`
- `--welcome-popup-background` - Background for the info pop-up shown on first load. Defaults to `--background-darker`
- `--welcome-popup-text-color` - Text color for the welcome pop-up. Defaults to `--primary`
- `--side-bar-background` - Background color of the sidebar used in the workspace view. Defaults to `--background-darker`
- `--side-bar-color` - Color of icons and text within the sidebar. Defaults to `--primary`
- `--status-check-tooltip-background` - Background color for status check tooltips. Defaults to `--background-darker`
- `--status-check-tooltip-color` - Text color for the status check tooltips. Defaults to `--primary`
- `--code-editor-color` - Text color used within raw code editors. Defaults to `--black`
- `--code-editor-background` - Background color for raw code editors. Defaults to `--white`
- `--context-menu-color` - Text color for right-click context menu over items. Defaults to `--primary`
- `--context-menu-background` - Background color of right-click context menu. Defaults to `--background`
- `--context-menu-secondary-color` - Border and outline color for context menu. Defaults to `--background-darker`
### Non-Color Variables
- `--outline-color` - Used to outline focused or selected elements
- `--curve-factor-navbar` - The border radius of the navbar. Usually this is greater than `--curve-factor`
- `--scroll-bar-width` - Width of horizontal and vertical scroll bars. E.g. `8px`
- `--item-group-padding` - Inner padding of sections, determines the width of outline. E.g. `5px`
- `--item-shadow` - Shadow for items. E.g. `1px 1px 2px #130f23`
- `--item-hover-shadow` - Shadow for items when hovered over. E.g. `1px 2px 4px #373737`
- `--item-icon-transform` - A [transform](https://developer.mozilla.org/en-US/docs/Web/CSS/transform) property, to modify item icons. E.g. `drop-shadow(2px 4px 6px var(--transparent-50)) saturate(0.65)`
- `--item-icon-transform-hover` - Same as above, but applied when an item is hovered over. E.g. `drop-shadow(4px 8px 3px var(--transparent-50)) saturate(2)`
- `--item-group-shadow` - The shadow for an item group/ section. Defaults to `--item-shadow`
- `--settings-container-shadow` - A shadow property for the settings container. E.g. `none`
### Action Colors
These colors represent intent, and so are not often changed, but you can do so if you wish
- `--info` - Information color, usually blue / `#04e4f4`
- `--success` - Success color, usually green / `#20e253`
- `--warning` - Warning color, usually yellow / `#f6f000`
- `--danger` - Error/ danger color, usually red / `#f80363`
- `--neutral` - Neutral color, usually grey / `#272f4d`
- `--white` - Just white / `#fff`
- `--black` - Just black / `#000`

628
docs/troubleshooting.md Normal file
View File

@@ -0,0 +1,628 @@
# Troubleshooting
> _**This document contains common problems and their solutions.**_<br>
> Please ensure your issue isn't listed here, before opening a new ticket.
>
> _Found something not listed here? Consider adding it, to help other users._
## Contents
- [Refused to Connect in Web Content View](#refused-to-connect-in-modal-or-workspace-view)
- [404 On Static Hosting](#404-on-static-hosting)
- [404 from Mobile Home Screen](#404-after-launch-from-mobile-home-screen)
- [Yarn Build or Run Error](#yarn-error)
- [Remote Config Not Loading](#remote-config-not-loading)
- [Heap limit Allocation failed](#ineffective-mark-compacts-near-heap-limit-allocation-failed)
- [Command failed with signal "SIGKILL"](#command-failed-with-signal-sigkill)
- [Auth Validation Error: "should be object"](#auth-validation-error-should-be-object)
- [App Not Starting After Update to 2.0.4](#app-not-starting-after-update-to-204)
- [Keycloak Redirect Error](#keycloak-redirect-error)
- [Docker Directory Error](#docker-directory)
- [Config Not Updating](#config-not-updating)
- [Config Still not Updating](#config-still-not-updating)
- [Styles and Assets not Updating](#styles-and-assets-not-updating)
- [DockerHub toomanyrequests](#dockerhub-toomanyrequests)
- [Config Validation Errors](#config-validation-errors)
- [Node Sass unsupported environment](#node-sass-does-not-yet-support-your-current-environment)
- [Unreachable Code Error](#unreachable-code-error)
- [Cannot find module './_baseValues'](#error-cannot-find-module-_basevalues)
- [Ngrok Invalid Host Headers](#invalid-host-header-while-running-through-ngrok)
- [Warnings in the Console during deploy](#warnings-in-the-console-during-deploy)
- [Docker Login Fails on Ubuntu](#docker-login-fails-on-ubuntu)
- [Status Checks Failing](#status-checks-failing)
- [Diagnosing Widget Errors](#widget-errors)
- [Fixing Widget CORS Errors](#widget-cors-errors)
- [Widget Shows Error Incorrectly](#widget-shows-error-incorrectly)
- [Weather Forecast Widget 401](#weather-forecast-widget-401)
- [Widget Displaying Inaccurate Data](#widget-displaying-inaccurate-data)
- [Font Awesome Icons not Displaying](#font-awesome-icons-not-displaying)
- [Copy to Clipboard not Working](#copy-to-clipboard-not-working)
- [Unsupported Digital Envelope Routines](#unsupported-digital-envelope-routines)
- [How to Reset Local Settings](#how-to-reset-local-settings)
- [How to make a bug report](#how-to-make-a-bug-report)
- [How-To Open Browser Console](#how-to-open-browser-console)
- [Git Contributions not Displaying](#git-contributions-not-displaying)
---
## `Refused to Connect` in Modal or Workspace View
This is not an issue with Dashy, but instead caused by the target app preventing direct access through embedded elements.
As defined in [RFC-7034](https://datatracker.ietf.org/doc/html/rfc7034), for any web content to be accessed through an embedded element, it must have the [`X-Frame-Options`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) HTTP header set to `ALLOW`. If you are getting a `Refused to Connect` error then this header is set to `DENY` (or `SAMEORIGIN` and it's on a different host). Thankfully, for self-hosted services, it is easy to set these headers.
These settings are usually set in the config file for the web server that's hosting the target application, here are some examples of how to enable cross-origin access with common web servers:
### NGINX
In NGINX, you can use the [`add_header`](https://nginx.org/en/docs/http/ngx_http_headers_module.html) module within the app block.
```text
server {
...
add_header X-Frame-Options SAMEORIGIN always;
}
```
Then reload with `service nginx reload`
### Caddy
In Caddy, you can use the [`header`](https://caddyserver.com/docs/caddyfile/directives/header) directive.
```text
header {
X-Frame-Options SAMEORIGIN
}
```
### Apache
In Apache, you can use the [`mod_headers`](https://httpd.apache.org/docs/current/mod/mod_headers.html) module to set the `X-Frame-Options` in your config file. This file is usually located somewhere like `/etc/apache2/httpd.conf
```text
Header set X-Frame-Options: "ALLOW-FROM http://[dashy-location]/"
```
### LightHttpd
```text
Content-Security-Policy: frame-ancestors 'self' https://[dashy-location]/
```
---
## 404 On Static Hosting
If you're seeing Dashy's 404 page on initial load/ refresh, and then the main app when you go back to Home, then this is likely caused by the Vue router, and if so can be fixed in one of two ways.
The first solution is to switch the routing mode, from HTML5 `history` mode to `hash` mode, by setting `appConfig.routingMode` to `hash`.
If this works, but you wish to continue using HTML5 history mode, then a bit of extra [server configuration](/docs/management.md#web-server-configuration) is required. This is explained in more detaail in the [Vue Docs](https://router.vuejs.org/guide/essentials/history-mode.html). Once completed, you can then use `routingMode: history` again, for neater URLs.
---
## 404 after Launch from Mobile Home Screen
Similar to the above issue, if you get a 404 after using iOS and Android's "Add to Home Screen" feature, then this is caused by Vue router.
It can be fixed by setting `appConfig.routingMode` to `hash`
See also: [#628](https://github.com/Lissy93/dashy/issues/628), [#762](https://github.com/Lissy93/dashy/issues/762)
---
## 404 On Multi-Page Apps
Similar to above, if you get a 404 error when visiting a page directly on multi-page apps, then this can be fixed under `appConfig`, by setting `routingMode` to `hash`. Then rebuilding, and refreshing the page.
See also: [#670](https://github.com/Lissy93/dashy/issues/670), [#763](https://github.com/Lissy93/dashy/issues/763)
---
## Yarn Error
For more info, see [Issue #1](https://github.com/Lissy93/dashy/issues/1)
First of all, check that you've got yarn installed correctly - see the [yarn installation docs](https://classic.yarnpkg.com/en/docs/install) for more info.
If you're getting an error about scenarios, then you've likely installed the wrong yarn... (you're [not](https://github.com/yarnpkg/yarn/issues/2821) the only one!). You can fix it by uninstalling, adding the correct repo, and reinstalling, for example, in Debian:
- `sudo apt remove yarn`
- `curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -`
- `echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list`
- `sudo apt update && sudo apt install yarn`
Alternatively, as a workaround, you have several options:
- Try using [NPM](https://www.npmjs.com/get-npm) instead: So clone, cd, then run `npm install`, `npm run build` and `npm start`
- Try using [Docker](https://www.docker.com/get-started) instead, and all of the system setup and dependencies will already be taken care of. So from within the directory, just run `docker build -t lissy93/dashy .` to build, and then use docker start to run the project, e.g: `docker run -it -p 8080:80 lissy93/dashy` (see the [deploying docs](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md#deploy-with-docker) for more info)
---
## Remote Config Not Loading
If you've got a multi-page dashboard, and are hosting the additional config files yourself, then CORS rules will apply. A CORS error will look something like:
```text
Access to XMLHttpRequest at 'https://example.com/raw/my-config.yml' from origin 'http://dashy.local' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
```
The solution is to add the appropriate headers onto the target server, to allow it to accept requests from the origin where you're running Dashy.
If it is a remote service, that you do not have admin access to, then another option is to proxy the request. Either host your own, or use a publicly accessible service, like [allorigins.win](https://allorigins.win), e.g: `https://api.allorigins.win/raw?url=https://pastebin.com/raw/4tZpaJV5`. For git-based services specifically, there's [raw.githack.com](https://raw.githack.com/)
---
## Ineffective mark-compacts near heap limit Allocation failed
If you see an error message, similar to:
```text
<--- Last few GCs --->
[61:0x74533040] 229060 ms: Mark-sweep (reduce) 127.1 (236.9) -> 127.1 (137.4) MB, 5560.7 / 0.3 ms (average mu = 0.286, current mu = 0.011) allocation failure scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
```
This is likely caused by insufficient memory allocation to the container. When the container first starts up, or has to rebuild, the memory usage spikes, and if there isn't enough memory, it may terminate. This can be specified with, for example: `--memory=1024m`. For more info, see [Docker: Runtime options with Memory, CPUs, and GPUs](https://docs.docker.com/config/containers/resource_constraints/).
See also: [#380](https://github.com/Lissy93/dashy/issues/380), [#350](https://github.com/Lissy93/dashy/issues/350), [#297](https://github.com/Lissy93/dashy/issues/297), [#349](https://github.com/Lissy93/dashy/issues/349), [#510](https://github.com/Lissy93/dashy/issues/510), [#511](https://github.com/Lissy93/dashy/issues/511) and [#834](https://github.com/Lissy93/dashy/issues/834)
---
## Command failed with signal "SIGKILL"
In Docker, this can be caused by not enough memory. When the container first starts up, or has to rebuild, the memory usage spikes, and so a larger allocation may be required. This can be specified with, for example: `--memory=1024m`. For more info, see [Docker: Runtime options with Memory, CPUs, and GPUs](https://docs.docker.com/config/containers/resource_constraints/)
See also [#624](https://github.com/Lissy93/dashy/issues/624)
---
## Auth Validation Error: "should be object"
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.
For more info, see [this announcement](https://github.com/Lissy93/dashy/discussions/177).
You can fix this by replacing:
```yaml
auth:
- user: xxx
hash: xxx
```
with
```yaml
auth:
users:
- user: xxx
hash: xxx
```
---
## App Not Starting After Update to 2.0.4
Version 2.0.4 introduced changes to how the config is read, and the app is build. If you were previously mounting `/public` as a volume, then this will over-write the build app, preventing it from starting. The solution is to just pass in the file(s) / sub-directories that you need. For example:
```yaml
volumes:
- /srv/dashy/conf.yml:/app/public/conf.yml
- /srv/dashy/item-icons:/app/public/item-icons
```
---
## Keycloak Redirect Error
Check the [browser's console output](#how-to-open-browser-console), if you've not set any headers, you will likely see a CORS error here, which would be the source of the issue.
You need to allow Dashy to make requests to Keycloak, and Keycloak to redirect to Dashy. The way you do this depends on how you're hosting these applications / which proxy you are using, and examples can be found in the [Management Docs](/docs/management.md#setting-headers).
For example, add the access control header to Keycloak, like:
`Access-Control-Allow-Origin [URL-of Dashy]`
Note that for requests that transport sensitive info like credentials, setting the accept header to a wildcard (`*`) is not allowed - see [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#requests_with_credentials), so you will need to specify the actual URL.
You should also ensure that Keycloak is correctly configured, with a user, realm and application, and be sure that you have set a valid redirect URL in Keycloak ([screenshot](https://user-images.githubusercontent.com/1862727/148599768-db4ee4f8-72c5-402d-8f00-051d999e6267.png)).
For more details on how to set headers, see the [Example Headers](/docs/management.md#setting-headers) in the management docs, or reference the documentation for your proxy.
If you're running in Kubernetes, you will need to enable CORS ingress rules, see [docs](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#enable-cors), e.g:
```text
nginx.ingress.kubernetes.io/cors-allow-origin: "https://dashy.example.com"
nginx.ingress.kubernetes.io/enable-cors: "true"
```
See also: #479, #409, #507, #491, #341, #520
---
## Docker Directory
```text
Error response from daemon: OCI runtime create failed: container_linux.go:380:
starting container process caused: process_linux.go:545: container init caused:
rootfs_linux.go:76: mounting "/home/ubuntu/my-conf.yml" to rootfs at
"/app/public/conf.yml" caused: mount through procfd: not a directory:
unknown: Are you trying to mount a directory onto a file (or vice-versa)?
Check if the specified host path exists and is the expected type.
```
If you get an error similar to the one above, you are mounting a directory to the config file's location, when a plain file is expected. Create a YAML file, (`touch my-conf.yml`), populate it with a sample config, then pass it as a volume: `-v ./my-local-conf.yml:/app/public/conf.yml`
---
## Config Not Updating
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".
---
## Config Still not Updating
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.
---
## Styles and Assets not Updating
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.
---
## DockerHub `toomanyrequests`
This situation relates to error messages similar to one of the following, returned when pulling, updating or running the Docker container from Docker Hub.
```text
Continuing execution. Pulling image lissy93/dashy:release-1.6.0
error pulling image configuration: toomanyrequests
```
or
```text
You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit
```
When DockerHub returns one of these errors, or a `429` status, that means you've hit your rate limit. This was [introduced](https://www.docker.com/blog/scaling-docker-to-serve-millions-more-developers-network-egress/) last year, and prevents unauthenticated or free users from running docker pull more than 100 times per 6 hours.
You can [check your rate limit status](https://www.docker.com/blog/checking-your-current-docker-pull-rate-limits-and-status/) by looking for the `ratelimit-remaining` header in any DockerHub responses.
### Solution 1 - Use an alternate container registry
- Dashy is also available through GHCR, which at present does not have any hard limits. Just use `docker pull ghcr.io/lissy93/dashy:latest` to fetch the image
- You can also build the image from source, by cloning the repo, and running `docker build -t dashy .` or use the pre-made docker compose
### Solution 2 - Increase your rate limits
- Logging in to DockerHub will increase your rate limit from 100 requests to 200 requests per 6 hour period
- Upgrading to a Pro for $5/month will increase your image requests to 5,000 per day, and any plans above have no rate limits
- Since rate limits are counted based on your IP address, proxying your requests, or using a VPN may work
---
## Config Validation Errors
The configuration file is validated against [Dashy's Schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json) using AJV.
First, check that your syntax is valid, using [YAML Validator](https://codebeautify.org/yaml-validator/) or [JSON Validator](https://codebeautify.org/jsonvalidator). If the issue persists, then take a look at the [schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json), and verify that the field you are trying to add/ modify matches the required format. You can also use [this tool](https://www.jsonschemavalidator.net/s/JFUj7X9J) to validate your JSON config against the schema, or run `yarn validate-config`.
If you're trying to use a recently released feature, and are getting a warning, this is likely because you've not yet updated the the current latest version of Dashy.
If the issue still persists, you should raise an issue.
---
## Node Sass does not yet support your current environment
Caused by node-sass's binaries being built for a for a different architecture
To fix this, just run: `yarn rebuild node-sass`
---
## Unreachable Code Error
An error similar to: `Fatal error in , line 0. Unreachable code, FailureMessage Object: 0xffe6c8ac. Illegal instruction (core dumped)`
Is related to a bug in a downstream package, see [nodejs/docker-node#1477](https://github.com/nodejs/docker-node/issues/1477).
Usually, updating your system and packages will resolve the issue.
See also: [#776](https://github.com/Lissy93/dashy/issues/776)
---
## Error: Cannot find module './_baseValues'
Clearing the cache should fix this: `yarn cache clean`
If the issue persists, remove (`rm -rf node_modules\ yarn.lock`) and reinstall (`yarn`) node_modules
---
## Invalid Host Header while running through ngrok
Just add the [-host-header](https://ngrok.com/docs#http-host-header) flag, e.g. `ngrok http 8080 -host-header="localhost:8080"`
---
## Warnings in the Console during deploy
Please acknowledge the difference between errors and warnings before raising an issue about messages in the console. It's not unusual to see warnings about a new version of a certain package being available, an asset bundle bing oversized or a service worker not yet having a cache. These shouldn't have any impact on the running application, so please don't raise issues about these unless it directly relates to a bug or issue you're experiencing. Errors on the other hand should not appear in the console, and they are worth looking into further.
---
## Docker Login Fails on Ubuntu
Run `sudo apt install gnupg2 pass && gpg2 -k`
---
## Status Checks Failing
If you're using status checks, and despite a given service being online, the check is displaying an error, there are a couple of things you can look at:
If your service requires requests to include any authorization in the headers, then use the `statusCheckHeaders` property, as described in the [docs](/docs/status-indicators.md#setting-custom-headers).
If you are still having issues, it may be because your target application is blocking requests from Dashy's IP. This is a [CORS error](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), and can be fixed by setting the headers on your target app, to include:
```text
Access-Control-Allow-Origin: https://location-of-dashy/
Vary: Origin
```
If the URL you are checking has an unsigned certificate, or is not using HTTPS, then you may need to disable the rejection of insecure requests. This can be done by setting `statusCheckAllowInsecure` to true for a given item.
If your service is online, but responds with a status code that is not in the 2xx range, then you can use `statusCheckAcceptCodes` to set an accepted status code.
If you get an error, like `Service Unavailable: Server resulted in a fatal error`, even when it's definitely online, this is most likely caused by missing the protocol. Don't forget to include `https://` (or whatever protocol) before the URL, and ensure that if needed, you've specified the port.
Running Dashy in HOST network mode, instead of BRIDGE will allow status check access to other services in HOST mode. For more info, see [#445](https://github.com/Lissy93/dashy/discussions/445).
If you have firewall rules configured, then ensure that they don't prevent Dashy from making requests to the other services you are trying to access.
Currently, the status check needs a page to be rendered, so if this URL in your browser does not return anything, then status checks will not work. This may be modified in the future, but in the meantime, a fix would be to make your own status service, which just checks if your app responds with whatever code you'd like, and then return a 200 plus renders an arbitrary message. Then just point `statusCheckUrl` to your custom page.
For further troubleshooting, use an application like [Postman](https://postman.com) to diagnose the issue. Set the parameter to `GET`, and then make a call to: `https://[url-of-dashy]/status-check/?&url=[service-url]`. Where the service URL must have first been encoded (e.g. with `encodeURIComponent()` or [urlencoder.io](https://www.urlencoder.io/))
If you're serving Dashy though a CDN, instead of using the Node server or Docker image, then the Node endpoint that makes requests will not be available to you, and all requests will fail. A workaround for this may be implemented in the future, but in the meantime, your only option is to use the Docker or Node deployment method.
---
## Widget Errors
### Find Error Message
If an error occurs when fetching or rendering results, you will see a short message in the UI. If that message doesn't adequately explain the problem, then you can [open the browser console](/docs/troubleshooting.md#how-to-open-browser-console) to see more details.
### Check Config
Before proceeding, ensure that if the widget requires auth your API is correct, and for custom widgets, double check that the URL and protocol is correct.
### Timeout Error
If the error message in the console includes: `Error: timeout of 500ms exceeded`, then your Glances endpoint is slower to respond than expected. You can fix this by [setting timeout](https://github.com/Lissy93/dashy/blob/master/docs/widgets.md#setting-timeout) to a larger value. This is done on each widget, with the `timeout` attribute, and is specified in ms. E.g. `timeout: 5000` would only fail if no response is returned within 5 seconds.
### CORS error
If the console message mentions to corss-origin blocking, then this is a CORS error, see: [Fixing Widget CORS Errors](#widget-cors-errors)
### More Info
If you're able to, you can find more information about why the request may be failing in the Dev Tools under the Network tab, and you can ensure your endpoint is correct and working using a tool like Postman.
---
## Widget CORS Errors
The most common widget issue is a CORS error. This is a browser security mechanism which prevents the client-side app (Dashy) from from accessing resources on a remote origin, without that server's explicit permission (e.g. with headers like Access-Control-Allow-Origin). See the MDN Docs for more info: [Cross-Origin Resource Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).
There are several ways to fix a CORS error:
### Option 1 - Ensure Correct Protocol
You will get a CORS error if you try and access a http service from a https source. So ensure that the URL you are requesting has the right protocol, and is correctly formatted.
### Option 2 - Set Headers
If you have control over the destination (e.g. for a self-hosted service), then you can simply apply the correct headers.
Add the `Access-Control-Allow-Origin` header, with the value of either `*` to allow requests from anywhere, or more securely, the host of where Dashy is served from. For example:
```text
Access-Control-Allow-Origin: https://url-of-dashy.local
```
or
```text
Access-Control-Allow-Origin: *
```
For more info on how to set headers, see: [Setting Headers](/docs/management.md#setting-headers) in the management docs
### Option 3 - Proxying Request
You can route requests through Dashy's built-in CORS proxy. Instructions and more details can be found [here](/docs/widgets.md#proxying-requests). If you don't have control over the target origin, and you are running Dashy either through Docker, with the Node server or on Netlify, then this solution will work for you.
Just add the `useProxy: true` option to the failing widget.
### Option 4 - Use a plugin
For testing purposes, you can use an addon, which will disable the CORS checks. You can get the Allow-CORS extension for [Chrome](https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=en-US) or [Firefox](https://addons.mozilla.org/en-US/firefox/addon/access-control-allow-origin/), more details [here](https://mybrowseraddon.com/access-control-allow-origin.html)
---
## Widget Shows Error Incorrectly
When there's an error fetching or displaying a widgets data, then it will be highlighted in yellow, and a message displayed on the UI.
In some instances, this is a false positive, and the widget is actually functioning correctly.
If this is the case, you can disable the UI error message of a given widget by setting: `ignoreErrors: true`
---
## Weather Forecast Widget 401
A 401 error means your API key is invalid, it is not an issue with Dashy.
Usually this happens due to an error in your config. If you're unsure, copy and paste the [example](/docs/widgets.md#weather) config, replacing the API key with your own.
Check that `apiKey` is correctly specified, and nested within `options`. Ensure your input city is valid.
To test your API key, try making a request to `https://api.openweathermap.org/data/2.5/weather?q=London&appid=[your-api-key]`
If [Weather widget](/docs/widgets.md#weather-forecast) is working fine, but you are getting a `401` for the [Weather Forecast widget](/docs/widgets.md#weather-forecast), then this is also an OWM API key issue.
Since the forecasting API requires an upgraded plan. ULPT: You can get a free, premium API key by filling in [this form](https://home.openweathermap.org/students). It's a student plan, but there's no verification to check that you are still a student.
A future update will be pushed out, to use a free weather forecasting API.
See also: [#803](https://github.com/Lissy93/dashy/issues/803), [#789](https://github.com/Lissy93/dashy/issues/789), [#577](https://github.com/Lissy93/dashy/issues/577), [#621](https://github.com/Lissy93/dashy/issues/621), [#578](https://github.com/Lissy93/dashy/issues/578), [#806](https://github.com/Lissy93/dashy/discussions/806)
---
## Widget Displaying Inaccurate Data
If any widget is not displaying the data you expect, first confirm that your config is correct, then try manually calling the API endpoint.
If the raw API output is correct, yet the widget is rendering incorrect results, then it is likely a bug, and a ticket should be raised. You can start to debug the issue, by looking at the widget's code ([here](https://github.com/Lissy93/dashy/tree/master/src/components/Widgets)), and the browser console + networking tab.
If the API itself is returning incorrect, incomplete or inaccurate data then an issue needs to be raised **with the API provider** (not Dashy!). You can find the API provider included within the widget docs, or for a full list see the [Privacy Docs](https://github.com/Lissy93/dashy/blob/master/docs/privacy.md#widgets).
See also: [#807](https://github.com/Lissy93/dashy/issues/807) (re, domain monitor)
---
## Font Awesome Icons not Displaying
Usually, Font Awesome will be automatically enabled if one or more of your icons are using Font-Awesome. If this is not happening, then you can always manually enable (or disable) Font Awesome by setting: [`appConfig`](/docs/configuring.md#appconfig-optional).`enableFontAwesome` to `true`.
If you are trying to use a premium icon, then you must have a [Pro License](https://fontawesome.com/plans). You'll then need to specify your Pro plan API key under `appConfig.fontAwesomeKey`. You can find this key, by logging into your FA account, navigate to Account → [Kits](https://fontawesome.com/kits) → New Kit → Copy Kit Code. The code is a 10-digit alpha-numeric code, and is also visible within the new kit's URL, for example: `81e48ce079`.
Be sure that you're specifying the icon category and name correctly. You're icon should look be `[category] fa-[icon-name]`. The following categories are supported: `far` _(regular)_, `fas` _(solid)_, `fal`_(light)_, `fad` _(duo-tone)_ and `fab`_(brands)_. With the exception of brands, you'll usually want all your icons to be in from same category, so they look uniform.
Ensure the icon you are trying to use, is available within [FontAwesome Version 5](https://fontawesome.com/v5/search).
Examples: `fab fa-raspberry-pi`, `fas fa-database`, `fas fa-server`, `fas fa-ethernet`
Finally, check the [browser console](#how-to-open-browser-console) for any error messages, and raise a ticket if the issue persists.
---
## Copy to Clipboard not Working
If the copy to clipboard feature (either under Config --> Export, or Item --> Copy URL) isn't functioning as expected, first check the browser console. If you see `TypeError: Cannot read properties of undefined (reading 'writeText')` then this feature is not supported by your browser.
The most common reason for this, is if you not running the app over HTTPS. Copying to the clipboard requires the app to be running in a secure origin / aka have valid HTTPS cert. You can read more about this [here](https://stackoverflow.com/a/71876238/979052).
As a workaround, you could either:
- Highlight the text and copy / <kbd>Ctrl</kbd> + <kbd>C</kbd>
- Or setup SSL - [here's a guide](https://github.com/Lissy93/dashy/blob/master/docs/management.md#ssl-certificates) on doing so
---
## Unsupported Digital Envelope Routines
If you're running on GitHub Codespaces, and seeing: `Error: error:0308010C:digital envelope routines::unsupported` when using Node 17+, it can be resolved by adding the `--openssl-legacy-provider` flag to your `NODE_OPTIONS` environmental variable.
For example:
```
export NODE_OPTIONS=--openssl-legacy-provider
```
For more info, see [webpack/webpack#14532](https://github.com/webpack/webpack/issues/14532) and [nodejs/node#40455](https://github.com/nodejs/node/issues/40455).
This occours because [Node 17+](https://medium.com/the-node-js-collection/node-js-17-is-here-8dba1e14e382) no longer supports MD4 as hash function, we're in the process of upgrading Dashy dependencies to all use SHA1 for hashing bundle IDs.
---
## How to Reset Local Settings
Some settings are stored locally, in the browser's storage.
In some instances cached assets can prevent your settings from being updated, in which case you may wish to reset local data.
To clear all local data from the UI, head to the Config Menu, then click "Reset Local Settings", and Confirm when prompted.
This will not affect your config file. But be sure that you keep a backup of your config, if you've not written changes it to disk.
You can also view any and all data that Dashy is storing, using the developer tools. Open your browser's dev tools (usually <kbd>F12</kbd>), in Chromium head to the Application tab, or in Firefox go to the Storage tab. Select Local Storage, then scroll down the the URL Dashy is running on. You should now see all data being stored, and you can select and delete any fields you wish.
For a full list of all data that may be cached, see the [Privacy Docs](/docs/privacy.md#browser-storage).
---
## How to make a bug report
### Step 1 - Where to open issues
You will need a GitHub account in order to raise a ticket. You can then [click here](https://github.com/Lissy93/dashy/issues/new?assignees=lissy93&labels=%F0%9F%90%9B+Bug&template=bug.yml&title=%5BBUG%5D+%3Ctitle%3E) to open a new bug report.
### Step 2 - Checking it's not already covered
Before submitting, please check that:
- A similar ticket has not previously been opened
- The issue is not covered in the [troubleshooting guide](https://github.com/Lissy93/dashy/blob/master/docs/troubleshooting.md) or [docs](https://github.com/Lissy93/dashy/tree/master/docs#readme)
### Step 3 - Describe the Issue
Your ticket will likely be dealt with more effectively if you can explain the issue clearly, and provide all relevant supporting material.
Complete the fields, asking for your environment info and version of Dashy.
Then describe the issue, briefly explaining the steps to reproduce, expected outcome and actual outcome.
### Step 4 - Provide Supporting Info
Where relevant please also include:
- A screenshot of the issue
- The relevant parts of your config file
- Logs
- If client-side issue, then include the browser logs ([see how](#how-to-open-browser-console))
- If server-side / during deployment, include the terminal output
_Take care to redact any personal info, (like IP addresses, auth hashes or API keys)._
### Step 5 - Fix Released
A maintainer will aim to respond within 48 hours.
The timeframe for resolving your issue, will vary depending on severity of the bug and the complexity of the fix.
You will be notified on your ticket, when a fix has been released.
Finally, be sure to remain respectful to other users and project maintainers, in line with the [Contributor Covenant Code of Conduct](https://github.com/Lissy93/dashy/blob/master/.github/CODE_OF_CONDUCT.md#contributor-covenant-code-of-conduct).
---
## How-To Open Browser Console
When raising a bug, one crucial piece of info needed is the browser's console output. This will help the developer diagnose and fix the issue.
If you've been asked for this info, but are unsure where to find it, then it is under the "Console" tab, in the browsers developer tools, which can be opened with <kbd>F12</kbd>. You can right-click the console, and select Save As to download the log.
To open dev tools, and jump straight to the console:
- Win / Linux: <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>J</kbd>
- MacOS: <kbd>Cmd</kbd> + <kbd>Option</kbd> + <kbd>J</kbd>
For more detailed walk through, see [this article](https://support.shortpoint.com/support/solutions/articles/1000222881-save-browser-console-file).
---
## Git Contributions not Displaying
If you've contributed to Dashy (or any other project), but your contributions are not showing up on your GH profile, or in Dashy's [Credits Page](https://github.com/Lissy93/dashy/blob/master/docs/credits.md), then this is likely a git config issue.
These statistics are generated using the username / email associated with commits. This info needs to be setup on your local machine using [`git config`](https://git-scm.com/docs/git-config).
Run the following commands (replacing name + email with your info):
- `git config --global user.name "John Doe"`
- `git config --global user.email johndoe@example.com`
For more info, see [Git First Time Setup Docs](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup).
Note that only contributions to the master / main branch or a project are counted

2932
docs/widgets.md Normal file
View File

File diff suppressed because it is too large Load Diff

49
netlify.toml Normal file
View File

@@ -0,0 +1,49 @@
# Enables you to easily deploy a fork of Dashy to Netlify
# without the need to configure anything in admin UI
# Docs: https://www.netlify.com/docs/netlify-toml-reference/
# Essential site config
[build]
base = "/"
command = "yarn build"
publish = "dist"
functions = "services/serverless-functions"
environment = { NODE_VERSION = "16.13.2" }
# Site info, used for the 1-Click deploy page
[template.environment]
STATUSKIT_PAGE_TITLE = "Dashy"
STATUSKIT_COMPANY_LOGO = "https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/logo.png"
STATUSKIT_SUPPORT_CONTACT_LINK = "https://github.com/lissy93/dashy"
STATUSKIT_RESOURCES_LINK = "https://dashy.to/docs"
# Redirect the Node endpoints to serverless functions
[[redirects]]
from = "/status-check"
to = "/.netlify/functions/cloud-status-check"
status = 301
force = true
[[redirects]]
from = "/config-manager/*"
to = "/.netlify/functions/not-supported"
status = 301
force = true
[[redirects]]
from = "/cors-proxy"
to = "/.netlify/functions/netlify-cors"
status = 301
force = true
# For router history mode, ensure pages land on index
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
# Set any security headers here
[[headers]]
for = "/*"
[headers.values]
# Uncomment to enable Netlify user control. Requires premium plan.
# Basic-Auth = "someuser:somepassword anotheruser:anotherpassword"

37419
package-lock.json generated Normal file
View File

File diff suppressed because it is too large Load Diff

107
package.json Normal file
View File

@@ -0,0 +1,107 @@
{
"name": "Dashy",
"version": "2.1.1",
"license": "MIT",
"main": "server",
"author": "Alicia Sykes <alicia@omg.lol> (https://aliciasykes.com)",
"scripts": {
"start": "node server",
"dev": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"pm2-start": "npx pm2 start server.js",
"build-watch": "vue-cli-service build --watch --mode production",
"build-and-start": "npm-run-all --parallel build-watch start",
"validate-config": "node services/config-validator",
"health-check": "node services/healthcheck",
"dependency-audit": "npx improved-yarn-audit --ignore-dev-deps"
},
"dependencies": {
"@formschema/native": "^2.0.0-beta.6",
"@sentry/tracing": "^6.17.5",
"@sentry/vue": "^6.17.4",
"ajv": "^8.10.0",
"axios": "^0.27.2",
"connect-history-api-fallback": "^1.6.0",
"crypto-js": "^4.1.1",
"express": "^4.17.2",
"frappe-charts": "^1.6.2",
"js-yaml": "^4.1.0",
"keycloak-js": "^20.0.3",
"mustache": "^4.2.0",
"register-service-worker": "^1.7.2",
"remedial": "^1.0.8",
"rss-parser": "3.13.0",
"rsup-progress": "^3.0.0",
"simple-icons": "^7.19.0",
"v-jsoneditor": "^1.4.5",
"v-tooltip": "^2.1.3",
"vue": "^2.7.0",
"vue-i18n": "^8.27.2",
"vue-js-modal": "^2.0.1",
"vue-json-tree-view": "^2.1.6",
"vue-material-tabs": "0.1.5",
"vue-router": "^3.5.3",
"vue-select": "^3.20.2",
"vue-swatches": "^2.1.1",
"vue-toasted": "^1.1.28",
"vuex": "^3.6.2"
},
"devDependencies": {
"@architect/sandbox": "^4.5.2",
"@babel/preset-env": "^7.17.10",
"@vue/cli-plugin-babel": "^4.5.15",
"@vue/cli-plugin-pwa": "^4.5.15",
"@vue/cli-service": "^4.5.15",
"@vue/eslint-config-standard": "^4.0.0",
"babel-eslint": "^10.0.1",
"eslint": "^7.24.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-plugin-vue": "^7.9.0",
"npm-run-all": "^4.1.5",
"progress-bar-webpack-plugin": "^2.1.0",
"sass": "^1.38.0",
"sass-loader": "^7.1.0",
"vue-cli-plugin-yaml": "^1.0.2",
"vue-svg-loader": "^0.16.0",
"vue-template-compiler": "^2.7.0"
},
"engines": {
"node": ">=16.0.0 <18.0.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"@vue/standard",
"airbnb-base"
],
"rules": {
"import/no-unresolved": "off",
"import/extensions": "off",
"arrow-parens": 0,
"no-else-return": 0
},
"parserOptions": {
"parser": "babel-eslint"
}
},
"babel": {
"presets": [
"@vue/app",
"@babel/preset-env"
]
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}

0
public/.nojekyll Normal file
View File

539
public/conf.bak.yml Normal file
View File

@@ -0,0 +1,539 @@
appConfig:
theme: adventure-basic
layout: auto
iconSize: small
language: en
startingView: default
defaultOpeningMethod: newtab
statusCheck: false
statusCheckInterval: 15
faviconApi: local
routingMode: history
enableMultiTasking: false
widgetsAlwaysUseProxy: false
webSearch:
disableWebSearch: false
searchEngine: duckduckgo
openingMethod: newtab
searchBangs: {}
enableFontAwesome: false
enableMaterialDesignIcons: false
hideComponents:
hideHeading: false
hideNav: false
hideSearch: true
hideSettings: true
hideFooter: true
auth:
enableGuestAccess: true
users: []
enableKeycloak: true
keycloak:
serverUrl: https://auth.rssa.top
realm: rssa
clientId: portal-test
legacySupport: false
showSplashScreen: false
preventWriteToDisk: false
preventLocalSave: false
disableConfiguration: false
disableConfigurationForNonAdmin: false
allowConfigEdit: false
enableServiceWorker: false
disableContextMenu: false
disableUpdateChecks: false
disableSmartSort: false
enableErrorReporting: false
colCount: 4
defaultIcon: link-round.svg
backgroundImg: /item-icons/background(3).svg
customColors:
adventure-basic:
primary: hsla(0,0%,100%,0.9019607843137255)
background: '#5c90eb'
background-darker: '#181c3a'
displayConfig:
hideForGuests: true
showForKeycloakUsers:
roles:
- stim
pageInfo:
title: Portal Test
description: Selamat Datang di Portal STIM
navLinks:
- title: Portal RSSA
path: https://portal.rssa.top
target: sametab
displayData:
showForKeycloakUsers:
roles:
- stim
- title: Akun
path: https://auth.rssa.top/realms/rssa/account/#/personal-info
target: newtab
displayData:
hideForGuests: true
footerText: stim @ 2023
logo: /item-icons/rocket.svg
sections:
- name: Admin Area
icon: mouse.svg
items:
- &ref_0
title: Aplicares
description: Admin Aplicares BPJS
icon: bpjs-pavicon.png
url: http://aplicares.rssa/admin
target: newtab
id: 0_898_aplicares
- &ref_1
title: Gitea
description: Git Repository
icon: https://git.rssa.top/assets/img/logo.svg
url: https://git.rssa.top/{{{gitea.path}}}
target: newtab
id: 1_898_gitea
- &ref_2
title: Guacamole
description: Remote Desktop Application
icon: https://guacamole.rssa.my.id/images/guac-tricolor.svg
url: https://guacamole.rssa.my.id
target: newtab
id: 2_898_guacamole
- &ref_3
title: Helpdesk
description: Aplikasi helpdesk STIM
icon: https://helpdesk.rssa.top/img/favicon/apple-touch-icon.png
url: https://helpdesk.rssa.top
target: newtab
id: 3_898_helpdesk
- &ref_4
title: Inventaris
description: Aplikasi Inventaris STIM
icon: inventory.svg
url: https://inventaris-stim.rssa.my.id
target: newtab
id: 4_898_inventaris
- &ref_5
title: QR Wifi
description: QR Code Wifi RSSA
icon: https://qrwifi.rssa.my.id/static/qrwifi/images/favicon.png
url: https://qrwifi.rssa.my.id/{{{qrwifi.path}}}
target: newtab
id: 5_898_qrwifi
- &ref_6
title: Stimpro
description: STIM Productivity Application
icon: team.svg
url: https://stimpro.rssa.top
target: newtab
id: 6_898_stimpro
filteredItems:
- *ref_0
- *ref_1
- *ref_2
- *ref_3
- *ref_4
- *ref_5
- *ref_6
displayData:
sortBy: alphabetical
rows: 2
cols: 2
collapsed: false
hideForGuests: false
- name: Network Console
icon: networking-scheme.svg
displayData:
sortBy: default
rows: 1
cols: 2
collapsed: false
hideForGuests: false
showForKeycloakUsers:
roles:
- stim
items:
- &ref_7
title: Fortigate
description: Fortigate Console
icon: hl-fortinet
url: https://fortigate.rssa.my.id
target: newtab
id: 0_1501_fortigate
- &ref_8
title: Ruckus
description: Ruckus Commscope
icon: https://ruckus.rssa.my.id/cas/favicon.ico
url: https://ruckus.rssa.my.id
target: newtab
id: 1_1501_ruckus
- &ref_9
title: Unifi
description: Unifi Controller
icon: >-
https://unifi.rssa.my.id/manage/angular/g6a10a46b3/images/favicons/favicon-152.png?v=2
url: https://unifi.rssa.my.id
target: newtab
id: 2_1501_unifi
filteredItems:
- *ref_7
- *ref_8
- *ref_9
- name: Software Administrator
displayData:
sortBy: alphabetical
rows: 1
cols: 2
collapsed: false
hideForGuests: true
showForKeycloakUsers:
roles:
- stim
items:
- &ref_10
title: Cloudbeaver
description: Aplikasi Database Administrator
icon: https://cloudbeaver.rssa.my.id/icons/logo_sm.svg
url: https://cloudbeaver.rssa.my.id
target: newtab
id: 0_2252_cloudbeaver
- &ref_11
title: Wireguard
description: Wireguard Web Admin
icon: hl-wireguard
url: https://wgui.rssa
target: newtab
statusCheckAllowInsecure: true
id: 1_2252_wireguard
displayData:
showForKeycloakUsers:
roles:
- serverAdmin
filteredItems:
- *ref_10
- *ref_11
icon: man-technologist-light-skin-tone.svg
- name: Server Administrator
displayData:
sortBy: alphabetical
rows: 1
cols: 2
collapsed: false
hideForGuests: false
showForKeycloakUsers:
roles:
- serverAdmin
items:
- &ref_12
title: Longhorn
description: Kubernetes Cluster Storage
icon: hl-longhorn
url: https://longhorn.rssa.top
target: newtab
id: 0_2040_longhorn
displayData:
showForKeycloakUsers:
roles:
- stim
- &ref_13
title: Portainer
description: Docker Web Console
icon: https://portainer.rssa.my.id/63a301f0574f1a696ce6.png
url: https://portainer.rssa.my.id
target: newtab
id: 1_2040_portainer
- &ref_14
title: Rancher
description: Kubernetes Dashboard
icon: hl-rancher
url: https://rancher.rssa.my.id/dashboard
target: newtab
statusCheckAllowInsecure: true
id: 2_2040_rancher
- &ref_15
title: Technitium 1
description: Local DNS Server Master
icon: hl-technitium
url: https://ns1.local
target: newtab
statusCheckAllowInsecure: true
id: 3_2040_technitium
- &ref_16
title: Technitium 2
description: Local DNS Server Slave
icon: hl-technitium
url: https://ns2.local
target: newtab
statusCheckAllowInsecure: true
id: 4_2040_technitium
- &ref_17
title: Traefik Docker
description: Reverse Proxy for Docker
icon: hl-traefik
url: https://traefik.rssa.my.id/dashboard
target: newtab
statusCheckAcceptCodes: '401'
id: 5_2040_traefikdocker
- &ref_18
title: Traefik K3S
description: Reverse Proxy for Kubernetes
icon: hl-traefik
url: https://traefik.rssa.top/dashboard
target: newtab
statusCheckAcceptCodes: '401'
id: 6_2040_traefikks
- &ref_19
title: Truenas
description: Network Attached Storage Server
icon: hl-truenas
url: http://truenas.rssa
target: newtab
id: 7_2040_truenas
filteredItems:
- *ref_12
- *ref_13
- *ref_14
- *ref_15
- *ref_16
- *ref_17
- *ref_18
- *ref_19
icon: hacker.svg
- name: Proxmox
icon: hl-proxmox
displayData:
sortBy: alphabetical
rows: 1
cols: 2
collapsed: false
hideForGuests: false
showForKeycloakUsers:
roles:
- stim
items:
- &ref_20
title: pve 1
icon: ''
url: https://10.10.123.31:8006
target: newtab
statusCheckAllowInsecure: true
id: 0_765_pve
- &ref_21
title: rx300-2
description: Server Fujitsu
url: https://10.10.123.102:8006
target: newtab
statusCheckAllowInsecure: true
id: 1_765_rx
- &ref_22
title: rx300-1
description: Server Fujitsu
url: https://10.10.123.101:8006
target: newtab
statusCheckAllowInsecure: true
id: 2_765_rx
- &ref_23
title: rx300-3
description: Server Fujitsu
url: https://10.10.123.103:8006
target: newtab
statusCheckAllowInsecure: true
id: 3_765_rx
- &ref_24
title: rx300-4
description: Server Fujitsu
url: https://10.10.123.104:8006
target: newtab
statusCheckAllowInsecure: true
id: 4_765_rx
- &ref_25
title: r740-1
description: Server Fujitsu
url: https://10.10.123.105:8006
target: newtab
statusCheckAllowInsecure: true
id: 5_765_r
- &ref_26
title: pve 7
description: Server Fujitsu
icon: ''
url: https://10.10.123.107:8006
target: newtab
statusCheckAllowInsecure: true
id: 6_765_pve
- &ref_27
title: ts300-2
description: Server Fujitsu
url: https://10.10.123.108:8006
target: newtab
statusCheckAllowInsecure: true
id: 7_765_ts
- &ref_28
title: pve 9
description: Server Fujitsu
icon: ''
url: https://10.10.123.109:8006
target: newtab
statusCheckAllowInsecure: true
id: 8_765_pve
- &ref_29
title: pbs
description: Proxmox Backup Server
url: https://10.10.123.112:8007/
target: newtab
statusCheckAllowInsecure: true
id: 9_765_pbs
filteredItems:
- *ref_20
- *ref_21
- *ref_22
- *ref_23
- *ref_24
- *ref_25
- *ref_26
- *ref_27
- *ref_28
- *ref_29
- name: Webmin
icon: webmin.svg
displayData:
sortBy: alphabetical
rows: 1
cols: 4
collapsed: false
hideForGuests: true
showForKeycloakUsers:
roles:
- stim
- serveradmin
items:
- &ref_30
title: Semakin Imut
description: Webmin Semakin Imut
url: https://semakin-imut.rssa:10000/
target: newtab
statusCheckAllowInsecure: true
id: 0_610_semakinimut
- &ref_31
title: Arsip Surat
description: Webmin Arsip Surat
url: https://arsip-surat.rssa:12321/
target: newtab
statusCheckAllowInsecure: true
id: 1_610_arsipsurat
- &ref_32
title: Simutu
description: Webmin Simutu
url: https://simutu.rssa:12321/
target: newtab
statusCheckAllowInsecure: true
id: 2_610_simutu
- &ref_33
title: Edata Evapor
description: Webmin Edata Evapor
url: https://edata-evapor.rssa:10000/
target: newtab
statusCheckAllowInsecure: true
id: 3_610_edataevapor
- &ref_34
title: SPPD
description: Webmin SPPD
url: https://sppd.rssa:10000/
target: newtab
statusCheckAllowInsecure: true
id: 4_610_sppd
- &ref_35
title: Eletter
description: Webmin Eletter
url: https://eletter.rssa:12321/
target: newtab
statusCheckAllowInsecure: true
id: 5_610_eletter
- &ref_36
title: Simak
description: Webmin Simak
url: https://eletter.rssa:12321/
target: newtab
statusCheckAllowInsecure: true
id: 6_610_simak
- &ref_37
title: SMB Server Ovy
description: Webmin SMB Server Ovy
url: https://10.10.123.3:10000/
target: newtab
statusCheckAllowInsecure: true
id: 7_610_smbserverovy
- &ref_38
title: RSSA Pintar
description: Webmin RSSA Pintar
url: https://rssa-pintar.rssa:10000/
target: newtab
statusCheckAllowInsecure: true
id: 8_610_rssapintar
- &ref_39
title: Simpro
description: Webmin Simpro
url: https://simpro.rssa:10000/
target: newtab
statusCheckAllowInsecure: true
id: 9_610_simpro
- &ref_40
title: Aplicares
description: Webmin Aplicares
url: https://aplicares.rssa:10000/
target: newtab
statusCheckAllowInsecure: true
id: 10_610_aplicares
- &ref_41
title: Singabaja
description: Webmin Singabaja
url: https://singabaja.rssa:10000/
target: newtab
statusCheckAllowInsecure: true
id: 11_610_singabaja
- &ref_42
title: SMB File Server
description: Webmin SMB File Server
url: https://10.10.123.56:12321/
target: newtab
statusCheckAllowInsecure: true
id: 12_610_smbfileserver
- &ref_43
title: Antrian
description: Webmin Antrian
url: https://10.10.123.56:12321/
target: newtab
statusCheckAllowInsecure: true
id: 13_610_antrian
- &ref_44
title: RIS NFS Server
description: Webmin RIS NFS Server
url: https://ris-nfs.rssa:10000/
target: newtab
statusCheckAllowInsecure: true
id: 14_610_risnfsserver
- &ref_45
title: RIS DB Server
description: Webmin RIS DB Server
url: https://ris-db.rssa:10000/
target: newtab
statusCheckAllowInsecure: true
id: 15_610_risdbserver
filteredItems:
- *ref_30
- *ref_31
- *ref_32
- *ref_33
- *ref_34
- *ref_35
- *ref_36
- *ref_37
- *ref_38
- *ref_39
- *ref_40
- *ref_41
- *ref_42
- *ref_43
- *ref_44
- *ref_45

704
public/conf.yml Normal file
View File

@@ -0,0 +1,704 @@
appConfig:
theme: adventure-basic
language: en
layout: auto
iconSize: large
startingView: default
defaultOpeningMethod: newtab
statusCheck: true
statusCheckInterval: 0
backgroundImg: /item-icons/background(3).svg
faviconApi: local
routingMode: history
enableMultiTasking: false
widgetsAlwaysUseProxy: false
webSearch:
disableWebSearch: false
searchEngine: duckduckgo
openingMethod: newtab
searchBangs: {}
enableFontAwesome: false
enableMaterialDesignIcons: false
hideComponents:
hideHeading: false
hideNav: false
hideSearch: false
hideSettings: true
hideFooter: false
auth:
enableGuestAccess: true
users: []
enableKeycloak: true
keycloak:
serverUrl: https://auth.rssa.top
realm: rssa-test
clientId: portal-test-id
legacySupport: false
showSplashScreen: false
preventWriteToDisk: false
preventLocalSave: false
disableConfiguration: false
allowConfigEdit: true
enableServiceWorker: false
disableContextMenu: false
disableUpdateChecks: false
disableSmartSort: false
enableErrorReporting: false
colCount: 4
customColors:
adventure-basic:
primary: hsla(0,0%,100%,0.9019607843137255)
background: '#00CCB4'
background-darker: '#181c3a'
displayConfig:
hideForGuests: true
showForKeycloakUsers:
roles:
- stim
pageInfo:
title: Portal RSSA
description: Selamat datang di Portal RSSA
logo: /item-icons/rocket.svg
footerText: stim @ 2023
navLinks:
- title: Portal STIM
path: https://portal-stim.rssa.top
target: sametab
displayData:
showForKeycloakUsers:
roles:
- stim
- title: Akun
path: https://auth.rssa.top/realms/rssa/account/#/personal-info
target: newtab
displayData:
hideForGuests: true
sections:
- name: Pelayanan
icon: ''
displayData:
sortBy: alphabetical
rows: 1
cols: 1
collapsed: false
hideForGuests: false
items:
- &ref_0
title: SIMRS 3.0
description: Sistem Informasi Manajemen Rumah Sakit
icon: medical-machine.svg
url: http://simrs.rssa
target: newtab
id: 0_921_simrs
- &ref_1
title: RIS
description: Radiologi Information System
icon: https://ris.rssa.my.id/radiologi.png
url: https://ris.rssa.my.id
target: newtab
id: 1_921_ris
- &ref_2
title: Viewer Lab
description: Viewer Lab Sentral
icon: https://viewerlab.rssa.my.id/dna-test.png
url: https://viewerlab.rssa.my.id
target: newtab
id: 2_921_viewerlab
- &ref_3
title: Antrian
description: Antrian Poliklinik
icon: group-talk.svg
url: http://antrian.rssa
target: newtab
id: 3_921_antrian
- &ref_4
title: GOMED
description: Dashboard Manajemen
icon: https://www.svgrepo.com/download/260752/analytics.svg
url: https://gomed-eis.rssa.my.id
target: newtab
id: 4_921_gomed
- &ref_5
title: Semakin Imut
description: Asuhan Keperawatan dan Indikator Mutu IGD
icon: ENsymbol.png
url: http://semakin-imut.rssa
target: newtab
id: 5_921_semakinimut
- &ref_6
title: Satu RSSA
description: Satu Data untuk RSSA
icon: altair.svg
url: https://satu.rssa.top/{{{satu.path}}}
displayData:
hideForGuests: false
showForKeycloakUsers:
roles:
- stim
target: newtab
id: 6_921_saturssa
- &ref_7
title: SIMRS 4.0
description: Sistem Informasi Manajemen Rumah Sakit
icon: https://sim.rssa.my.id/images/logo_login/LOG%20RSSAGRP-03.png
url: https://sim.rssa.my.id
target: newtab
id: 7_921_simrs
filteredItems:
- *ref_0
- *ref_1
- *ref_2
- *ref_3
- *ref_4
- *ref_5
- *ref_6
- *ref_7
- name: Penunjang Umum
icon: ''
displayData:
sortBy: alphabetical
rows: 1
cols: 1
collapsed: false
hideForGuests: false
items:
- &ref_8
title: Telepon
description: Buku Telepon RSSA
icon: fax.svg
url: http://telepon.rssa/index.php/ps_dashboard
target: newtab
id: 0_1386_telepon
- &ref_9
title: Eletter
description: Surat Menyurat Elektronik
icon: email-mail.svg
url: http://eletter.rssa
target: newtab
id: 1_1386_eletter
- &ref_10
title: Nextcloud
description: Penyimpanan Cloud RSSA
icon: nextcloud.svg
url: https://nc.rssa.top
target: newtab
id: 2_1386_nextcloud
- &ref_11
title: Simutu
description: Sistem Informasi Undangan TU
icon: calendar.svg
url: http://simutu.rssa
target: newtab
id: 3_1386_simutu
- &ref_12
title: SPPD
description: Surat Perintah Perjalanan Dinas
icon: hurry-worker.svg
url: http://sppd.rssa
target: newtab
id: 4_1386_sppd
- &ref_13
title: Sidokar
description: Sistem Informasi Dokumen Akreditasi KARS
icon: kars.png
url: https://sidokar.rssa.my.id
target: newtab
id: 5_1386_sidokar
- &ref_14
title: Eklaim Test
description: Eklaim Inacbg Test Area
icon: logo_icc.png
url: http://eklaim-test.rssa/
target: newtab
id: 6_1386_eklaimtest
displayData:
hideForGuests: false
showForKeycloakUsers:
roles:
- ikpk
- stim
filteredItems:
- *ref_8
- *ref_9
- *ref_10
- *ref_11
- *ref_12
- *ref_13
- *ref_14
- name: Penunjang Khusus
displayData:
sortBy: alphabetical
rows: 1
cols: 2
collapsed: false
hideForGuests: false
items:
- &ref_15
title: Eklaim
description: Eklaim Inacbg
icon: inacbg.png
url: http://eklaim.rssa
target: newtab
id: 0_1609_eklaim
displayData:
hideForGuests: false
showForKeycloakUsers:
roles:
- ikpk
- title: Biakes
description: Tarif Biakes Maskin
icon: https://biakes.rssa.top/assets/ico/apple-icon-180x180.png
url: https://biakes.rssa.top
target: newtab
id: 1_1609_biakes
displayData:
hideForGuests: true
showForKeycloakUsers:
roles:
- ikpk
- &ref_16
title: Edata Evapor
description: Data Pelaporan Evapor
icon: data-analytic-document-paper.svg
url: http://edata-evapor.rssa
target: newtab
id: 2_1609_edataevapor
- &ref_17
title: SIMAK
description: Sistem Informasi Anggaran Krusial
icon: budget-cost.svg
url: http://simak.rssa
target: newtab
id: 3_1609_simak
- &ref_18
title: Singabaja
description: Aplikasi Pengadaan Barang dan Jasa
icon: shopping-cart-supermarket.svg
url: http://singabaja.rssa
target: newtab
id: 4_1609_singabaja
- &ref_19
title: SIMPRO
description: Sistem Informasi Manajemen Profesional
icon: networking-employee.svg
url: http://simpro.rssa
target: newtab
id: 5_1609_simpro
- &ref_20
title: Eregulasi
description: Aplikasi Penyimpanan Regulasi RSSA
icon: policy-term-and-condition-term.svg
url: https://eregulasi.rssa.top
target: newtab
id: 6_1609_eregulasi
- &ref_21
title: Sikembang
description: Sistem Informasi Pendidikan dan Penelitian
icon: sikembang-64.png
url: https://sikembang.rssa.top/{{{sikembang.path}}}
displayData:
hideForGuests: false
showForKeycloakUsers:
roles:
- stim
- diklit
target: newtab
id: 7_1609_sikembang
- &ref_22
title: Simpelkes
description: Sistem Informasi Pemeliharaan Alat Kesehatan
icon: https://simpelkes.rssa.my.id/icon/android-icon-192x192.png
url: https://simpelkes.rssa.my.id
target: newtab
id: 8_1609_simpelkes
- &ref_23
title: Siruter
description: Aplikasi Akuntansi
icon: bill-invoice.svg
url: https://siruter.rssa.my.id
target: newtab
id: 9_1609_siruter
- &ref_24
title: Siruter RSU
icon: https://siruter-rsu.rssa.my.id/assets/img/logo.png
url: https://siruter-rsu.rssa.my.id
target: newtab
id: 10_1609_siruterrsu
- &ref_25
title: Surat PNM
description: Aplikasi Surat Penunjang Non Medik
icon: letter-contact.svg
url: http://surat-pnm.rssa
target: newtab
id: 11_1609_suratpnm
- &ref_26
title: Uptodate
description: Aplikasi Interaksi Obat
icon: uptodate-logo.png
url: https://uptodate.com
target: newtab
id: 12_1609_uptodate
displayData:
hideForGuests: false
showForKeycloakUsers:
roles:
- stim
- farmasi
- &ref_27
title: STIMPRO
description: STIM Productivity App
icon: stimpro-128.png
url: https://stimpro.rssa.top/{{{stimpro.path}}}
target: newtab
id: 13_1609_stimpro
displayData:
hideForGuests: false
showForKeycloakUsers:
roles:
- stim
- &ref_39
title: UpToDate
description: Aplikasi yang digunakan untuk mencari interaksi obat
#icon: altair.svg
url: https://www.uptodate.com/contents/search
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_40
title: Biakes Maskin
description: aplikasi pengolah data entri pasien miskin
#icon: altair.svg
url: https://biakes.rssa.top/login
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_41
title: BMP DB
description: Pengelolaan data elektronik pemeriksaan BMP/BMA
#icon: altair.svg
url: https://bmppk.kedokteranub.org/admin/beranda
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
filteredItems:
- *ref_15
- *ref_16
- *ref_17
- *ref_18
- *ref_19
- *ref_20
- *ref_21
- *ref_22
- *ref_23
- *ref_24
- *ref_25
- *ref_26
- *ref_27
- *ref_39
- *ref_40
- *ref_41
- name: External
displayData:
sortBy: alphabetical
rows: 1
cols: 2
collapsed: false
hideForGuests: false
items:
- &ref_28
title: Kolak Pisang
description: Pengajuan Akta Dukcapil
icon: banana-fruit-healthy.svg
url: https://kolakpisang.rssa.top/kolak-pisang/login
target: newtab
id: 0_835_kolakpisang
- &ref_29
title: Vclaim BPJS
description: Virtual Claim BPJS
icon: https://vclaim.bpjs-kesehatan.go.id/VClaim/image/bpjsIcon.ico
url: https://vclaim.bpjs-kesehatan.go.id/vclaim
target: newtab
id: 1_835_vclaimbpjs
- &ref_30
title: Emaster BKD
description: Master Provinsi Jawa Timur
icon: bkd.png
url: https://master.bkd.jatimprov.go.id/
target: newtab
id: 2_835_emasterbkd
- &ref_31
title: PTT-PK BKD
description: Login Area PTT-PK
icon: bkd.png
url: https://bkd.jatimprov.go.id/pttpk/personal/
target: newtab
id: 3_835_pttpkbkd
- &ref_32
title: Aplicares BPJS
description: Informasi Ketersediaan Tempat Tidur BPJS
icon: >-
https://faskes.bpjs-kesehatan.go.id/aplicares/libs/assets/images/pavicon.ico
url: https://faskes.bpjs-kesehatan.go.id
target: newtab
id: 4_835_aplicaresbpjs
- &ref_33
title: SIPP BPJS
description: Saluran Informasi Penanganan Pengaduan BPJS
icon: >-
https://sipp.bpjs-kesehatan.go.id/sipp/libs/assets/images/logo-sipp.png
url: https://sipp.bpjs-kesehatan.go.id
target: newtab
id: 5_835_sippbpjs
- &ref_34
title: Lupis BPJS
description: Luar Paket Inacbg BPJS
icon: >-
https://lupis.bpjs-kesehatan.go.id/lupis/lupis/4299133C4AD9E4D6AC3B70380119FD5C.cache.png
url: https://lupis.bpjs-kesehatan.go.id
target: newtab
id: 6_835_lupisbpjs
- &ref_35
title: Apotek BPJS
description: Apotek BPJS
icon: bpjs.svg
url: https://apotek.bpjs-kesehatan.go.id
target: newtab
id: 7_835_apotekbpjs
- &ref_42
title: SIPNAP
description: Sistem Pelaporan Narkotika dan Psikotropika
#icon: altair.svg
url: http://sipnap.kemkes.go.id
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_43
title: SIMONA
description: Sistem Informasi Monitoring dan Pembinaan Fasilitas Pelayanan Kefarmasian
#icon: altair.svg
url: https://simona.kemkes.go.id/simona_Login/
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_44
title: SIMO
description: Sistem Informasi Manajemen Obat (Mandiri Inhealth)
#icon: altair.svg
url: https://simo2.inhealth.co.id
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_45
title: e-MESO
description: Sistem pelaporan efek samping penggunaan obat ke BPOM
#icon: altair.svg
url: https://e-meso.pom.go.id/ADR
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_46
title: Ditjen Yankes
description: aplikasi untuk pelaporan terkait covid mulai dari informasi pasien,fasyankes,logistik,nakes, oksigen
#icon: altair.svg
url: https://sirs.kemkes.go.id/fo/login
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_47
title: e-Monev Obat
description: aplikasi pelaporan Rencana Kebutuhan Obat (RKO) tahunan
#icon: altair.svg
url: https://monevkatalogobat.kemkes.go.id/#front/home
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_48
title: SITB
description: Sistem Informasi Tuberkolusis
#icon: altair.svg
url: http://jatim.sitb.id/sitb/app
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_49
title: SIHA
description: Sistem Informasi HIV AIDS
#icon: altair.svg
url: https://sihapims2.kemkes.go.id/login
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_50
title: SIHEPI
description: Sistem Informasi Hepatitis dan PISP
#icon: altair.svg
url: https://sihepi.kemkes.go.id/
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_51
title: e-Katalog 5.0
description: katalog elektronik yang disusun dan dikelola kementerian/kelembagaan
#icon: altair.svg
url: https://e-katalog.lkpp.go.id
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_52
title: Cek BPOM
description: web/aplikasi dari BPOM yang memuat obat-obat yang sudah mendapatkan ijin edar
#icon: altair.svg
url: https://cekbpom.pom.go.id/
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_53
title: HFIS
description: sistem informasi bpjs kesehatan untuk menambah, menghapus, dan mengelola dokter aktif di rumah sakit
#icon: altair.svg
url: https://hfis.bpjs-kesehatan.go.id/hfis/login
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_54
title: INHEALTH
description: aplikasi untuk membuat, menghapus, dan mengolah surat jaminan peserta asuransi mandiri inhealth
#icon: altair.svg
url: https://pelkesonline.inhealth.co.id/Account/Login
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
- &ref_55
title: SUKMA-E JATIM RSSA
description: SISTEM SURVEY KEPUASAN MASYARAKAT PADA RSSA
#icon: altair.svg
url: https://sukma.jatimprov.go.id/fe/survey?idUser=1478&idEvent=469
#displayData:
# hideForGuests: false
# showForKeycloakUsers:
# roles:
# - stim
target: newtab
#id: 6_921_saturssa
filteredItems:
- *ref_28
- *ref_29
- *ref_30
- *ref_31
- *ref_32
- *ref_33
- *ref_34
- *ref_35
- *ref_42
- *ref_43
- *ref_44
- *ref_45
- *ref_46
- *ref_47
- *ref_48
- *ref_49
- *ref_50
- *ref_51
- *ref_52
- *ref_53
- *ref_54
- *ref_55
- name: Publik
displayData:
sortBy: alphabetical
rows: 1
cols: 2
collapsed: false
hideForGuests: false
items:
- &ref_36
title: Sijakabara
description: Panduan Stabilisasi Prehospital
icon: baby-newborn.svg
url: https://sijakabara.rssa.top
target: newtab
id: 0_615_sijakabara
- &ref_37
title: Teman RSSA
description: Telenutrition Pemandu Gizi Masyarakat
icon: teman-rssa-128.png
url: https://www.temanrssa.com
target: newtab
id: 1_615_temanrssa
- &ref_38
title: Pelatihan RSSA
description: Website Instalasi Pelatihan RSSA
icon: rssa.svg
url: https://www.pelatihanrssaifulanwar.com/
target: newtab
id: 2_615_pelatihanrssa
filteredItems:
- *ref_36
- *ref_37
- *ref_38

BIN
public/favicon.ico Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

54
public/index.html Normal file
View File

@@ -0,0 +1,54 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Encoding and Viewport -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- Favicon, App Icon -->
<link rel="icon" type="image/png" sizes="64x64" href="<%= BASE_URL %>/web-icons/favicon-64x64.png">
<link rel="icon" type="image/png" sizes="32x32" href="web-icons/favicon-32x32.png">
<link rel="icon" type="image/png" href="/favicon.ico" />
<link rel="stylesheet" type="text/css" href="/loading-screen.css" />
<!-- Default Page Title -->
<title>Portal RSSA</title>
</head>
<body>
<!-- built files will be auto injected -->
<div id="app">
<!-- Loading screen, will be replaced when app loaded -->
<div class="loading-placeholder" id="loader">
<h1>Portal RSSA</h1>
<p class="loading">Loading... </p>
<!-- Error message, only visible if app not mounted within 5 secs -->
<div class="catastrophic-error" id="err-wrap" style="display:none;">
<p class="err-l1">It looks like something's gone wrong...</p>
<p class="err-l2">
This is likely caused by the app source not being found at the current domain
</p>
<p class="err-l2">
If you need additional support, check the browser console then
<a href="https://github.com/Lissy93/dashy/blob/master/.github/SUPPORT.md">
raise a ticket
</a>
</p>
</div>
</div>
</div>
<!-- Devices without JS enabled -->
<noscript>
<strong>Sorry, JavaScript needs to be enabled to run Portal RSSA 😥</strong>
</noscript>
<!-- Show error message if app not mounted within reasonable time frame -->
<script>
setTimeout(() => {
const loaderElem = document.getElementById('loader');
if (loaderElem) loaderElem.classList.add('still-not-loaded');
}, 7500);
</script>
</body>
</html>

265
public/initialization.html Normal file
View File

@@ -0,0 +1,265 @@
<!doctype html>
<!-- Dashy: Licensed under MIT, (C) 2021 Alicia Sykes <https://aliciasykes.com> -->
<!-- This is the default page, displayed while the app is still building -->
<html lang="en">
<head>
<title>Portal RSSA</title>
<meta name="description" content="Welcome to Portal RSSA">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Fredoka+One&display=swap" rel="stylesheet">
</head>
<body>
<!-- Dashy Title Wavey Text -->
<svg viewbox="0 0 100 20">
<defs>
<linearGradient id="gradient" x1="0" x2="0" y1="0" y2="1">
<stop offset="5%" stop-color="#00CCB4" />
<stop offset="95%" stop-color="#1186cf" />
</linearGradient>
<pattern id="wave" x="0" y="0" width="120" height="20" patternUnits="userSpaceOnUse">
<path id="wavePath" d="M-40 9 Q-30 7 -20 9 T0 9 T20 9 T40 9 T60 9 T80 9 T100 9 T120 9 V20 H-40z"
mask="url(#mask)" fill="url(#gradient)">
<animateTransform attributeName="transform" begin="0s" dur="3s" type="translate" from="0,0" to="40,0"
repeatCount="indefinite" />
</path>
</pattern>
</defs>
<text text-anchor="middle" x="50" y="15" font-size="17" fill="url(#wave)" fill-opacity="0.8">Portal RSSA</text>
<text text-anchor="middle" x="50" y="15" font-size="17" fill="url(#gradient)" fill-opacity="0.5">Portal RSSA</text>
</svg>
<!-- Progress Bar -->
<div class="progress-outer" id="bar-outer">
<div class="progress-inner" id="bar"></div>
</div>
<!-- Status label, with animated dots -->
<div>
<h2 id="status-text">Initializing</h2>
<span id="dots" class="dots-cont">
<span class="dot dot-1"></span>
<span class="dot dot-2"></span>
<span class="dot dot-3"></span>
<span class="dot dot-4"></span>
</span>
</div>
<p class="time-note" id="note">This may take a minute or two</p>
<style lang="css">
/* Page Layout Styles */
body,
html {
margin: 0;
padding: 0;
height: 100%;
}
body {
background: #141b33;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
svg {
font-family: 'Fredoka One', 'Cabin Condensed', 'Courier New', Courier, monospace;
font-weight: bold;
max-width: 80%;
height: auto;
}
h2 {
color: #fff;
font-family: 'Courier New', Courier, monospace;
display: inline;
}
/* Animated Dots */
.dots-cont {
display: inline;
}
.dot {
width: 4px;
height: 4px;
background: #fff;
display: inline-block;
border-radius: 35%;
right: 0px;
bottom: 0px;
margin: 0px 2.5px;
position: relative;
animation: jump 1s infinite;
}
.dots-cont .dot-1 { -webkit-animation-delay: 100ms; animation-delay: 100ms; }
.dots-cont .dot-2 { -webkit-animation-delay: 200ms; animation-delay: 200ms; }
.dots-cont .dot-3 { -webkit-animation-delay: 300ms; animation-delay: 300ms; }
.dots-cont .dot-4 { -webkit-animation-delay: 400ms; animation-delay: 400ms; }
@keyframes jump {
0% { bottom: 0px; }
20% { bottom: 5px; }
40% { bottom: 0px; }
}
/* Little note */
p.time-note, p.time-note a {
font-size: 1rem;
color: #808080a6;
font-family: Tahoma, 'Trebuchet MS', sans-serif;
}
/* Progress Bar */
.progress-outer {
position: relative;
margin: 1rem;
height: 0.5rem;
width: 20rem;
border: 1px solid #fff;
border-radius: 6px;
}
.progress-outer .progress-inner {
position: absolute;
background-color: #fff;
width: 0px;
height: 0.5rem;
border-radius: 15px;
}
#bar.stage-0 { animation: progress-0 8s infinite linear; }
#bar.stage-1 { animation: progress-1 8s infinite linear; }
#bar.stage-2 { animation: progress-2 8s infinite linear; }
#bar.stage-3 { animation: progress-3 8s infinite linear; }
#bar.stage-4 { animation: progress-4 8s infinite linear; }
#bar.stage-5 { animation: progress-5 8s infinite linear; }
#bar.stage-6 { animation: progress-6 8s infinite linear; }
#bar.stage-7 { animation: progress-7 8s infinite linear; }
#bar.stage-8 { animation: progress-8 8s infinite linear; }
@keyframes progress {
0% { width: 0%; }
25% { width: 50%; }
50% { width: 75%; }
75% { width: 85%; }
100% { width: 100%; }
}
@keyframes progress-0 {
0% { width: 0%; }
50% { width: 20%; }
100% { width: 30%; }
}
@keyframes progress-1 {
0% { width: 30%; }
50% { width: 42%; }
100% { width: 50%; }
}
@keyframes progress-2 {
0% { width: 50%; }
50% { width: 60%; }
100% { width: 65%; }
}
@keyframes progress-3 {
0% { width: 65%; }
100% { width: 75%; }
}
@keyframes progress-4 {
0% { width: 75%; }
100% { width: 85%; }
}
@keyframes progress-5 {
0% { width: 85%; }
100% { width: 90%; }
}
@keyframes progress-6 {
0% { width: 90%; }
100% { width: 94%; }
}
@keyframes progress-7 {
0% { width: 94%; }
50% { width: 96%; }
75% { width: 90%; }
100% { width: 96%; }
}
@keyframes progress-8 {
0% { width: 95%; }
50% { width: 97%; }
75% { width: 94%; }
100% { width: 98%; }
}
.hide { display: none; }
</style>
<script>
const refreshRate = 8000;
// Refresh at interval
setTimeout(() => { location.reload(); }, refreshRate);
// Get current stage
let initStage = parseInt(sessionStorage.getItem('initStage') || 0);
// Check if stage in session storage is old, and if so, reset it
const now = Math.round(Date.now()/1000);
const buildStarted = sessionStorage.getItem('buildStarted');
if (!buildStarted) { // First time build
sessionStorage.setItem('buildStarted', now);
} else if ((now - parseInt(buildStarted)) > 600) {
initStage = 0;
sessionStorage.setItem('buildStarted', now);
}
// Grab elements from page
const statusTextElem = document.getElementById('status-text');
const progressBarElem = document.getElementById('bar');
const progressOuterElem = document.getElementById('bar-outer');
const loadingDotsElem = document.getElementById('dots');
const noteElem = document.getElementById('note');
// Based on stage, modify element content/ styles
if (initStage === 0) {
statusTextElem.innerHTML = 'Initializing'
progressBarElem.classList.add('stage-0');
} else if (initStage === 1) {
statusTextElem.innerHTML = 'Running Checks'
progressBarElem.classList.add('stage-1');
} else if (initStage === 2) {
statusTextElem.innerHTML = 'Building'
progressBarElem.classList.add('stage-2');
} else if (initStage === 3) {
statusTextElem.innerHTML = 'Building'
progressBarElem.classList.add('stage-3');
} else if (initStage === 4) {
statusTextElem.innerHTML = 'Finishing Off'
progressBarElem.classList.add('stage-4');
} else if (initStage === 5) {
statusTextElem.innerHTML = 'Almost Done'
progressBarElem.classList.add('stage-5');
} else if (initStage === 6) {
statusTextElem.innerHTML = 'Not Long Left'
progressBarElem.classList.add('stage-6');
} else if (initStage === 7) {
statusTextElem.innerHTML = 'Taking Longer than Expected'
progressBarElem.classList.add('stage-7');
noteElem.innerHTML = 'See the console for more info';
} else if (initStage >= 8) {
const docsLink = '<a href="https://github.com/Lissy93/dashy/tree/master/docs#readme">Documentation</a>';
statusTextElem.innerHTML = 'Possible Error, Check Logs'
noteElem.innerHTML = 'For troubleshooting, please see the ' + docsLink;
progressOuterElem.classList.add('hide');
loadingDotsElem.classList.add('hide');
} else {
statusTextElem.innerHTML = 'Building App'
progressOuterElem.classList.add('hide')
}
// Iterate the stage number
sessionStorage.setItem('initStage', initStage + 1)
</script>
</body>
</html>

7
public/item-icons/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
# Place any custom icons used by your instance of Dashy here.
# For more info, see Icon docs at: https://git.io/JZwc5
# Ignore everything in this directory
*
# Except this file
!.gitignore

63
public/loading-screen.css Normal file
View File

@@ -0,0 +1,63 @@
/* Styles applied to index.html for the loading screen, prior to the app being injected */
/* Dashy - Licensed under MIT, (C) Alicia Sykes 2022 */
body { margin: 0; }
#app .loading-placeholder {
position: absolute;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
cursor: progress;
background: #121212;
}
#app .loading-placeholder h1 {
font-size: 20vh;
margin: 1rem auto;
font-family: Tahoma, monospace;
cursor: progress;
color: #0c0c0c;
text-shadow: 0px 4px 4px #090909, 0 0 0 #000, 0px 2px 2px #000000;
}
#app .loading-placeholder p.loading {
font-size: 2rem;
opacity: 0.75;
font-family: monospace;
cursor: progress;
color: #0c0c0c;
display: flex;
flex-direction: column;
align-items: center;
text-shadow: 0 1px 1px #090909, 0 0 0 #000, 0 1px 1px #000000;
}
#app .loading-placeholder .catastrophic-error p {
color: #e11a4bfc;
margin: 0.5rem 0;
font-weight: bold;
font-size: 4vh;
text-align: center;
font-family: monospace;
text-shadow: 1px 2px 1px #090909, 0 0 0 #000, 0 1px 1px #000000
}
#app .loading-placeholder .catastrophic-error p.err-l2 {
opacity: 0.75;
font-size: 2vh;
font-weight: normal;
padding: 0 1rem;
}
#app .loading-placeholder .catastrophic-error p.err-l2 a {
color: #e11a4bfc;
}
#app .loading-placeholder.still-not-loaded { cursor: default; }
#app .loading-placeholder.still-not-loaded p.loading { display: none; }
#app .loading-placeholder.still-not-loaded .catastrophic-error { display: block !important; }
@media (max-width: 780px) {
.loading-placeholder h1 { font-size: 12vh !important; }
#app .loading-placeholder .catastrophic-error p { font-size: 2.5vh !important; }
#app .loading-placeholder .catastrophic-error p.err-l2 { font-size: 1.2vh !important; }
}
::selection { background-color: #e11a4bfc; color: #121212; }

38
public/manifest.json Normal file
View File

@@ -0,0 +1,38 @@
{
"name": "Dashy Web",
"short_name": "Dashy",
"description": "A Dashboard for your Homelab",
"scope": "/",
"start_url": "./",
"display": "standalone",
"background_color": "#0b1021",
"theme_color": "#4DBA87",
"lang": "en-GB",
"orientation": "portrait-primary",
"icons": [
{
"src": "./web-icons/dashy-pwa_512x512.png",
"sizes": "512x512"
},
{
"src": "./web-icons/dashy-pwa_192x192.png",
"sizes": "192x192"
},
{
"src": "./web-icons/dashy-pwa_144x144.png",
"sizes": "144x144"
},
{
"src": "./web-icons/dashy-pwa_96x96.png",
"sizes": "96x96"
},
{
"src": "./web-icons/dashy-pwa_72x72.png",
"sizes": "72x72"
},
{
"src": "./web-icons/dashy-pwa_48x48.png",
"sizes": "48x48"
}
]
}

2
public/robots.txt Normal file
View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow:

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Binary file not shown.

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<font id="WeatherIcons" horiz-adv-x="514.451">
<font-face font-family="WeatherIcons"
units-per-em="512" ascent="512"
descent="0" />
<missing-glyph horiz-adv-x="0" />
<glyph glyph-name="01d"
unicode="&#xEA02;"
horiz-adv-x="512" d=" M256 132.414C324.414 132.414 379.586 188.028 379.586 256C379.586 323.972 323.972 379.586 256 379.586C188.028 379.586 132.414 323.972 132.414 256C132.414 188.028 187.586 132.414 256 132.414zM256 343.834C304.552 343.834 343.834 304.552 343.834 256C343.834 207.448 304.552 168.166 256 168.166C207.448 168.166 168.166 207.448 168.166 256C168.166 304.552 207.448 343.834 256 343.834z M274.097 436.966L274.097 493.903C274.097 504.055 266.152 512 256 512C245.848 512 237.903 504.055 237.903 493.903L237.903 436.966C237.903 426.814 245.848 418.8690000000001 256 418.8690000000001C266.152 418.8690000000001 274.097 426.814 274.097 436.966z M237.903 75.034L237.903 18.097C237.903 7.945 245.848 0 256 0C266.152 0 274.097 7.945 274.097 18.097L274.097 75.034C274.097 85.186 266.152 93.131 256 93.131C245.848 93.131 237.903 85.186 237.903 75.034z M396.8 371.2L436.966 411.366C444.028 418.428 444.028 429.903 436.966 436.966C429.903 444.028 418.428 444.028 411.366 436.966L371.2 396.8C364.138 389.738 364.138 378.262 371.2 371.2C374.731 367.669 379.145 365.903 384 365.903C388.855 365.903 393.269 367.669 396.8 371.2L396.8 371.2z M75.034 75.034C78.566 71.503 82.979 69.738 87.834 69.738C92.248 69.738 97.103 71.503 100.634 75.034L140.8 115.2C147.862 122.262 147.862 133.738 140.8 140.8C133.738 147.862 122.262 147.862 115.2 140.8L75.034 100.634C67.972 93.572 67.972 82.097 75.034 75.034z M512 256C512 266.152 504.055 274.097 493.903 274.097L436.966 274.097C426.814 274.097 418.8690000000001 266.152 418.8690000000001 256C418.8690000000001 245.848 426.814 237.903 436.966 237.903L493.903 237.903C503.614 237.903 512 245.848 512 256z M18.097 237.903L75.034 237.903C85.186 237.903 93.131 245.848 93.131 256C93.131 266.152 85.186 274.097 75.034 274.097L18.097 274.097C7.945 274.097 0 266.152 0 256C0 245.848 8.386 237.903 18.097 237.903z M424.166 69.738C428.579 69.738 433.4340000000001 71.503 436.966 75.034C444.028 82.097 444.028 93.572 436.966 100.634L396.8 140.8C389.738 147.862 378.262 147.862 371.2 140.8C364.138 133.738 364.138 122.262 371.2 115.2L411.366 75.034C414.897 71.503 419.752 69.738 424.166 69.738L424.166 69.738z M140.8 371.2C147.862 378.262 147.862 389.738 140.8 396.8L100.634 436.966C93.572 444.028 82.097 444.028 75.034 436.966C67.972 429.903 67.972 418.428 75.034 411.366L115.2 371.2C118.731 367.669 123.145 365.903 128 365.903C132.855 365.903 137.269 367.669 140.8 371.2z" />
<glyph glyph-name="01n"
unicode="&#xEA01;"
horiz-adv-x="512" d=" M337.556 322.748L332.533 293.456C331.759 288.958 333.572 284.499 337.256 281.828C339.3 280.341 341.716 279.555 344.246 279.555C346.168 279.555 348.082 280.029 349.778 280.921L376.089 294.752L402.386 280.926C404.087 280.029 406.004 279.554 407.93 279.554C410.451 279.554 412.863 280.336 414.918 281.823C418.608 284.505 420.421 288.962 419.647 293.45L414.623 322.747L435.907 343.495C439.1739999999999 346.68 440.3259999999999 351.353 438.9149999999999 355.676C437.5079999999999 360.013 433.8319999999999 363.115 429.318 363.77L399.902 368.045L386.7459999999999 394.705C384.728 398.788 380.644 401.325 376.0899999999999 401.325C371.529 401.325 367.4439999999999 398.785 365.431 394.699L352.274 368.044L322.8589999999999 363.769C318.353 363.115 314.6769999999999 360.017 313.2609999999999 355.677C311.8549999999999 351.347 313.0059999999999 346.681 316.2699999999999 343.492L337.556 322.748zM358.816 352.627C361.455 353.01 363.735 354.6670000000001 364.916 357.058L376.089 379.6950000000001L387.26 357.0590000000001C388.438 354.668 390.72 353.011 393.359 352.6280000000001L418.343 348.997L400.266 331.376C398.358 329.515 397.486 326.8350000000001 397.936 324.207L402.203 299.326L379.858 311.074C378.678 311.694 377.384 312.004 376.089 312.004C374.794 312.004 373.499 311.694 372.318 311.072L349.974 299.326L354.24 324.206C354.691 326.834 353.82 329.515 351.911 331.376L333.832 348.996L358.816 352.627z M445.893 82.507C437.604 81.607 429.239 81.152 421.029 81.152C366.835 81.152 314.324 100.501 273.1670000000001 135.635C269.7650000000001 138.539 264.651 138.134 261.7480000000001 134.733C258.8440000000001 131.33 259.2480000000001 126.217 262.6500000000001 123.313C306.737 85.677 362.9840000000001 64.95 421.029 64.95C421.66 64.95 422.293 64.953 422.925 64.958C381.373 33.367 330.735 16.199 277.985 16.199C145.759 16.199 38.185 123.774 38.185 256C38.185 383.344 137.957 487.8209999999999 263.437 495.3639999999999C208.891 449.204 176.967 381.203 176.967 309.01C176.967 246.365 200.665 186.814 243.695 141.3229999999999C246.768 138.0729999999999 251.894 137.9309999999999 255.146 141.005C258.396 144.0799999999999 258.538 149.2049999999999 255.464 152.456C215.291 194.925 193.167 250.524 193.167 309.01C193.167 384.148 230.215 454.4299999999999 292.272 497.015C295.15 498.99 296.439 502.5889999999999 295.47 505.943C294.501 509.297 291.49 511.653 288.002 511.788C284.296 511.931 281.02 512 277.986 512C209.604 512 145.317 485.371 96.966 437.02C48.614 388.668 21.986 324.381 21.986 256.001S48.614 123.333 96.966 74.982C145.317 26.629 209.605 0 277.986 0C342.874 0 404.773 24.335 452.282 68.523C454.837 70.9 455.585 74.645 454.133 77.8200000000001C452.683 80.995 449.3690000000001 82.882 445.893 82.507z M327.465 186.76C327.465 168.623 342.222 153.867 360.36 153.867C378.497 153.867 393.253 168.6229999999999 393.253 186.76C393.253 204.898 378.497 219.654 360.3599999999999 219.654C342.222 219.654 327.465 204.898 327.465 186.76zM377.053 186.76C377.053 177.555 369.564 170.067 360.36 170.067C351.154 170.067 343.665 177.556 343.665 186.76S351.1550000000001 203.454 360.36 203.454S377.053 195.966 377.053 186.76z M472.699 255.998C463.138 255.998 455.386 248.248 455.386 238.684C455.386 229.121 463.137 221.369 472.699 221.369C482.264 221.369 490.014 229.121 490.014 238.684C490.014 248.249 482.264 255.998 472.699 255.998z" />
<glyph glyph-name="02d"
unicode="&#xEA03;"
horiz-adv-x="512" d=" M326.4 467.2C315.795 467.2 307.2 458.604 307.2 448V435.2C307.2 424.596 315.795 416 326.4 416C337.002 416 345.6 424.596 345.6 435.2V448C345.6 458.604 337.002 467.2 326.4 467.2z M422.4 281.6C422.4 334.534 379.334 377.6 326.4 377.6C305.455 377.6 285.548 370.971 268.829 358.428C258.714 350.839 250.172 341.233 243.746 330.3930000000001C229.643 336.058 214.314 339.148 198.398 339.148C133.21 339.148 79.838 287.588 76.926 223.106C33.499 216.934 0 179.506 0 134.4C0 84.993 40.195 44.8 89.6 44.8H313.6C373.5920000000001 44.8 422.4000000000001 93.608 422.4000000000001 153.6C422.4000000000001 178.482 413.985 201.423 399.877 219.773C414.363 236.897 422.4 258.565 422.4 281.6zM313.6 83.2H89.6C61.37 83.2 38.4 106.168 38.4 134.4S61.37 185.6 89.6 185.6H96C106.605 185.6 115.2 194.196 115.2 204.8V217.549C115.2 263.427 152.525 300.749 198.4 300.749C236.37 300.749 269.5 275.112 278.967 238.405C281.155 229.925 288.803 224 297.559 224H313.6C352.42 224 384 192.419 384 153.6C384 114.781 352.42 83.2 313.6 83.2zM371.443 245.6840000000001C354.673 256.256 334.848 262.4 313.6 262.4H311.468C303.927 281.4600000000001 291.814 297.923 276.625 310.669C286.755 328.1330000000001 305.445 339.2000000000001 326.4 339.2000000000001C358.161 339.2000000000001 384 313.362 384 281.6C384 268.303 379.525 255.77 371.443 245.6840000000001z M492.8 300.8H480C469.395 300.8 460.8 292.204 460.8 281.6S469.395 262.4000000000001 480 262.4000000000001H492.8C503.402 262.4000000000001 512 270.9960000000001 512 281.6S503.402 300.8 492.8 300.8z M457.637 412.841C450.14 420.337 437.983 420.337 430.484 412.838L421.434 403.787C413.937 396.289 413.937 384.131 421.437 376.633C425.185 372.885 430.097 371.01 435.011 371.01C439.924 371.01 444.839 372.885 448.588 376.636L457.638 385.687C465.138 393.187 465.138 405.344 457.637 412.841z M231.364 403.789L222.314 412.839C214.814 420.336 202.66 420.337 195.159 412.839C187.662 405.342 187.662 393.1860000000001 195.159 385.6860000000001L204.21 376.636C207.96 372.886 212.873 371.01 217.787 371.01C222.7 371.01 227.615 372.885 231.361 376.634C238.861 384.132 238.861 396.288 231.364 403.789z" />
<glyph glyph-name="02n"
unicode="&#xEA04;"
horiz-adv-x="514.451" d=" M513.493 206.586C511.776 210.732 507.979 213.648 503.53 214.24C462.581 219.674 427.344 246.707 411.568 284.791C395.793 322.876 401.592 366.911 426.705 399.708C429.433 403.271 430.057 408.019 428.34 412.166C426.623 416.312 422.826 419.228 418.377 419.818C393.88 423.072 368.837 419.781 345.96 410.306C302.692 392.384 272.2200000000001 355.1040000000001 262.326 311.304C242.283 333.942 212.747 347.953 181.04 347.953C121.795 347.953 73.595 300.707 73.595 242.636C73.595 242.431 73.595 242.229 73.597 242.024C33.858 239.0350000000001 2.451 206.35 2.451 166.602C2.451 124.894 37.032 90.963 79.539 90.963L286.34 90.963C323.599 90.963 356.057 111.472 372.609 141.578C381.7320000000001 139.756 390.917 138.833 400.082 138.833C418.364 138.833 436.552 142.455 453.926 149.651C476.803 159.128 496.835 174.508 511.86 194.13C514.588 197.691 515.212 202.44 513.493 206.586zM286.338 116.113L79.539 116.113C50.9 116.113 27.601 138.763 27.601 166.602C27.601 194.443 50.9 217.095 79.539 217.095C81.306 217.095 83.272 216.963 85.719 216.676C89.604 216.217 93.472 217.598 96.197 220.402C98.92 223.203 100.186 227.113 99.622 230.981C99.041 234.9700000000001 98.745 238.892 98.745 242.636C98.745 286.8400000000001 135.662 322.803 181.04 322.803C217.033 322.803 249.352 299.426 259.776 265.915C259.9100000000001 265.444 260.073 264.986 260.259 264.54C262.447 259.1190000000001 268.138 255.86 273.993 256.852C278.05 257.533 282.203 257.877 286.338 257.877C326.476 257.877 359.129 226.079 359.129 186.996C359.129 147.911 326.476 116.113 286.338 116.113zM444.3 172.887C424.226 164.572 402.8450000000001 162.085 381.772 165.486C383.394 172.405 384.281 179.598 384.281 186.994C384.281 239.947 340.344 283.025 286.34 283.025C285.575 283.025 284.811 282.973 284.046 282.957C285.136 328.456 312.724 369.315 355.586 387.068C367.95 392.19 381.085 395.111 394.352 395.751C374.641 358.833 372.078 314.409 388.335 275.165C404.588 235.926 437.817 206.324 477.856 194.157C468.019 185.229 456.666 178.009 444.3 172.887z" />
<glyph glyph-name="03d"
unicode="&#xEA05;"
horiz-adv-x="512" d=" M320 384C372.562 384 415.375 341.562 416 289.187C415.75 287.249 415.562 285.312 415.5 283.312L414.688 259.812L436.938 252.062C462.688 243.094 480 218.938 480 192C480 156.688 451.312 128 416 128H96C60.719 128 32 156.688 32 192C32 226.938 60.188 255.438 95 256C96.5 255.781 98.063 255.594 99.625 255.5L123.938 253.906L131.938 276.875C140.938 302.687 165.063 320 192 320C195.125 320 198.563 319.625 203.188 318.812L225.594 314.781L236.75 334.625C253.875 365.062 285.75 384 320 384M320 416C272.062 416 230.781 389.312 208.844 350.312C203.375 351.281 197.781 352 192 352C150.062 352 114.781 324.937 101.719 287.437C99.813 287.562 97.969 288 96 288C43 288 0 245 0 192S43 96 96 96H416C469 96 512 139 512 192C512 233.938 484.938 269.25 447.438 282.313C447.5 284.25 448 286.062 448 288C448 358.687 390.688 416 320 416L320 416z" />
<glyph glyph-name="03n"
unicode="&#xEA06;"
horiz-adv-x="512" d=" M320 384C372.562 384 415.375 341.562 416 289.187C415.75 287.249 415.562 285.312 415.5 283.312L414.688 259.812L436.938 252.062C462.688 243.094 480 218.938 480 192C480 156.688 451.312 128 416 128H96C60.719 128 32 156.688 32 192C32 226.938 60.188 255.438 95 256C96.5 255.781 98.063 255.594 99.625 255.5L123.938 253.906L131.938 276.875C140.938 302.687 165.063 320 192 320C195.125 320 198.563 319.625 203.188 318.812L225.594 314.781L236.75 334.625C253.875 365.062 285.75 384 320 384M320 416C272.062 416 230.781 389.312 208.844 350.312C203.375 351.281 197.781 352 192 352C150.062 352 114.781 324.937 101.719 287.437C99.813 287.562 97.969 288 96 288C43 288 0 245 0 192S43 96 96 96H416C469 96 512 139 512 192C512 233.938 484.938 269.25 447.438 282.313C447.5 284.25 448 286.062 448 288C448 358.687 390.688 416 320 416L320 416z" />
<glyph glyph-name="04d"
unicode="&#xEA07;"
horiz-adv-x="512" d=" M320 384C372.562 384 415.375 341.562 416 289.187C415.75 287.249 415.562 285.312 415.5 283.312L414.688 259.812L436.938 252.062C462.688 243.094 480 218.938 480 192C480 156.688 451.312 128 416 128H96C60.719 128 32 156.688 32 192C32 226.938 60.188 255.438 95 256C96.5 255.781 98.063 255.594 99.625 255.5L123.938 253.906L131.938 276.875C140.938 302.687 165.063 320 192 320C195.125 320 198.563 319.625 203.188 318.812L225.594 314.781L236.75 334.625C253.875 365.062 285.75 384 320 384M320 416C272.062 416 230.781 389.312 208.844 350.312C203.375 351.281 197.781 352 192 352C150.062 352 114.781 324.937 101.719 287.437C99.813 287.562 97.969 288 96 288C43 288 0 245 0 192S43 96 96 96H416C469 96 512 139 512 192C512 233.938 484.938 269.25 447.438 282.313C447.5 284.25 448 286.062 448 288C448 358.687 390.688 416 320 416L320 416z" />
<glyph glyph-name="04n"
unicode="&#xEA08;"
horiz-adv-x="512" d=" M320 384C372.562 384 415.375 341.562 416 289.187C415.75 287.249 415.562 285.312 415.5 283.312L414.688 259.812L436.938 252.062C462.688 243.094 480 218.938 480 192C480 156.688 451.312 128 416 128H96C60.719 128 32 156.688 32 192C32 226.938 60.188 255.438 95 256C96.5 255.781 98.063 255.594 99.625 255.5L123.938 253.906L131.938 276.875C140.938 302.687 165.063 320 192 320C195.125 320 198.563 319.625 203.188 318.812L225.594 314.781L236.75 334.625C253.875 365.062 285.75 384 320 384M320 416C272.062 416 230.781 389.312 208.844 350.312C203.375 351.281 197.781 352 192 352C150.062 352 114.781 324.937 101.719 287.437C99.813 287.562 97.969 288 96 288C43 288 0 245 0 192S43 96 96 96H416C469 96 512 139 512 192C512 233.938 484.938 269.25 447.438 282.313C447.5 284.25 448 286.062 448 288C448 358.687 390.688 416 320 416L320 416z" />
<glyph glyph-name="09d"
unicode="&#xEA09;"
horiz-adv-x="512" d=" M431.401 370.45C431.989 375.45 432.55 381.241 432.55 385.488C432.55 455.248 376.363 512 307.313 512C263.363 512 222.816 488.572 200.274 451.19C186.281 460.87 169.727 466.063 152.416 466.063C105.527 466.063 67.377 427.522 67.377 380.149C67.377 374.937 67.853 369.7390000000001 68.762 364.635C28.498 349.899 1.294 311.3350000000001 1.294 267.078C1.294 210.755 45.48 168.292 104.082 168.292L398.3210000000001 168.292C454.998 168.292 501.109 214.865 501.109 272.111C501.114 316.603 472.376 356.326 431.401 370.45zM398.326 192.054L104.082 192.054C58.889 192.054 24.816 224.319 24.816 267.083C24.816 304.371 49.835 336.396 85.659 344.988C88.884 345.746 91.638 347.846 93.239 350.775C94.849 353.703 95.151 357.173 94.105 360.337C91.977 366.693 90.904 373.35 90.904 380.149C90.904 414.419 118.498 442.282 152.406 442.282C168.701 442.282 184.068 435.907 195.66 424.335C198.4 421.618 202.284 420.366 206.065 421.1190000000001C209.86 421.806 213.056 424.358 214.648 427.875C231.107 464.533 267.492 488.215 307.308 488.215C363.382 488.215 409.009 442.145 409.009 385.488C409.009 379.659 407.366 367.776 406.74 363.689C405.784 357.4840000000001 409.739 351.603 415.784 350.233C451.594 342.131 477.597 309.2820000000001 477.597 272.111C477.588 227.972 442.041 192.054 398.326 192.054zM132.185 135.241C125.725 136.131 119.798 131.621 118.889 125.133L111.036 68.998C110.132 62.505 114.619 56.483 121.041 55.561C121.606 55.485 122.161 55.462 122.707 55.462C128.484 55.462 133.512 59.727 134.351 65.664L142.19 121.799C143.098 128.292 138.607 134.309 132.185 135.241zM213.565 135.241C207.105 136.131 201.178 131.621 200.269 125.133L184.577 13.55C183.668 7.057 188.146 1.036 194.568 0.113C195.133 0.014 195.688 0 196.239 0C202.006 0 207.035 4.27 207.873 10.198L223.565 121.785C224.474 128.292 220.006 134.281 213.565 135.241zM297.855 135.241C291.404 136.131 285.449 131.621 284.545 125.133L268.867 13.55C267.944 7.057 272.421 1.036 278.853 0.113C279.4220000000001 0.014 279.968 0 280.519 0C286.287 0 291.324 4.27 292.153 10.198L307.841 121.785C308.749 128.292 304.281 134.281 297.855 135.241zM379.225 135.241C372.742 136.131 366.838 131.621 365.929 125.133L358.076 68.998C357.182 62.505 361.654 56.483 368.09 55.561C368.641 55.485 369.192 55.462 369.743 55.462C375.525 55.462 380.548 59.727 381.391 65.664L389.235 121.799C390.129 128.292 385.642 134.309 379.225 135.241z" />
<glyph glyph-name="09n"
unicode="&#xEA0A;"
horiz-adv-x="512" d=" M431.401 370.45C431.989 375.45 432.55 381.241 432.55 385.488C432.55 455.248 376.363 512 307.313 512C263.363 512 222.816 488.572 200.274 451.19C186.281 460.87 169.727 466.063 152.416 466.063C105.527 466.063 67.377 427.522 67.377 380.149C67.377 374.937 67.853 369.7390000000001 68.762 364.635C28.498 349.899 1.294 311.3350000000001 1.294 267.078C1.294 210.755 45.48 168.292 104.082 168.292L398.3210000000001 168.292C454.998 168.292 501.109 214.865 501.109 272.111C501.114 316.603 472.376 356.326 431.401 370.45zM398.326 192.054L104.082 192.054C58.889 192.054 24.816 224.319 24.816 267.083C24.816 304.371 49.835 336.396 85.659 344.988C88.884 345.746 91.638 347.846 93.239 350.775C94.849 353.703 95.151 357.173 94.105 360.337C91.977 366.693 90.904 373.35 90.904 380.149C90.904 414.419 118.498 442.282 152.406 442.282C168.701 442.282 184.068 435.907 195.66 424.335C198.4 421.618 202.284 420.366 206.065 421.1190000000001C209.86 421.806 213.056 424.358 214.648 427.875C231.107 464.533 267.492 488.215 307.308 488.215C363.382 488.215 409.009 442.145 409.009 385.488C409.009 379.659 407.366 367.776 406.74 363.689C405.784 357.4840000000001 409.739 351.603 415.784 350.233C451.594 342.131 477.597 309.2820000000001 477.597 272.111C477.588 227.972 442.041 192.054 398.326 192.054zM132.185 135.241C125.725 136.131 119.798 131.621 118.889 125.133L111.036 68.998C110.132 62.505 114.619 56.483 121.041 55.561C121.606 55.485 122.161 55.462 122.707 55.462C128.484 55.462 133.512 59.727 134.351 65.664L142.19 121.799C143.098 128.292 138.607 134.309 132.185 135.241zM213.565 135.241C207.105 136.131 201.178 131.621 200.269 125.133L184.577 13.55C183.668 7.057 188.146 1.036 194.568 0.113C195.133 0.014 195.688 0 196.239 0C202.006 0 207.035 4.27 207.873 10.198L223.565 121.785C224.474 128.292 220.006 134.281 213.565 135.241zM297.855 135.241C291.404 136.131 285.449 131.621 284.545 125.133L268.867 13.55C267.944 7.057 272.421 1.036 278.853 0.113C279.4220000000001 0.014 279.968 0 280.519 0C286.287 0 291.324 4.27 292.153 10.198L307.841 121.785C308.749 128.292 304.281 134.281 297.855 135.241zM379.225 135.241C372.742 136.131 366.838 131.621 365.929 125.133L358.076 68.998C357.182 62.505 361.654 56.483 368.09 55.561C368.641 55.485 369.192 55.462 369.743 55.462C375.525 55.462 380.548 59.727 381.391 65.664L389.235 121.799C390.129 128.292 385.642 134.309 379.225 135.241z" />
<glyph glyph-name="10d"
unicode="&#xEA0B;"
horiz-adv-x="512" d=" M98.59 109.285C92.277 110.12 86.348 105.687 85.446 99.264L79.423 56.097C78.53 49.646 82.959 43.665 89.324 42.754C89.875 42.683 90.421 42.64 90.967 42.64C96.658 42.64 101.647 46.898 102.468 52.789L108.482 95.956C109.375 102.407 104.946 108.359 98.59 109.285zM160.972 109.285C154.649 110.182 148.735 105.715 147.819 99.264L135.795 13.452C134.903 7.001 139.322 1.03 145.678 0.119C146.238 0.019 146.784 0 147.335 0C153.026 0 158.015 4.244 158.831 10.125L170.855 95.956C171.757 102.378 167.328 108.359 160.972 109.285zM225.566 109.285C219.21 110.182 213.305 105.715 212.413 99.264L200.389 13.452C199.487 7.001 203.902 1.03 210.272 0.119C210.818 0.019 211.378 0 211.914 0C217.615 0 222.595 4.244 223.425 10.125L235.449 95.956C236.341 102.378 231.922 108.359 225.566 109.285zM287.924 109.285C281.592 110.12 275.673 105.687 274.776 99.264L268.766 56.097C267.86 49.646 272.288 43.665 278.649 42.754C279.209 42.683 279.75 42.64 280.291 42.64C285.992 42.64 290.981 46.898 291.807 52.789L297.8210000000001 95.956C298.718 102.407 294.28 108.359 287.924 109.285zM417.914 341.216C408.715 393.91 358.96 429.169 306.983 419.884C288.029 416.49 271.026 407.676 257.35 394.29C249.836 396.236 242.004 397.38 233.901 397.38C201.604 397.38 171.733 380.6430000000001 154.365 353.738C144.164 360.094 132.378 363.502 120.117 363.502C84.022 363.502 54.664 333.735 54.664 297.166C54.664 293.976 54.877 290.81 55.319 287.692C25.851 275.7820000000001 6.114 246.86 6.114 213.808C6.114 170.58 39.854 137.96 84.601 137.96L300.769 137.96C344.04 137.96 379.252 173.656 379.252 217.535C379.252 226.216 377.795 234.651 375.1600000000001 242.598C407.301 263.4360000000001 424.683 302.449 417.914 341.216zM300.769 161.523L84.601 161.523C53.111 161.523 29.378 183.999 29.378 213.808C29.378 239.882 46.803 262.2870000000001 71.757 268.2920000000001C74.947 269.0560000000001 77.662 271.13 79.257 274.031C80.837 276.9360000000001 81.151 280.391 80.116 283.534C78.649 287.891 77.928 292.486 77.928 297.176C77.928 320.748 96.858 339.939 120.117 339.939C131.295 339.939 141.828 335.558 149.793 327.579C152.494 324.892 156.339 323.677 160.07 324.389C163.82 325.082 166.986 327.603 168.557 331.101C180.163 357.0320000000001 205.82 373.793 233.901 373.793C273.461 373.793 305.634 341.197 305.634 301.101C305.634 297.442 304.642 289.771 303.987 285.5080000000001C303.033 279.366 306.954 273.5320000000001 312.93 272.175C337.879 266.483 355.998 243.504 355.998 217.53C355.998 186.643 331.224 161.523 300.769 161.523zM364.504 263.678C355.556 276.361 343.044 286.41 328.291 292.049C328.623 295.192 328.884 298.481 328.884 301.097C328.884 336.522 309.864 367.456 281.687 384.179C290.35 390.445 300.266 394.717 311.032 396.644C350.453 403.741 388.062 377.002 395.006 337.096C400.014 308.525 387.644 279.741 364.504 263.678zM323.834 455.309L323.905 455.309C330.332 455.362 335.496 460.669 335.463 467.195L335.249 500.29C335.197 506.76 330.004 512 323.62 512L323.544 512C317.117 511.953 311.948 506.641 311.981 500.119L312.194 467.024C312.247 460.545 317.435 455.309 323.834 455.309zM494.257 323.3590000000001L494.166 323.3590000000001L461.513 323.145C455.086 323.093 449.9220000000001 317.786 449.955 311.288C450.007 304.785 455.195 299.573 461.585 299.573L461.661 299.573L494.323 299.7870000000001C500.75 299.834 505.919 305.146 505.886 311.644C505.839 318.142 500.65 323.3590000000001 494.257 323.3590000000001zM427.963 413.12C430.963 413.12 433.963 414.283 436.2320000000001 416.642L459.178 440.1910000000001C463.692 444.814 463.635 452.286 459.074 456.857C454.517 461.428 447.154 461.409 442.635 456.762L419.694 433.19C415.171 428.5660000000001 415.218 421.0950000000001 419.789 416.524C422.054 414.264 425.011 413.12 427.963 413.12zM203.294 416.642C205.568 414.283 208.568 413.12 211.568 413.12C214.52 413.12 217.473 414.264 219.737 416.528C224.318 421.1 224.356 428.5710000000001 219.841 433.194L196.9 456.767C192.377 461.414 185.019 461.428 180.462 456.862C175.891 452.29 175.844 444.819 180.358 440.1960000000001L203.294 416.642zM423.435 223.402C418.921 228.049 411.544 228.091 406.997 223.501C402.411 218.925 402.373 211.478 406.892 206.831L429.838 183.258C432.112 180.923 435.1070000000001 179.76 438.1070000000001 179.76C441.06 179.76 444.012 180.875 446.276 183.163C450.857 187.734 450.895 195.187 446.381 199.834L423.435 223.402z" />
<glyph glyph-name="10n"
unicode="&#xEA0C;"
horiz-adv-x="512" d=" M114.55 115.983C107.778 116.872 101.386 112.191 100.421 105.329L93.953 59.512C92.989 52.679 97.755 46.349 104.584 45.374C105.178 45.275 105.763 45.256 106.347 45.256C112.482 45.256 117.833 49.761 118.722 56.01L125.176 101.831C126.145 108.689 121.393 115.004 114.55 115.983zM181.589 115.983C174.779 116.934 168.421 112.191 167.451 105.357L154.53 14.276C153.551 7.413 158.308 1.098 165.147 0.119C165.745 0.048 166.339 0 166.924 0C173.035 0 178.386 4.505 179.285 10.759L192.206 101.841C193.175 108.665 188.433 115.004 181.589 115.983zM251.015 115.983C244.224 116.934 237.846 112.191 236.882 105.357L223.96 14.276C222.981 7.413 227.738 1.098 234.577 0.119C235.171 0.048 235.755 0 236.349 0C242.466 0 247.817 4.505 248.715 10.759L261.636 101.841C262.61 108.665 257.853 115.004 251.015 115.983zM318.031 115.983C311.254 116.872 304.863 112.191 303.907 105.329L297.454 59.512C296.4700000000001 52.679 301.246 46.349 308.066 45.374C308.664 45.275 309.2440000000001 45.256 309.843 45.256C315.969 45.256 321.32 49.761 322.2080000000001 56.01L328.662 101.831C329.631 108.689 324.874 115.004 318.031 115.983zM481.779 393.424C481.779 393.9940000000001 481.75 394.564 481.708 395.111C481.608 400.381 478.262 405.005 473.301 406.7440000000001C468.316 408.46 462.827 406.887 459.515 402.814C446.741 387.127 427.836 378.117 407.682 378.117C370.819 378.117 340.818 408.151 340.818 445.052C340.818 462.098 347.305 478.38 359.062 490.892C362.674 494.708 363.496 500.378 361.139 505.102C358.772 509.797 353.64 512.582 348.517 511.897C285.606 504.479 243.35 460.24 243.35 401.769C243.35 400.9940000000001 243.445 400.243 243.578 399.502C215.473 396.94 190.02 381.743 174.58 358.666C164.762 364.483 153.518 367.581 141.827 367.581C106.214 367.581 77.225 338.55 77.225 302.889C77.225 300.099 77.392 297.334 77.748 294.62C49.244 282.815 30.221 254.977 30.221 223.18C30.221 181.127 63.425 149.42 107.454 149.42L316.734 149.42C359.318 149.42 393.962 184.107 393.962 226.729C393.962 245.159 387.252 262.462 376.032 276.024C434.423 286.327 481.779 336.7630000000001 481.779 393.424zM316.724 174.46L107.445 174.46C77.672 174.46 55.218 195.407 55.218 223.184C55.218 247.544 71.703 268.449 95.317 274.076C98.739 274.889 101.657 277.103 103.358 280.202C105.064 283.257 105.387 286.921 104.261 290.262C102.916 294.264 102.222 298.531 102.222 302.894C102.222 324.754 119.981 342.5610000000001 141.818 342.5610000000001C152.306 342.5610000000001 162.21 338.483 169.671 331.07C172.574 328.209 176.699 326.897 180.729 327.6860000000001C184.759 328.423 188.162 331.093 189.858 334.814C200.893 359.174 225.282 374.909 251.989 374.909C289.589 374.909 320.174 344.305 320.174 306.6670000000001C320.174 303.231 319.21 295.818 318.616 291.93C317.594 285.401 321.8 279.227 328.2200000000001 277.773C351.819 272.4840000000001 368.956 251.004 368.956 226.739C368.966 197.912 345.532 174.46 316.724 174.46zM354.238 299.101C351.962 299.101 349.847 298.4410000000001 348.008 297.376C346.915 297.871 345.832 298.379 344.715 298.8210000000001C344.986 301.558 345.19 304.372 345.19 306.6620000000001C345.19 352.683 311.692 390.915 267.847 398.48C268.142 399.535 268.342 400.623 268.342 401.769C268.342 437.52 289.28 466.461 322.683 479.834C318.197 468.913 315.831 457.142 315.831 445.057C315.831 394.355 357.052 353.092 407.701 353.092C423.165 353.092 438.077 356.9310000000001 451.289 364.079C437.189 327.178 397.8450000000001 299.101 354.238 299.101z" />
<glyph glyph-name="11d"
unicode="&#xEA0D;"
horiz-adv-x="512" d=" M411.247 366.3300000000001C405.951 439.213 342.843 496.943 266.038 496.943C205.107 496.943 151.411 460.914 129.988 406.511C128.499 406.565 126.998 406.5900000000001 125.489 406.5900000000001C56.295 406.593 0 350.299 0 281.101C0 211.903 56.295 155.609 125.492 155.609L143.733 155.609L141.236 149.226C140.031 146.138 140.422 142.652 142.295 139.907C144.167 137.168 147.275 135.529 150.589 135.529L250.981 135.529L250.981 25.097C250.981 20.401 254.236 16.332 258.814 15.302C259.549 15.136 260.295 15.057 261.019 15.057C264.8330000000001 15.057 268.401 17.233 270.087 20.792L334.27 156.113C335.092 155.896 335.892 155.606 336.7850000000001 155.606C361.735 155.606 411.599 155.733 412.089 155.75C468.107 158.633 512 204.873 512 261.019C512.003 317.586 467.221 363.886 411.247 366.3300000000001zM271.058 69.693L271.058 145.572C271.061 151.115 266.5710000000001 155.612 261.021 155.612L165.294 155.612L230.902 323.27L230.902 215.603C230.902 210.059 235.392 205.563 240.942 205.563L335.501 205.563L271.058 69.693zM411.543 175.818C411.543 175.818 369.739 175.711 343.556 175.691L360.443 211.295C361.924 214.409 361.698 218.055 359.854 220.966C358.021 223.875 354.815 225.637 351.374 225.637L250.981 225.637L250.981 376.476C250.981 381.305 247.549 385.4460000000001 242.805 386.339C238.059 387.24 233.354 384.627 231.589 380.134L151.591 175.694L127.119 175.703L125.492 175.694C67.365 175.694 20.08 222.982 20.08 281.107C20.08 339.231 67.365 386.519 125.492 386.519C128.992 386.519 132.463 386.347 135.884 386.015C140.501 385.534 144.924 388.389 146.394 392.857C162.991 443.104 211.081 476.869 266.041 476.869C335.239 476.869 391.533 422.824 391.533 356.397C391.533 350.9550000000001 395.866 346.503 401.3090000000001 346.363C402.545 346.337 403.758 346.343 404.9940000000001 346.349L406.593 346.36C453.642 346.36 491.926 308.081 491.926 261.027C491.926 215.572 456.404 178.141 411.543 175.818z" />
<glyph glyph-name="11n"
unicode="&#xEA0E;"
horiz-adv-x="512" d=" M411.247 366.3300000000001C405.951 439.213 342.843 496.943 266.038 496.943C205.107 496.943 151.411 460.914 129.988 406.511C128.499 406.565 126.998 406.5900000000001 125.489 406.5900000000001C56.295 406.593 0 350.299 0 281.101C0 211.903 56.295 155.609 125.492 155.609L143.733 155.609L141.236 149.226C140.031 146.138 140.422 142.652 142.295 139.907C144.167 137.168 147.275 135.529 150.589 135.529L250.981 135.529L250.981 25.097C250.981 20.401 254.236 16.332 258.814 15.302C259.549 15.136 260.295 15.057 261.019 15.057C264.8330000000001 15.057 268.401 17.233 270.087 20.792L334.27 156.113C335.092 155.896 335.892 155.606 336.7850000000001 155.606C361.735 155.606 411.599 155.733 412.089 155.75C468.107 158.633 512 204.873 512 261.019C512.003 317.586 467.221 363.886 411.247 366.3300000000001zM271.058 69.693L271.058 145.572C271.061 151.115 266.5710000000001 155.612 261.021 155.612L165.294 155.612L230.902 323.27L230.902 215.603C230.902 210.059 235.392 205.563 240.942 205.563L335.501 205.563L271.058 69.693zM411.543 175.818C411.543 175.818 369.739 175.711 343.556 175.691L360.443 211.295C361.924 214.409 361.698 218.055 359.854 220.966C358.021 223.875 354.815 225.637 351.374 225.637L250.981 225.637L250.981 376.476C250.981 381.305 247.549 385.4460000000001 242.805 386.339C238.059 387.24 233.354 384.627 231.589 380.134L151.591 175.694L127.119 175.703L125.492 175.694C67.365 175.694 20.08 222.982 20.08 281.107C20.08 339.231 67.365 386.519 125.492 386.519C128.992 386.519 132.463 386.347 135.884 386.015C140.501 385.534 144.924 388.389 146.394 392.857C162.991 443.104 211.081 476.869 266.041 476.869C335.239 476.869 391.533 422.824 391.533 356.397C391.533 350.9550000000001 395.866 346.503 401.3090000000001 346.363C402.545 346.337 403.758 346.343 404.9940000000001 346.349L406.593 346.36C453.642 346.36 491.926 308.081 491.926 261.027C491.926 215.572 456.404 178.141 411.543 175.818z" />
<glyph glyph-name="1232n"
unicode="&#xEA0F;"
horiz-adv-x="512" d=" M467.4 213C459.6 221.1 450.8 227.9 441.2 233.4C443.4 235.3 445.5 237.3 447.6 239.4C470.8 262.6 485.1 291.4 490.4 321.5C493.1 336.6 474.7 346.1 463.8 335.3C445.6 317.2 420.3 306.2 392.5 306.8C340.2 307.9 297.5 350.5 296.4 402.9C296 430.7 307 456 325.1 474.2C335.9 485.1 326.4 503.4 311.3 500.8C281.2 495.5 252.4 481.2 229.2 458C201.4 430.2 186.4 394.4 184.2 358C140.9 336.6 108.9 295.3 100.6 245.7C48.4 232.5 10.9 185.5 10.9 130.2C10.8999999999999 64.5 64.3 11 130 11H381.7C447.3999999999999 11 500.8 64.5 500.8 130.2C500.9 161.2 488.9999999999999 190.7 467.4 213zM262.6 432.7C260.7 423.8 259.7 414.5 259.7 405C259.7 330.4 320.1 270 394.7 270C404.2 270 413.5 271 422.4 272.9C401.7 250 371.7 235.6 338.4 235.6C275.9 235.6 225.2 286.3 225.2 348.8C225.2 382 239.6 411.9 262.6 432.7000000000001zM381.7 52.1H130C86.9999999999999 52.1 51.9 87.1 51.9 130.1999999999999C51.9 170.0999999999999 81.8 203.5 121.4 207.8L138.5999999999999 209.6999999999999L139.6999999999999 227C141.8999999999999 262.7 160.5999999999999 293.7 188.0999999999999 312.7C194.5 285.8999999999999 208.1999999999999 260.3999999999999 229.1 239.5C274.8999999999999 193.6999999999999 342.3 182.6999999999999 398.5 206.3999999999999C433.8 198.6999999999999 459.6999999999999 167.5999999999999 459.6999999999999 130.1999999999999C459.8 87.0999999999999 424.8 52.0999999999999 381.7 52.0999999999999z" />
<glyph glyph-name="13d"
unicode="&#xEA10;"
horiz-adv-x="512" d=" M426.315 326.183C415.245 409.819 361.61 470.955 276.757 470.955C205.714 470.955 166.387 428.141 142.143 361.692C133.286 363.851 124.181 364.93 114.993 364.93C51.532 364.929 0 309.661 0 246.229C0 185.536 49.678 141.504 110.703 137.851L124.541 137.851L124.541 165.527L110.703 165.527C66.643 168.156 27.677 202.141 27.677 246.229C27.677 292.337 68.885 333.517 114.993 333.517C125.786 333.517 136.387 331.415 146.488 327.3450000000001L163.176 320.5370000000001L167.687 337.9460000000001C183.296 398.666 214.099 442.863 276.757 442.863C350.346 442.863 392.939 383.443 396.233 309.882L396.953 293.913L416.05 295.2970000000001C451.64 295.2970000000001 484.353 267.732 484.353 232.197C484.353 196.633 450.754 165.553 415.163 165.553L373.65 165.553L373.65 137.878L415.135 137.878C468.051 137.878 512 179.336 512 232.197C511.999 281.128 474.637 321.0080000000001 426.315 326.183zM334.848 216.921L321.121 208.59L322.366 222.705L300.668 224.836L297.928 194.558L260.012 171.588L260.012 217.53L283.62 235.159L271 253.84L260.012 245.62L260.012 262.28L238.149 262.28L238.149 245.62L227.19 253.84L214.542 235.132L238.177 217.503L238.177 171.534L200.262 194.504L197.522 224.782L175.824 222.651L177.069 208.537L163.342 216.867L152.355 197.078L166.11 188.748L153.85 182.853L162.955 162.014L189.302 174.689L227.218 151.691L189.302 128.692L162.955 141.368L153.85 120.528L166.11 114.633L152.355 106.303L163.314 86.432L177.041 94.762L175.796 80.648L197.493 78.516L200.234 108.794L238.149 131.792L238.149 85.824L214.514 68.194L227.162 49.486L238.121 57.678L238.121 41.045L259.984 41.045L259.984 57.678L270.944 49.486L283.592 68.194L259.984 85.824L259.984 131.792L297.9 108.794L300.64 78.516L322.337 80.648L321.093 94.762L334.82 86.432L345.724 106.303L331.997 114.606L344.257 120.501L335.152 141.341L308.777 128.665L270.862 151.664L308.777 174.662L335.152 161.987L344.257 182.826L331.969 188.722L345.724 197.052L334.848 216.921z" />
<glyph glyph-name="13n"
unicode="&#xEA11;"
horiz-adv-x="512" d=" M426.315 326.183C415.245 409.819 361.61 470.955 276.757 470.955C205.714 470.955 166.387 428.141 142.143 361.692C133.286 363.851 124.181 364.93 114.993 364.93C51.532 364.929 0 309.661 0 246.229C0 185.536 49.678 141.504 110.703 137.851L124.541 137.851L124.541 165.527L110.703 165.527C66.643 168.156 27.677 202.141 27.677 246.229C27.677 292.337 68.885 333.517 114.993 333.517C125.786 333.517 136.387 331.415 146.488 327.3450000000001L163.176 320.5370000000001L167.687 337.9460000000001C183.296 398.666 214.099 442.863 276.757 442.863C350.346 442.863 392.939 383.443 396.233 309.882L396.953 293.913L416.05 295.2970000000001C451.64 295.2970000000001 484.353 267.732 484.353 232.197C484.353 196.633 450.754 165.553 415.163 165.553L373.65 165.553L373.65 137.878L415.135 137.878C468.051 137.878 512 179.336 512 232.197C511.999 281.128 474.637 321.0080000000001 426.315 326.183zM334.848 216.921L321.121 208.59L322.366 222.705L300.668 224.836L297.928 194.558L260.012 171.588L260.012 217.53L283.62 235.159L271 253.84L260.012 245.62L260.012 262.28L238.149 262.28L238.149 245.62L227.19 253.84L214.542 235.132L238.177 217.503L238.177 171.534L200.262 194.504L197.522 224.782L175.824 222.651L177.069 208.537L163.342 216.867L152.355 197.078L166.11 188.748L153.85 182.853L162.955 162.014L189.302 174.689L227.218 151.691L189.302 128.692L162.955 141.368L153.85 120.528L166.11 114.633L152.355 106.303L163.314 86.432L177.041 94.762L175.796 80.648L197.493 78.516L200.234 108.794L238.149 131.792L238.149 85.824L214.514 68.194L227.162 49.486L238.121 57.678L238.121 41.045L259.984 41.045L259.984 57.678L270.944 49.486L283.592 68.194L259.984 85.824L259.984 131.792L297.9 108.794L300.64 78.516L322.337 80.648L321.093 94.762L334.82 86.432L345.724 106.303L331.997 114.606L344.257 120.501L335.152 141.341L308.777 128.665L270.862 151.664L308.777 174.662L335.152 161.987L344.257 182.826L331.969 188.722L345.724 197.052L334.848 216.921z" />
<glyph glyph-name="50d"
unicode="&#xEA12;"
horiz-adv-x="512" d=" M0 158.202H477.483V123.685H0V158.202z M0 388.315H477.483V353.798H0V388.315z M0 273.2580000000001H477.483V238.741H0V273.258z M34.517 330.7870000000001H126.562V296.27H34.517V330.7870000000001z M161.079 330.7870000000001H512V296.27H161.079V330.7870000000001z M419.955 215.73H512V181.213H419.955V215.73z M34.517 215.73H385.438V181.213H34.517V215.73z" />
<glyph glyph-name="50n"
unicode="&#xEA13;"
horiz-adv-x="512" d=" M0 158.202H477.483V123.685H0V158.202z M0 388.315H477.483V353.798H0V388.315z M0 273.2580000000001H477.483V238.741H0V273.258z M34.517 330.7870000000001H126.562V296.27H34.517V330.7870000000001z M161.079 330.7870000000001H512V296.27H161.079V330.7870000000001z M419.955 215.73H512V181.213H419.955V215.73z M34.517 215.73H385.438V181.213H34.517V215.73z" />
</font>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 36 KiB

View File

Binary file not shown.

View File

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More