Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run as non root #606

Closed
wants to merge 13 commits into from
8 changes: 8 additions & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog


## 🐳 2.0.9 - 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.8 Adds Multi-Page Support [PR #617](https://github.com/Lissy93/dashy/pull/617)
- Adds support for multiple pages per-dashboard
- Adds new attribute at root of main config file: `pages`
Expand Down
10 changes: 6 additions & 4 deletions .github/LATEST_CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
## ✨ 2.0.8 Adds Multi-Page Support [PR #617](https://github.com/Lissy93/dashy/pull/617)
- Adds support for multiple pages per-dashboard
- Adds new attribute at root of main config file: `pages`
- Updates router and nav-bar to automatically create paths for both local and remote configs
## 🐳 2.0.9 - 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
34 changes: 25 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -25,12 +25,16 @@ 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 \
DIRECTORY=/app \
IS_DOCKER=true
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}
Expand All @@ -39,9 +43,21 @@ WORKDIR ${DIRECTORY}
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
COPY --from=BUILD_IMAGE /app ${DIRECTORY}

# fix permissions
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}

# Finally, run start command to serve up the built application
ENTRYPOINT [ "/sbin/tini", "--" ]
Expand All @@ -51,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
HEALTHCHECK --interval=5m --timeout=2s --start-period=30s CMD yarn health-check
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,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)


<p align="center">
Expand All @@ -116,14 +116,14 @@
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

```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 \
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 3 additions & 3 deletions docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down
45 changes: 29 additions & 16 deletions docs/developing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
18 changes: 9 additions & 9 deletions docs/management.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -523,7 +523,7 @@ upstream dashy {
}

server {
listen 80;
listen 8080;
server_name dashy.mydomain.com;

# Setup SSL
Expand All @@ -549,7 +549,7 @@ Similarly, a basic `Caddyfile` might look like:

```
dashy.example.com {
reverse_proxy / nginx:80
reverse_proxy / nginx:8080
}
```

Expand Down Expand Up @@ -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

Expand All @@ -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`
Expand Down Expand 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;
Expand Down Expand Up @@ -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`.

Expand Down
4 changes: 2 additions & 2 deletions docs/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

---

Expand All @@ -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 \
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Dashy",
"version": "2.0.8",
"version": "2.0.9",
"license": "MIT",
"main": "server",
"author": "Alicia Sykes <[email protected]> (https://aliciasykes.com)",
Expand All @@ -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",
Expand Down
4 changes: 2 additions & 2 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {
Expand Down
2 changes: 1 addition & 1 deletion services/healthcheck.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down