From 6ec6eec21499fd6f6b14a57441ebc7c35a92d509 Mon Sep 17 00:00:00 2001 From: Benjamin Montgomery Date: Thu, 21 Apr 2022 07:57:54 -0400 Subject: [PATCH 01/11] add --no-clean --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d03a43d6d3..d0340572bb 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "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-watch": "vue-cli-service build --watch --mode production --no-clean", "build-and-start": "npm-run-all --parallel build-watch start", "validate-config": "node services/config-validator", "health-check": "node services/healthcheck", From f7c211b7481fa80cfbbd0186723e63d4f693db4a Mon Sep 17 00:00:00 2001 From: Benjamin Montgomery Date: Thu, 21 Apr 2022 07:58:27 -0400 Subject: [PATCH 02/11] update node image version --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8d7b15ed67..029e2cb22e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16.13.2-alpine AS BUILD_IMAGE +FROM node:16.14.2-alpine AS BUILD_IMAGE # Set the platform to build image for ARG TARGETPLATFORM @@ -25,7 +25,7 @@ COPY . ./ RUN yarn build # Production stage -FROM node:16.13.2-alpine +FROM node:16.14.2-alpine # Define some ENV Vars ENV PORT=80 \ From 84764285f5ef261e7e3d8e847aa8747bfb45be6f Mon Sep 17 00:00:00 2001 From: Benjamin Montgomery Date: Thu, 21 Apr 2022 08:05:05 -0400 Subject: [PATCH 03/11] add new env var --- docs/developing.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/developing.md b/docs/developing.md index edd98f5fc6..2dbe9eef08 100644 --- a/docs/developing.md +++ b/docs/developing.md @@ -73,6 +73,7 @@ You can set variables either in your environment, or using the [`.env`](https:// - `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 +- `DEST_DIRECTORY` - Location for the output of the `vue-cli-service build` command. Set automatically during build. ### 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). From 79e6544a89bcd648495c31f11c1068da3684c703 Mon Sep 17 00:00:00 2001 From: Benjamin Montgomery Date: Thu, 21 Apr 2022 08:05:20 -0400 Subject: [PATCH 04/11] changes to run as non-root user --- Dockerfile | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 029e2cb22e..f78eab7e35 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,9 +28,12 @@ RUN yarn build FROM node:16.14.2-alpine # Define some ENV Vars -ENV PORT=80 \ +ENV PORT=8080 \ DIRECTORY=/app \ - IS_DOCKER=true + DEST_DIRECTORY=/app/dist \ + IS_DOCKER=true \ + UID=5000 \ + GID=5000 # Create and set the working directory WORKDIR ${DIRECTORY} @@ -40,8 +43,14 @@ RUN apk add --no-cache tzdata tini # Copy built application from build phase COPY --from=BUILD_IMAGE /app ./ -# Ensure only one version of conf.yml exists -RUN rm dist/conf.yml + +# fix permissions +RUN rm -rf ${DEST_DIRECTORY} && \ + mkdir ${DEST_DIRECTORY} && \ + chown $UID:$GID ${DEST_DIRECTORY} && \ + chmod 755 ${DEST_DIRECTORY} + +USER ${UID} # Finally, run start command to serve up the built application ENTRYPOINT [ "/sbin/tini", "--" ] From a4584bd2235dd5b25f18ae86ebb6920c04a99805 Mon Sep 17 00:00:00 2001 From: Benjamin Montgomery Date: Thu, 21 Apr 2022 08:15:38 -0400 Subject: [PATCH 05/11] revert doc change --- docs/developing.md | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/docs/developing.md b/docs/developing.md index 2dbe9eef08..fa9d700ac5 100644 --- a/docs/developing.md +++ b/docs/developing.md @@ -4,22 +4,35 @@ 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) +- [Developing](#developing) + - [Setting up the Dev Environment](#setting-up-the-dev-environment) + - [Prerequisites](#prerequisites) + - [Running the Project](#running-the-project) + - [Project Commands](#project-commands) + - [Basics](#basics) + - [Development](#development) + - [Utils and Checks](#utils-and-checks) + - [Alternate Start Commands](#alternate-start-commands) + - [Notes](#notes) + - [Environmental Variables](#environmental-variables) + - [Environment Modes](#environment-modes) + - [Git Strategy](#git-strategy) + - [Git Flow](#git-flow) + - [Git Branch Naming](#git-branch-naming) + - [Commit Emojis](#commit-emojis) + - [PR Guidelines](#pr-guidelines) + - [Resources for Beginners](#resources-for-beginners) + - [App Info](#app-info) + - [Style Guide](#style-guide) + - [Application Structure](#application-structure) + - [Files in the Root: `./`](#files-in-the-root-) + - [Frontend Source: `./src/`](#frontend-source-src) + - [Visualisation of Source Directory](#visualisation-of-source-directory) + - [Development Tools](#development-tools) + - [Performance - Lighthouse](#performance---lighthouse) + - [Dependencies - BundlePhobia](#dependencies---bundlephobia) + - [Notes](#notes-1) + - [Known Warnings](#known-warnings) ## Setting up the Dev Environment @@ -73,7 +86,6 @@ You can set variables either in your environment, or using the [`.env`](https:// - `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 -- `DEST_DIRECTORY` - Location for the output of the `vue-cli-service build` command. Set automatically during build. ### 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). From 0d4d86de97b522e024b6cefb0cb926e8280fa550 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 21 Apr 2022 15:03:02 +0100 Subject: [PATCH 06/11] =?UTF-8?q?=F0=9F=94=96=20Bumped=20version=20to=202.?= =?UTF-8?q?0.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d0340572bb..2121e9df48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Dashy", - "version": "2.0.7", + "version": "2.0.8", "license": "MIT", "main": "server", "author": "Alicia Sykes (https://aliciasykes.com)", From 6ae691ef65d616c009382714d2be1657358b4e75 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 21 Apr 2022 16:23:03 +0100 Subject: [PATCH 07/11] =?UTF-8?q?=F0=9F=90=B3=20Updates=20port=20in=20dock?= =?UTF-8?q?er-compose=20and=20source?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docker-compose.yml | 2 +- server.js | 4 ++-- services/healthcheck.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d9766fdd79..2742fa442d 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ You will need [Docker](https://docs.docker.com/get-docker/) installed on your system ``` -docker run -p 8080:80 lissy93/dashy +docker run -p 8080:8080 lissy93/dashy ``` Or diff --git a/docker-compose.yml b/docker-compose.yml index 0d09a26abb..ab11adb89c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,7 +26,7 @@ services: # Set port that web service will be served on. Keep container port as 80 ports: - - 4000:80 + - 4000:8080 # Set any environmental variables environment: diff --git a/server.js b/server.js index 4da6dafb3e..94e81d0182 100644 --- a/server.js +++ b/server.js @@ -35,8 +35,8 @@ const ENDPOINTS = require('./src/utils/defaults').serviceEndpoints; // API endpo /* Checks if app is running within a container, from env var */ const isDocker = !!process.env.IS_DOCKER; -/* Checks env var for port. If undefined, will use Port 80 for Docker, or 4000 for metal */ -const port = process.env.PORT || (isDocker ? 80 : 4000); +/* Checks env var for port. If undefined, will use Port 8080 for Docker, or 4000 for metal */ +const port = process.env.PORT || (isDocker ? 8080 : 4000); /* Attempts to get the users local IP, used as part of welcome message */ const getLocalIp = () => { diff --git a/services/healthcheck.js b/services/healthcheck.js index f9540ad083..8355dba59b 100644 --- a/services/healthcheck.js +++ b/services/healthcheck.js @@ -7,7 +7,7 @@ const http = require('http'); /* Location of the server to test */ -const port = process.env.PORT || !!process.env.IS_DOCKER ? 80 : 4000; +const port = process.env.PORT || !!process.env.IS_DOCKER ? 8080 : 4000; const host = process.env.HOST || '0.0.0.0'; const timeout = 2000; From af3dc7c0b66047a08da615edefbddaacce838d42 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 21 Apr 2022 16:28:50 +0100 Subject: [PATCH 08/11] =?UTF-8?q?=F0=9F=93=9D=20Updates=20docs=20with=20ne?= =?UTF-8?q?w=20port=20number?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- docs/deployment.md | 6 +++--- docs/management.md | 18 +++++++++--------- docs/quick-start.md | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 2742fa442d..5275c3cea6 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ **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) +**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:8080 lissy93/dashy`](./docs/quick-start.md)

