diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8c918fa --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +.vscode +persist-data/** +server-dotlocal/** +server-logs/** + diff --git a/README.md b/README.md index f240937..bf671fe 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,6 @@ clients use ports all over the place. The assignment-clients need some taming on their port usage and some parameterization for running multiple domain-servers on one processor. -TODO: Break out all the assignment clients into separate containers running -on the 'internal' virtual network. Use `docker-compose` or similar to -start them all up and to do scaling for things like audio load, etc. - ## Ice Server The Docker image also contains an ice-server which you can run if you @@ -91,8 +87,30 @@ was built with: "GIT_COMMIT_SHORT": "FirstEightCharactersOfGitCommitString", "GIT_TAG": "GitBranchTag", "BUILD_DATE": "YYYYMMDD.HHMM", - "BUILD_DAY": "YYYYMMDD" + "BUILD_DAY": "YYYYMMDD", "VERSION_TAG": "TAG-YYYYMMDD-xxxxxxxx" } ``` + +### Docker Compose +Start and stop all necessary services using `docker-compose`. +A. In order to do so, followig the instruction for the domain-server and the ice-server build above. It will create vircadia-domain-server. Based on this docker image, domain-server and ice-server can be launched. +B. Create a mentaverse docker image. To do so, consult https://github.com/vircadia/vircadia-metaverse/blob/master/docs/RunningDockerImage.md + +C. Run `build-mongo.sh` from `vircadia-mongo` dir. +``` + cd vircadia-mongo && ./buid-mongo.sh +``` +Mongo will be pulled from Mongo(4.4) repository. + +For now, it will deploy vircadia domain-server, ice-server, mongoDB, and metaverse server. +MongoDB will be persists at `./persist-data/vircadia-mongo`. + +D. Launch docker-compose. +``` + docker-compose up -d +``` +This will launch 1) vircadia-mongodb 2) metaverseserver 3) vircadia-ice-server and 4) vircadia-domain-server + +TODO: Split network to configuration frontend and backend and hide backend serveses such as mongodb and metaverse-server. diff --git a/add-mailuser.sh b/add-mailuser.sh new file mode 100755 index 0000000..4f76acf --- /dev/null +++ b/add-mailuser.sh @@ -0,0 +1,5 @@ +#! /bin/bash + +docker run --rm -v ${PWD}/persist-data/dms/config/:/tmp/docker-mailserver/ vircadia-mailserver setup email add cadia@n=vircadia-metaverse.com noneknowsit mailuser.sh +docker run --rm -v ${PWD}/persist-data/dms/config/:/tmp/docker-mailserver/ vircadia-mailserver setup alias add postmaster@vircadia-metaverse.com cadia@vircadia-metaverse.com +docker run --rm -v ${PWD}/persist-data/dms/config/:/tmp/docker-mailserver/ vircadia-mailserver setup config dkim diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9230dc3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,110 @@ +version: '3.9' + +services: + vircadia-mongodb: + image: vircadia-mongodb:4.4 + container_name: vircadia-mongodb + restart: unless-stopped + hostname: vircadia-mongodb + ports: + - 27017:27017 + volumes: + - ./persist-data/vircadia-mongo/data/db:/data/db + - ./persist-data/vircadia-mongo/data/log:/var/log/mongodb + networks: + - vircadia + + vircadia-metaverse-server: + image: metaverse-server:latest + container_name: vircadia-metaverse-server + restart: unless-stopped + hostname: vircadia-metaverse-server + environment: + - IAMUS_CONFIG_FILE=/home/cadia/config/iamus.json + volumes: + - ./files/metaverse/iamus.json:/home/cadia/config/iamus.json + - ./persist-data/vircadia-metaverse/metaverse/logs:/home/cadia/vircadia-metaverse/logs + - ./persist-data/vircadia-metaverse/metaverse/Logs:/home/cadia/vircadia-metaverse/Logs + ports: + - 9400:9400 + links: + - vircadia-mongodb + networks: + - vircadia + depends_on: + - vircadia-mongodb + + vircadia-metaverse-dashboard: + image: metaverse-dashboard:latest + container_name: vircadia-metaverse-dashboard + restart: unless-stopped + hostname: vircadia-metaverse-dashboard + volumes: + - ./persist-data/vircadia-metaverse-dashboard/logs:/home/cadia/metaverse-dashboard/log + ports: + - 8090:8080 + links: + - vircadia-metaverse-server + networks: + - vircadia + depends_on: + - vircadia-metaverse-server + + vircadia-ice-server: + image: vircadia-domain-server:latest + container_name: vircadia-ice-server + restart: unless-stopped + hostname: vircadia-ice-server + ports: + - 7337:7337 + - 7337:7337/udp + environment: + - METAVERSE_URL=http://localhost:9400 + entrypoint: /home/cadia/start-ice-server.sh + volumes: + - ./persist-data/vircadia-ice-server/server-dotlocal/testmeteverse:/home/cadia/.local + - ./persist-data/vircadia-ice-server/server-logs/testmeteverse:/home/cadia/logs + networks: + - vircadia + depends_on: + - vircadia-metaverse-server + + vircadia-domain-server: + image: vircadia-domain-server:latest + container_name: vircadia-domain-server + restart: unless-stopped + hostname: vircadia-domain-server + ports: + - 40100-40102:40100-40102 + - 40100-40102:40100-40102/udp + - 48000-48009:48000-48009/udp + environment: + - METAVERSE_URL=http://localhost:9400 + - ICE_SERVER=localhost:7337 + - CLEANNAME=vircadia-metaverse-server + - INSTANCE=0 + volumes: + - ./persist-data/vircadia-domain-server/server-dotlocal/testmeteverse:/home/cadia/.local + - ./persist-data/vircadia-domain-server/server-logs/testmeteverse:/home/cadia/logs + networks: + - vircadia + depends_on: + - vircadia-ice-server + + vircadia-web: + image: vircadia-web:latest + container_name: vircadia-web + restart: unless-stopped + hostname: vircadia-web + ports: + - 8080:8080 + volumes: + - ./persist-data/vircadia-web/logs:/home/cadia/vircadia-web/log + networks: + - vircadia + depends_on: + - vircadia-domain-server + +networks: + vircadia: + driver: bridge diff --git a/files/metaverse/iamus.json b/files/metaverse/iamus.json new file mode 100644 index 0000000..725410e --- /dev/null +++ b/files/metaverse/iamus.json @@ -0,0 +1,19 @@ +{ + "metaverse": { + "metaverse-name": "TestMetaverse", + "metaverse-nick-name": "TestMetaverse", + "metaverse-server-url": "http://localhost:9400", + "default-ice-server-url": "http://localhost:7337", + "dashboard-url": "http://localhost:8080" + }, + "database": { + "db": "domainstore", + "db-host": "vircadia-mongodb", + "db-user": "cadiauser", + "db-pw": "noneknowsit" + }, + "debug": { + "loglevel": "debug", + "devel": true + } +} diff --git a/files/start-domain-server.sh b/files/start-domain-server.sh index 84dbcdb..dfced64 100755 --- a/files/start-domain-server.sh +++ b/files/start-domain-server.sh @@ -39,13 +39,13 @@ DOMAIN_SERVER_PORT=$(( $DOMAIN_SERVER_BASE + 2 )) cd "${RUNDIR}" -#./run_assignment-client -t 0 -p $(( $ASSIGNMENT_BASE + 0 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-0.log" 2>&1 & -#./run_assignment-client -t 1 -p $(( $ASSIGNMENT_BASE + 1 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-1.log" 2>&1 & -#./run_assignment-client -t 6 -p $(( $ASSIGNMENT_BASE + 6 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-6.log" 2>&1 & -#./run_assignment-client -t 3 -p $(( $ASSIGNMENT_BASE + 3 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-3.log" 2>&1 & -#./run_assignment-client -t 5 -p $(( $ASSIGNMENT_BASE + 5 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-5.log" 2>&1 & -#./run_assignment-client -t 4 -p $(( $ASSIGNMENT_BASE + 4 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-4.log" 2>&1 & -#./run_assignment-client -t 2 -p $(( $ASSIGNMENT_BASE + 2 )) --server-port ${DOMAIN_SERVER_PORT} --max 60 >> "${ALOGFILE}-2.log" 2>&1 & +# ./run_assignment-client -t 0 -p $(( $ASSIGNMENT_BASE + 0 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-0.log" 2>&1 & +# ./run_assignment-client -t 1 -p $(( $ASSIGNMENT_BASE + 1 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-1.log" 2>&1 & +# ./run_assignment-client -t 6 -p $(( $ASSIGNMENT_BASE + 6 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-6.log" 2>&1 & +# ./run_assignment-client -t 3 -p $(( $ASSIGNMENT_BASE + 3 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-3.log" 2>&1 & +# ./run_assignment-client -t 5 -p $(( $ASSIGNMENT_BASE + 5 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-5.log" 2>&1 & +# ./run_assignment-client -t 4 -p $(( $ASSIGNMENT_BASE + 4 )) --server-port ${DOMAIN_SERVER_PORT} >> "${ALOGFILE}-4.log" 2>&1 & +# ./run_assignment-client -t 2 -p $(( $ASSIGNMENT_BASE + 2 )) --server-port ${DOMAIN_SERVER_PORT} --max 60 >> "${ALOGFILE}-2.log" 2>&1 & ./run_assignment-client -p $ASSIGNMENT_BASE --server-port ${DOMAIN_SERVER_PORT} --max 20 >> "${ALOGFILE}-A.log" 2>&1 & diff --git a/run-domain-server.sh b/run-domain-server.sh index 3e2ce35..b7463ee 100755 --- a/run-domain-server.sh +++ b/run-domain-server.sh @@ -23,9 +23,15 @@ if [[ ! -z "$2" ]] ; then ICE_SERVER=$2 fi -export DOCKER_REPOSITORY=${DOCKER_REPOSITORY:-misterblue} -export IMAGE_NAME=${IMAGE_NAME:-vircadia-domain-server} -export IMAGE_VERSION=${IMAGE_VERSION:-latest} +# export DOCKER_REPOSITORY=${DOCKER_REPOSITORY:-misterblue} +# export IMAGE_NAME=${IMAGE_NAME:-vircadia-domain-server} +# export IMAGE_VERSION=${IMAGE_VERSION:-latest} + +# runs local +export DOCKER_REPOSITORY=LOCAL +export IMAGE_NAME=vircadia-domain-server +export IMAGE_VERSION=latest + if [[ "${DOCKER_REPOSITORY}" == "LOCAL" ]] ; then export DOCKER_IMAGE=${IMAGE_NAME}:${IMAGE_VERSION} else diff --git a/vircadia-mongo/Dockerfile b/vircadia-mongo/Dockerfile new file mode 100644 index 0000000..35f7f7e --- /dev/null +++ b/vircadia-mongo/Dockerfile @@ -0,0 +1,118 @@ +# Majority of the script is from https://github.com/docker-library/mongo +# Adding vircadia related stuffs. + +FROM ubuntu:20.04 + +# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added +RUN groupadd -r mongodb && useradd -r -g mongodb mongodb + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + jq \ + numactl \ + ; \ + if ! command -v ps > /dev/null; then \ + apt-get install -y --no-install-recommends procps; \ + fi; \ + rm -rf /var/lib/apt/lists/* + +# grab gosu for easy step-down from root (https://github.com/tianon/gosu/releases) +ENV GOSU_VERSION 1.12 +# grab "js-yaml" for parsing mongod's YAML config files (https://github.com/nodeca/js-yaml/releases) +ENV JSYAML_VERSION 3.13.1 + +RUN set -ex; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + wget \ + ; \ + if ! command -v gpg > /dev/null; then \ + apt-get install -y --no-install-recommends gnupg dirmngr; \ + savedAptMark="$savedAptMark gnupg dirmngr"; \ + elif gpg --version | grep -q '^gpg (GnuPG) 1\.'; then \ +# "This package provides support for HKPS keyservers." (GnuPG 1.x only) + apt-get install -y --no-install-recommends gnupg-curl; \ + fi; \ + rm -rf /var/lib/apt/lists/*; \ + \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + command -v gpgconf && gpgconf --kill all || :; \ + rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc; \ + \ + wget -O /js-yaml.js "https://github.com/nodeca/js-yaml/raw/${JSYAML_VERSION}/dist/js-yaml.js"; \ +# TODO some sort of download verification here + \ + apt-mark auto '.*' > /dev/null; \ + apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ +# smoke test + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true + +RUN mkdir /docker-entrypoint-initdb.d + +RUN set -ex; \ + export GNUPGHOME="$(mktemp -d)"; \ + set -- '20691EEC35216C63CAF66CE1656408E390CFB1F5'; \ + for key; do \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ + done; \ + gpg --batch --export "$@" > /etc/apt/trusted.gpg.d/mongodb.gpg; \ + command -v gpgconf && gpgconf --kill all || :; \ + rm -r "$GNUPGHOME"; \ + apt-key list + +# Allow build-time overrides (eg. to build image with MongoDB Enterprise version) +# Options for MONGO_PACKAGE: mongodb-org OR mongodb-enterprise +# Options for MONGO_REPO: repo.mongodb.org OR repo.mongodb.com +# Example: docker build --build-arg MONGO_PACKAGE=mongodb-enterprise --build-arg MONGO_REPO=repo.mongodb.com . +ARG MONGO_PACKAGE=mongodb-org +ARG MONGO_REPO=repo.mongodb.org +ENV MONGO_PACKAGE=${MONGO_PACKAGE} MONGO_REPO=${MONGO_REPO} + +ENV MONGO_MAJOR 4.4 +RUN echo "deb http://$MONGO_REPO/apt/ubuntu focal/${MONGO_PACKAGE%-unstable}/$MONGO_MAJOR multiverse" | tee "/etc/apt/sources.list.d/${MONGO_PACKAGE%-unstable}.list" + +# http://docs.mongodb.org/master/release-notes/4.4/ +ENV MONGO_VERSION 4.4.11 +# 12/28/2021, https://github.com/mongodb/mongo/tree/b7530cacde8432d2f22ed506f258ff9c3b45c5e9 + +RUN set -x \ +# installing "mongodb-enterprise" pulls in "tzdata" which prompts for input + && export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ +# starting with MongoDB 4.3 (and backported to 4.0 and 4.2 *and* 3.6??), the postinst for server includes an unconditional "systemctl daemon-reload" (and we don't have anything for "systemctl" to talk to leading to dbus errors and failed package installs) + && ln -s /bin/true /usr/local/bin/systemctl \ + && apt-get install -y \ + ${MONGO_PACKAGE}=$MONGO_VERSION \ + ${MONGO_PACKAGE}-server=$MONGO_VERSION \ + ${MONGO_PACKAGE}-shell=$MONGO_VERSION \ + ${MONGO_PACKAGE}-mongos=$MONGO_VERSION \ + ${MONGO_PACKAGE}-tools=$MONGO_VERSION \ + && rm -f /usr/local/bin/systemctl \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /var/lib/mongodb \ + && mv /etc/mongod.conf /etc/mongod.conf.orig + +RUN mkdir -p /data/db /data/configdb \ + && chown -R mongodb:mongodb /data/db /data/configdb +VOLUME /data/db /data/configdb + +COPY add_db_users.js /docker-entrypoint-initdb.d/ +COPY docker-entrypoint.sh /usr/local/bin/ +COPY config/mongod.conf /opt/mongod.conf +ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] + +EXPOSE 27017 +CMD ["mongod", "-f", "/opt/mongod.conf"] \ No newline at end of file diff --git a/vircadia-mongo/add_db_users.js b/vircadia-mongo/add_db_users.js new file mode 100644 index 0000000..f035953 --- /dev/null +++ b/vircadia-mongo/add_db_users.js @@ -0,0 +1,29 @@ +print("Started Adding the Users."); +db = db.getSiblingDB("admin"); +db.createUser({ + user:"adminer", + pwd: "noneknowsit", + roles: [ "root" ] +}); +db.createUser({ + user:"backuper", + pwd: "noneknowsit", + roles: [ "backup" ] +}); +db.createUser({ + user:"cadiauser", + pwd: "noneknowsit", + roles: [{ + role: "readWrite", + db: "domainstore" + }] +}); +db.createUser({ + user:"metaverse", + pwd: "noneknowsit", + roles: [{ + role: "readWrite", + db: "tester" + }] +}); +print("End Adding the User Roles."); diff --git a/vircadia-mongo/build-mongo.sh b/vircadia-mongo/build-mongo.sh new file mode 100755 index 0000000..75b0b49 --- /dev/null +++ b/vircadia-mongo/build-mongo.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker build -t vircadia-mongodb:4.4 . diff --git a/vircadia-mongo/config/mongod.conf b/vircadia-mongo/config/mongod.conf new file mode 100644 index 0000000..c75bd31 --- /dev/null +++ b/vircadia-mongo/config/mongod.conf @@ -0,0 +1,43 @@ +# mongod.conf + +# for documentation of all options, see: +# http://docs.mongodb.org/manual/reference/configuration-options/ + +# Where and how to store data. +storage: + dbPath: /data/db + journal: + enabled: true +# engine: +# mmapv1: +# wiredTiger: + +# where to write logging data. +systemLog: + destination: file + logAppend: true + path: /var/log/mongodb/mongod.log + +# network interfaces +net: + port: 27017 + bindIp: 127.0.0.1 + +# how the process runs +processManagement: + timeZoneInfo: /usr/share/zoneinfo + +security: + authorization: enabled + +#operationProfiling: + +#replication: + +#sharding: + +## Enterprise-Only Options: + +#auditLog: + +#snmp: diff --git a/vircadia-mongo/docker-entrypoint.sh b/vircadia-mongo/docker-entrypoint.sh new file mode 100755 index 0000000..d08f7b4 --- /dev/null +++ b/vircadia-mongo/docker-entrypoint.sh @@ -0,0 +1,414 @@ +#!/bin/bash +set -Eeuo pipefail + +if [ "${1:0:1}" = '-' ]; then + set -- mongod "$@" +fi + +originalArgOne="$1" + +# allow the container to be started with `--user` +# all mongo* commands should be dropped to the correct user +if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then + if [ "$originalArgOne" = 'mongod' ]; then + find /data/configdb /data/db \! -user mongodb -exec chown mongodb '{}' + + fi + + # make sure we can write to stdout and stderr as "mongodb" + # (for our "initdb" code later; see "--logpath" below) + chown --dereference mongodb "/proc/$$/fd/1" "/proc/$$/fd/2" || : + # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 + + exec gosu mongodb "$BASH_SOURCE" "$@" +fi + +dpkgArch="$(dpkg --print-architecture)" +case "$dpkgArch" in + amd64) # https://github.com/docker-library/mongo/issues/485#issuecomment-891991814 + if ! grep -qE '^flags.* avx( .*|$)' /proc/cpuinfo; then + { + echo + echo 'WARNING: MongoDB 5.0+ requires a CPU with AVX support, and your current system does not appear to have that!' + echo ' see https://jira.mongodb.org/browse/SERVER-54407' + echo ' see also https://www.mongodb.com/community/forums/t/mongodb-5-0-cpu-intel-g4650-compatibility/116610/2' + echo ' see also https://github.com/docker-library/mongo/issues/485#issuecomment-891991814' + echo + } >&2 + fi + ;; + + arm64) # https://github.com/docker-library/mongo/issues/485#issuecomment-970864306 + # https://en.wikichip.org/wiki/arm/armv8#ARMv8_Extensions_and_Processor_Features + # http://javathunderx.blogspot.com/2018/11/cheat-sheet-for-cpuinfo-features-on.html + if ! grep -qE '^Features.* (fphp|dcpop|sha3|sm3|sm4|asimddp|sha512|sve)( .*|$)' /proc/cpuinfo; then + { + echo + echo 'WARNING: MongoDB 5.0+ requires ARMv8.2-A or higher, and your current system does not appear to implement any of the common features for that!' + echo ' see https://jira.mongodb.org/browse/SERVER-55178' + echo ' see also https://en.wikichip.org/wiki/arm/armv8#ARMv8_Extensions_and_Processor_Features' + echo ' see also https://github.com/docker-library/mongo/issues/485#issuecomment-970864306' + echo + } >&2 + fi + ;; +esac + +# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. +# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux +if [[ "$originalArgOne" == mongo* ]]; then + numa='numactl --interleave=all' + if $numa true &> /dev/null; then + set -- $numa "$@" + fi +fi + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) +_mongod_hack_have_arg() { + local checkArg="$1"; shift + local arg + for arg; do + case "$arg" in + "$checkArg"|"$checkArg"=*) + return 0 + ;; + esac + done + return 1 +} +# _mongod_hack_get_arg_val '--some-arg' "$@" +_mongod_hack_get_arg_val() { + local checkArg="$1"; shift + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$checkArg") + echo "$1" + return 0 + ;; + "$checkArg"=*) + echo "${arg#$checkArg=}" + return 0 + ;; + esac + done + return 1 +} +declare -a mongodHackedArgs +# _mongod_hack_ensure_arg '--some-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg() { + local ensureArg="$1"; shift + mongodHackedArgs=( "$@" ) + if ! _mongod_hack_have_arg "$ensureArg" "$@"; then + mongodHackedArgs+=( "$ensureArg" ) + fi +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$ensureNoArg" ]; then + continue + fi + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg_val() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$ensureNoArg") + shift # also skip the value + continue + ;; + "$ensureNoArg"=*) + # value is already included + continue + ;; + esac + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg_val() { + local ensureArg="$1"; shift + local ensureVal="$1"; shift + _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" + mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) +} + +# _js_escape 'some "string" value' +_js_escape() { + jq --null-input --arg 'str' "$1" '$str' +} + +: "${TMPDIR:=/tmp}" +jsonConfigFile="$TMPDIR/docker-entrypoint-config.json" +tempConfigFile="$TMPDIR/docker-entrypoint-temp-config.json" +_parse_config() { + if [ -s "$tempConfigFile" ]; then + return 0 + fi + + local configPath + if configPath="$(_mongod_hack_get_arg_val --config "$@")" && [ -s "$configPath" ]; then + # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) + # see https://docs.mongodb.com/manual/reference/configuration-options/ + if grep -vEm1 '^[[:space:]]*(#|$)' "$configPath" | grep -qE '^[[:space:]]*[^=:]+[[:space:]]*='; then + # if the first non-comment/non-blank line of the config file looks like "foo = ...", this is probably the 2.4 and older "ini-style config format" + # https://docs.mongodb.com/v2.4/reference/configuration-options/ + # https://docs.mongodb.com/v2.6/reference/configuration-options/ + # https://github.com/mongodb/mongo/blob/r4.4.2/src/mongo/util/options_parser/options_parser.cpp#L1359-L1375 + # https://stackoverflow.com/a/25518018/433558 + echo >&2 + echo >&2 "WARNING: it appears that '$configPath' is in the older INI-style format (replaced by YAML in MongoDB 2.6)" + echo >&2 ' This script does not parse the older INI-style format, and thus will ignore it.' + echo >&2 + return 1 + fi + mongo --norc --nodb --quiet --eval "load('/js-yaml.js'); printjson(jsyaml.load(cat($(_js_escape "$configPath"))))" > "$jsonConfigFile" + if [ "$(head -c1 "$jsonConfigFile")" != '{' ] || [ "$(tail -c2 "$jsonConfigFile")" != '}' ]; then + # if the file doesn't start with "{" and end with "}", it's *probably* an error ("uncaught exception: YAMLException: foo" for example), so we should print it out + echo >&2 'error: unexpected "js-yaml.js" output while parsing config:' + cat >&2 "$jsonConfigFile" + exit 1 + fi + jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" + return 0 + fi + + return 1 +} +dbPath= +_dbPath() { + if [ -n "$dbPath" ]; then + echo "$dbPath" + return + fi + + if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then + if _parse_config "$@"; then + dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" + fi + fi + + if [ -z "$dbPath" ]; then + if _mongod_hack_have_arg --configsvr "$@" || { + _parse_config "$@" \ + && clusterRole="$(jq -r '.sharding.clusterRole // empty' "$jsonConfigFile")" \ + && [ "$clusterRole" = 'configsvr' ] + }; then + # if running as config server, then the default dbpath is /data/configdb + # https://docs.mongodb.com/manual/reference/program/mongod/#cmdoption-mongod-configsvr + dbPath=/data/configdb + fi + fi + + : "${dbPath:=/data/db}" + + echo "$dbPath" +} + +if [ "$originalArgOne" = 'mongod' ]; then + file_env 'MONGO_INITDB_ROOT_USERNAME' + file_env 'MONGO_INITDB_ROOT_PASSWORD' + # pre-check a few factors to see if it's even worth bothering with initdb + shouldPerformInitdb= + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + # if we have a username/password, let's set "--auth" + _mongod_hack_ensure_arg '--auth' "$@" + set -- "${mongodHackedArgs[@]}" + shouldPerformInitdb='true' + elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + cat >&2 <<-'EOF' + error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' + both must be specified for a user to be created + EOF + exit 1 + fi + + if [ -z "$shouldPerformInitdb" ]; then + # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh|*.js) # this should match the set of files we check for below + shouldPerformInitdb="$f" + break + ;; + esac + done + fi + + # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) + if [ -n "$shouldPerformInitdb" ]; then + dbPath="$(_dbPath "$@")" + for path in \ + "$dbPath/WiredTiger" \ + "$dbPath/journal" \ + "$dbPath/local.0" \ + "$dbPath/storage.bson" \ + ; do + if [ -e "$path" ]; then + shouldPerformInitdb= + break + fi + done + fi + + if [ -n "$shouldPerformInitdb" ]; then + mongodHackedArgs=( "$@" ) + if _parse_config "$@"; then + _mongod_hack_ensure_arg_val --config "$tempConfigFile" "${mongodHackedArgs[@]}" + fi + _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" + + # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) + # https://github.com/docker-library/mongo/issues/211 + _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" + # "keyFile implies security.authorization" + # https://docs.mongodb.com/manual/reference/configuration-options/#mongodb-setting-security.keyFile + _mongod_hack_ensure_no_arg_val --keyFile "${mongodHackedArgs[@]}" + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" + fi + + # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" + tlsMode='disabled' + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "$@"; then + tlsMode='allowTLS' + elif _mongod_hack_have_arg '--sslPEMKeyFile' "$@"; then + tlsMode='allowSSL' + fi + # 4.2 switched all configuration/flag names from "SSL" to "TLS" + if [ "$tlsMode" = 'allowTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + else + _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + + if stat "/proc/$$/fd/1" > /dev/null && [ -w "/proc/$$/fd/1" ]; then + # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 + # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 + _mongod_hack_ensure_arg_val --logpath "/proc/$$/fd/1" "${mongodHackedArgs[@]}" + else + initdbLogPath="$(_dbPath "$@")/docker-initdb.log" + echo >&2 "warning: initdb logs cannot write to '/proc/$$/fd/1', so they are in '$initdbLogPath' instead" + _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" + fi + _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" + + pidfile="$TMPDIR/docker-entrypoint-temp-mongod.pid" + rm -f "$pidfile" + _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" + + "${mongodHackedArgs[@]}" --fork + + mongo=( mongo --host 127.0.0.1 --port 27017 --quiet ) + + # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) + # https://jira.mongodb.org/browse/SERVER-16292 + tries=30 + while true; do + if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then + # bail ASAP if "mongod" isn't even running + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" + echo >&2 + exit 1 + fi + if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then + # success! + break + fi + (( tries-- )) + if [ "$tries" -le 0 ]; then + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" + echo >&2 + exit 1 + fi + sleep 1 + done + + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + rootAuthDatabase='admin' + + "${mongo[@]}" "$rootAuthDatabase" <<-EOJS + db.createUser({ + user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), + pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), + roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] + }) + EOJS + fi + + export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" + + echo + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + "${mongodHackedArgs[@]}" --shutdown + rm -f "$pidfile" + + echo + echo 'MongoDB init process complete; ready for start up.' + echo + fi + + # MongoDB 3.6+ defaults to localhost-only binding + haveBindIp= + if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then + haveBindIp=1 + elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then + haveBindIp=1 + fi + if [ -z "$haveBindIp" ]; then + # so if no "--bind_ip" is specified, let's add "--bind_ip_all" + set -- "$@" --bind_ip_all + fi + + unset "${!MONGO_INITDB_@}" +fi + +rm -f "$jsonConfigFile" "$tempConfigFile" + +exec "$@" \ No newline at end of file diff --git a/vircadia-mongo/run-mongo.sh b/vircadia-mongo/run-mongo.sh new file mode 100755 index 0000000..c973cc5 --- /dev/null +++ b/vircadia-mongo/run-mongo.sh @@ -0,0 +1,12 @@ +#! /bin/bash + +DOCKER_IMAGE=vircadia-mongodb +DOCKER_IMAGE_VER=4.4 + +docker run -d \ + --restart=unless-stopped \ + --name=vircadia-mongodb \ + -e LC_ALL="C.UTF-8" \ + -p 27017:27017 \ + --volume mongodb_data:/data/db \ + ${DOCKER_IMAGE}:${DOCKER_IMAGE_VER} \ No newline at end of file