deployment: add example deployment config and readme
This commit is contained in:
parent
59651d3cb9
commit
4eb504d719
100
deployment/README.md
Normal file
100
deployment/README.md
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
# Deploying an OpenBikeSensor Portal with Docker
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
The main idea of this document is to provide an easy docker-based
|
||||||
|
production-ready setup of the openbikesensor portal. It uses the [the traefik
|
||||||
|
proxy](https://doc.traefik.io/traefik/) as a reverse proxy, which listens
|
||||||
|
on port 80 and 443. Based on some labels, traefik routes the domains to the
|
||||||
|
corresponding docker containers.
|
||||||
|
|
||||||
|
## Before Getting Started
|
||||||
|
|
||||||
|
The guide and example configuration assumes one domain, which points to the
|
||||||
|
server's IP address. This documentation uses `portal.example.com` as an
|
||||||
|
example. The API is hosted at `https://portal.example.com/api`, while the main
|
||||||
|
frontend is reachable at the domain root.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### Clone the repo
|
||||||
|
|
||||||
|
Create a folder somewhere in your system, we'll name it `$ROOT` from now on.
|
||||||
|
|
||||||
|
Clone the repository to `$ROOT/source`. Ensure you also cloned the submodules,
|
||||||
|
as described in the main [README](../README.md).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /opt/openbikesensor
|
||||||
|
cd /opt/openbikesensor
|
||||||
|
git clone https://github.com/openbikesensor/portal source/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure `traefik.toml`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p config/
|
||||||
|
cp source/deployment/examples/traefik.toml config/traefik.toml
|
||||||
|
vim config/traefik.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure your email in the `config/traefik.toml`. This email is uses by
|
||||||
|
Let's Encrypt to send you some mails regarding your certificates.
|
||||||
|
|
||||||
|
### Configure `docker-compose.yaml`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp source/deployment/examples/docker-compose.yaml docker-compose.yaml
|
||||||
|
vim docker-compose.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Change the domain where it occurs, such as in `Host()` rules.
|
||||||
|
|
||||||
|
### Configure frontend
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp source/frontend/config.json.example config/frontend.json
|
||||||
|
vim frontend/src/config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
* Change all URLs to your domain
|
||||||
|
* Create a UUID by using `uuidgen` and set the `clientId`
|
||||||
|
|
||||||
|
### Configure API
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp source/api/config.json.example config/api.json
|
||||||
|
vim config/api.json
|
||||||
|
```
|
||||||
|
|
||||||
|
* Change all URLs to your domain
|
||||||
|
* Generate and set a random `cookieSecret` (for example with `uuidgen`)
|
||||||
|
* Generate and set a random `jwtSecret` (for example with `uuidgen`)
|
||||||
|
* Configure you SMTP mail server
|
||||||
|
* Set the `clientId` for the `oAuth2Client` of the portal (from step 3)
|
||||||
|
|
||||||
|
### Build container and run them
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
The services are being built the first time this is run. It can take some
|
||||||
|
minutes.
|
||||||
|
|
||||||
|
## Miscellaneous
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
To read logs, run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
If something went wrong, you can reconfigure your config files and rerun:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
125
deployment/examples/docker-compose.yaml
Normal file
125
deployment/examples/docker-compose.yaml
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
networks:
|
||||||
|
gateway:
|
||||||
|
external: true
|
||||||
|
name: gateway
|
||||||
|
backend:
|
||||||
|
internal: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
mongo:
|
||||||
|
image: mongo
|
||||||
|
tty: true
|
||||||
|
volumes:
|
||||||
|
- ./data/mongo:/data/db
|
||||||
|
restart: on-failure
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
volumes:
|
||||||
|
- ./data/redis:/data
|
||||||
|
command: redis-server --appendonly yes
|
||||||
|
restart: on-failure
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
api:
|
||||||
|
image: obs-api
|
||||||
|
build:
|
||||||
|
context: ./source/api
|
||||||
|
volumes:
|
||||||
|
- ./data/api-data:/data
|
||||||
|
- ./config/api-config.json:/opt/obs/api/config.json
|
||||||
|
environment:
|
||||||
|
- MONGODB_URL=mongo://mongo/obs
|
||||||
|
restart: on-failure
|
||||||
|
labels:
|
||||||
|
- traefik.http.middlewares.obsapi-prefix.stripprefix.prefixes=/api
|
||||||
|
- traefik.http.middlewares.obsapi-wellknown.replacepathregex.regex=^/\.well-known/oauth-authorization-server/api$$
|
||||||
|
- traefik.http.middlewares.obsapi-wellknown.replacepathregex.replacement=/.well-known/oauth-authorization-server
|
||||||
|
- traefik.http.routers.obsapi.rule=Host(`portal.example.com`) && (PathPrefix(`/api/`) || Path(`/.well-known/oauth-authorization-server/api`))
|
||||||
|
- traefik.http.routers.obsapi.entrypoints=websecure
|
||||||
|
- traefik.http.routers.obsapi.tls=true
|
||||||
|
- traefik.http.routers.obsapi.tls.certresolver=leresolver
|
||||||
|
- traefik.http.routers.obsapi.middlewares=obsapi-prefix@docker,obsapi-wellknown@docker
|
||||||
|
- traefik.docker.network=gateway
|
||||||
|
networks:
|
||||||
|
- gateway
|
||||||
|
- backend
|
||||||
|
|
||||||
|
worker:
|
||||||
|
image: obs-api
|
||||||
|
build:
|
||||||
|
context: ./source/api
|
||||||
|
volumes:
|
||||||
|
- ./data/api-data:/data
|
||||||
|
- ./config/api-config.json:/opt/obs/api/config.json
|
||||||
|
links:
|
||||||
|
- mongo
|
||||||
|
- redis
|
||||||
|
restart: on-failure
|
||||||
|
command:
|
||||||
|
- npm
|
||||||
|
- run
|
||||||
|
- start:worker
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
# Not requred for traefik, but to reach overpass-api.de
|
||||||
|
- gateway
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
image: obs-frontend
|
||||||
|
build:
|
||||||
|
context: ./source/frontend
|
||||||
|
dockerfile: Dockerfile-prod
|
||||||
|
links:
|
||||||
|
- api
|
||||||
|
restart: on-failure
|
||||||
|
labels:
|
||||||
|
- traefik.http.routers.obsfrontend.rule=Host(`portal.example.com`)
|
||||||
|
- traefik.http.routers.obsfrontend.entrypoints=websecure
|
||||||
|
- traefik.http.routers.obsfrontend.tls=true
|
||||||
|
- traefik.http.routers.obsfrontend.tls.certresolver=leresolver
|
||||||
|
- traefik.docker.network=gateway
|
||||||
|
networks:
|
||||||
|
- gateway
|
||||||
|
- backend
|
||||||
|
|
||||||
|
traefik:
|
||||||
|
image: traefik:2.4.8
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
# The Web UI (enabled by [api] in traefik.toml)
|
||||||
|
# - "8080:8080"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./config/traefik.toml:/traefik.toml
|
||||||
|
- ./config/usersfile:/usersfile
|
||||||
|
- ./data/acme.json:/acme.json
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- gateway
|
||||||
|
|
||||||
|
labels:
|
||||||
|
# global redirect from http to https
|
||||||
|
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
|
||||||
|
- "traefik.http.routers.http-catchall.entrypoints=web"
|
||||||
|
# Define middlewares to be used
|
||||||
|
- "traefik.http.routers.http-catchall.middlewares=redirect-http-to-https"
|
||||||
|
# Configure middlewares
|
||||||
|
- "traefik.http.middlewares.redirect-http-to-https.redirectscheme.scheme=https"
|
||||||
|
|
||||||
|
# Show Traefik Dashboard. Enable the dashboard in traefik.toml if you use these.
|
||||||
|
# - "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
|
||||||
|
# - "traefik.http.routers.traefik.service=api@internal"
|
||||||
|
# - "traefik.http.routers.traefik.tls=true"
|
||||||
|
# - "traefik.http.routers.traefik.entrypoints=websecure"
|
||||||
|
# - "traefik.http.routers.traefik.tls.certresolver=leresolver"
|
||||||
|
# - "traefik.http.routers.traefik.middlewares=basic-auth"
|
||||||
|
# - "traefik.http.middlewares.basic-auth.basicauth.usersfile=/usersfile"
|
29
deployment/examples/traefik.toml
Normal file
29
deployment/examples/traefik.toml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# https://doc.traefik.io/traefik/v2.4/routing/entrypoints/
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.web]
|
||||||
|
address = ":80"
|
||||||
|
|
||||||
|
[entryPoints.web.http]
|
||||||
|
[entryPoints.web.http.redirections]
|
||||||
|
[entryPoints.web.http.redirections.entryPoint]
|
||||||
|
to = "websecure"
|
||||||
|
scheme = "https"
|
||||||
|
|
||||||
|
[entryPoints.websecure]
|
||||||
|
address = ":443"
|
||||||
|
|
||||||
|
# Enable API
|
||||||
|
[api]
|
||||||
|
dashboard = false
|
||||||
|
|
||||||
|
# Enable docker backend
|
||||||
|
[providers.docker]
|
||||||
|
network = "gateway"
|
||||||
|
|
||||||
|
# https://doc.traefik.io/traefik/v2.4/https/acme/#configuration-examples
|
||||||
|
[certificatesResolvers.leresolver.acme]
|
||||||
|
email = "info@example.com"
|
||||||
|
storage = "acme.json"
|
||||||
|
[certificatesResolvers.leresolver.acme.httpChallenge]
|
||||||
|
# used during the challenge
|
||||||
|
entryPoint = "web"
|
Loading…
Reference in a new issue