216 lines
7.8 KiB
Bash
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 |