Ensure plugin installation works on Cloudron

This commit is contained in:
Your Name
2025-11-07 04:17:23 -06:00
parent ef3eea7ee1
commit a2f315f959
6 changed files with 129 additions and 32 deletions

View File

@@ -4,6 +4,10 @@
# Java memory settings - leave empty to auto-configure based on container limits # Java memory settings - leave empty to auto-configure based on container limits
ES_JAVA_HEAP= ES_JAVA_HEAP=
# Comma or space separated list of plugins to install automatically
# analysis-icu is required for Nextcloud full-text search with language analyzers
ES_PLUGINS_INSTALL=analysis-icu
# Security settings - DO NOT CHANGE # Security settings - DO NOT CHANGE
ES_JAVA_HOME=/app/data/jdk ES_JAVA_HOME=/app/data/jdk
ES_PATH_CONF=/app/data/config ES_PATH_CONF=/app/data/config

View File

@@ -4,7 +4,7 @@
"author": "Elastic and Cloudron Community", "author": "Elastic and Cloudron Community",
"description": "Elasticsearch is a distributed, open source search and analytics engine for all types of data. This package is designed for internal use only.", "description": "Elasticsearch is a distributed, open source search and analytics engine for all types of data. This package is designed for internal use only.",
"tagline": "Distributed search and analytics engine", "tagline": "Distributed search and analytics engine",
"version": "1.0.0", "version": "1.0.7",
"healthCheckPath": "/_cluster/health?pretty", "healthCheckPath": "/_cluster/health?pretty",
"httpPort": 9200, "httpPort": 9200,
"manifestVersion": 2, "manifestVersion": 2,
@@ -17,10 +17,6 @@
"localDir": "/data" "localDir": "/data"
} }
}, },
"accessRestriction": {
"users": true,
"defaultValue": "internal"
},
"tags": [ "tags": [
"elasticsearch", "elasticsearch",
"search", "search",
@@ -37,4 +33,4 @@
"description": "Elasticsearch transport port for node-to-node communication" "description": "Elasticsearch transport port for node-to-node communication"
} }
} }
} }

View File

@@ -16,11 +16,11 @@ RUN apt-get update && \
net-tools \ net-tools \
iputils-ping \ iputils-ping \
dnsutils \ dnsutils \
openjdk-17-jdk openjdk-21-jdk
# Set Elasticsearch version # Set Elasticsearch version
ENV ELASTIC_VERSION=9.1.5 ENV ELASTIC_VERSION=9.1.5
ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
# Create elasticsearch user and group # Create elasticsearch user and group
RUN groupadd elasticsearch && \ RUN groupadd elasticsearch && \
@@ -39,6 +39,7 @@ RUN mkdir -p /app/data/{elasticsearch,logs,config,secrets,jdk/bin,run} && \
# Copy configuration files # Copy configuration files
COPY elasticsearch.yml /app/elasticsearch.yml COPY elasticsearch.yml /app/elasticsearch.yml
COPY .env.template /app/.env.template
COPY start.sh /app/start.sh COPY start.sh /app/start.sh
COPY stop.sh /app/stop.sh COPY stop.sh /app/stop.sh
@@ -50,4 +51,4 @@ HEALTHCHECK --interval=15s --timeout=10s --start-period=120s --retries=5 \
CMD curl -fs -u elastic:$(cat /app/data/secrets/elastic_password) http://localhost:9200/_cluster/health?pretty || exit 1 CMD curl -fs -u elastic:$(cat /app/data/secrets/elastic_password) http://localhost:9200/_cluster/health?pretty || exit 1
# Command to run # Command to run
CMD ["/app/start.sh"] CMD ["/app/start.sh"]

View File

@@ -32,6 +32,17 @@ After installation:
1. Check the app logs to ensure Elasticsearch has started correctly 1. Check the app logs to ensure Elasticsearch has started correctly
2. Note the generated password from the logs or from `/app/data/credentials.txt` 2. Note the generated password from the logs or from `/app/data/credentials.txt`
3. Configure your other Cloudron apps to connect to Elasticsearch using the format: `http://elastic:<password>@localhost:9200` 3. Configure your other Cloudron apps to connect to Elasticsearch using the format: `http://elastic:<password>@localhost:9200`
4. (Recommended) Ensure the required analysis plugins are installed before integrating apps like Nextcloud:
1. Open the Cloudron File Manager for the Elasticsearch app and edit `/app/data/.env`
2. Set `ES_PLUGINS_INSTALL="analysis-icu"` (add extra plugins separated by spaces or commas)
3. Restart the Elasticsearch app so it installs the requested plugins on startup
4. Verify installation from the web terminal:
```bash
curl -X GET -u elastic:<password> "localhost:9200/_nodes/plugins?pretty"
```
You should see `analysis-icu` listed before running any index commands.
## Troubleshooting ## Troubleshooting
@@ -174,4 +185,4 @@ If successful, you should see a JSON response with Elasticsearch information.
#### Advanced Configuration #### Advanced Configuration
In some cases, you might need to modify additional Elasticsearch settings. You can do this via the elasticsearch.yml file, which is stored in `/app/data/config/elasticsearch.yml` within the Elasticsearch app container. In some cases, you might need to modify additional Elasticsearch settings. You can do this via the elasticsearch.yml file, which is stored in `/app/data/config/elasticsearch.yml` within the Elasticsearch app container.

