Configuration Options

Installer Configuration

Some items in the installer can be configured through an installer.conf file in the install directory. These settings are helpful if you are running multiple instances of Atlas Hub on the same server.

Key Definition
NGINX_FILE Alternate name for the nginx config file. Default is atlas-hub.conf.
PM2_PREFIX Alternate prefix for pm2 processes. Default is atlas-hub.

The file format should be:

KEY=VALUE

App Configuration

Create/edit the project .env

mkdir -p /home/websites/atlas/system
cd /home/websites/atlas/system

nano .env

Here’s a list of the config values that should be set.

DATABASE_URL="postgresql://web_user:1234_with_single_quotes@localhost:5432/atlas-system"
SESSION_SECRET="03efg9241c4fc6bc9b98529f69bfj5ce"

# saml sso configuration.
SAML_IDP_METADATA="http://localhost:7000/metadata"
SAML_SP_AUTHNREQUESTSSIGNED=false
SAML_SP_WANTMESSAGESIGNED=false
SAML_SP_WANTASSERTIONSIGNED=false
SAML_SP_WANTLOGOUTREQUESTSIGNED=false
SAML_PRIVATE_KEY="/etc/certs/idp-private-key.pem"
SAML_PRIVATE_KEY_PASS=""
SAML_ENC_PRIVATE_KEY="/etc/certs/idp-private-key.pem"
SAML_SP_ISASSERTIONENCRYPTED=false
SAML_SIGNING_CERT="/etc/certs/idp-private-key.crt"
SAML_ENC_CERT="/etc/certs/idp-private-key.crt"

# ldap settings.
LDAP_HOST=ldap://localhost
LDAP_START_TLS=false
LDAP_USERNAME=cn=admin,dc=example,dc=org
LDAP_PASSWORD=adminpassword
LDAP_BASE_DN=dc=example,dc=org
LDAP_GROUP_SEARCH=(objectClass=groupOfNames)
LDAP_USER_SEARCH=(&(objectClass=inetOrgPerson)(sn=*)(givenName=*)(displayName=*))
LDAP_EMAIL_FIELD=sn
LDAP_GROUP_NAME=cn
LDAP_FIRSTNAME=givenName
LDAP_LASTNAME=displayName
LDAP_PHOTO_FIELD=jpegPhoto
LDAP_USER_GROUP=memberOf

# email box settings
SMTP_HOST=localhost
SMTP_PORT=25
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_TLS=false
SMTP_SENDER_NAME=Atlas System | Riverside Healthcare Analytics
SMTP_SENDER_EMAIL=[email protected]
IMAP_HOST=localhost
IMAP_PORT=143

# the URL your site will be accessed at.
HOSTNAME=https://system.atlas.bi

Configure

If this is a new install proceed to the install guide.

Update the app with your new configuration by running:

curl -sSL https://atlas.bi/installers/system.sh | bash -s -- --configure

#!/usr/bin/env bash
# Setup global variables.
APP=atlas-system
SOURCE=https://api.github.com/repos/atlas-bi/System/releases/latest
NGINX_FILE="$APP.conf"
PM2_PREFIX="$APP"
if [[ -f "installer.conf" ]]; then
. installer.conf
fi
# Setup basic colors
color() {
  YELLOW=$(printf '\033[1m\033[33m')
  BLUE=$(printf '\033[1m\033[34m')
  RED=$(printf '\033[1m\033[31m')
  RESET=$(printf '\033[0m') # No Color
  GREEN=$(printf '\033[1m\033[32m')
  CYAN=$(printf '\033[1m\033[36m')
  BOLD=$(printf '\033[1m')
}

color

fmt_yellow() {
  echo "${YELLOW}$1${RESET}"
}
fmt_red() {
  echo "${RED}$1${RESET}"
}
fmt_blue() {
  echo "${BLUE}$1${RESET}"
}
fmt_green() {
  echo "${GREEN}$1${RESET}"
}
fmt_cyan() {
  echo "${BLUE}$1${RESET}"
}
check_command() {
  if ! [ -x "$(command -v $1)" ]; then
    fmt_red "Error: $1 is not installed. ${GREEN}See https://atlas.bi/docs/" >&2
    exit 1
  fi
}

warn_command() {
  if ! [ -x "$(command -v $1)" ]; then
    fmt_cyan "$2" >&2
  fi
}

check_file() {
  if ! [[ -n $(compgen -G $1) ]]; then
    fmt_red "File $1 must be created before running this script. ${GREEN}See https://atlas.bi/docs/" >&2
    exit 1
  fi
}

exporter() {
  echo $1 | tee -a .env .env.local >/dev/null
}
random_number() {
  floor=3000
  range=3999
  number=0
  while [ "$number" -le $floor ]
  do
    number=$RANDOM
    let "number %= $range"
  done
  echo $number
}

get_port() {
  PORT=$(random_number)
  while [[ $(lsof -i -P -n | grep :$PORT) ]]
  do
    PORT=$(random_number)
  done
  echo $PORT
}
# from https://dev.to/justincy/blue-green-node-js-deploys-with-nginx-bkc
nginx_workers() {
  echo $(ps -ef | grep "nginx: worker process" | grep -v grep | wc -l)
}

nginx_reload() {
  numWorkerProcesses=$(nginx_workers)
  nginx -s reload

  # Wait for the old nginx workers to be retired before we kill the old server.
  while [ $(nginx_workers) -ne $numWorkerProcesses ]
  do
    sleep 1;
  done;
}
set -Eeuo pipefail
trap cleanup SIGINT SIGTERM ERR EXIT

