Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Docker

on:
push:
# Publish `master` as Docker `latest` image.
branches:
- master

# Publish `v1.2.3` tags as releases.
tags:
- '*'

# Run tests for any PRs.
pull_request:

jobs:
# Run tests.
# See also https://docs.docker.com/docker-hub/builds/automated-testing/
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Run tests
run: docker build . --file Dockerfile

# Push image to GitHub Packages.
# See also https://docs.docker.com/docker-hub/builds/
push:
# Ensure test job passes before pushing image.
needs: test

runs-on: ubuntu-latest
if: github.event_name == 'push'

steps:
- uses: actions/checkout@v2

- name: Login to ghcr.io
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Compute tag
id: compute-tag
run: |
IMAGE_ID=ghcr.io/${{ github.repository }}

# Change all uppercase to lowercase
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

# Strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

# Strip "v" prefix from tag name
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

# Use Docker `latest` tag convention
[ "$VERSION" == "master" ] && VERSION=latest

echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION

echo "DOCKER_TAG=$IMAGE_ID:$VERSION" >> "$GITHUB_OUTPUT"

- name: Push multi-arch image
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.compute-tag.outputs.DOCKER_TAG }}

31 changes: 31 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# syntax=docker/dockerfile:1
ARG NODE_VERSION=18.0.0

FROM node:${NODE_VERSION}-alpine

# Use production node environment by default.
ENV NODE_ENV=production


WORKDIR /usr/src/app

# Download dependencies as a separate step to take advantage of Docker's caching.
# Leverage a cache mount to /root/.npm to speed up subsequent builds.
# Leverage a bind mounts to package.json and package-lock.json to avoid having to copy them into
# into this layer.
RUN --mount=type=bind,source=package.json,target=package.json \
--mount=type=bind,source=package-lock.json,target=package-lock.json \
--mount=type=cache,target=/root/.npm \
npm ci --omit=dev

# Run the application as a non-root user.
USER node

# Copy the rest of the source files into the image.
COPY . .

# Expose the port that the application listens on.
EXPOSE 3000

# Run the application.
CMD ["node", "src/index.js"]
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,19 @@ The key server uses [nodemailer](https://nodemailer.com) to send out emails upon

For production you should use a service like [Amazon SES](https://aws.amazon.com/ses/), [Mailgun](https://www.mailgun.com/) or [Sendgrid](https://sendgrid.com/use-cases/transactional-email/). Nodemailer supports all of these out of the box.

### Docker compose

Docker images are built from this repository and available at ghcr. You can use the sample docker-compose.yml - review it and populate an .env file with the required [settings](#Settings) before running the server. To create the database automatically, the following parameters are needed in .env file:

```
MONGO_URI=mongodb:27017/keyserver_db
MONGO_USER=keyserver
MONGO_PASS=somepassword
MONGO_INITDB_DATABASE=keyserver_db
```

The sample docker-compose.yml also contains common traefik settings, but you may need to adjust them for your own reverse proxy.

## Run tests

```shell
Expand Down
12 changes: 12 additions & 0 deletions config/mongo-init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
db.createUser(
{
user: process.env.MONGO_USER,
pwd: process.env.MONGO_PASS,
roles: [
{
role: "readWrite",
db: process.env.MONGO_INITDB_DATABASE
}
]
}
);
35 changes: 35 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
services:
mongodb:
image: mongo:7
restart: always
volumes:
- ./data/db:/data/db
- ./config/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
networks:
- backend
env_file: .env
security_opt:
- apparmor=unconfined

keyserver:
image: ghcr.io/mailvelope/keyserver:latest
restart: always
depends_on:
- mongodb
networks:
- traefik-proxy
- backend
env_file: .env
security_opt:
- apparmor=unconfined
labels:
- "traefik.enable=true"
- "traefik.http.routers.keyserver.rule=Host(`keyserver.example.com`)"
- "traefik.http.routers.keyserver.entrypoints=websecure"
- "traefik.http.routers.keyserver.tls.certresolver=acme-le"
- "traefik.http.services.keyserver.loadbalancer.server.port=3000"

networks:
backend:
traefik-proxy:
22 changes: 22 additions & 0 deletions env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
NODE_ENV=production
LOG_LEVEL=debug
PORT=3000
PAPERTRAIL_HOST=''
PAPERTRAIL_PORT=''
MONGO_URI=mongodb:27017/keyserver_db
MONGO_USER=keyserver
MONGO_PASS=changeme
MONGO_INITDB_DATABASE=keyserver_db
SENDER_NAME=keyserver
SENDER_EMAIL=changeme
SMTP_HOST=changeme
SMTP_PORT=587
SMTP_TLS=false
SMTP_STARTTLS=true
SMTP_PGP=''
SMTP_USER=''
SMTP_PASS=''
HTTPS_UPGRADE=true
HTTPS_KEY_PIN=''
HTTPS_KEY_PIN_BACKUP=''
PUBLIC_KEY_PURGE_TIME=30