Create/edit the project .env
mkdir -p /home/websites/atlas/requests
cd /home/websites/atlas/requests
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-requests"
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
# 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 Requests | Riverside Healthcare Analytics
SMTP_SENDER_EMAIL=[email protected]
IMAP_HOST=localhost
IMAP_PORT=143
# the URL your site will be accessed at.
HOSTNAME=https://requests.atlas.bi
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/requests.sh | bash -s -- --configure
#!/usr/bin/env bash
# Setup global variables.
APP=atlas-requests
SOURCE=https://api.github.com/repos/atlas-bi/Requests/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 "Update .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
cat .env.local >> .env 2>&1 >/dev/null
fi
done
fmt_yellow "Restarting processes.."
pm2 list | grep -oP "$PM2_PREFIX-((quirrel|meili)-)?\d+" | uniq | while IFS=$'\n' read process; do
pm2 restart $process
done
}
usage() {
cat << EOF
${BOLD}Usage: $(basename "${BASH_SOURCE[0]}") [-h, -b, -c, -u]
${BLUE}Atlas Requests Installer.${RESET}
Available options:
-h, --help Print this help and exit
-c, --configure Reconfigure Atlas Requests
-i, --install [DEFAULT] Install or Upgrade Atlas Requests
Additional Altas Requests Help at https://atlas.bi/docs/requests
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 meilsearch 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 '"')"
# Copy in the .env file.
fmt_yellow "Setting up website.."
cp ../.env .
# Install dependencies.
npm i --omit=dev --loglevel error --no-fund --no-audit --legacy-peer-deps
# Apply database migrations.
fmt_yellow "Applying database migrations.."
npx prisma migrate deploy
npx prisma generate
# Set a few process names.
APP_PROCESS="$APP-$PORT"
QUIRREL_PROCESS="$APP-quirrel-$QUIRREL_PORT"
MEILI_PROCESS="$APP-meili-$MEILI_PORT"
exporter NODE_ENV=production
exporter WEB_PORT=$PORT
exporter QUIRREL_PORT=$QUIRREL_PORT
exporter MEILI_PORT=$MEILI_PORT
exporter APP_PROCESS=$APP_PROCESS
exporter QUIRREL_PROCESS=$QUIRREL_PROCESS
exporter MEILI_PROCESS=$MEILI_PROCESS
# Download meilisearch.
fmt_yellow "Installing meilisearch.."
curl -L https://install.meilisearch.com | sh
fmt_yellow "Starting new services.."
exporter PASSPHRASES=$QUIRREL_PROCESS
exporter DISABLE_TELEMETRY=1
exporter SESSION_SECRET=$APP_PROCESS
# Start quirrel and get a token.
# this is now down in the app's server.js file
# so that the correct token can be used on a restart.
# dotenv -v PORT=$QUIRREL_PORT -- pm2 start node --name="$QUIRREL_PROCESS" -- node_modules/quirrel/dist/cjs/src/api/main.js
# Set quirrel env vars.
# set in server.ts now.
# exporter QUIRREL_TOKEN=$(curl --retry 5 --retry-delay 3 --retry-all-errors --connect-timeout 10 --user ignored:$QUIRREL_PROCESS -X PUT "localhost:$QUIRREL_PORT/tokens/prod")
exporter QUIRREL_API_URL=http://localhost:$QUIRREL_PORT
exporter QUIRREL_BASE_URL=http://localhost:$PORT
# Load quirrel cron jobs.
# now done in server.js
# npm run quirrel:ci
# Add a few env vars to get meilisearch running
exporter MEILI_NO_ANALYTICS=true
exporter MEILI_DB_PAT=$(pwd)/$PORT/data.ms/
exporter MEILI_ENV=production
exporter MEILI_MASTER_KEY=$MEILI_PROCESS
exporter MEILISEARCH_URL=http://localhost:$MEILI_PORT
exporter MEILI_HTTP_ADDR=localhost:$MEILI_PORT
# Start web process.
dotenv -v PORT=$PORT -- pm2 start node --name="$APP_PROCESS" --merge-logs -- ./build/server.js
# Start meili process.
dotenv -- pm2 start meilisearch --name="$MEILI_PROCESS"
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 && $process != $QUIRREL_PROCESS && $process != $MEILI_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 Requests!"
echo ""
fmt_green "Read the full install guide at https://atlas.bi/docs/requests/"
echo ""
fmt_blue "Next Steps"
cat <<EOF
${CYAN}Current Configuration
${YELLOW}$(cat $PORT/.env.local)
${YELLOW}Web process was started with ${BLUE}dotenv -v PORT=$PORT -- pm2 start node --name="$APP_PROCESS" --merge-logs -- ./build/server.js
${YELLOW}Quirrel process was started with ${BLUE}dotenv -v PORT=$QUIRREL_PORT -- pm2 start node --name="$QUIRREL_PROCESS" -- node_modules/quirrel/dist/cjs/src/api/main.js
${YELLOW}Meilisearch process was started with ${BLUE}dotenv -- pm2 start meilisearch --name="$MEILI_PROCESS"
${CYAN}Updating App Settings
${YELLOW}1. Update user configuration file ${BLUE}nano $(pwd)/.env
${YELLOW}2. Copy config into app ${BLUE}cp $(pwd)/.env $(pwd)/$PORT/.env
${YELLOW}3. Restart the apps:
${BLUE} pm2 restart $APP_PROCESS
${BLUE} pm2 restart $MEILI_PROCESS
${BLUE} pm2 restart $QUIRREL_PROCESS
${CYAN}Updating Nginx Settings
${YELLOW}1. Update configuration file ${BLUE}nano $(find -L /etc/nginx -name "$NGINX_FILE")
${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 "$@"