View File

@@ -7,6 +7,7 @@ This package provides Elasticsearch for Cloudron, configured for internal use on
- Elasticsearch 9.1.5 - Elasticsearch 9.1.5
- Single-node configuration optimized for Cloudron - Single-node configuration optimized for Cloudron
- Security enabled with basic authentication - Security enabled with basic authentication
- Automatically installs the `analysis-icu` plugin (configurable)
- Internal access only by default (not publicly exposed) - Internal access only by default (not publicly exposed)
- Automatic optimization based on container resources - Automatic optimization based on container resources
@@ -69,6 +70,22 @@ curl -X PUT "http://elastic:PASSWORD@IPADDRESS:9200/nextcloud" -H 'Content-Type:
You can get the IP address from the Cloudron admin panel or by using the `cloudron status` command. The password is stored in `/app/data/credentials.txt`. You can get the IP address from the Cloudron admin panel or by using the `cloudron status` command. The password is stored in `/app/data/credentials.txt`.
### Language Analysis Plugins
Many integrations (for example, Nextcloud Full-Text Search with German documents) require the `analysis-icu` plugin so Elasticsearch understands language-specific analyzers. This package installs `analysis-icu` automatically on every start. To add additional plugins, edit `/app/data/.env` via the Cloudron File Manager and tweak the `ES_PLUGINS_INSTALL` variable:
```
ES_PLUGINS_INSTALL="analysis-icu ingest-attachment"
```
Plugins are installed sequentially and skipped if already present. After restarting the app you can verify the installed plugins from the Elasticsearch web terminal:
```bash
curl -X GET -u elastic:<password> "localhost:9200/_nodes/plugins?pretty"
```
Look for `analysis-icu` (and any other requested plugins) in the output before running `occ fulltextsearch:index`.
## Security Notes ## Security Notes
- The app is configured as internal-only by default, so it's not exposed to the public internet - The app is configured as internal-only by default, so it's not exposed to the public internet
@@ -94,4 +111,4 @@ The package automatically configures Elasticsearch based on the container's avai
## Support ## Support
For support, please create an issue on the package's GitHub repository or contact the package maintainer. For support, please create an issue on the package's GitHub repository or contact the package maintainer.

110
start.sh
View File

