🔀 Merge pull request #326 from Lissy93/PERFORMANCE/server-speed-improvments

[ARCHITECTURE] Performance and Speed Improvements
This commit is contained in:
Alicia Sykes 2021-11-10 18:42:08 +00:00 committed by GitHub
commit a88e899f53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 968 additions and 889 deletions

9
.env
View File

@ -7,12 +7,19 @@
# The port to expose the running application on
# PORT=4000
# If you've proved SSL certs, then can set HTTPS port
# SSL_PORT=4001
# The host that Dashy is running on, domain or IP
# HOST=localhost
# The default base path for serving up static assets
# BASE_URL=./
# Optionally, specify the path of SSL private + public keys
# SSL_PRIV_KEY_PATH=/etc/ssl/certs/dashy-priv.key
# SSL_PUB_KEY_PATH=/etc/ssl/certs/dashy-pub.pem
# Usually the same as BASE_URL, but accessible in frontend
# VUE_APP_DOMAIN=https://dashy.to
@ -23,4 +30,4 @@
# IS_DOCKER=true
# Again, set automatically using package.json during build time
# VUE_APP_VERSION=1.7.0
# VUE_APP_VERSION=2.0.0

View File

@ -1,5 +1,12 @@
# Changelog
## ⚡️ 1.9.2 - Native SSL Support + Performance Improvements [PR #326](https://github.com/Lissy93/dashy/pull/326)
- Updates the server to use Express, removing serve-static, connect and body-parser
- Adds native support for passing in self-signed SSL certificates and updates docs
- Updates router to lazy-load additional pages (minimal, workspace, etc)
- Changes default favicon API to allesedv, since faviconkit is down, and adds basic fallback
- Updates GH action build scripts to fallback on context token when running on fork
## 💄 1.9.1 - Editor and Theming Fixes and Improvements [PR #319](https://github.com/Lissy93/dashy/pull/319)
- Bug fixes for interactive editor: #310, #311, #312
- Adds option to modify text font through the UI

View File

@ -10,4 +10,4 @@ jobs:
steps:
- uses: logerfo/close-label@0.0.4
with:
repo-token: ${{ secrets.BOT_GITHUB_TOKEN }}
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}

View File

@ -12,4 +12,4 @@ jobs:
- name: Assign author
uses: technote-space/assign-author@v1
with:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}

View File

@ -15,9 +15,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v2
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
fetch-depth: 0
- name: Rebase
uses: cirrus-actions/rebase@1.4
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}

View File

@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v2
- uses: butlerlogic/action-autotag@stable
with:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
strategy: package
commit_message_template: "🔖 {{number}} {{message}} (by {{author}})\nSHA: {{sha}}\n."
mark-issue-fixed:
@ -22,5 +22,5 @@ jobs:
- name: Label Fixed Issues
uses: gh-bot/fix-labeler@master
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
label: '✅ Fixed'

View File

@ -11,4 +11,4 @@ jobs:
steps:
- uses: jenschelkopf/broadcast-action@master
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}

View File

@ -18,6 +18,7 @@ jobs:
npm run build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.1.4
if: ${{ github.repository_owner === 'lissy93' }}
with:
branch: dev-demo
folder: dist

View File

@ -9,7 +9,7 @@ jobs:
steps:
- uses: wow-actions/potential-duplicates@v1
with:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
filter: ''
exclude: '[BUG] [QUESTION] [FEEDBACK] [SHOWCASE]'
label: '🕸️ Potential Duplicate'

View File

@ -11,6 +11,6 @@ jobs:
- uses: mschilde/auto-label-merge-conflicts@master
with:
CONFLICT_LABEL_NAME: "🚫 Merge Conflicts"
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
MAX_RETRIES: 5
WAIT_MS: 5000

View File

@ -12,7 +12,7 @@ jobs:
- name: Automatically close issues that don't follow the issue template
uses: lucasbento/auto-close-issues@v1.0.2
with:
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
github-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
closed-issues-label: '🙁 Auto-Closed'
issue-close-message: |
Hello @${issue.user.login} 👋

View File

