diff --git a/.env.prod.template b/.env.prod.template new file mode 100644 index 00000000..184daf3c --- /dev/null +++ b/.env.prod.template @@ -0,0 +1,17 @@ +# The base domain +DOMAIN=workadventure.localhost + +DEBUG_MODE=false +JITSI_URL=meet.jit.si +# If your Jitsi environment has authentication set up, you MUST set JITSI_PRIVATE_MODE to "true" and you MUST pass a SECRET_JITSI_KEY to generate the JWT secret +JITSI_PRIVATE_MODE=false +JITSI_ISS= +SECRET_JITSI_KEY= + +# URL of the TURN server (needed to "punch a hole" through some networks for P2P connections) +TURN_SERVER= +TURN_USER= +TURN_PASSWORD= + +# The URL used by default, in the form: "/_/global/map/url.json" +START_ROOM_URL=/_/global/maps.workadventu.re/Floor0/floor0.json diff --git a/back/src/Enum/EnvironmentVariable.ts b/back/src/Enum/EnvironmentVariable.ts index 2cbfbf2e..95a705fa 100644 --- a/back/src/Enum/EnvironmentVariable.ts +++ b/back/src/Enum/EnvironmentVariable.ts @@ -1,4 +1,3 @@ -const SECRET_KEY = process.env.SECRET_KEY || "THECODINGMACHINE_SECRET_KEY"; const MINIMUM_DISTANCE = process.env.MINIMUM_DISTANCE ? Number(process.env.MINIMUM_DISTANCE) : 64; const GROUP_RADIUS = process.env.GROUP_RADIUS ? Number(process.env.GROUP_RADIUS) : 48; const ALLOW_ARTILLERY = process.env.ALLOW_ARTILLERY ? process.env.ALLOW_ARTILLERY == 'true' : false; @@ -14,7 +13,6 @@ const GRPC_PORT = parseInt(process.env.GRPC_PORT || '50051') || 50051; export const SOCKET_IDLE_TIMER = parseInt(process.env.SOCKET_IDLE_TIMER as string) || 30; // maximum time (in second) without activity before a socket is closed export { - SECRET_KEY, MINIMUM_DISTANCE, ADMIN_API_URL, ADMIN_API_TOKEN, diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml index 1837d06b..e25b07d5 100644 --- a/docker-compose.prod.yaml +++ b/docker-compose.prod.yaml @@ -1,62 +1,91 @@ -version: "3" +version: "3.3" services: reverse-proxy: - image: traefik:v2.3.7 + image: traefik:v2.3 command: + - --log.level=WARN + #- --api.insecure=true - --providers.docker - --entryPoints.web.address=:80 + - --entrypoints.web.http.redirections.entryPoint.to=websecure + - --entrypoints.web.http.redirections.entryPoint.scheme=https - --entryPoints.websecure.address=:443 + - --certificatesresolvers.myresolver.acme.email=d.negrier@thecodingmachine.com + - --certificatesresolvers.myresolver.acme.storage=/acme.json + # used during the challenge + - --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web ports: - "80:80" - "443:443" + # The Web UI (enabled by --api.insecure=true) + #- "8080:8080" depends_on: - - back + - pusher - front volumes: - /var/run/docker.sock:/var/run/docker.sock + - ./acme.json:/acme.json + restart: unless-stopped + front: - build: - context: . - dockerfile: front/Dockerfile - args: - BASE_DOMAIN: ${BASE_DOMAIN:-workadventure.localhost} + image: thecodingmachine/workadventure-front:master + environment: + DEBUG_MODE: "$DEBUG_MODE" + JITSI_URL: $JITSI_URL + JITSI_PRIVATE_MODE: "$JITSI_PRIVATE_MODE" + API_URL: pusher.${DOMAIN} + TURN_SERVER: "${TURN_SERVER}" + TURN_USER: "${TURN_USER}" + TURN_PASSWORD: "${TURN_PASSWORD}" + START_ROOM_URL: "${START_ROOM_URL}" labels: - - "traefik.http.routers.front.rule=Host(`play.${BASE_DOMAIN:-workadventure.localhost}`)" - - "traefik.http.routers.front.entryPoints=web" - - "traefik.http.services.front.loadbalancer.server.port=8000" - - "traefik.http.routers.front-ssl.rule=Host(`play.${BASE_DOMAIN:-workadventure.localhost}`)" + - "traefik.http.routers.front.rule=Host(`play.${DOMAIN}`)" + - "traefik.http.routers.front.entryPoints=web,traefik" + - "traefik.http.services.front.loadbalancer.server.port=80" + - "traefik.http.routers.front-ssl.rule=Host(`play.${DOMAIN}`)" - "traefik.http.routers.front-ssl.entryPoints=websecure" - "traefik.http.routers.front-ssl.tls=true" - "traefik.http.routers.front-ssl.service=front" - - back: - build: - context: . - dockerfile: back/Dockerfile - environment: - SECRET_KEY: yourSecretKey - SECRET_JITSI_KEY: "$SECRET_JITSI_KEY" - ADMIN_API_TOKEN: "$ADMIN_API_TOKEN" - JITSI_URL: $JITSI_URL - JITSI_ISS: $JITSI_ISS + - "traefik.http.routers.front-ssl.tls.certresolver=myresolver" + restart: unless-stopped pusher: - build: - context: . - dockerfile: pusher/Dockerfile + image: thecodingmachine/workadventure-pusher:master + command: yarn run runprod environment: - SECRET_KEY: yourSecretKey SECRET_JITSI_KEY: "$SECRET_JITSI_KEY" - ADMIN_API_TOKEN: "$ADMIN_API_TOKEN" + SECRET_KEY: yourSecretKey API_URL: back:50051 JITSI_URL: $JITSI_URL JITSI_ISS: $JITSI_ISS labels: - - "traefik.http.routers.pusher.rule=Host(`pusher.${BASE_DOMAIN:-workadventure.localhost}`)" - - "traefik.http.routers.pusher.entryPoints=web" + - "traefik.http.routers.pusher.rule=Host(`pusher.${DOMAIN}`)" + - "traefik.http.routers.pusher.entryPoints=web,traefik" - "traefik.http.services.pusher.loadbalancer.server.port=8080" - - "traefik.http.routers.pusher-ssl.rule=Host(`pusher.${BASE_DOMAIN:-workadventure.localhost}`)" + - "traefik.http.routers.pusher-ssl.rule=Host(`pusher.${DOMAIN}`)" - "traefik.http.routers.pusher-ssl.entryPoints=websecure" - "traefik.http.routers.pusher-ssl.tls=true" - "traefik.http.routers.pusher-ssl.service=pusher" + - "traefik.http.routers.pusher-ssl.tls.certresolver=myresolver" + restart: unless-stopped + + back: + image: thecodingmachine/workadventure-back:master + command: yarn run runprod + environment: + SECRET_JITSI_KEY: "$SECRET_JITSI_KEY" + ADMIN_API_TOKEN: "$ADMIN_API_TOKEN" + ADMIN_API_URL: "$ADMIN_API_URL" + JITSI_URL: $JITSI_URL + JITSI_ISS: $JITSI_ISS + labels: + - "traefik.http.routers.back.rule=Host(`api.${DOMAIN}`)" + - "traefik.http.routers.back.entryPoints=web" + - "traefik.http.services.back.loadbalancer.server.port=8080" + - "traefik.http.routers.back-ssl.rule=Host(`api.${DOMAIN}`)" + - "traefik.http.routers.back-ssl.entryPoints=websecure" + - "traefik.http.routers.back-ssl.tls=true" + - "traefik.http.routers.back-ssl.service=back" + - "traefik.http.routers.back-ssl.tls.certresolver=myresolver" + restart: unless-stopped diff --git a/front/Dockerfile b/front/Dockerfile index 573eeca2..b0d17877 100644 --- a/front/Dockerfile +++ b/front/Dockerfile @@ -1,29 +1,16 @@ -# protobuf build -FROM node:14.15.4-buster-slim@sha256:cbae886186467bbfd274b82a234a1cdfbbd31201c2a6ee63a6893eefcf3c6e76 as builder -WORKDIR /usr/src -COPY messages . +FROM thecodingmachine/workadventure-back-base:latest as builder +WORKDIR /var/www/messages +COPY --chown=docker:docker messages . RUN yarn install && yarn proto -# webpack build -FROM node:14.15.4-buster-slim@sha256:cbae886186467bbfd274b82a234a1cdfbbd31201c2a6ee63a6893eefcf3c6e76 as builder2 -WORKDIR /usr/src -COPY front/yarn.lock front/package.json ./ +# we are rebuilding on each deploy to cope with the API_URL environment URL +FROM thecodingmachine/nodejs:14-apache + +COPY --chown=docker:docker front . +COPY --from=builder --chown=docker:docker /var/www/messages/generated /var/www/html/src/Messages/generated RUN yarn install -COPY front . -COPY --from=builder /usr/src/generated src/Messages/generated ENV NODE_ENV=production - -ARG BASE_DOMAIN=workadventure.localhost -ARG API_URL=pusher.$BASE_DOMAIN -ARG UPLOADER_URL=uploader.$BASE_DOMAIN -ARG ADMIN_URL=admin.$BASE_DOMAIN - -RUN API_URL=$API_URL UPLOADER_URL=$UPLOADER_URL ADMIN_URL=$ADMIN_URL \ - yarn run build - -# final production image -FROM nginx:1.19.6-alpine@sha256:01747306a7247dbe928db991eab42e4002118bf636dd85b4ffea05dd907e5b66 -COPY front/nginx-vhost.conf /etc/nginx/conf.d/default.conf -COPY front/templater.sh /docker-entrypoint.d/templater.sh -COPY --from=builder2 /usr/src/dist /usr/share/nginx/html +ENV STARTUP_COMMAND_0="./templater.sh" +ENV STARTUP_COMMAND_1="yarn run build" +ENV APACHE_DOCUMENT_ROOT=dist/ diff --git a/front/dist/index.html.tmpl b/front/dist/index.tmpl.html similarity index 100% rename from front/dist/index.html.tmpl rename to front/dist/index.tmpl.html diff --git a/front/templater.sh b/front/templater.sh index ac899bbd..e63617c5 100755 --- a/front/templater.sh +++ b/front/templater.sh @@ -1,15 +1,15 @@ #!/usr/bin/env bash set -x set -o nounset errexit -template_file_index=/usr/share/nginx/html/index.html.tmpl -generated_file_index=/usr/share/nginx/html/index.html +template_file_index=dist/index.html.tmpl +generated_file_index=dist/index.html tmp_trackcodefile=/tmp/trackcode # To inject tracking code, you have two choices: # 1) Template using the provided google analytics # 2) Insert with your own provided code, by overriding the ANALYTICS_CODE_PATH # The ANALYTICS_CODE_PATH is the location of a file inside the container -ANALYTICS_CODE_PATH="${ANALYTICS_CODE_PATH:-/usr/share/nginx/html/ga.html.tmpl}" +ANALYTICS_CODE_PATH="${ANALYTICS_CODE_PATH:-dist/ga.html.tmpl}" if [[ "${INSERT_ANALYTICS:-NO}" == "NO" ]]; then echo "" > "${tmp_trackcodefile}" diff --git a/front/webpack.config.js b/front/webpack.config.js index 3b97081c..e4294650 100644 --- a/front/webpack.config.js +++ b/front/webpack.config.js @@ -39,7 +39,16 @@ module.exports = { plugins: [ new HtmlWebpackPlugin( { - template: './dist/index.html' + template: './dist/index.tmpl.html', + minify: { + collapseWhitespace: true, + keepClosingSlash: true, + removeComments: false, + removeRedundantAttributes: true, + removeScriptTypeAttributes: true, + removeStyleLinkTypeAttributes: true, + useShortDoctype: true + } } ), new webpack.ProvidePlugin({