From 4de7e7f1ea12cefad1bee93345eb51aff89ec417 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Wed, 20 Apr 2022 20:42:51 +0100 Subject: [PATCH] add production environment --- environment/production/.env.sample | 50 +++++++++++++++ environment/production/README.md | 32 ++++++++++ environment/production/docker-compose.yml | 70 +++++++++++++++++++++ environment/production/traefik/traefik.toml | 34 ++++++++++ 4 files changed, 186 insertions(+) create mode 100644 environment/production/.env.sample create mode 100644 environment/production/README.md create mode 100644 environment/production/docker-compose.yml create mode 100644 environment/production/traefik/traefik.toml diff --git a/environment/production/.env.sample b/environment/production/.env.sample new file mode 100644 index 0000000..6794d23 --- /dev/null +++ b/environment/production/.env.sample @@ -0,0 +1,50 @@ +NODE_ENV=production +APP_SALT=CHANGE_ME +LOG_LEVEL=debug + +DB_NAME=retro-pilot +DB_USER=root +DB_PASS=root +# If using docker compose, this should match the container service name +DB_HOST=10.0.0.2 +DB_PORT=5432 +# Whether or not to DROP all tables and recreate to match the current models +DB_FORCE_SYNC=false + +ALLOW_REGISTRATION=true +AUTH_2FA_ISSUER=RetroPilot + +HTTP_INTERFACE=0.0.0.0 +HTTP_PORT=8080 + +# Set to false to skip sending mail, all attempted mail is logged under DEBUG +CAN_SEND_MAIL=true +# credentials for smtp server to send account registration mails. if not filled in, get the generated tokens from the server.log manually +SMTP_HOST="localhost" +SMTP_PORT=25 +SMTP_USER=root +SMTP_PASS= +SMTP_FROM="no-reply@retropilot.org" + +# base url of the retropilot server +BASE_URL="https://api.retropilot.org/" +# base url sent to devices for POSTing drives & logs +BASE_UPLOAD_URL="https://api.retropilot.org/backend/post_upload" +# base download url for drive & log data +BASE_DRIVE_DOWNLOAD_URL="https://api.retropilot.org/realdata/" +# path mapping of above download url for expressjs, prefix with "/" +BASE_DRIVE_DOWNLOAD_PATH_MAPPING="/realdata" +# relative or absolute ( "/..." for absolute path ) +STORAGE_PATH="/realdata/" + +CABANA_URL="https://api.retropilot.org/cabana/index.html" + +DEVICE_STORAGE_QUOTA_MB=25000 +DEVICE_EXPIRATION_DAYS=90 + +WELCOME_MESSAGE="<><><><><><><><><><><><><><><><><><><><><><>
2022 RetroPilot" + +USE_USER_ADMIN_API=0 + +CLIENT_SOCKET_PORT=81 +CLIENT_SOCKET_HOST="0.0.0.0" diff --git a/environment/production/README.md b/environment/production/README.md new file mode 100644 index 0000000..0500a63 --- /dev/null +++ b/environment/production/README.md @@ -0,0 +1,32 @@ +# Production environment + +Hostname: `api.retropilot.org` + +## Setup + +Refer to the `environments/uat` environment for setup instructions. + +## Deployment + +Make sure to create and modify the `.env` file as required for your environment. + +Note that the first time you run the API it will initialise the database. It is a good idea to do this once before +starting all the services together. + +Before first run (in `/data/retropilot-server`): +```sh +cd environment/production + +# copy and modify the `.env` file as required +cp .env.sample .env + +# allow the API to initialise the database schema +docker compose up api +# CTRL-C when "RetroPilot Server listening at" message appears +``` + +To start all the services: +```sh +cd environment/production +docker compose up -d +``` diff --git a/environment/production/docker-compose.yml b/environment/production/docker-compose.yml new file mode 100644 index 0000000..068b2ba --- /dev/null +++ b/environment/production/docker-compose.yml @@ -0,0 +1,70 @@ +version: "3.0" + +services: + # Traefik reverse proxy + # https://doc.traefik.io/traefik/ + reverse-proxy: + image: traefik:v2.6.3 + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + # See traefik/traefik.toml for static config + - ./traefik:/etc/traefik + labels: + - "traefik.enable=true" + # Expose traefik dashboard at http://localhost:8080 + - "traefik.http.routers.dashboard.rule=Host(`localhost`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" + - "traefik.http.routers.dashboard.entrypoints=dashboard" + - "traefik.http.routers.dashboard.service=api@internal" + # Secure the dashboard with IPWhiteList middleware + - "traefik.http.routers.dashboard.middlewares=dashboard-allowlist@docker" + - "traefik.http.middlewares.dashboard-allowlist.ipwhitelist.sourcerange=127.0.0.1/32" + + # API server + api: + # Use the retropilot-server image from the GitHub Container Registry + image: ghcr.io/retropilot/retropilot-server:uat + restart: unless-stopped + volumes: + # Mount realdata dir to /realdata in the container + - ./realdata:/realdata + env_file: + - .env + labels: + - "traefik.enable=true" + # API service forwards requests to container port 8080 + - "traefik.http.services.api.loadbalancer.server.port=8080" + # Expose api at https://uat.api.retropilot.org + - "traefik.http.routers.api.rule=Host(`uat.api.retropilot.org`) || Host(`uat.api.retropilot.org`)" + - "traefik.http.routers.api.entrypoints=websecure" + - "traefik.http.routers.api.service=api@docker" + - "traefik.http.routers.api.tls=true" + - "traefik.http.routers.api.tls.certresolver=retropilot" + + # Monitor for image updates and restart automatically + - "com.centurylinklabs.watchtower.enable=true" + + # API worker + worker: + # Use the same image as the server + image: ghcr.io/retropilot/retropilot-server:uat + # But run the worker script instead + command: npm run worker + restart: unless-stopped + volumes: + - ./realdata:/realdata + env_file: + - .env + labels: + # Monitor for image updates and restart automatically + - "com.centurylinklabs.watchtower.enable=true" + + watchtower: + # automatically update containers when new images are released + image: containrrr/watchtower + volumes: + - /var/run/docker.sock:/var/run/docker.sock + command: --interval 30 --label-enable diff --git a/environment/production/traefik/traefik.toml b/environment/production/traefik/traefik.toml new file mode 100644 index 0000000..c953af2 --- /dev/null +++ b/environment/production/traefik/traefik.toml @@ -0,0 +1,34 @@ +# traefik reverse proxy config +# docs: https://doc.traefik.io/traefik/ + +[api] + dashboard = true + +[log] + level = "INFO" + +[providers] + [providers.docker] + endpoint = "unix:///var/run/docker.sock" + exposedByDefault = false + +[entryPoints] + [entryPoints.web] + address = ":80" + [entryPoints.web.http] + [entryPoints.web.http.redirections] + [entryPoints.web.http.redirections.entryPoint] + to = "websecure" + [entryPoints.websecure] + address = ":443" + [entryPoints.dashboard] + address = ":8080" + +[certificatesResolvers] + [certificatesResolvers.retropilot] + [certificatesResolvers.retropilot.acme] + caServer = "https://acme-v02.api.letsencrypt.org/directory" + email = "admin@retropilot.org" + storage = "acme.json" + [certificatesResolvers.retropilot.acme.httpChallenge] + entryPoint = "web"