@ -12,7 +12,7 @@ jobs:
- name: Close Stale Issues
uses: actions/stale@v4
with:
repo-token: ${{ secrets.BOT_GITHUB_TOKEN }}
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
days-before-stale: 30
days-before-close: 5
operations-per-run: 30
@ -40,7 +40,7 @@ jobs:
- name: Close Issues without Response
uses: actions/stale@v4
with:
repo-token: ${{ secrets.BOT_GITHUB_TOKEN }}
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
days-before-stale: 5
days-before-close: 3
operations-per-run: 30
@ -60,7 +60,7 @@ jobs:
- name: Notify Repo Owner to Respond
uses: actions/stale@v4
with:
repo-token: ${{ secrets.BOT_GITHUB_TOKEN }}
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
days-before-stale: 7
days-before-close: 365
operations-per-run: 30

View File

@ -20,7 +20,7 @@ jobs:
uses: peter-evans/create-pull-request@v3.10.1
if: startsWith(github.head_ref, 'AUTO/') == false
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
base: master
commit-message: ':pencil2: Auto-fix typos in text'
title: '[AUTO] Fix spelling and language'

View File

@ -21,7 +21,7 @@ jobs:
if: ${{ steps.check-domain.outputs.paid-till-days-left && steps.check-domain.outputs.paid-till-days-left < 30 }}
uses: rishabhgupta/git-action-issue@v2
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
assignees: Lissy93
title: '[WEBSITE] Domain Expiring Soon'
body: >
@ -33,7 +33,7 @@ jobs:
if: ${{ steps.check-domain.outputs.ssl-expire-days-left && steps.check-domain.outputs.ssl-expire-days-left < 14 }}
uses: rishabhgupta/git-action-issue@v2
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
assignees: Lissy93
title: '[WEBSITE] SSL Cert Expiring Soon'
body: >

View File

@ -12,7 +12,7 @@ jobs:
steps:
- uses: bubkoo/contributors-list@v1
with:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
svgPath: docs/assets/CONTRIBUTORS.svg
affiliation: all
includeBots: false
@ -30,12 +30,12 @@ jobs:
- name: Generate Sponsors in Readme 💖
uses: JamesIves/github-sponsors-readme-action@1.0.5
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
file: 'README.md'
- name: Generate Sponsors in Credits 💖
uses: JamesIves/github-sponsors-readme-action@1.0.5
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
file: 'docs/credits.md'
# Job #3 - Update the Credits page
insert-credits:
@ -45,7 +45,7 @@ jobs:
- name: Contribute List - Credits Page
uses: akhilmhdh/contributors-readme-action@v2.2
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
with:
image_size: 80
readme_path: docs/credits.md
@ -56,7 +56,7 @@ jobs:
- name: Sponsors List - Readme
uses: akhilmhdh/contributors-readme-action@v2.2
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
with:
image_size: 80
readme_path: README.md
@ -74,7 +74,7 @@ jobs:
fetch-depth: 0
- uses: wow-actions/update-authors@v1
with:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
sort: commits
bots: true
path: .github/AUTHORS.txt

View File

@ -19,7 +19,7 @@ jobs:
- name: close
uses: uhyo/please-star-first@v1
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
message: |
Welcome to Dashy 👋
It's great to have you here, but unfortunately your ticket has been closed to prevent spam. Before reopening this issue, please ensure the following criteria are met.

View File

@ -12,7 +12,7 @@ jobs:
steps:
- uses: tomsun28/issues-translate-action@v2.5
with:
BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
BOT_LOGIN_NAME: liss-bot
IS_MODIFY_TITLE: true
CUSTOM_BOT_NOTE: It looks like this issue isn't in English - not a problem, here's the translation! 🇬🇧

View File

@ -12,7 +12,7 @@ jobs:
- name: Label Issues
uses: adamzolyak/top-issues-action@master
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
TOP_NUMBER_OF_ISSUES: 10
TOP_LABEL_NAME: "👍 Top 10 Issue!"
TOP_LABEL_COLOR: FBCA04

View File

@ -12,6 +12,6 @@ jobs:
uses: actions-cool/issues-helper@v2
with:
actions: remove-labels
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
labels: '🚏 Awaiting User Response,⚰️ Stale,👤 Awaiting Maintainer Response'

View File

@ -13,7 +13,7 @@ jobs:
uses: actions-cool/issues-helper@v2
with:
actions: remove-labels
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
labels: '🚏 Awaiting User Response,⚰️ Stale'
@ -31,7 +31,7 @@ jobs:
uses: actions-cool/issues-helper@v2
with:
actions: add-labels
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
labels: '👤 Awaiting Maintainer Response'
@ -43,6 +43,6 @@ jobs:
uses: actions-cool/issues-helper@v2
with:
actions: remove-labels
token: ${{ secrets.BOT_GITHUB_TOKEN }}
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
labels: '👤 Awaiting Maintainer Response'

