simple-opensearch-installer/opensearch-node-installer.sh

404 lines
12 KiB
Bash

#!/bin/bash
# Opensearch 1.x Engine via Docker
#
# SwITNet Ltd © - 2023, https://switnet.net/
# T&M Hansson IT AB © - 2022, https://www.hanssonit.se/
# GPLv3 or later.
#
{
echo "Started at $(date +'%Y-%m-%d %H:%M:%S')" >> opensearch-installer.log
while getopts m: option
do
case "${option}"
in
m) MODE=${OPTARG};;
\?) echo "Usage: sudo bash ./$0 [-m debug]" && exit;;
esac
done
#DEBUG
if [ "$MODE" = "debug" ]; then
set -x
fi
# Reset
Color_Off='\e[0m' # Text Reset
# Regular Colors
Black='\e[0;30m' # Black
Red='\e[0;31m' # Red
Green='\e[0;32m' # Green
Yellow='\e[0;33m' # Yellow
Blue='\e[0;34m' # Blue
Purple='\e[0;35m' # Purple
Cyan='\e[0;36m' # Cyan
MEM_AVAILABLE="$(grep MemTotal /proc/meminfo| grep -o '[0-9]\+')"
DIST=$(lsb_release -sc)
TODAY=$(date +%s)
NEXT_LTS_DATE=$(date -d 2024-04-01 +%s)
OPNSDIR="/opt/opensearch"
INDEX_USER="$(tr -dc '[:lower:]' < /dev/urandom | fold -w 24 | head -n1)"
OPNSREST="$(tr -dc "a-zA-Z0-9" < /dev/urandom | fold -w 32 | head -n1)"
PUBLIC_IP="$(dig -4 +short myip.opendns.com @resolver1.opendns.com)"
opens_fts="opensearchproject/opensearch:1"
fts_node="fts_os-node"
max_map_count="512000"
NL="$(printf '\n ')"
rename_distro() {
if [ "$DIST" = "$1" ]; then
DIST="$2"
fi
}
#Trisquel distro upstream referencing.
rename_distro nabia focal
rename_distro aramo jammy
printwc() {
printf "%b$2%b" "$1" "${Color_Off}"
}
print_title() {
printwc "${Blue}" "\n#--------------------------------------------------"
printwc "${Blue}" "\n# $1"
printwc "${Blue}" "\n#--------------------------------------------------\n"
}
install_if_not() {
if [ "$(dpkg-query -W -f='${Status}' "$1" 2>/dev/null | \
grep -c "ok installed")" == "1" ]; then
echo " $1 is installed, skipping..."
else
printf "\n---- Installing %s ----\n" "$1"
apt-get -yq2 install "$1"
fi
}
docker-compose_down() {
if [ -f "$1" ]
then
cd "$(dirname "$1")"
docker-compose down --volume --rmi all
else
echo "Non-existing docker-compose file path, skipping..."
fi
}
set_once_hash_comment() {
if ! awk '!/^ *#/ && NF {print}' "$2"| \
grep -q "$(awk -F '=' '{print$1}' <<< "$1")" ; then
echo "Setting $1 on $2..."
echo "$1" | tee -a "$2"
else
printf "%s\"$(awk -F '=' '{print$1}' <<< "$1")\"" "\n"
printf " seems already present, skipping setting this variable\n"
fi
}
dig_dns_ip() {
dig -4 +short "$1"||awk -v RS='([0-9]+\\.){3}[0-9]+' 'RT{print RT}'
}
create_certs() {
cp static/opensearch_certs.sh "$OPNSDIR"
sed -i "s|__FTSDOMAIN__|$1|" "$OPNSDIR"/opensearch_certs.sh
cd "$OPNSDIR"
bash opensearch_certs.sh
rm -f "$OPNSDIR"/opensearch_certs.sh
}
countdown() {
printwc "$Cyan" "$1"
secs="$(($2))"
while [ $secs -gt 0 ]; do
echo -ne "$secs\033[0K\r"
sleep 1
: $((secs--))
done
}
wait_for_bootstrapping() {
if [ "$(nproc)" -gt 2 ]
then
countdown "Waiting for Docker bootstrapping..." "30"
else
countdown "Waiting for Docker bootstrapping..." "60"
fi
}
#Check if user is root
if ! [ "$(id -u)" = 0 ]; then
echo "You need to be root or have sudo privileges!"
exit 0
fi
printf "\nOS: %s" "$(lsb_release -sd)"
if [ "$DIST" = "focal" ] || \
[ "$DIST" = "jammy" ]; then
printf "\nGood, this is a supported platform!"
else
printf "\nSorry, this platform is not supported... exiting"
exit
fi
# Suggest 22.04 LTS release over 20.04 in April 2024
if [ "$DIST" = "focal" ]; then
if [ "$TODAY" -gt "$NEXT_LTS_DATE" ]; then
echo " > $(lsb_release -sc), even when it's compatible and functional."
echo -n " We suggest to use the next (LTS) release, for longer"
echo " support and security reasons."
read -n 1 -s -r -p "Press any key to continue..."$'\n'
else
echo "Focal is supported."
fi
fi
# Check update
apt-get update -q2
# Test RAM size (4GB min) + CPUs (min 2)
print_title "Check system resources"
printf "\n\nVerifying System Resources:"
if [ "$(nproc --all)" -lt 2 ];then
printf "\nWarning!: The system do not meet the minimum CPU"
printf " requirements for Opensearch to run."
printf "\n>> We recommend 2 cores/threads for Opensearch!\n"
CPU_MIN="N"
else
printf "\nCPU Cores/Threads: OK (%s)\n" "$(nproc --all)"
CPU_MIN="Y"
fi
sleep .1
### Test RAM size (4GB min) ###
if [ "$MEM_AVAILABLE" -lt 3700000 ]; then
printf "\nWarning!: The system do not meet the minimum RAM"
printf " requirements for Jibri to run."
printf "\n>> We recommend at least 4GB RAM for Opensearch!\n\n"
MEM_MIN="N"
else
printf "\nMemory: OK (%s) MiB\n\n" "$((MEM_AVAILABLE/1024))"
MEM_MIN="Y"
fi
sleep .1
if [ "$CPU_MIN" = "Y" ] && [ "$MEM_MIN" = "Y" ];then
echo "All requirements seems meet!"
else
printf "CPU (%s)/RAM (%s MiB)" "$(nproc --all)" "$((MEM_AVAILABLE/1024))"
printf " does NOT meet minimum recommended requirements!"
sleep .1
while [ "$CONTINUE_LR" != "yes" ] && [ "$CONTINUE_LR" != "no" ]
do
read -p "> Do you want to continue?: (yes or no)$NL" -r CONTINUE_LR
if [ "$CONTINUE_LR" = "no" ]; then
printf "\n - See you next time with more resources!..."
exit
elif [ "$CONTINUE_LR" = "yes" ]; then
printf "\n - We highly recommend to increase the server resources."
fi
done
fi
sleep .1
if [ "$CONTINUE_LR" = "yes" ]; then
printf '\nThis server will likely have issues due the lack of resources.\n'
printf '>>> We highly recommend to increase resources of this server. <<<\n'
fi
sleep .1
print_title "Set CA domain"
while [ "$ANS_DMN" != "yes" ]
do
read -p "> Set your CA domain (or subdomain) here: $NL" -r DOMAIN
read -p " > Did you mean?: $DOMAIN (yes or no)$NL" -r ANS_DMN
if [ "$ANS_DMN" = "yes" ]
then
echo " - Alright, let's use $DOMAIN."
else
echo " - Please try again."
fi
done
sleep .1
# Simple DNS test
if [ "$PUBLIC_IP" = "$(dig_dns_ip "$DOMAIN")" ]; then
printf "\nServer public IP & DNS record for"
printf " %s seems to match, continuing..." "$DOMAIN"
else
echo -n "Server public IP ($PUBLIC_IP) & DNS record for $DOMAIN"
echo " don't seem to match."
echo -n " > Please check your dns records are applied and updated,"
echo " otherwise components may fail."
read -p " > Do you want to continue?: (yes or no)$NL" -r DNS_CONTINUE
if [ "$DNS_CONTINUE" = "yes" ]; then
echo " - We'll continue anyway..."
else
echo " - Exiting for now..."
exit
fi
fi
sleep .1
print_title "Set system vm.max_map_count."
sysctl -w vm.max_map_count="$max_map_count"
set_once_hash_comment "vm.max_map_count=$max_map_count" "/etc/sysctl.conf"
print_title "Install and setup Docker"
install_if_not docker.io
install_if_not docker-compose
mkdir -p "$OPNSDIR"
docker pull "$opens_fts"
BCRYPT_HASH="$(docker run --rm -it $opens_fts \
bash -c "plugins/opensearch-security/tools/hash.sh \
-p $OPNSREST | tr -d ':\n' ")"
# Create configurations YML
# opensearch.yml
cat << YML_OPENSEARCH > $OPNSDIR/opensearch.yml
cluster.name: docker-cluster
# Avoid Docker assigning IP.
network.host: 0.0.0.0
# Declaring single node cluster.
discovery.type: single-node
######## Start Security Configuration ########
plugins.security.ssl.transport.pemcert_filepath: node.pem
plugins.security.ssl.transport.pemkey_filepath: node-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: root-ca.pem
plugins.security.ssl.transport.enforce_hostname_verification: false
# Disable ssl at REST as Fulltextsearch can't accept self-signed CA certs.
plugins.security.ssl.http.enabled: false
#plugins.security.ssl.http.pemcert_filepath: node.pem
#plugins.security.ssl.http.pemkey_filepath: node-key.pem
#plugins.security.ssl.http.pemtrustedcas_filepath: root-ca.pem
plugins.security.allow_unsafe_democertificates: false
plugins.security.allow_default_init_securityindex: true
plugins.security.authcz.admin_dn:
- 'CN=admin,OU=FTS,O=OPENSEARCH,L=FTS,ST=OPENSEARCH,,C=CA'
plugins.security.nodes_dn:
- 'CN=${DOMAIN},OU=FTS,O=OPENSEARCH,L=FTS,ST=OPENSEARCH,C=CA'
plugins.security.audit.type: internal_opensearch
plugins.security.enable_snapshot_restore_privilege: true
plugins.security.check_snapshot_restore_write_privileges: true
plugins.security.restapi.roles_enabled: ["all_access", "security_rest_api_access"]
plugins.security.system_indices.enabled: true
plugins.security.system_indices.indices: [".opendistro-alerting-config", ".opendistro-alerting-alert*", ".opendistro-anomaly-results*", ".opendistro-anomaly-detector*", ".opendistro-anomaly-checkpoints", ".opendistro-anomaly-detection-state", ".opendistro-reports-*", ".opendistro-notifications-*", ".opendistro-notebooks", ".opensearch-observability", ".opendistro-asynchronous-search-response*", ".replication-metadata-store"]
node.max_local_storage_nodes: 1
######## End Security Configuration ########
YML_OPENSEARCH
# internal_users.yml
cat << YML_INTERNAL_USERS > $OPNSDIR/internal_users.yml
_meta:
type: "internalusers"
config_version: 2
${INDEX_USER}:
hash: "${BCRYPT_HASH}"
reserved: true
backend_roles:
- "admin"
description: "admin user for fts at opensearch."
YML_INTERNAL_USERS
# roles_mapping.yml
cat << YML_ROLES_MAPPING > $OPNSDIR/roles_mapping.yml
_meta:
type: "rolesmapping"
config_version: 2
# Roles mapping
all_access:
reserved: false
backend_roles:
- "admin"
description: "Maps admin to all_access"
YML_ROLES_MAPPING
# docker-compose.yml
cat << YML_DOCKER_COMPOSE > $OPNSDIR/docker-compose.yml
version: '3'
services:
fts_os-node:
image: $opens_fts
container_name: fts_os-node
restart: always
command:
- sh
- -c
- "/usr/share/opensearch/bin/opensearch-plugin list | grep -q ingest-attachment \
|| /usr/share/opensearch/bin/opensearch-plugin install --batch ingest-attachment ;
./opensearch-docker-entrypoint.sh"
environment:
- cluster.name=fts_os-cluster
- node.name=fts_os-node
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms1024M -Xmx1024M"
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- fts_os-data:/usr/share/opensearch/data
- $OPNSDIR/root-ca.pem:/usr/share/opensearch/config/root-ca.pem
- $OPNSDIR/node.pem:/usr/share/opensearch/config/node.pem
- $OPNSDIR/node-key.pem:/usr/share/opensearch/config/node-key.pem
- $OPNSDIR/admin.pem:/usr/share/opensearch/config/admin.pem
- $OPNSDIR/admin-key.pem:/usr/share/opensearch/config/admin-key.pem
- $OPNSDIR/opensearch.yml:/usr/share/opensearch/config/opensearch.yml
- $OPNSDIR/internal_users.yml:/usr/share/opensearch/plugins/opensearch-security/securityconfig/internal_users.yml
- $OPNSDIR/roles_mapping.yml:/usr/share/opensearch/plugins/opensearch-security/securityconfig/roles_mapping.yml
ports:
- 127.0.0.1:9200:9200
- 127.0.0.1:9600:9600 # Performance Analyzer [1]
networks:
- fts_os-net
volumes:
fts_os-data:
networks:
fts_os-net:
#[1] https://github.com/opensearch-project/performance-analyzer
YML_DOCKER_COMPOSE
print_title "Prepare certs"
create_certs "$DOMAIN"
# Set permissions
chmod 744 -R $OPNSDIR
print_title "Launch opensearch via docker-compose"
cd $OPNSDIR
docker-compose up -d
wait_for_bootstrapping
# Make sure password setup is enforced.
docker-compose exec fts_os-node \
bash -c "cd \
plugins/opensearch-security/tools/ && \
bash securityadmin.sh -f \
../securityconfig/internal_users.yml \
-t internalusers \
-icl \
-nhnv \
-cacert ../../../config/root-ca.pem \
-cert ../../../config/admin.pem \
-key ../../../config/admin-key.pem && \
chmod 0600 ../../../config/root-ca.pem \
../../../config/admin.pem \
../../../config/admin-key.pem"
wait_for_bootstrapping
docker logs $fts_node
print_title "Final node test:"
if curl -sXGET "http://${INDEX_USER}:${OPNSREST}@localhost:9200"
then
printwc "$Green" "\n\nYou can now use: "
printwc "$Cyan" "'http://${INDEX_USER}:${OPNSREST}@localhost:9200'\n"
else
printwc "$Red" "\n\nSetup have failed please report to: "
printwc "$Cyan" \
"'https://forge.switnet.net/switnet/simple-opensearch-installer'\n\n"
fi
} > >(tee -a opensearch-installer.log) 2> >(tee -a opensearch-installer.log >&2)