2017-12-14 11:58:23 +01:00
#!/bin/bash
2019-12-30 17:34:15 +01:00
DOMAINS = ( )
2019-12-31 10:11:16 +01:00
welcome_message( )
{
echo "============================================"
echo -e "\e[31m Fab-Manager's setup\e[0m"
echo "============================================"
echo "Thank you for installing Fab-Manager."
2019-12-31 11:21:34 +01:00
printf "This script will guide you through the installation process of Fab-Manager\n\n"
2019-12-31 10:11:16 +01:00
echo -e "Please report any \e[1mfeedback or improvement request\e[21m on https://feedback.fab-manager.com/"
echo -e "For \e[1mbug reports\e[21m, please open a new issue on https://github.com/sleede/fab-manager/issues"
echo -e "You can call for \e[1mcommunity assistance\e[21m on https://forum.fab-manager.com/"
printf "\nYou can interrupt this installation at any time by pressing Ctrl+C\n"
2019-12-31 11:21:34 +01:00
printf "If you do not feel confortable with this installation, you can \e[4msubscribe to our hosting plan\e[24m: contact@fab-manager.com\n\n"
read -rp "Continue? (Y/n) " confirm </dev/tty
2019-12-31 10:11:16 +01:00
if [ [ " $confirm " = "n" ] ] ; then exit 1; fi
}
2019-12-30 17:34:15 +01:00
system_requirements( )
{
if [ " $( whoami) " = "root" ] ; then
echo "It is not recommended to run this script as root. As a normal user, elevation will be prompted if needed."
read -rp "Continue anyway? (Y/n) " confirm </dev/tty
if [ [ " $confirm " = "n" ] ] ; then exit 1; fi
else
if ! command -v sudo; then
echo "Please install and configure sudo before running this script."
echo "sudo was not found, exiting..." && exit 1
fi
local _groups = ( "sudo" "docker" )
for _group in " ${ _groups [@] } " ; do
if ! groups | grep " $_group " ; then
echo " Please add your current user to the $_group group. "
echo " You can run the following as root: \"usermod -aG $_group $( whoami) \", then logout and login again "
echo "current user is misconfigured, exiting..." && exit 1
fi
done
fi
2019-12-31 10:11:16 +01:00
local _commands = ( "curl" "sed" "openssl" "docker" "docker-compose" "systemctl" )
2019-12-30 17:34:15 +01:00
for _command in " ${ _commands [@] } " ; do
echo " detecting $_command ... "
if ! command -v " $_command "
then
echo " Please install $_command before running this script. "
echo " $_command was not found, exiting... " && exit 1
fi
done
}
2019-12-31 12:30:31 +01:00
read_email( )
{
local email
read -rp "Please input a valid email address > " email </dev/tty
if [ [ " $email " = = *"@" *"." * ] ] ; then
EMAIL = " $email "
else
read_email
fi
}
2019-12-30 17:34:15 +01:00
config( )
{
2019-12-31 11:21:34 +01:00
echo 'We recommand nginx to serve the application over the network (internet). You can use your own solution or let this script install and configure nginx for Fab-Manager.'
2019-12-30 17:34:15 +01:00
read -rp 'Do you want install nginx? (Y/n) ' NGINX </dev/tty
if [ " $NGINX " != "n" ] ; then
# if the user doesn't want nginx, let him use its own solution for HTTPS
2019-12-31 12:30:31 +01:00
echo "We recommand let's encrypt to secure the application with HTTPS. You can use your own certificate or let this script install and configure let's encrypt for Fab-Manager."
2019-12-30 17:34:15 +01:00
read -rp "Do you want install let's encrypt? (Y/n) " LETSENCRYPT </dev/tty
if [ " $LETSENCRYPT " != "n" ] ; then
2019-12-31 11:21:34 +01:00
echo "Let's encrypt requires an email address to receive notifications about certificate expiration."
2019-12-31 12:30:31 +01:00
read_email
2019-12-30 17:34:15 +01:00
fi
# if the user doesn't want nginx, let him configure his own solution
echo "What's the domain name where the instance will be active (eg. fab-manager.com)?"
read_domain
MAIN_DOMAIN = ( " ${ DOMAINS [0] } " )
OTHER_DOMAINS = ${ DOMAINS [*]/ $MAIN_DOMAIN }
fi
}
read_domain( )
{
read -rp 'Please input the domain name > ' domain </dev/tty
2019-12-31 12:30:31 +01:00
if [ [ " $domain " = = *"." * ] ] ; then
DOMAINS += ( " $domain " )
else
echo "The domain name entered is invalid"
read_domain
return
fi
2019-12-31 11:21:34 +01:00
read -rp 'Do you have any other domain (eg. www.fab-manager.com)? (y/N) ' confirm </dev/tty
2019-12-30 17:34:15 +01:00
if [ " $confirm " = = "y" ] ; then
read_domain
fi
}
prepare_files( )
2017-12-14 11:58:23 +01:00
{
2017-12-14 12:02:50 +01:00
FABMANAGER_PATH = ${ 1 :- /apps/fabmanager }
2017-12-14 11:58:23 +01:00
2019-12-31 11:21:34 +01:00
sudo mkdir -p " $FABMANAGER_PATH "
sudo chown -R " $( whoami) " " $FABMANAGER_PATH "
2018-12-03 16:06:08 +01:00
mkdir -p " $FABMANAGER_PATH /elasticsearch/config "
2017-12-14 11:58:23 +01:00
# fab-manager environment variables
2019-12-24 16:19:44 +01:00
\c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/setup/env.example > " $FABMANAGER_PATH /config/env "
2017-12-14 11:58:23 +01:00
# nginx configuration
2019-12-30 17:34:15 +01:00
if [ " $NGINX " = "y" ] ; then
mkdir -p " $FABMANAGER_PATH /config/nginx "
\c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/setup/nginx_with_ssl.conf.example > " $FABMANAGER_PATH /config/nginx/fabmanager.conf.ssl "
\c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/setup/nginx.conf.example > " $FABMANAGER_PATH /config/nginx/fabmanager.conf "
fi
2017-12-14 11:58:23 +01:00
# let's encrypt configuration
2019-12-30 17:34:15 +01:00
if [ " $LETSENCRYPT " = "y" ] ; then
mkdir -p " $FABMANAGER_PATH /letsencrypt/config "
mkdir -p " $FABMANAGER_PATH /letsencrypt/systemd "
mkdir -p " $FABMANAGER_PATH /letsencrypt/etc/webrootauth "
\c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/setup/webroot.ini.example > " $FABMANAGER_PATH /letsencrypt/config/webroot.ini "
# temp systemd files
\c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/setup/letsencrypt.service > " $FABMANAGER_PATH /letsencrypt/systemd/letsencrypt.service "
\c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/setup/letsencrypt.timer > " $FABMANAGER_PATH /letsencrypt/systemd/letsencrypt.timer "
fi
2017-12-14 11:58:23 +01:00
2018-12-03 16:06:08 +01:00
# ElasticSearch configuration files
2019-12-24 16:19:44 +01:00
\c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/setup/elasticsearch.yml > " $FABMANAGER_PATH /elasticsearch/config/elasticsearch.yml "
\c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/setup/log4j2.properties > " $FABMANAGER_PATH /elasticsearch/config/log4j2.properties "
2018-12-03 16:06:08 +01:00
2017-12-14 11:58:23 +01:00
# docker-compose
2019-12-24 16:19:44 +01:00
\c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/setup/docker-compose.yml > " $FABMANAGER_PATH /docker-compose.yml "
2017-12-14 11:58:23 +01:00
}
2019-12-30 17:34:15 +01:00
prepare_nginx( )
{
if [ " $NGINX " != "n" ] ; then
sed -i.bak " s/MAIN_DOMAIN/ ${ MAIN_DOMAIN [0] } /g " " $FABMANAGER_PATH /config/nginx/fabmanager.conf "
sed -i.bak " s/MAIN_DOMAIN/ ${ MAIN_DOMAIN [0] } /g " " $FABMANAGER_PATH /config/nginx/fabmanager.conf.ssl "
sed -i.bak " s/ANOTHER_DOMAIN_1/ $OTHER_DOMAINS /g " " $FABMANAGER_PATH /config/nginx/fabmanager.conf.ssl "
2019-12-31 11:21:34 +01:00
sed -i.bak " s/URL_WITH_PROTOCOL_HTTPS/https:\/\/ ${ MAIN_DOMAIN [0] } /g " " $FABMANAGER_PATH /config/nginx/fabmanager.conf.ssl "
2019-12-30 17:34:15 +01:00
fi
}
prepare_letsencrypt( )
{
2019-12-31 10:11:16 +01:00
if [ " $LETSENCRYPT " = "y" ] ; then
2019-12-30 17:34:15 +01:00
mkdir -p " $FABMANAGER_PATH /config/nginx/ssl "
echo "Now, we will generate a Diffie-Hellman (DH) 4096 bits encryption key, to encrypt connections. This will take a moment, please wait..."
openssl dhparam -out " $FABMANAGER_PATH /config/nginx/ssl/dhparam.pem " 4096
sed -i.bak " s/REPLACE_WITH_YOUR@EMAIL.COM/ $EMAIL /g " " $FABMANAGER_PATH /letsencrypt/config/webroot.ini "
sed -i.bak " s/MAIN_DOMAIN/ ${ MAIN_DOMAIN [0] } /g " " $FABMANAGER_PATH /letsencrypt/config/webroot.ini "
sed -i.bak " s/ANOTHER_DOMAIN_1/ $OTHER_DOMAINS /g " " $FABMANAGER_PATH /letsencrypt/config/webroot.ini "
2019-12-31 10:11:16 +01:00
echo "Now downloading and configuring the certificate signing bot..."
2019-12-30 17:34:15 +01:00
docker pull certbot/certbot:latest
sed -i.bak " s:/apps/fabmanager: $FABMANAGER_PATH :g " " $FABMANAGER_PATH /letsencrypt/systemd/letsencrypt.service "
sudo cp " $FABMANAGER_PATH /letsencrypt/systemd/letsencrypt.service " /etc/systemd/system/letsencrypt.service
sudo cp " $FABMANAGER_PATH /letsencrypt/systemd/letsencrypt.timer " /etc/systemd/system/letsencrypt.timer
2019-12-31 10:11:16 +01:00
sudo systemctl daemon-reload
fi
2019-12-30 17:34:15 +01:00
}
prepare_docker( )
{
cd " $FABMANAGER_PATH " && docker-compose pull
}
get_md_anchor( )
{
local md_file = " $1 "
local anchor = " $2 "
2019-12-31 12:30:31 +01:00
local section lastline
2019-12-30 17:34:15 +01:00
section = $( echo " $md_file " | sed -n " /<a name=\" $anchor /,/<a name=/p " | tail -n +2)
2019-12-31 12:30:31 +01:00
lastline = $( echo " $section " | tail -n -1)
if [ [ " $lastline " = = *"<a name=" * ] ] ; then
section = $( echo " $section " | head -n -1)
2019-12-30 17:34:15 +01:00
fi
echo " $section "
}
configure_env_file( )
{
echo "We will now configure the environment variables."
echo "This allows you to customize Fab-Manager's appearance and behavior."
2019-12-31 12:30:31 +01:00
read -rp "Proceed? (Y/n) " confirm </dev/tty
2019-12-30 17:34:15 +01:00
if [ " $confirm " = "n" ] ; then return ; fi
2019-12-31 11:21:34 +01:00
local doc variables secret
2019-12-30 17:34:15 +01:00
doc = $( \c url -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/doc/environment.md)
variables = ( STRIPE_API_KEY STRIPE_PUBLISHABLE_KEY STRIPE_CURRENCY INVOICE_PREFIX FABLAB_WITHOUT_PLANS FABLAB_WITHOUT_SPACES FABLAB_WITHOUT_ONLINE_PAYMENT FABLAB_WITHOUT_INVOICES \
PHONE_REQUIRED EVENTS_IN_CALENDAR SLOT_DURATION DEFAULT_MAIL_FROM DELIVERY_METHOD DEFAULT_HOST DEFAULT_PROTOCOL SMTP_ADDRESS SMTP_PORT SMTP_USER_NAME SMTP_PASSWORD SMTP_AUTHENTICATION \
SMTP_ENABLE_STARTTLS_AUTO SMTP_OPENSSL_VERIFY_MODE SMTP_TLS GA_ID RECAPTCHA_SITE_KEY RECAPTCHA_SECRET_KEY DISQUS_SHORTNAME TWITTER_NAME TWITTER_CONSUMER_KEY TWITTER_CONSUMER_SECRET \
TWITTER_ACCESS_TOKEN TWITTER_ACCESS_TOKEN_SECRET FACEBOOK_APP_ID LOG_LEVEL ALLOWED_EXTENSIONS ALLOWED_MIME_TYPES MAX_IMAGE_SIZE MAX_CAO_SIZE MAX_IMPORT_SIZE DISK_SPACE_MB_ALERT \
2019-12-31 12:30:31 +01:00
SUPERADMIN_EMAIL APP_LOCALE RAILS_LOCALE MOMENT_LOCALE SUMMERNOTE_LOCALE ANGULAR_LOCALE MESSAGEFORMAT_LOCALE FULLCALENDAR_LOCALE ELASTICSEARCH_LANGUAGE_ANALYZER TIME_ZONE \
WEEK_STARTING_DAY D3_DATE_FORMAT UIB_DATE_FORMAT EXCEL_DATE_FORMAT OPENLAB_APP_ID OPENLAB_APP_SECRET OPENLAB_DEFAULT OPENLAB_BASE_URI)
2019-12-30 17:34:15 +01:00
for variable in " ${ variables [@] } " ; do
2019-12-31 11:21:34 +01:00
local var_doc current
2019-12-30 17:34:15 +01:00
var_doc = $( get_md_anchor " $doc " " $variable " )
current = $( grep " $variable " " $FABMANAGER_PATH /config/env " )
2019-12-31 12:30:31 +01:00
printf "\n\n\n==== \e[4m%s\e[24m ====\n" " $variable "
printf "**** \e[1mDocumentation:\e[21m ****\n"
2019-12-30 17:34:15 +01:00
echo " $var_doc "
2019-12-31 12:30:31 +01:00
printf "=======================\n- \e[1mCurrent value: %s\e[21m\n- New value? (leave empty to keep current value)\n" " $current "
read -rp " > " value </dev/tty
echo "======================="
2019-12-30 17:34:15 +01:00
if [ " $value " != "" ] ; then
sed -i.bak " s/ $current / $variable = $value /g " " $FABMANAGER_PATH /config/env "
fi
done
# we automatically generate the SECRET_KEY_BASE
secret = $( cd " $FABMANAGER_PATH " && docker-compose run --rm fabmanager bundle exec rake secret)
2019-12-31 12:30:31 +01:00
sed -i.bak " s/SECRET_KEY_BASE=/SECRET_KEY_BASE= ${ secret :- 2 } /g " " $FABMANAGER_PATH /config/env "
2019-12-30 17:34:15 +01:00
}
read_password( )
{
2019-12-31 11:21:34 +01:00
local password confirmation
2019-12-31 12:30:31 +01:00
echo "Please input a password for this administrator's account"
read -rsp " > " password </dev/tty
echo "Confirm the password"
read -rsp " > " confirmation </dev/tty
2019-12-30 17:34:15 +01:00
if [ " $password " != " $confirmation " ] ; then
echo "Error: passwords mismatch"
password = $( read_password)
fi
echo " $password "
}
setup_assets_and_databases( )
{
echo "We will now setup the database."
read -rp "Continue? (Y/n)" confirm </dev/tty
if [ " $confirm " = "n" ] ; then return ; fi
cd " $FABMANAGER_PATH " && docker-compose run --rm fabmanager bundle exec rake db:create # create the database
cd " $FABMANAGER_PATH " && docker-compose run --rm fabmanager bundle exec rake db:migrate # run all the migrations
# prompt default admin email/password
2019-12-31 12:30:31 +01:00
echo "We will create the default administrator of Fab-Manager."
read_email
2019-12-30 17:34:15 +01:00
PASSWORD = $( read_password)
cd " $FABMANAGER_PATH " && docker-compose run --rm -e ADMIN_EMAIL = " $EMAIL " -e ADMIN_PASSWORD = " $PASSWORD " fabmanager bundle exec rake db:seed # seed the database
# now build the assets
cd " $FABMANAGER_PATH " && docker-compose run --rm fabmanager bundle exec rake assets:precompile
# and prepare elasticsearch
cd " $FABMANAGER_PATH " && docker-compose run --rm fabmanager bundle exec rake fablab:es:build_stats
}
2019-12-31 10:11:16 +01:00
stop( )
{
cd " $FABMANAGER_PATH " && docker-compose down
}
2019-12-30 17:34:15 +01:00
start( )
{
cd " $FABMANAGER_PATH " && docker-compose up -d
}
2019-12-31 10:11:16 +01:00
enable_ssl( )
{
if [ " $LETSENCRYPT " = "y" ] ; then
# generate certificate
sudo systemctl start letsencrypt.service
# serve http content over ssl
mv " $FABMANAGER_PATH /config/nginx/fabmanager.conf " " $FABMANAGER_PATH /config/nginx/fabmanager.conf.nossl "
mv " $FABMANAGER_PATH /config/nginx/fabmanager.conf.ssl " " $FABMANAGER_PATH /config/nginx/fabmanager.conf "
stop
start
sudo systemctl enable letsencrypt.timer
sudo systemctl start letsencrypt.timer
fi
}
final_message( )
{
echo -e "\e[5mCongratulations!\e[25m"
echo "Installation process in now complete."
echo -e "Please \e[1mkeep track of the logs\e[21m produced by this script and check that everything is running correctly."
echo "You can call for the community assistance on https://forum.fab-manager.com"
echo -e "We wish you a pleasant use of \e[31mFab-Manager\e[0m"
}
2019-12-24 16:19:44 +01:00
function trap_ctrlc( )
{
echo "Ctrl^C, exiting..."
exit 2
}
2019-12-30 17:34:15 +01:00
setup( )
{
trap "trap_ctrlc" 2 # SIGINT
2019-12-31 10:11:16 +01:00
welcome_message
2019-12-30 17:34:15 +01:00
system_requirements
config
prepare_files " $@ "
prepare_nginx
prepare_letsencrypt
prepare_docker
configure_env_file
setup_assets_and_databases
start
2019-12-31 10:11:16 +01:00
enable_ssl
final_message
2019-12-30 17:34:15 +01:00
}
setup " $@ "