View File

@ -17,4 +17,4 @@ jobs:
- name: Profanity check step
uses: tailaiw/mind-your-language-action@v1.0.3
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}

View File

@ -9,4 +9,4 @@ jobs:
if: github.event.action == 'opened'
uses: ffittschen/pr-branch-labeler@v1
with:
repo-token: ${{ secrets.BOT_GITHUB_TOKEN }}
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}

View File

@ -10,4 +10,4 @@ jobs:
uses: "alstr/todo-to-issue-action@v4.2"
id: "todo"
with:
TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}

View File

@ -9,7 +9,7 @@ jobs:
steps:
- uses: apexskier/github-release-commenter@v1
with:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
label-template: 🛩️ Released {release_tag}, 🔨 Fixed
comment-template: |
**The fix for this issue has now been released in {release_name} ✨**

View File

@ -46,7 +46,7 @@ jobs:
uses: lowlighter/metrics@latest
with:
token: ${{ secrets.LISSY93_PAT }}
committer_token: ${{ secrets.BOT_GITHUB_TOKEN }}
committer_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
committer_branch: master
committer_message: ':purple_heart: Adds repo metrics'
filename: docs/assets/repo-metrics.*
@ -59,7 +59,7 @@ jobs:
uses: lowlighter/metrics@latest
with:
token: ${{ secrets.LISSY93_PAT }}
committer_token: ${{ secrets.BOT_GITHUB_TOKEN }}
committer_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
committer_branch: master
committer_message: ':purple_heart: Adds license metrics'
filename: docs/assets/license-metrics.*
@ -76,7 +76,7 @@ jobs:
uses: lowlighter/metrics@latest
with:
token: ${{ secrets.LISSY93_PAT }}
committer_token: ${{ secrets.BOT_GITHUB_TOKEN }}
committer_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
committer_branch: master
committer_message: ':purple_heart: Adds contributor metrics'
filename: docs/assets/controbutor-metrics.*

View File

@ -12,4 +12,4 @@ jobs:
with:
repository: lissy93/dashy
databranch: DATA/repo-stats
ghtoken: ${{ secrets.BOT_GITHUB_TOKEN }}
ghtoken: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}

View File

@ -13,7 +13,7 @@ jobs:
- name: Upload Docs to GH Wiki
uses: docker://decathlon/wiki-page-creator-action:latest
env:
GH_PAT: ${{ secrets.BOT_GITHUB_TOKEN }}
GH_PAT: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
ACTION_MAIL: alicia-gh-bot@mail.as93.net
ACTION_NAME: liss-bot
OWNER: Lissy93

View File