@@ -122,7 +122,7 @@ Or ```docker docker run -d \ - -p 4000:80 \ + -p 4000:8080 \ -v /root/my-local-conf.yml:/app/public/conf.yml \ --name my-dashboard \ --restart=always \ diff --git a/docs/deployment.md b/docs/deployment.md index e9710e6a23..499de820a0 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -5,7 +5,7 @@ Welcome to Dashy, so glad you're here :) Deployment is super easy, and there are #### 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: ``` -docker run -p 8080:80 lissy93/dashy +docker run -p 8080:8080 lissy93/dashy ``` See [Management Docs](/docs/management.md) for info about securing, monitoring, updating, health checks, auto starting, web server configuration, etc @@ -47,7 +47,7 @@ Dashy has a built container image hosted on [Docker Hub](https://hub.docker.com/ ```docker docker run -d \ - -p 8080:80 \ + -p 8080:8080 \ -v /root/my-local-conf.yml:/app/public/conf.yml \ --name my-dashboard \ --restart=always \ @@ -136,7 +136,7 @@ Installing dashy is really simply and fast: ``` docker run -d \ - -p 4000:80 \ + -p 4000:8080 \ -v /volume1/docker/dashy/my-local-conf.yml:/app/public/conf.yml \ --name dashy \ --restart=always \ diff --git a/docs/management.md b/docs/management.md index 2d1d12c002..55da16b49a 100644 --- a/docs/management.md +++ b/docs/management.md @@ -215,7 +215,7 @@ Once you've generated your SSL cert, you'll need to pass it to Dashy. This can b ``` docker run -d \ - -p 8080:80 \ + -p 8080:8080 \ -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 @@ -255,7 +255,7 @@ services: volumes: - /root/my-config.yml:/app/public/conf.yml ports: - - 4000:80 + - 4000:8080 environment: - BASE_URL=/my-dashboard restart: unless-stopped @@ -523,7 +523,7 @@ upstream dashy { } server { - listen 80; + listen 8080; server_name dashy.mydomain.com; # Setup SSL @@ -549,7 +549,7 @@ Similarly, a basic `Caddyfile` might look like: ``` dashy.example.com { - reverse_proxy / nginx:80 + reverse_proxy / nginx:8080 } ``` @@ -597,7 +597,7 @@ One of the best ways to prevent privilege escalation attacks, is to configure th 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` +`docker run --user 1000:1000 -p 8080:8080 lissy93/dashy` Of if you're using Docker-compose, you could use an environmental variable @@ -607,7 +607,7 @@ services: dashy: image: lissy93/dashy user: ${CURRENT_UID} - ports: [ 4000:80 ] + ports: [ 4000:8080 ] ``` And then to set the variable, and start the container, run: `CURRENT_UID=$(id -u):$(id -g) docker-compose up` @@ -732,8 +732,8 @@ Create a new file in `/etc/nginx/sites-enabled/dashy` ``` server { - listen 80; - listen [::]:80; + listen 8080; + listen [::]:8080; root /var/www/dashy/html; index index.html; @@ -847,7 +847,7 @@ Similar to above, you'll first need to fork and clone Dashy to your local system 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`. +To build and deploy locally, first build the app with: `docker build -t dashy .`, and then start the app with `docker run -p 8080:8080 --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`. diff --git a/docs/quick-start.md b/docs/quick-start.md index 7041fc76a0..203e1c0ca1 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -2,7 +2,7 @@ Welcome to Dashy! So glad you're here 😊 In a couple of minutes, you'll have your new dashboard up and running 🚀 -**TDLR;** Run `docker run -p 8080:80 lissy93/dashy`, then open `http://localhost:8080` +**TDLR;** Run `docker run -p 8080:8080 lissy93/dashy`, then open `http://localhost:8080` --- @@ -18,7 +18,7 @@ If you don't want to use Docker, then you can use one of Dashy's other supported To pull the latest image, and build and start the app run: ``` docker run -d \ - -p 8080:80 \ + -p 8080:8080 \ -v ~/my-conf.yml:/app/public/conf.yml \ --name my-dashboard \ --restart=always \ From a851efbd886c2c32295d304d16faad71ad9cebe3 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 21 Apr 2022 16:29:58 +0100 Subject: [PATCH 09/11] =?UTF-8?q?=F0=9F=94=96=20Updates=20the=20changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/CHANGELOG.md | 7 +++++++ .github/LATEST_CHANGELOG.md | 13 ++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 380e8bc9d3..4a61eff91d 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 🐳 2.0.8 - Container run without root [PR #606](https://github.com/Lissy93/dashy/pull/606) +- Uses an unprivileged port (8080 instead of 80) +- Adds the UID and GID variables to not be 0 +- Adds a DEST_DIRECTORY variable to control where build output goes +- Adds a RUN block to set permissions on the DEST_DIRECTORY so the non-root user can write +- Adds a USER directive to make the process run as the non-root user + ## ⚡️ 2.0.7 Improves handling of Sections and Items [PR #595](https://github.com/Lissy93/dashy/pull/595) - Adds functionality for sub-items / item-groups - Creates an item mixin, for reusing functionality diff --git a/.github/LATEST_CHANGELOG.md b/.github/LATEST_CHANGELOG.md index b0f310c3ef..a10163940e 100644 --- a/.github/LATEST_CHANGELOG.md +++ b/.github/LATEST_CHANGELOG.md @@ -1,7 +1,6 @@ -## ⚡️ 2.0.7 Improves handling of Sections and Items [PR #595](https://github.com/Lissy93/dashy/pull/595) -- Adds functionality for sub-items / item-groups -- Creates an item mixin, for reusing functionality -- Item width calculated based on parent section width -- Improved mobile support, long-press for right-click -- Adds 2 new themes (`lissy` and `charry-blossom`) -- Adds 2 new widgets (`mullvad-status`, and `blacklist-check`) +## 🐳 2.0.8 - Container run without root [PR #606](https://github.com/Lissy93/dashy/pull/606) +- Uses an unprivileged port (8080 instead of 80) +- Adds the UID and GID variables to not be 0 +- Adds a DEST_DIRECTORY variable to control where build output goes +- Adds a RUN block to set permissions on the DEST_DIRECTORY so the non-root user can write +- Adds a USER directive to make the process run as the non-root user \ No newline at end of file From ce8522521eed0bec121c639ab9ae8f48ae8b5ae6 Mon Sep 17 00:00:00 2001 From: Benjamin Montgomery Date: Sat, 23 Apr 2022 08:06:01 -0400 Subject: [PATCH 10/11] update permissions on dist and public --- Dockerfile | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index f78eab7e35..9af2787776 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,12 +28,13 @@ RUN yarn build FROM node:16.14.2-alpine # Define some ENV Vars -ENV PORT=8080 \ - DIRECTORY=/app \ - DEST_DIRECTORY=/app/dist \ - IS_DOCKER=true \ - UID=5000 \ - GID=5000 +ENV DIRECTORY=/app \ + PUBLIC_DIR=public \ + DEST_DIR=dist \ + IS_DOCKER=true \ + UID=5000 \ + GID=5000 \ + PORT=8080 # Create and set the working directory WORKDIR ${DIRECTORY} @@ -42,13 +43,19 @@ WORKDIR ${DIRECTORY} RUN apk add --no-cache tzdata tini # Copy built application from build phase -COPY --from=BUILD_IMAGE /app ./ +COPY --from=BUILD_IMAGE /app ${DIRECTORY} # fix permissions -RUN rm -rf ${DEST_DIRECTORY} && \ - mkdir ${DEST_DIRECTORY} && \ - chown $UID:$GID ${DEST_DIRECTORY} && \ - chmod 755 ${DEST_DIRECTORY} +RUN chown ${UID}:${GID} ${DEST_DIR} && \ + chmod 755 ${DEST_DIR} && \ + find ${DEST_DIR} -exec chown ${UID}:${GID} "{}" \; && \ + find ${DEST_DIR} -type d -exec chmod 755 "{}" \; && \ + find ${DEST_DIR} -type f -exec chmod 644 "{}" \; && \ + chown ${UID}:${GID} ${PUBLIC_DIR} && \ + chmod 755 ${PUBLIC_DIR} && \ + find ${PUBLIC_DIR} -exec chown $UID:$GID "{}" \; && \ + find ${PUBLIC_DIR} -type d -exec chmod 755 "{}" \; && \ + find ${PUBLIC_DIR} -type f -exec chmod 644 "{}" \; USER ${UID} @@ -60,4 +67,4 @@ CMD [ "yarn", "build-and-start" ] EXPOSE ${PORT} # Run simple healthchecks every 5 mins, to check that everythings still great -HEALTHCHECK --interval=5m --timeout=2s --start-period=30s CMD yarn health-check \ No newline at end of file +HEALTHCHECK --interval=5m --timeout=2s --start-period=30s CMD yarn health-check From 8d9c43c0ee78c2f5f677d25417728a698c11ab2d Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 5 May 2022 13:55:56 +0100 Subject: [PATCH 11/11] =?UTF-8?q?=F0=9F=94=96=20Bumps=20to=20V=202.0.9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2121e9df48..638c27adb6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Dashy", - "version": "2.0.8", + "version": "2.0.9", "license": "MIT", "main": "server", "author": "Alicia Sykes (https://aliciasykes.com)",