diff --git a/.env.sample b/.env.sample index 9d8279412..e092a7fe5 100644 --- a/.env.sample +++ b/.env.sample @@ -1,3 +1,8 @@ +########### +# General # +########### +EXPOSED_PORT=3000 + ###### # DB # ###### @@ -15,89 +20,4 @@ DB_MIGRATIONS_PATH=dist/migrations/*.js ######### REDIS_PORT=6379 -REDIS_URL=redis://cache - -########## -# SHARED # -########## - -AUTH_JWT_SECRET=changeme123 - -############### -# API GATEWAY # -############### - -API_GATEWAY_LOG_LEVEL="info" -API_GATEWAY_NODE_ENV=production -API_GATEWAY_VERSION=local - -API_GATEWAY_NEW_RELIC_ENABLED=false -API_GATEWAY_NEW_RELIC_APP_NAME="API Gateway" -API_GATEWAY_NEW_RELIC_NO_CONFIG_FILE=true - -API_GATEWAY_SYNCING_SERVER_JS_URL=http://localhost:3002 -API_GATEWAY_AUTH_SERVER_URL=http://localhost:3003 -API_GATEWAY_WORKSPACE_SERVER_URL=http://localhost:3004 -API_GATEWAY_REVISIONS_SERVER_URL=http://localhost:3005 - -API_GATEWAY_REDIS_EVENTS_CHANNEL="api-gateway-event" - -API_GATEWAY_PORT=3000 - -######## -# AUTH # -######## - -AUTH_SERVER_LOG_LEVEL="info" -AUTH_SERVER_NODE_ENV="production" -AUTH_SERVER_VERSION="local" - -AUTH_SERVER_PORT=3003 - -AUTH_SERVER_AUTH_JWT_TTL=60000 - -AUTH_SERVER_NEW_RELIC_ENABLED=false -AUTH_SERVER_NEW_RELIC_APP_NAME=Auth -AUTH_SERVER_NEW_RELIC_NO_CONFIG_FILE=true - -AUTH_SERVER_REDIS_EVENTS_CHANNEL="auth-events" - -AUTH_SERVER_DISABLE_USER_REGISTRATION=false - -AUTH_SERVER_PSEUDO_KEY_PARAMS_KEY=changeme123 - -AUTH_SERVER_ACCESS_TOKEN_AGE=5184000 -AUTH_SERVER_REFRESH_TOKEN_AGE=31556926 - -AUTH_SERVER_MAX_LOGIN_ATTEMPTS=6 -AUTH_SERVER_FAILED_LOGIN_LOCKOUT=3600 - -AUTH_SERVER_EPHEMERAL_SESSION_AGE=259200 - -# Must be a hex string exactly 32 bytes long -# e.g. feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 -AUTH_SERVER_ENCRYPTION_SERVER_KEY=changeme123 - -AUTH_SERVER_SYNCING_SERVER_URL=http://localhost:3002 - -# File Uploads -AUTH_SERVER_VALET_TOKEN_TTL=7200 - -# Localstack Setup (Do not change unless you want to use your real AWS account) -AUTH_SERVER_SNS_TOPIC_ARN="arn:aws:sns:us-east-1:000000000000:auth-local-topic" -AUTH_SERVER_SNS_ENDPOINT="http://localstack:4566" -AUTH_SERVER_SNS_DISABLE_SSL=true -AUTH_SERVER_SNS_SECRET_ACCESS_KEY="x" -AUTH_SERVER_SNS_ACCESS_KEY_ID="x" -AUTH_SERVER_SNS_AWS_REGION="us-east-1" -AUTH_SERVER_SQS_QUEUE_URL="http://localstack:4566/000000000000/auth-local-queue" -AUTH_SERVER_SQS_AWS_REGION="us-east-1" -AUTH_SERVER_SQS_ACCESS_KEY_ID="x" -AUTH_SERVER_SQS_SECRET_ACCESS_KEY="x" -AUTH_SERVER_SQS_ENDPOINT="http://localstack:4566" - -# (Optional) U2F Setup -AUTH_SERVER_U2F_RELYING_PARTY_ID="localhost" -AUTH_SERVER_U2F_RELYING_PARTY_NAME="Standard Notes" -AUTH_SERVER_U2F_EXPECTED_ORIGIN="http://localhost,http://localhost:3001" # address of the app you host locally -AUTH_SERVER_U2F_REQUIRE_USER_VERIFICATION=false \ No newline at end of file +REDIS_URL=redis://cache \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index aacdbfa44..cfc48f8a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,7 @@ RUN apk add --update \ bash \ curl \ py3-pip \ + openssl \ && rm -rf /var/cache/apk/* ENV NODE_ENV production diff --git a/docker-compose.yml b/docker-compose.yml index a6818c35d..204a71b98 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,8 @@ services: server: build: . env_file: .env + ports: + - ${EXPOSED_PORT}:3000 volumes: - ./logs:/var/lib/server/logs @@ -13,7 +15,7 @@ services: MYSQL_PASSWORD: '${DB_PASSWORD}' MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' expose: - - ${DB_PORT}:3306 + - 3306 restart: unless-stopped command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8 --collation-server=utf8_general_ci volumes: @@ -25,5 +27,5 @@ services: volumes: - ./data/redis/:/data expose: - - ${REDIS_PORT}:6379 + - 6379 restart: unless-stopped diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index 380262566..3e6cf7578 100755 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -2,7 +2,186 @@ # Setup environment variables +###### +# DB # +###### + +if [ -z "$DB_HOST" ]; then + export DB_HOST="db" +fi +if [ -z "$DB_PORT" ]; then + export DB_PORT="3306" +fi +if [ -z "$DB_USERNAME" ]; then + export DB_USERNAME="std_notes_user" +fi +if [ -z "$DB_PASSWORD" ]; then + export DB_PASSWORD=$(openssl rand -hex 32) +fi +if [ -z "$DB_DATABASE" ]; then + export DB_DATABASE="standard_notes_db" +fi +if [ -z "$DB_DEBUG_LEVEL" ]; then + export DB_DEBUG_LEVEL="all" +fi +if [ -z "$DB_MIGRATIONS_PATH" ]; then + export DB_MIGRATIONS_PATH="dist/migrations/*.js" +fi + +######### +# CACHE # +######### + +if [ -z "$REDIS_PORT" ]; then + export REDIS_PORT=6379 +fi +if [ -z "$REDIS_URL" ]; then + export REDIS_URL="redis://cache" +fi + +########## +# SHARED # +########## + +if [ -z "$AUTH_JWT_SECRET" ]; then + export AUTH_JWT_SECRET=$(openssl rand -hex 32) +fi + +############### +# API GATEWAY # +############### + +if [ -z "$API_GATEWAY_LOG_LEVEL" ]; then + export API_GATEWAY_LOG_LEVEL="info" +fi +export API_GATEWAY_NODE_ENV=production +export API_GATEWAY_VERSION=local + +export API_GATEWAY_NEW_RELIC_ENABLED=false +export API_GATEWAY_NEW_RELIC_APP_NAME="API Gateway" +export API_GATEWAY_NEW_RELIC_NO_CONFIG_FILE=true + +export API_GATEWAY_SYNCING_SERVER_JS_URL=http://localhost:3002 +export API_GATEWAY_AUTH_SERVER_URL=http://localhost:3003 +export API_GATEWAY_WORKSPACE_SERVER_URL=http://localhost:3004 +export API_GATEWAY_REVISIONS_SERVER_URL=http://localhost:3005 + +export API_GATEWAY_REDIS_EVENTS_CHANNEL="api-gateway-event" + +export API_GATEWAY_PORT=3000 + printenv | grep API_GATEWAY_ | sed 's/API_GATEWAY_//g' > /opt/server/packages/api-gateway/.env + +######## +# AUTH # +######## + +if [ -z "$AUTH_SERVER_LOG_LEVEL" ]; then + export AUTH_SERVER_LOG_LEVEL="info" +fi +export AUTH_SERVER_NODE_ENV="production" +export AUTH_SERVER_VERSION="local" + +if [ -z "$AUTH_SERVER_AUTH_JWT_TTL" ]; then + export AUTH_SERVER_AUTH_JWT_TTL=60000 +fi + +if [ -z "$AUTH_SERVER_PORT" ]; then + export AUTH_SERVER_PORT=3003 +fi + +export AUTH_SERVER_JWT_SECRET=$AUTH_JWT_SECRET +export AUTH_SERVER_LEGACY_JWT_SECRET=$(openssl rand -hex 32) + +export AUTH_SERVER_NEW_RELIC_ENABLED=false +export AUTH_SERVER_NEW_RELIC_APP_NAME=Auth +export AUTH_SERVER_NEW_RELIC_NO_CONFIG_FILE=true + +export AUTH_SERVER_REDIS_EVENTS_CHANNEL="auth-events" + +if [ -z "$AUTH_SERVER_DISABLE_USER_REGISTRATION" ]; then + export AUTH_SERVER_DISABLE_USER_REGISTRATION=false +fi + +if [ -z "$AUTH_SERVER_PSEUDO_KEY_PARAMS_KEY" ]; then + export AUTH_SERVER_PSEUDO_KEY_PARAMS_KEY=$(openssl rand -hex 32) +fi + +if [ -z "$AUTH_SERVER_ACCESS_TOKEN_AGE" ]; then + export AUTH_SERVER_ACCESS_TOKEN_AGE=5184000 +fi +if [ -z "$AUTH_SERVER_REFRESH_TOKEN_AGE" ]; then + export AUTH_SERVER_REFRESH_TOKEN_AGE=31556926 +fi + +if [ -z "$AUTH_SERVER_MAX_LOGIN_ATTEMPTS" ]; then + export AUTH_SERVER_MAX_LOGIN_ATTEMPTS=6 +fi +if [ -z "$AUTH_SERVER_FAILED_LOGIN_LOCKOUT" ]; then + export AUTH_SERVER_FAILED_LOGIN_LOCKOUT=3600 +fi + +if [ -z "$AUTH_SERVER_EPHEMERAL_SESSION_AGE" ]; then + export AUTH_SERVER_EPHEMERAL_SESSION_AGE=259200 +fi + +if [ -z "$AUTH_SERVER_ENCRYPTION_SERVER_KEY" ]; then + export AUTH_SERVER_ENCRYPTION_SERVER_KEY=$(openssl rand -hex 32) +fi + +export AUTH_SERVER_SYNCING_SERVER_URL=http://localhost:3000 + +# File Uploads +if [ -z "$AUTH_SERVER_VALET_TOKEN_TTL" ]; then + export AUTH_SERVER_VALET_TOKEN_TTL=7200 +fi + +# Localstack Setup +if [ -z "$AUTH_SERVER_SNS_TOPIC_ARN" ]; then + export AUTH_SERVER_SNS_TOPIC_ARN="arn:aws:sns:us-east-1:000000000000:auth-local-topic" +fi +if [ -z "$AUTH_SERVER_SNS_ENDPOINT" ]; then + export AUTH_SERVER_SNS_ENDPOINT="http://localstack:4566" +fi +if [ -z "$AUTH_SERVER_SNS_SECRET_ACCESS_KEY" ]; then + export AUTH_SERVER_SNS_SECRET_ACCESS_KEY="x" +fi +if [ -z "$AUTH_SERVER_SNS_ACCESS_KEY_ID" ]; then + export AUTH_SERVER_SNS_ACCESS_KEY_ID="x" +fi +if [ -z "$AUTH_SERVER_SNS_AWS_REGION" ]; then + export AUTH_SERVER_SNS_AWS_REGION="us-east-1" +fi +if [ -z "$AUTH_SERVER_SQS_QUEUE_URL" ]; then + export AUTH_SERVER_SQS_QUEUE_URL="http://localstack:4566/000000000000/auth-local-queue" +fi +if [ -z "$AUTH_SERVER_SQS_AWS_REGION" ]; then + export AUTH_SERVER_SQS_AWS_REGION="us-east-1" +fi +if [ -z "$AUTH_SERVER_SQS_ACCESS_KEY_ID" ]; then + export AUTH_SERVER_SQS_ACCESS_KEY_ID="x" +fi +if [ -z "$AUTH_SERVER_SQS_SECRET_ACCESS_KEY" ]; then + export AUTH_SERVER_SQS_SECRET_ACCESS_KEY="x" +fi +if [ -z "$AUTH_SERVER_SQS_ENDPOINT" ]; then + export AUTH_SERVER_SQS_ENDPOINT="http://localstack:4566" +fi + +# U2F Setup +if [ -z "$AUTH_SERVER_U2F_RELYING_PARTY_ID" ]; then + export AUTH_SERVER_U2F_RELYING_PARTY_ID="localhost" +fi +if [ -z "$AUTH_SERVER_U2F_RELYING_PARTY_NAME" ]; then + export AUTH_SERVER_U2F_RELYING_PARTY_NAME="Standard Notes" +fi +if [ -z "$AUTH_SERVER_U2F_EXPECTED_ORIGIN" ]; then + export AUTH_SERVER_U2F_EXPECTED_ORIGIN="http://localhost,http://localhost:3001" +fi +if [ -z "$AUTH_SERVER_U2F_REQUIRE_USER_VERIFICATION" ]; then + export AUTH_SERVER_U2F_REQUIRE_USER_VERIFICATION=false +fi + printenv | grep AUTH_SERVER_ | sed 's/AUTH_SERVER_//g' > /opt/server/packages/auth/.env # Run supervisor diff --git a/docker/supervisord.conf b/docker/supervisord.conf index 129b6631f..66fb4b24c 100644 --- a/docker/supervisord.conf +++ b/docker/supervisord.conf @@ -12,7 +12,7 @@ stderr_logfile=/var/lib/server/logs/api-gateway.err [program:auth] directory=/opt/server -command=docker/wait-for.sh db 3306 && yarn start:auth +command=yarn start:auth autostart=true autorestart=true stdout_logfile=/var/lib/server/logs/auth.log @@ -20,7 +20,7 @@ stderr_logfile=/var/lib/server/logs/auth.err [program:auth-worker] directory=/opt/server -command=docker/wait-for.sh localhost 3003 && yarn start:auth-worker +command=yarn start:auth-worker autostart=true autorestart=true stdout_logfile=/var/lib/server/logs/auth-worker.log diff --git a/docker/wait-for.sh b/docker/wait-for.sh index 1ed073412..90438f0d2 100755 --- a/docker/wait-for.sh +++ b/docker/wait-for.sh @@ -1,16 +1,13 @@ -#!/bin/sh +#!/bin/bash -set -e - -host="$1" +WAIT_FOR_HOST="$1" shift -port="$1" +WAIT_FOR_PORT="$1" shift -cmd="$@" -while ! nc -vz $host $port; do - >&2 echo "$host:$port is unavailable yet - waiting for it to start" +while ! nc -vz $WAIT_FOR_HOST $WAIT_FOR_PORT; do + echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is unavailable yet - waiting for it to start" sleep 10 done ->&2 echo "$host:$port is up. Proceeding to startup." \ No newline at end of file +echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is up. Proceeding to startup." \ No newline at end of file diff --git a/package.json b/package.json index 835ac9e7b..52b728c18 100644 --- a/package.json +++ b/package.json @@ -24,14 +24,16 @@ "lint:revisions": "yarn workspace @standardnotes/revisions-server lint", "clean": "yarn workspaces foreach -p --verbose run clean", "setup:env": "cp .env.sample .env && yarn workspaces foreach -p --verbose run setup:env", - "start:auth": "yarn workspace @standardnotes/auth-server start", - "start:auth-worker": "yarn workspace @standardnotes/auth-server worker", + "wait-for:db": "docker/wait-for.sh $DB_HOST $DB_PORT", + "wait-for:auth": "docker/wait-for.sh localhost $AUTH_SERVER_PORT", + "start:auth": "yarn wait-for:db && yarn workspace @standardnotes/auth-server start", + "start:auth-worker": "yarn wait-for:auth && yarn workspace @standardnotes/auth-server worker", "start:scheduler": "yarn workspace @standardnotes/scheduler-server worker", "start:syncing-server": "yarn workspace @standardnotes/syncing-server start", "start:syncing-server-worker": "yarn workspace @standardnotes/syncing-server worker", "start:files": "yarn workspace @standardnotes/files-server start", "start:files-worker": "yarn workspace @standardnotes/files-server worker", - "start:api-gateway": "yarn workspace @standardnotes/api-gateway start", + "start:api-gateway": "yarn wait-for:auth && yarn workspace @standardnotes/api-gateway start", "start:websockets": "yarn workspace @standardnotes/websockets-server start", "start:workspace": "yarn workspace @standardnotes/workspace-server start", "start:analytics": "yarn workspace @standardnotes/analytics worker",