@ -28,13 +28,13 @@ Dashy can auto-fetch an icon for a given service, using it's favicon. Just set `
If the service is hosted under a local IP, then Dashy will attempt to find the favicon from `http://[ip]/favicon.ico`. This has two issues, favicons are not always hosted at the same location for every service, and often the default favicon is sometimes low resolution. Therefore for remote services, by default an API is used to return a high-quality icon for almost any online service.
The default favicon API is [Favicon Kit](https://faviconkit.com/), a free and reliable service for returning images from any given URL. However several other API's are supported. To change the API used, under `appConfig`, set `faviconApi` to one of the following values:
The default favicon API is [allesedv.com](https://favicon.allesedv.com/), but several other API's are supported. To change the API used, under `appConfig`, set `faviconApi` to one of the following values:
- `faviconkit` - [faviconkit.com](https://faviconkit.com/) (Recommend)
- `google` - Official Google favicon API service, good support for all sites, but poor quality
- `clearbit` - [Clearbit](https://clearbit.com/logo) returns high-quality logos from mainstream websites
- `webmasterapi` - [WebMasterAPI](https://www.webmasterapi.com/get-favicons)
- `allesedv` - [allesedv.com](https://favicon.allesedv.com/) is a highly efficient IPv6-enabled service
- `faviconkit` - [faviconkit.com](https://faviconkit.com/) (Note: currently down, as of Nov 2021)
- `clearbit` - [Clearbit](https://clearbit.com/logo) returns high-quality logos from mainstream websites
- `google` - Official Google favicon API service, good support for all sites, but poor quality
- `webmasterapi` - [WebMasterAPI](https://www.webmasterapi.com/get-favicons)
You can also force Dashy to always get favicons from the root of the domain, and not use an external service, by setting `appConfig.faviconApi` to `local`, although you may face the issue explained above.
@ -80,7 +80,7 @@ sections:
---
## 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/), and use a hash of the services domain/ ip for entropy, so each domain will always have the same icon.
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" />

View File

@ -195,17 +195,34 @@ I recommend combining this with [healthchecks](https://github.com/healthchecks/h
## SSL Certificates
Enabling HTTPS with an SSL certificate is recommended if you hare hosting Dashy anywhere other than your home. This will ensure that all traffic is encrypted in transit.
Enabling HTTPS with an SSL certificate is recommended, especially if you hare hosting Dashy anywhere other than your home. This will ensure that all traffic is encrypted in transit.
[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
### 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.
[ZeroSSL](https://zerossl.com/) is another popular certificate issuer, they are free for personal use, and also provide easy-to-use tools for getting things setup.
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.
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/).
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/) to generate your Let's Encrypt or ZeroSSL certificate, and support shared hosting servers. They also provide step-by-step tutorials on setting up your certificate on most common platforms. 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.
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:
```
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)**
@ -213,8 +230,7 @@ If you're not so comfortable on the command line, then you can use a tool like [
## Authentication
Dashy natively supports secure authentication using KeyCloak. There is also a Simple Auth feature that doesn't require any additional setup. Setup instructions for which, and alternative auth methods, has now moved to the **[Authentication Docs](/docs/authentication.md)** page.
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)**

View File

@ -1,6 +1,6 @@
{
"name": "Dashy",
"version": "1.9.1",
"version": "1.9.2",
"license": "MIT",
"main": "server",
"author": "Alicia Sykes <alicia@omg.lol> (https://aliciasykes.com)",
@ -22,16 +22,14 @@
"@sentry/vue": "^6.13.1",
"ajv": "^8.6.3",
"axios": "^0.23.0",
"body-parser": "^1.19.0",
"connect": "^3.7.0",
"connect-history-api-fallback": "^1.6.0",
"crypto-js": "^4.1.1",
"express": "^4.17.1",
"js-yaml": "^4.1.0",
"keycloak-js": "^15.0.2",
"register-service-worker": "^1.6.2",
"remedial": "^1.0.8",
"rsup-progress": "^2.0.4",
"serve-static": "^1.14.1",
"simple-icons": "^5.14.0",
"v-jsoneditor": "^1.4.2",
"v-tooltip": "^2.1.3",

View File

@ -1,7 +1,7 @@
<!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>
<html lang="en">
<head>
<title>Dashy</title>
<meta name="description" content="Welcome to Dashy">

View File

@ -5,13 +5,15 @@
* Also includes some routes for status checks/ ping and config saving
* */
/* Include required node dependencies */
const serveStatic = require('serve-static');
const connect = require('connect');
/* Import built-in Node server modules */
const http = require('http');
const path = require('path');
const util = require('util');
const dns = require('dns');
const os = require('os');
const bodyParser = require('body-parser');
/* Import Express + middleware functions */
const express = require('express');
const history = require('connect-history-api-fallback');
/* Kick of some basic checks */
@ -22,6 +24,7 @@ require('./services/config-validator'); // Include and kicks off the config file
const statusCheck = require('./services/status-check'); // Used by the status check feature, uses GET
const saveConfig = require('./services/save-config'); // Saves users new conf.yml to file-system
const rebuild = require('./services/rebuild-app'); // A script to programmatically trigger a build
const sslServer = require('./services/ssl-server');
/* Helper functions, and default config */
const printMessage = require('./services/print-message'); // Function to print welcome msg on start
@ -55,44 +58,43 @@ const printWarning = (msg, error) => {
/* A middleware function for Connect, that filters requests based on method type */
const method = (m, mw) => (req, res, next) => (req.method === m ? mw(req, res, next) : next());
try {
connect()
.use(history())
.use(bodyParser.json())
// Serves up the main built application to the root
.use(serveStatic(`${__dirname}/dist`))
// During build, a custom page will be served before the app is available
.use(serveStatic(`${__dirname}/public`, { index: 'default.html' }))
// GET endpoint to run status of a given URL with GET request
.use(ENDPOINTS.statusCheck, (req, res) => {
try {
statusCheck(req.url, async (results) => {
await res.end(results);
});
} catch (e) {
printWarning(`Error running status check for ${req.url}\n`, e);
}
})
// POST Endpoint used to save config, by writing conf.yml to disk
.use(ENDPOINTS.save, method('POST', (req, res) => {
try {
saveConfig(req.body, (results) => { res.end(results); });
} catch (e) {
res.end(JSON.stringify({ success: false, message: e }));
}
}))
// GET endpoint to trigger a build, and respond with success status and output
.use(ENDPOINTS.rebuild, (req, res) => {
rebuild().then((response) => {
res.end(JSON.stringify(response));
}).catch((response) => {
res.end(JSON.stringify(response));
const app = express()
// Serves up static files
.use(express.static(path.join(__dirname, 'dist')))
.use(express.static(path.join(__dirname, 'public'), { index: 'initialization.html' }))
// Load middlewares for parsing JSON, and supporting HTML5 history routing
.use(express.json())
.use(history())
// GET endpoint to run status of a given URL with GET request
.use(ENDPOINTS.statusCheck, (req, res) => {
try {
statusCheck(req.url, async (results) => {
await res.end(results);
});
})
// Finally, initialize the server then print welcome message
.listen(port, () => {
try { printWelcomeMessage(); } catch (e) { printWarning('Dashy is Starting...'); }
} catch (e) {
printWarning(`Error running status check for ${req.url}\n`, e);
}
})
// POST Endpoint used to save config, by writing conf.yml to disk
.use(ENDPOINTS.save, method('POST', (req, res) => {
try {
saveConfig(req.body, (results) => { res.end(results); });
} catch (e) {
printWarning('Error writing config file to disk', e);
res.end(JSON.stringify({ success: false, message: e }));
}
}))
// GET endpoint to trigger a build, and respond with success status and output
.use(ENDPOINTS.rebuild, (req, res) => {
rebuild().then((response) => {
res.end(JSON.stringify(response));
}).catch((response) => {
res.end(JSON.stringify(response));
});
} catch (error) {
printWarning('Sorry, a critical error occurred ', error);
}
});
/* Create HTTP server from app on port, and print welcome message */
http.createServer(app).listen(port, () => { printWelcomeMessage(); });
/* Check, and if possible start SSL server too */
sslServer(app);

40
services/ssl-server.js Normal file
View File

@ -0,0 +1,40 @@
const fs = require('fs');
const util = require('util');
const https = require('https');
const promise = util.promisify;
const stat = promise(fs.stat);
module.exports = (app) => {
const httpsCerts = {
private: process.env.SSL_PRIV_KEY_PATH || '/etc/ssl/certs/dashy-priv.key',
public: process.env.SSL_PUB_KEY_PATH || '/etc/ssl/certs/dashy-pub.pem',
};
const isDocker = !!process.env.IS_DOCKER;
const SSLPort = process.env.SSL_PORT || (isDocker ? 443 : 4001);
const printSuccess = () => {
console.log(`🔐 HTTPS server successfully started (port: ${SSLPort} ${isDocker ? 'of container' : ''})`);
};
const printNotSoGood = (msg) => {
console.log(`SSL Not Enabled: ${msg}`);
};
/* Starts SSL-secured node server */
const startSSLServer = () => {
const httpsServer = https.createServer({
key: fs.readFileSync(httpsCerts.private),
cert: fs.readFileSync(httpsCerts.public),
}, app);
httpsServer.listen(SSLPort, () => { printSuccess(); });
};
/* Check if SSL certs present, if so also start the HTTPS server */
stat(httpsCerts.public).then(() => {
stat(httpsCerts.private).then(() => {
startSSLServer();
}).catch(() => { printNotSoGood('Private key not present'); });
}).catch(() => { printNotSoGood('Public key not present'); });
};

View File

@ -49,12 +49,14 @@ export default {
},
/* Gets the icon path, dependent on icon type */
iconPath: function iconPath() {
if (this.broken) return this.getFallbackIcon();
return this.getIconPath(this.icon, this.url);
},
},
data() {
return {
broken: false, // If true, was unable to resolve icon
attemptedFallback: false,
};
},
methods: {
@ -94,12 +96,12 @@ export default {
},
/* Get favicon URL, for items which use the favicon as their icon */
getFavicon(fullUrl, specificApi) {
if (this.shouldUseDefaultFavicon(fullUrl)) { // Check if we should use local icon
const faviconApi = specificApi || this.appConfig.faviconApi || defaultFaviconApi;
if (this.shouldUseDefaultFavicon(fullUrl) || faviconApi === 'local') { // Check if we should use local icon
const urlParts = fullUrl.split('/');
if (urlParts.length >= 2) return `${urlParts[0]}/${urlParts[1]}/${urlParts[2]}/${iconCdns.faviconName}`;
} else if (fullUrl.includes('http')) { // Service is running publicly
const host = this.getHostName(fullUrl);
const faviconApi = specificApi || this.appConfig.faviconApi || defaultFaviconApi;
const endpoint = faviconApiEndpoints[faviconApi];
return endpoint.replace('$URL', host);
}
@ -130,9 +132,9 @@ export default {
return `${iconCdns.localPath}/${img}`;
},
/* Formats the URL for fetching the generative icons */
getGenerativeIcon(url) {
getGenerativeIcon(url, cdn) {
const host = encodeURI(url) || Math.random().toString();
return iconCdns.generative.replace('{icon}', asciiHash(host));
return (cdn || iconCdns.generative).replace('{icon}', asciiHash(host));
},
/* Returns the SVG path content */
getSimpleIcon(img) {
@ -187,6 +189,23 @@ export default {
this.broken = true;
ErrorHandler(`The path to '${this.icon}' could not be resolved`);
},
/* Called when initial icon has resulted in 404. Attempts to find new icon */
getFallbackIcon() {
if (this.attemptedFallback) return undefined; // If this is second attempt, then give up
const { iconType } = this;
const markAsSttempted = () => {
this.broken = false;
this.attemptedFallback = true;
};
if (iconType.includes('favicon')) { // Specify fallback for favicon-based icons
markAsSttempted();
return this.getFavicon(this.url, 'local');
} else if (iconType === 'generative') {
markAsSttempted();
return this.getGenerativeIcon(this.url, iconCdns.generativeFallback);
}
return undefined;
},
},
};
</script>

View File

@ -11,9 +11,6 @@ import ProgressBar from 'rsup-progress';
// Import views, that are not lazy-loaded
import Home from '@/views/Home.vue';
import Login from '@/views/Login.vue';
import Workspace from '@/views/Workspace.vue';
import Minimal from '@/views/Minimal.vue';
import ConfigAccumulator from '@/utils/ConfigAccumalator';
// Import helper functions, config data and defaults
@ -52,9 +49,8 @@ const getStartingView = () => appConfig.startingView || startingView;
const getStartingComponent = () => {
const usersPreference = getStartingView();
switch (usersPreference) {
case 'default': return Home;
case 'minimal': return Minimal;
case 'workspace': return Workspace;
case 'minimal': return () => import('./views/Minimal.vue');
case 'workspace': return () => import('./views/Workspace.vue');
default: return Home;
}
};
@ -93,19 +89,19 @@ const router = new Router({
{ // Workspace view page
path: routePaths.workspace,
name: 'workspace',
component: Workspace,
component: () => import('./views/Workspace.vue'),
meta: makeMetaTags('Workspace'),
},
{ // Minimal view page
path: routePaths.minimal,
name: 'minimal',
component: Minimal,
component: () => import('./views/Minimal.vue'),
meta: makeMetaTags('Start Page'),
},
{ // The login page
path: routePaths.login,
name: 'login',
component: Login,
component: () => import('./views/Login.vue'),
beforeEnter: (to, from, next) => {
// If the user already logged in + guest mode not enabled, then redirect home
if (isAuthenticated() && !isGuestAccessEnabled()) router.push({ path: '/' });

View File

@ -24,7 +24,7 @@ module.exports = {
/* Default Font-Awesome API key, for FA icons (if used) */
fontAwesomeKey: '0821c65656',
/* Default API to use for fetching of user service favicon icons (if enabled) */
faviconApi: 'faviconkit',
faviconApi: 'allesedv',
/* The default sort order for sections */
sortOrder: 'default',
/* The page paths for each route within the app for the router */
@ -184,6 +184,7 @@ module.exports = {
mdi: 'https://cdn.jsdelivr.net/npm/@mdi/font@5.9.55/css/materialdesignicons.min.css',
si: 'https://unpkg.com/simple-icons@v5/icons',
generative: 'https://avatars.dicebear.com/api/identicon/{icon}.svg',
generativeFallback: 'https://evatar.io/{icon}',
localPath: './item-icons',
faviconName: 'favicon.ico',
homeLabIcons: 'https://raw.githubusercontent.com/WalkxCode/dashboard-icons/master/png/{icon}.png',

1542
yarn.lock

File diff suppressed because it is too large Load Diff