configure(){
    check_file .env

    fmt_yellow "Updating .env file in site.."
    pm2 list | grep -oP "$PM2_PREFIX-((quirrel|meili)-)?\d+" | uniq | grep -oP "\d+" | uniq  | while IFS=$'\n' read DIRECTORY; do
      if [ -d "$DIRECTORY" ]; then
        cp .env $DIRECTORY
      fi
    done

    fmt_yellow "Restarting processes.."
    pm2 list | grep -oP "$PM2_PREFIX-((quirrel|meili)-)?\d+" | uniq | while IFS=$'\n' read process; do
      dotenv -- pm2 restart $process --update-env
    done
}

usage() {
  cat << EOF

${BOLD}Usage: $(basename "${BASH_SOURCE[0]}") [-h, -b, -c, -u]

${BLUE}Atlas System Installer.${RESET}

Available options:

    -h, --help               Print this help and exit
    -c, --configure          Reconfigure Atlas System
    -i, --install [DEFAULT]  Install or Upgrade Atlas System

Additional Altas System Help at https://atlas.bi/docs/system

EOF
  exit
}

install() {
  # Check if commands and files exist.
check_command node
check_command npm
check_command curl
check_command pm2
check_command nginx
check_command lsof
check_command dotenv
check_command grep
check_file .env
check_file "/etc/nginx/**/$NGINX_FILE"


# Get free internal ports.
fmt_yellow "Finding a free port.."

PORT=$(get_port)
QUIRREL_PORT=$(get_port)
MEILI_PORT=$(get_port)

fmt_blue "Using web port $PORT"
fmt_blue "Using quirrel port $QUIRREL_PORT"
fmt_blue "Using meili port $MEILI_PORT"

# Download the latest release.
fmt_yellow "Downloading latest version into $(pwd)/$PORT.."

mkdir "$PORT"
curl -sSL $(curl -sSL "$SOURCE" | grep browser_download_url | cut -d : -f 2,3 | tr -d \") | tar zxf - -C "$PORT"
cd "$PORT"

fmt_blue "Downloaded version $(npm pkg get version | tr -d '"')"

fmt_yellow "Installing meilisearch.."
mkdir etc; cd etc;
curl -L https://install.meilisearch.com | sh
cd ..

# Copy in the .env file.
fmt_yellow "Setting up website.."
cp ../.env .

npm i --omit=dev --loglevel error --no-fund --no-audit --legacy-peer-deps

fmt_yellow "Building app.."
npm run build:remix
npm run build:server

fmt_yellow "Applying database migrations.."
npm run db


# Set a few process names.
APP_PROCESS="$APP-$PORT"


exporter NODE_ENV=production
exporter WEB_PORT=$PORT
exporter QUIRREL_PORT=$QUIRREL_PORT
exporter MEILI_PORT=$MEILI_PORT

fmt_yellow "Starting new services.."

# Start web process.
dotenv -- pm2 start node --name="$APP_PROCESS" --merge-logs -- ./build/server.js

fmt_blue "Done setting up."
cd ..

fmt_yellow "Updating nginx.."
sed -i "s/localhost:3[0-9]*/localhost:${PORT}/" `find -L /etc/nginx -name "$NGINX_FILE"`

fmt_yellow "Gracefully reloading nginx..."
nginx_reload

fmt_yellow "Removing old pm2 processes.."

# gnu grep
pm2 list | grep -oP "$APP-((quirrel|meili)-)?\d+" | uniq | while IFS=$'\n' read process; do
  if [[ $process != $APP_PROCESS ]];
  then
    fmt_yellow "Removing $process"
    pm2 delete $process || true
  fi
done

pm2 save

fmt_yellow "Archiving old installs.."

for olddir in $(ls -d 3*); do
  if [[ $olddir != $PORT ]];
  then
    fmt_yellow "Moving $olddir"
    mv -f $olddir "backup-$olddir"
  fi
done;

fmt_blue "Finished cleaning up."
echo ""
echo ${YELLOW}Back folders can be manually removed. ${BLUE}rm -r $(pwd)/backup-*
echo ""
fmt_green "Thanks for installing Atlas System!"
echo ""
fmt_green "Read the full install guide at https://atlas.bi/docs/system/"
echo ""
fmt_blue "Next Steps"

cat <<EOF
${CYAN}View Current Configuration

${BLUE}cat $PORT/.env

${YELLOW}Web process was started with ${BLUE}dotenv -v PORT=$PORT -- pm2 start node --name="$APP_PROCESS" --merge-logs -- ./build/server.js

${CYAN}Updating App Settings

${YELLOW}1. Update user configuration file ${BLUE}nano $(pwd)/.env
${YELLOW}2. Reconfigure the app
${BLUE}   curl -sSL https://atlas.bi/installers/system.sh | bash -s -- --configure

${CYAN}Updating Nginx Settings

${YELLOW}1. Update configuration file ${BLUE}nano $(find -L /etc/nginx -name "$NGINX_FILE")
${YELLOW}2. Test nginx config ${BLUE}nginx -t
${YELLOW}2. Reload nginx ${BLUE}nginx -s reload


${CYAN}Monitoring and Viewing Logs

${YELLOW}Live Logging ${BLUE}pm2 monit

${RESET}
EOF

warn_command ufw "Recommendation: secure your server with ufw."
echo ""

}

cleanup() {
  trap - SIGINT SIGTERM ERR EXIT
}

die() {
  echo >&2 -e "${1-}"
  exit 1
}

# https://betterdev.blog/minimal-safe-bash-script-template/
parse_params() {
  while :; do
    case "${1-}" in
    -h | --help) usage;break ;;

    -c | --configure) configure;break ;;
    -i | --install) install;break ;;
    -?*) die "${RED}Unknown option: $1. Run $(basename "${BASH_SOURCE[0]}") -h for help.${RESET}";break ;;
    *)  install;break ;;
    esac
    shift
  done

  return 0
}

parse_params "$@"