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
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
ES_JAVA_HOME=/app/data/jdk
ES_PATH_CONF=/app/data/config

View File

@@ -4,7 +4,7 @@
"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.",
"tagline": "Distributed search and analytics engine",
"version": "1.0.0",
"version": "1.0.7",
"healthCheckPath": "/_cluster/health?pretty",
"httpPort": 9200,
"manifestVersion": 2,
@@ -17,10 +17,6 @@
"localDir": "/data"
}
},
"accessRestriction": {
"users": true,
"defaultValue": "internal"
},
"tags": [
"elasticsearch",
"search",
@@ -37,4 +33,4 @@
"description": "Elasticsearch transport port for node-to-node communication"
}
}
}
}

View File

@@ -16,11 +16,11 @@ RUN apt-get update && \
net-tools \
iputils-ping \
dnsutils \
openjdk-17-jdk
openjdk-21-jdk
# Set Elasticsearch version
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
RUN groupadd elasticsearch && \
@@ -39,6 +39,7 @@ RUN mkdir -p /app/data/{elasticsearch,logs,config,secrets,jdk/bin,run} && \
# Copy configuration files
COPY elasticsearch.yml /app/elasticsearch.yml
COPY .env.template /app/.env.template
COPY start.sh /app/start.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
# 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
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`
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
@@ -174,4 +185,4 @@ If successful, you should see a JSON response with Elasticsearch information.
#### 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
- Single-node configuration optimized for Cloudron
- Security enabled with basic authentication
- Automatically installs the `analysis-icu` plugin (configurable)
- Internal access only by default (not publicly exposed)
- 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`.
### 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
- 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
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
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
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
JAVA_FOUND=0
for candidate in /usr/lib/jvm/java-21-openjdk-amd64/bin /usr/lib/jvm/java-17-openjdk-amd64/bin; do
if [ -x "$candidate/java" ]; then
ln -sf "$candidate/java" /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
[ -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
else
echo "ERROR: No Java found on system. Elasticsearch requires Java to run."
@@ -78,15 +91,13 @@ setup_java() {
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
if [ ! -x /app/data/jdk/bin/java ]; then
echo "ERROR: Failed to link Java executable"
ls -l /app/data/jdk/bin || true
exit 1
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
}
@@ -204,12 +215,14 @@ configure_elasticsearch() {
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
ensure_directory_structure
clean_legacy_settings
ensure_setting "xpack.security.http.ssl.enabled" "false"
ensure_setting "network.host" "0.0.0.0"
ensure_setting "discovery.type" "single-node"
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
echo "Final permission check on all data directories..."
@@ -360,6 +373,60 @@ setup_keystore() {
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_heap() {
# Calculate optimal heap size (50% of available memory)
@@ -461,7 +528,8 @@ chmod 600 /app/data/secrets/elastic_password
set_system_limits
configure_heap
install_plugins
start_elasticsearch
# 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