onepush/onepush.sh
2025-07-23 02:31:40 +00:00

233 lines
No EOL
9.8 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ==============================================================================
# Automated Open WebUI & SearXNG Installer (v27 - The Final)
#
# This script will:
# 1. Deploy a complete, secure, and automated stack for Open WebUI.
# 2. Optionally deploy SearXNG and add a user-defined JSON engine override.
# 3. All previous bug fixes and best practices are retained.
# ==============================================================================
# --- Safety Checks ---
set -euo pipefail
# --- Pre-flight Checks ---
if [[ "$EUID" -ne 0 ]]; then echo "❌ This script must be run as root."; exit 1; fi
if ! grep -qi "debian" /etc/os-release; then echo "⚠️ This script is optimized for Debian."; fi
# --- User Input ---
echo "---"
echo "Welcome to the Full Stack Open WebUI & SearXNG Installer."
echo "---"
read -p "Enter your domain for Open WebUI (e.g., ai.example.com): " UI_DOMAIN
read -p "Enter your email address (for Let's Encrypt): " EMAIL
read -p "Also secure the 'www' version of this domain (www.$UI_DOMAIN)? [y/N]: " UI_INCLUDE_WWW
read -p "Use Let's Encrypt staging environment (for testing)? [y/N]: " USE_STAGING
echo ""
if command -v ufw &> /dev/null; then
echo " UFW firewall is detected on this system."
read -p "Allow this script to manage UFW rules (allow HTTP/HTTPS)? [Y/n]: " MANAGE_UFW
else
read -p "Install and configure UFW firewall? (Recommended) [Y/n]: " MANAGE_UFW
fi
echo ""
read -p "Deploy a private SearXNG instance for the research tool? [y/N]: " DEPLOY_SEARXNG
BRAVE_API_KEY=""
if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then
SEARCH_DOMAIN="search.r21.io"
echo " SearXNG will be deployed to https://$SEARCH_DOMAIN"
read -p "Enter your Brave Search API key (highly recommended, or press Enter): " BRAVE_API_KEY
fi
# --- Main Script ---
echo "---"; echo "✅ Thank you. Starting the setup."; sleep 3
# --- Configuration ---
UI_CONTAINER="open-webui"
SEARXNG_CONTAINER="searxng"
NETWORK_NAME="open-webui-net"
SEARXNG_CONFIG_DIR="/srv/searxng"
# --- Step 1: Dependencies ---
echo "▶️ [1/9] Installing dependencies..."
export DEBIAN_FRONTEND=noninteractive
apt-get update
BASE_PACKAGES="ca-certificates curl gnupg nginx certbot python3-certbot-nginx fail2ban unattended-upgrades openssl"
if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then apt-get install -y $BASE_PACKAGES apache2-utils; else apt-get install -y $BASE_PACKAGES; fi
# --- Step 2: Firewall Management ---
echo "▶️ [2/9] Managing Firewall..."
if [[ -z "${MANAGE_UFW+x}" ]]; then MANAGE_UFW="y"; fi
if [[ "${MANAGE_UFW,,}" != "n" ]]; then
if ! command -v ufw &> /dev/null; then apt-get install -y ufw; fi
ufw allow ssh > /dev/null; ufw allow 'Nginx Full' > /dev/null; ufw --force enable
else
if command -v ufw &> /dev/null && ufw status | grep -q "Status: active"; then
echo " - ⚠️ UFW is active but not managed. Disabling to prevent setup failure."
ufw disable
fi
fi
# --- Step 3: Docker & Network ---
echo "▶️ [3/9] Installing Docker and setting up network..."
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
if ! docker network ls | grep -q "$NETWORK_NAME"; then docker network create $NETWORK_NAME; fi
# --- Step 4: Stop Old Containers ---
echo "▶️ [4/9] Stopping and removing any old containers..."
docker stop $UI_CONTAINER $SEARXNG_CONTAINER 2>/dev/null || true
docker rm $UI_CONTAINER $SEARXNG_CONTAINER 2>/dev/null || true
# --- Step 5: Configure and Deploy SearXNG (Optional) ---
if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then
echo "▶️ [5/9] Configuring and deploying SearXNG..."
# Create a user-defined settings override to add the JSON engine
sudo mkdir -p $SEARXNG_CONFIG_DIR
sudo tee "$SEARXNG_CONFIG_DIR/user.yml" >/dev/null <<'EOF'
use_default_settings: true # <- keep everything from the upstream settings
search:
formats:
- html
- json
EOF
sudo chown 1000:1000 "$SEARXNG_CONFIG_DIR/user.yml"
# Generate a robust, shell-safe secret key
SECRET_KEY=$(openssl rand -hex 32)
# Build the docker run command safely in an array
docker_cmd=(
docker run -d
--name "$SEARXNG_CONTAINER"
--network "$NETWORK_NAME"
-p "127.0.0.1:8081:8080"
-v "$SEARXNG_CONFIG_DIR:/etc/searxng"
-e "SEARXNG_SETTINGS_PATH=/etc/searxng/user.yml"
-e "SEARXNG_SECRET=$SECRET_KEY"
-e "SEARXNG_BIND_ADDRESS=0.0.0.0"
-e "SEARXNG_BASE_URL=https://$SEARCH_DOMAIN"
--restart always
)
# Add optional Brave integration
if [[ -n "$BRAVE_API_KEY" ]]; then
echo " - Enabling Brave engine with API key..."
docker_cmd+=(
-e "SEARXNG_ENGINES_BRAVE_API_KEY=$BRAVE_API_KEY"
-e "SEARXNG_ENGINES_BRAVE_DISABLED=false"
)
fi
docker_cmd+=(searxng/searxng)
"${docker_cmd[@]}"
else
echo "▶️ [5/9] Skipping SearXNG deployment."
fi
# --- Step 6: Deploy Open WebUI ---
echo "▶️ [6/9] Deploying Open WebUI..."
docker run -d -p 127.0.0.1:3000:8080 -v open-webui:/app/backend/data --name $UI_CONTAINER --network $NETWORK_NAME --restart always ghcr.io/open-webui/open-webui:main
# --- Step 7: Configure Nginx ---
echo "▶️ [7/9] Configuring Nginx sites..."
NGINX_UI_CONF="/etc/nginx/sites-available/$UI_DOMAIN"
if [[ "${UI_INCLUDE_WWW,,}" == "y" ]]; then UI_SERVER_NAME="$UI_DOMAIN www.$UI_DOMAIN"; else UI_SERVER_NAME="$UI_DOMAIN"; fi
cat <<EOF > "$NGINX_UI_CONF"
server {
listen 80; listen [::]:80; server_name $UI_SERVER_NAME;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto \$scheme;
proxy_http_version 1.1; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection "upgrade";
}
}
EOF
ln -sfn "$NGINX_UI_CONF" "/etc/nginx/sites-enabled/$UI_DOMAIN"
if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then
NGINX_SEARCH_CONF="/etc/nginx/sites-available/$SEARCH_DOMAIN"
echo "Please set a password for the public SearXNG instance."
sudo htpasswd -c /etc/nginx/.htpasswd admin
cat <<EOF > "$NGINX_SEARCH_CONF"
server {
listen 80; listen [::]:80; server_name $SEARCH_DOMAIN;
location / {
proxy_pass http://127.0.0.1:8081;
auth_basic "Private Search Instance";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header X-Forwarded-Host \$server_name;
}
}
EOF
ln -sfn "$NGINX_SEARCH_CONF" "/etc/nginx/sites-enabled/$SEARCH_DOMAIN"
fi
# --- Step 8: SSL Certificates & Automations ---
echo "▶️ [8/9] Obtaining SSL certificates and configuring automations..."
nginx -t
CERTBOT_STAGING_FLAG=""
if [[ "${USE_STAGING,,}" == "y" ]]; then CERTBOT_STAGING_FLAG="--staging"; fi
certbot --nginx -d $UI_SERVER_NAME $CERTBOT_STAGING_FLAG --non-interactive --agree-tos -m "$EMAIL" --redirect
if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then
certbot --nginx -d $SEARCH_DOMAIN $CERTBOT_STAGING_FLAG --non-interactive --agree-tos -m "$EMAIL" --redirect
fi
NGINX_UI_LOG="/var/log/nginx/$UI_DOMAIN.access.log"
touch $NGINX_UI_LOG && chown www-data:adm $NGINX_UI_LOG
cat <<EOF > /etc/fail2ban/filter.d/open-webui.conf
[Definition]
failregex = ^<HOST> .* "POST /api/v1/auths/signin.*" 400
ignoreregex =
EOF
cat <<EOF > /etc/fail2ban/jail.d/open-webui.local
[open-webui]
enabled = true; port = http,https; filter = open-webui;
logpath = $NGINX_UI_LOG; maxretry = 5; findtime = 3600; bantime = 86400;
EOF
systemctl restart fail2ban
dpkg-reconfigure -plow unattended-upgrades
if ! [ "$(docker ps -q -f name=watchtower)" ]; then
docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock --restart always containrrr/watchtower
fi
echo "0 9 * * 5 root /sbin/reboot" > /etc/cron.d/weekly-reboot
# --- Step 9: Finalization ---
echo "▶️ [9/9] Finalizing..."
systemctl restart nginx
echo "---"; echo "✅🎉 **DEPLOYMENT COMPLETE!** 🎉✅"; echo ""
echo "--- ACCESS ---"
echo " - Open WebUI: https://$UI_DOMAIN"
if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then echo " - SearXNG: https://$SEARCH_DOMAIN (user: admin)"; fi
echo ""
echo "--- NEXT STEPS: USING YOUR PRIVATE SEARCH ENGINE ---"
if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then
echo "You now have two ways to use your private SearXNG instance:"
echo ""
echo " OPTION A: Native Web Search (Recommended for most users)"
echo " 1. Go to your Open WebUI Admin Panel -> Settings -> Web Search."
echo " 2. Enable the 'Web Search' toggle."
echo " 3. In the 'SearXNG URL' field, enter: http://searxng:8080"
echo " (This works because the containers are on a private network)."
echo " 4. Save settings. You can now enable web search for any model."
echo ""
echo " OPTION B: Advanced Python Tool (For custom logic)"
echo " 1. Go to Settings -> Tools and click 'Add Tool'."
echo " 2. In the 'Load from URL' field, paste:"
echo " https://raw.githubusercontent.com/iamarcel/open-webui-utils/main/research_tool.py"
echo " 3. Go to the tool's 'Settings' tab (gear icon)."
echo " 4. Add Environment Variable -> Key: SEARXNG_BASE_URL, Value: http://searxng:8080"
echo " 5. Save the tool. You can now call it with '@research' in a chat."
fi
echo "---"