@@ -56,21 +56,34 @@ setup_password() {
# Set up Java environment # Set up Java environment
setup_java() { setup_java() {
if [ -L /app/data/jdk/bin/java ]; then mkdir -p /app/data/jdk/bin
if [ -x /app/data/jdk/bin/java ]; then
echo "Java already configured: $(/app/data/jdk/bin/java -version 2>&1 | head -n 1)"
return 0 return 0
fi fi
echo "Setting up Java environment..." echo "Setting up Java environment..."
# Try Java 17 first, then fall back to system Java JAVA_FOUND=0
if [ -f /usr/lib/jvm/java-17-openjdk-amd64/bin/java ]; then for candidate in /usr/lib/jvm/java-21-openjdk-amd64/bin /usr/lib/jvm/java-17-openjdk-amd64/bin; do
ln -sf /usr/lib/jvm/java-17-openjdk-amd64/bin/{java,javac,javadoc,jar} /app/data/jdk/bin/ if [ -x "$candidate/java" ]; then
else ln -sf "$candidate/java" /app/data/jdk/bin/java
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 for tool in javac javadoc jar; do
ln -sf $(which $tool 2>/dev/null) /app/data/jdk/bin/$tool 2>/dev/null || true [ -x "$candidate/$tool" ] && ln -sf "$candidate/$tool" /app/data/jdk/bin/$tool
done
JAVA_FOUND=1
break
fi
done
if [ $JAVA_FOUND -eq 0 ]; then
JAVA_PATH=$(command -v java || true)
if [ -n "$JAVA_PATH" ]; then
ln -sf "$JAVA_PATH" /app/data/jdk/bin/java
for tool in javac javadoc jar; do
TOOL_PATH=$(command -v $tool 2>/dev/null || true)
[ -n "$TOOL_PATH" ] && ln -sf "$TOOL_PATH" /app/data/jdk/bin/$tool
done done
else else
echo "ERROR: No Java found on system. Elasticsearch requires Java to run." echo "ERROR: No Java found on system. Elasticsearch requires Java to run."
@@ -78,15 +91,13 @@ setup_java() {
fi fi
fi fi
# Verify Java is available if [ ! -x /app/data/jdk/bin/java ]; then
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" echo "ERROR: Failed to link Java executable"
ls -l /app/data/jdk/bin || true
exit 1 exit 1
fi fi
# Ensure Java symlinks have correct ownership echo "Java version: $(/app/data/jdk/bin/java -version 2>&1 | head -n 1)"
chown -R elasticsearch:elasticsearch /app/data/jdk chown -R elasticsearch:elasticsearch /app/data/jdk
} }
@@ -204,12 +215,14 @@ configure_elasticsearch() {
chmod 600 $ES_PATH_CONF/{users,users_roles} chmod 600 $ES_PATH_CONF/{users,users_roles}
fi fi
# Ensure basic settings in elasticsearch.yml ensure_directory_structure
for setting in "xpack.security.http.ssl.enabled: false" "network.host: 0.0.0.0" "discovery.type: single-node"; do clean_legacy_settings
if ! grep -q "$setting" $ES_PATH_CONF/elasticsearch.yml; then ensure_setting "xpack.security.http.ssl.enabled" "false"
echo "$setting" >> $ES_PATH_CONF/elasticsearch.yml ensure_setting "network.host" "0.0.0.0"
fi ensure_setting "discovery.type" "single-node"
done ensure_setting "path.data" "/app/data/elasticsearch/data"
ensure_setting "path.logs" "/app/data/logs"
ensure_setting "path.plugins" "/app/data/elasticsearch/plugins"
# Final permission check # Final permission check
echo "Final permission check on all data directories..." echo "Final permission check on all data directories..."
@@ -360,6 +373,60 @@ setup_keystore() {
return 0 return 0
} }
# Ensure writable dirs exist
ensure_directory_structure() {
mkdir -p /app/data/elasticsearch/{data,plugins}
mkdir -p /app/data/logs
chown -R elasticsearch:elasticsearch /app/data/elasticsearch
}
clean_legacy_settings() {
sed -i '/^path\.home:/d' "$ES_PATH_CONF/elasticsearch.yml"
}
ensure_setting() {
local key="$1"
local value="$2"
if grep -q "^$key:" "$ES_PATH_CONF/elasticsearch.yml"; then
sed -i "s|^$key:.*|$key: $value|" "$ES_PATH_CONF/elasticsearch.yml"
else
echo "$key: $value" >> "$ES_PATH_CONF/elasticsearch.yml"
fi
}
# Install optional Elasticsearch plugins (analysis-icu required for multi-language indexing)
install_plugins() {
local plugin_list="${ES_PLUGINS_INSTALL:-analysis-icu}"
local plugin_dir="/app/data/elasticsearch/plugins"
if [ -z "$plugin_list" ]; then
echo "No Elasticsearch plugins requested for installation."
return 0
fi
# Normalize separators (commas/semicolons/newlines) to whitespace
plugin_list=$(echo "$plugin_list" | tr ',;' ' ')
for plugin in $plugin_list; do
plugin=$(echo "$plugin" | xargs)
[ -z "$plugin" ] && continue
if [ -d "$plugin_dir/$plugin" ]; then
echo "Plugin '$plugin' already installed. Skipping."
continue
fi
echo "Installing Elasticsearch plugin '$plugin'..."
if ! su -c "ES_PATH_CONF=$ES_PATH_CONF ES_JAVA_HOME=/app/data/jdk ES_TMPDIR=/tmp $ES_HOME/bin/elasticsearch-plugin install --batch $plugin" elasticsearch; then
echo "ERROR: Failed to install plugin '$plugin'."
return 1
fi
done
echo "✅ Requested Elasticsearch plugins installed."
return 0
}
# Configure JVM heap size # Configure JVM heap size
configure_heap() { configure_heap() {
# Calculate optimal heap size (50% of available memory) # Calculate optimal heap size (50% of available memory)
@@ -461,7 +528,8 @@ chmod 600 /app/data/secrets/elastic_password
set_system_limits set_system_limits
configure_heap configure_heap
install_plugins
start_elasticsearch start_elasticsearch
# Keep container running # Keep container running
tail -f /app/data/logs/*.log 2>/dev/null || sleep infinity tail -f /app/data/logs/*.log 2>/dev/null || sleep infinity