216 lines
7.8 KiB
Bash

#!/bin/bash
set -e
# Source environment variables
source /app/.env
# Set constants
ELASTIC_PASSWORD="cloudron"
ES_HOME=/usr/share/elasticsearch
ES_PATH_CONF=/app/data/config
export ES_HOME ES_PATH_CONF
# Create directory structure
mkdir -p /app/data/{elasticsearch,logs/gc,config,run,secrets,jdk/bin}
echo "$ELASTIC_PASSWORD" > /app/data/secrets/elastic_password
# Set up Java environment
setup_java() {
if [ -L /app/data/jdk/bin/java ]; then
return 0
fi
echo "Setting up Java environment..."
# Try Java 17 first, then fall back to system Java
if [ -f /usr/lib/jvm/java-17-openjdk-amd64/bin/java ]; then
ln -sf /usr/lib/jvm/java-17-openjdk-amd64/bin/{java,javac,javadoc,jar} /app/data/jdk/bin/
else
JAVA_PATH=$(which java)
if [ -n "$JAVA_PATH" ]; then
ln -sf $JAVA_PATH /app/data/jdk/bin/java
for tool in javac javadoc jar; do
ln -sf $(which $tool 2>/dev/null) /app/data/jdk/bin/$tool 2>/dev/null || true
done
else
echo "ERROR: No Java found on system. Elasticsearch requires Java to run."
exit 1
fi
fi
# Verify Java is available
if [ -L /app/data/jdk/bin/java ]; then
echo "Java version: $(/app/data/jdk/bin/java -version 2>&1 | head -n 1)"
else
echo "ERROR: Failed to link Java executable"
exit 1
fi
}
# Configure Elasticsearch
configure_elasticsearch() {
cd $ES_HOME
# Handle keystore creation and password
if [ ! -f $ES_PATH_CONF/elasticsearch.keystore ] || [ "$1" = "force" ]; then
echo "Creating Elasticsearch keystore..."
[ -f $ES_PATH_CONF/elasticsearch.keystore ] && rm -f $ES_PATH_CONF/elasticsearch.keystore
su -c "ES_PATH_CONF=$ES_PATH_CONF ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-keystore create" elasticsearch
fi
# Add bootstrap password to keystore
echo "Setting bootstrap password..."
echo "$ELASTIC_PASSWORD" | su -c "ES_PATH_CONF=$ES_PATH_CONF ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-keystore add -f -x 'bootstrap.password' --stdin" elasticsearch
# Copy configuration files if needed
if [ ! -f $ES_PATH_CONF/elasticsearch.yml ]; then
echo "Setting up configuration files..."
cp -r $ES_HOME/config/* $ES_PATH_CONF/ || true
cp /app/elasticsearch.yml $ES_PATH_CONF/elasticsearch.yml || true
fi
# Update JVM options for GC logs
if [ -f $ES_PATH_CONF/jvm.options ]; then
echo "Updating JVM options..."
sed -i 's|logs/gc.log|/app/data/logs/gc/gc.log|g' $ES_PATH_CONF/jvm.options
fi
# Generate SSL certificates if needed
if [ ! -f $ES_PATH_CONF/elastic-certificates.p12 ]; then
echo "Generating self-signed certificates..."
mkdir -p /tmp/elastic-certs
ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-certutil ca \
--out /tmp/elastic-certs/elastic-stack-ca.p12 \
--pass "" \
--silent
ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch-certutil cert \
--ca /tmp/elastic-certs/elastic-stack-ca.p12 \
--ca-pass "" \
--out $ES_PATH_CONF/elastic-certificates.p12 \
--pass "" \
--silent
chown elasticsearch:elasticsearch $ES_PATH_CONF/elastic-certificates.p12
chmod 600 $ES_PATH_CONF/elastic-certificates.p12
fi
# Create users file if needed
if [ ! -f $ES_PATH_CONF/users ]; then
echo "Creating users file..."
echo 'elastic:$2a$10$BtVRGAoL8AbgEKnlvYj8cewQF3QkUz1pyL.Ga3j.jFKNUk2yh7.zW' > $ES_PATH_CONF/users
echo 'kibana_system:$2a$10$BtVRGAoL8AbgEKnlvYj8cewQF3QkUz1pyL.Ga3j.jFKNUk2yh7.zW' >> $ES_PATH_CONF/users
echo 'superuser:elastic' > $ES_PATH_CONF/users_roles
chown elasticsearch:elasticsearch $ES_PATH_CONF/{users,users_roles}
chmod 600 $ES_PATH_CONF/{users,users_roles}
fi
# Ensure basic settings in elasticsearch.yml
for setting in "xpack.security.http.ssl.enabled: false" "network.host: 0.0.0.0" "discovery.type: single-node"; do
if ! grep -q "$setting" $ES_PATH_CONF/elasticsearch.yml; then
echo "$setting" >> $ES_PATH_CONF/elasticsearch.yml
fi
done
}
# Set system limits
set_system_limits() {
echo "Setting system limits for Elasticsearch..."
ulimit -n 65536 || echo "Warning: Could not set file descriptor limit"
ulimit -l unlimited || echo "Warning: Could not set memory lock limit"
echo never > /sys/kernel/mm/transparent_hugepage/enabled 2>/dev/null || true
sysctl -w vm.max_map_count=262144 2>/dev/null || echo "Warning: Could not set vm.max_map_count"
}
# Configure JVM heap size
configure_heap() {
# Calculate optimal heap size (50% of available memory)
CONTAINER_MEM=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || echo "4294967296")
[ "$CONTAINER_MEM" = "max" ] && CONTAINER_MEM="4294967296" # Default to 4GB if unlimited
HEAP_SIZE=$(expr $CONTAINER_MEM / 2097152) # Convert to MB and take 50%
[ $HEAP_SIZE -gt 31744 ] && HEAP_SIZE=31744 # Max 31GB
[ $HEAP_SIZE -lt 512 ] && HEAP_SIZE=512 # Min 512MB
# Set JVM options
export ES_JAVA_OPTS="-Xms${HEAP_SIZE}m -Xmx${HEAP_SIZE}m -XX:+UseG1GC -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30"
export ES_JAVA_OPTS="$ES_JAVA_OPTS -Xlog:gc*,gc+age=trace,safepoint:file=/app/data/logs/gc/gc.log:utctime,level,pid,tags:filecount=32,filesize=64m"
export PATH=$ES_HOME/bin:$PATH
}
# Start Elasticsearch
start_elasticsearch() {
# Create PID file
touch /app/data/run/elasticsearch.pid
chown elasticsearch:elasticsearch /app/data/run/elasticsearch.pid
# Command to start Elasticsearch
ES_START_CMD="ES_PATH_CONF=$ES_PATH_CONF ES_JAVA_HOME=/app/data/jdk $ES_HOME/bin/elasticsearch"
ES_START_CMD="$ES_START_CMD -E xpack.security.enabled=true -E bootstrap.password=$ELASTIC_PASSWORD"
ES_START_CMD="$ES_START_CMD -d -p /app/data/run/elasticsearch.pid"
echo "Starting Elasticsearch..."
cd $ES_HOME
su -c "$ES_START_CMD" elasticsearch
# Wait for Elasticsearch to start
echo "Waiting for Elasticsearch to start..."
attempts=0
max_attempts=60
until $(curl --output /dev/null --silent --head --fail http://localhost:9200); do
if ! ps -p $(cat /app/data/run/elasticsearch.pid 2>/dev/null) > /dev/null 2>&1; then
echo "ERROR: Elasticsearch process is not running. Logs:"
cat /app/data/logs/*.log
exit 1
fi
printf '.'
sleep 5
attempts=$((attempts+1))
if [ $attempts -ge $max_attempts ]; then
echo "ERROR: Elasticsearch failed to start after 5 minutes. Logs:"
cat /app/data/logs/*.log
exit 1
fi
done
echo "Elasticsearch is up and running!"
# Reset the elastic user password
cd $ES_HOME
echo "y" | ES_JAVA_HOME=/app/data/jdk bin/elasticsearch-reset-password -u elastic -b -p "$ELASTIC_PASSWORD" --url "http://localhost:9200" || true
# Create credentials file
cat > /app/data/credentials.txt << EOL
Elasticsearch credentials:
URL: http://localhost:9200
User: elastic
Password: $ELASTIC_PASSWORD
EOL
echo "-----------------------------"
echo "Elasticsearch is ready to use!"
echo "URL: http://localhost:9200"
echo "User: elastic"
echo "Password: $ELASTIC_PASSWORD"
echo "-----------------------------"
}
# Main execution flow
setup_java
configure_elasticsearch
[ ! -f /app/data/.initialized ] && touch /app/data/.initialized
# Ensure correct permissions
chown -R elasticsearch:elasticsearch /app/data/{elasticsearch,logs,config,jdk,run,secrets}
set_system_limits
configure_heap
start_elasticsearch
# Keep container running
tail -f /app/data/logs/*.log 2>/dev/null || sleep infinity