diff --git a/onepush.sh b/onepush.sh index 945860b..b8b095e 100644 --- a/onepush.sh +++ b/onepush.sh @@ -1,11 +1,11 @@ #!/bin/bash # ============================================================================== -# Automated Open WebUI & SearXNG Installer (v12 - GPG-Powered) +# Automated Open WebUI & SearXNG Installer (v19 - The Definitive) # # This script will: -# 1. Use `gpg` for random data generation, removing the `openssl` dependency. -# 2. Correctly configure Nginx to resolve Docker container names. +# 1. Use the user's superior method of `curl` to fetch the default SearXNG config. +# 2. Surgically inject the Brave API key into the downloaded config. # 3. Deploy a complete, secure, and automated stack for Open WebUI and SearXNG. # ============================================================================== @@ -13,28 +13,17 @@ set -euo pipefail # --- Pre-flight Checks --- -if [[ "$EUID" -ne 0 ]]; then - echo "❌ This script must be run as root. Please use 'sudo ./onepush.sh'" - exit 1 -fi -if ! grep -qi "debian" /etc/os-release; then - echo "⚠️ This script is optimized for Debian. Running on another OS may have unintended results." -fi +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 "---" -echo "--- Part 1: Open WebUI Configuration ---" read -p "Enter your domain for Open WebUI (e.g., ai.example.com): " UI_DOMAIN -if [[ -z "$UI_DOMAIN" ]]; then echo "❌ Domain name cannot be empty."; exit 1; fi - read -p "Enter your email address (for Let's Encrypt): " EMAIL -if [[ -z "$EMAIL" ]]; then echo "❌ Email address cannot be empty."; exit 1; fi - 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." @@ -42,59 +31,33 @@ if command -v ufw &> /dev/null; then else read -p "Install and configure UFW firewall? (Recommended) [Y/n]: " MANAGE_UFW fi - echo "" -echo "--- Part 2: Optional SearXNG Search Engine ---" read -p "Deploy a private SearXNG instance for the research tool? [y/N]: " DEPLOY_SEARXNG - BRAVE_API_KEY="" -RESEARCH_TOOL_URL="" if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then SEARCH_DOMAIN="search.r21.io" echo "ℹ️ SearXNG will be deployed to https://$SEARCH_DOMAIN" - echo "You can provide a Brave Search API key for enhanced, ad-free results." - read -p "Enter your Brave Search API key (or press Enter to skip): " BRAVE_API_KEY - - if [[ -z "$BRAVE_API_KEY" ]]; then - echo "" - echo "You can provide a URL to a custom research_tool.py file." - read -p "Enter URL for a custom research_tool.py (or press Enter for default): " RESEARCH_TOOL_URL - if [[ -n "$RESEARCH_TOOL_URL" ]]; then - echo "Validating URL..." - if ! curl --head --fail -sL "$RESEARCH_TOOL_URL" > /dev/null || [[ ! "$RESEARCH_TOOL_URL" == *.py ]]; then - echo "❌ Invalid or unreachable URL, or it doesn't end in .py. Proceeding with default." - RESEARCH_TOOL_URL="" - else - echo "✅ URL is valid." - fi - fi - fi + read -p "Enter your Brave Search API key (highly recommended, or press Enter): " BRAVE_API_KEY fi -echo "---" -echo "✅ Thank you. Starting the setup." -sleep 3 +# --- Main Script --- +echo "---"; echo "✅ Thank you. Starting the setup."; sleep 3 -# --- Configuration Variables --- +# --- Configuration --- UI_CONTAINER="open-webui" -UI_VOLUME="open-webui" -NGINX_UI_CONF="/etc/nginx/sites-available/$UI_DOMAIN" -NGINX_UI_LOG="/var/log/nginx/$UI_DOMAIN.access.log" +SEARXNG_CONTAINER="searxng" +NETWORK_NAME="open-webui-net" +SEARXNG_CONFIG_DIR="/srv/searxng" -# --- Step 1: System Preparation and Dependencies --- -echo "▶️ [1/11] Updating system and installing dependencies..." +# --- Step 1: Dependencies --- +echo "▶️ [1/9] Installing dependencies..." export DEBIAN_FRONTEND=noninteractive apt-get update -# MODIFIED: Removed 'openssl' from the dependency list. 'gnupg' is already installed. BASE_PACKAGES="ca-certificates curl gnupg nginx certbot python3-certbot-nginx fail2ban unattended-upgrades" -if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then - apt-get install -y $BASE_PACKAGES apache2-utils -else - apt-get install -y $BASE_PACKAGES -fi +if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then apt-get install -y $BASE_PACKAGES apache2-utils; else apt-get install -y $BASE_PACKAGES; fi -# --- Step 2: Configure Firewall --- -echo "▶️ [2/11] Managing Firewall..." +# --- Step 2: Firewall Management --- +echo "▶️ [2/9] Managing Firewall..." 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 @@ -105,41 +68,63 @@ else fi fi -# --- Step 3: Install Docker --- -echo "▶️ [3/11] Installing Docker..." +# --- 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: Create Shared Docker Network --- -echo "▶️ [4/11] Setting up Docker network..." -if ! docker network ls | grep -q "open-webui-net"; then - docker network create open-webui-net +# --- 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..." + + # 1. Fetch the default settings.yml directly from GitHub + echo " - Fetching default SearXNG configuration from GitHub..." + sudo mkdir -p $SEARXNG_CONFIG_DIR + sudo curl -sL "https://raw.githubusercontent.com/searxng/searxng/master/searx/settings.yml" -o "$SEARXNG_CONFIG_DIR/settings.yml" + + # 2. Surgically inject the Brave API key if provided + if [[ -n "$BRAVE_API_KEY" ]]; then + echo " - Injecting Brave API key..." + sudo sed -i "/^- name: brave/a \ api_key: \"$BRAVE_API_KEY\"" "$SEARXNG_CONFIG_DIR/settings.yml" + else + echo " - No Brave API key provided, using default settings." + fi + + # 3. Add a mandatory secret_key + SECRET_KEY=$(gpg --gen-random --armor 1 24) + sudo sed -i "s/ultrasecretkey/\"$SECRET_KEY\"/" "$SEARXNG_CONFIG_DIR/settings.yml" + + # 4. Set correct permissions + sudo chown -R 1000:1000 $SEARXNG_CONFIG_DIR + + # 5. Launch the final container + echo " - Starting SearXNG container..." + docker run -d --name $SEARXNG_CONTAINER --network $NETWORK_NAME -v $SEARXNG_CONFIG_DIR:/etc/searxng --restart always searxng/searxng +else + echo "▶️ [5/9] Skipping SearXNG deployment." fi -# --- Step 5: Deploy Open WebUI Container --- -echo "▶️ [5/11] Deploying Open WebUI container..." -docker stop $UI_CONTAINER 2>/dev/null || true -docker rm $UI_CONTAINER 2>/dev/null || true -docker run -d -p 127.0.0.1:3000:8080 \ - --add-host=host.docker.internal:host-gateway \ - -v $UI_VOLUME:/app/backend/data \ - --name $UI_CONTAINER \ - --network open-webui-net \ - --restart always \ - ghcr.io/open-webui/open-webui:main +# --- 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 6: Configure Nginx for Open WebUI --- -echo "▶️ [6/11] Configuring Nginx for Open WebUI..." -if [[ "${UI_INCLUDE_WWW,,}" == "y" ]]; then NGINX_UI_SERVER_NAME="$UI_DOMAIN www.$UI_DOMAIN"; else NGINX_UI_SERVER_NAME="$UI_DOMAIN"; fi +# --- 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 < "$NGINX_UI_CONF" server { - listen 80; listen [::]:80; - server_name $NGINX_UI_SERVER_NAME; - access_log $NGINX_UI_LOG; error_log /var/log/nginx/$UI_DOMAIN.error.log; + 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; @@ -150,70 +135,20 @@ server { EOF ln -sfn "$NGINX_UI_CONF" "/etc/nginx/sites-enabled/$UI_DOMAIN" -# --- Step 7: Deploy SearXNG (Optional) --- if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then - echo "▶️ [7/11] Deploying SearXNG..." - - sudo mkdir -p /srv/searxng - - SECRET_KEY=$(gpg --gen-random --armor 1 24) - - # Dynamically create settings.yml - { - echo "server:" - echo " https: false" - echo " secret_key: \"$SECRET_KEY\"" - echo "" - echo "search:" - echo " default_lang: en" - echo "" - echo "engines:" - if [[ -n "$BRAVE_API_KEY" ]]; then - # MODIFIED: Changed engine name from "brave_search" to "brave" - echo " - name: brave" - echo " engine: brave" - echo " api_key: \"$BRAVE_API_KEY\"" - echo " shortcut: b" - echo " disabled: false" - fi - echo " - name: google" - echo " engine: google" - echo " disabled: false" - } | sudo tee /srv/searxng/settings.yml > /dev/null - - SEARXNG_CONTAINER="searxng" - docker stop $SEARXNG_CONTAINER 2>/dev/null || true - docker rm $SEARXNG_CONTAINER 2>/dev/null || true - docker run -d \ - --name $SEARXNG_CONTAINER \ - --network open-webui-net \ - -v /srv/searxng:/etc/searxng \ - --restart always \ - searxng/searxng -else - echo "▶️ [7/11] Skipping SearXNG deployment." -fi - -# --- Step 8: Configure Nginx for SearXNG (Optional) --- -if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then - echo "▶️ [8/11] Configuring Nginx for SearXNG..." 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 < "$NGINX_SEARCH_CONF" server { - listen 80; listen [::]:80; - server_name $SEARCH_DOMAIN; + listen 80; listen [::]:80; server_name $SEARCH_DOMAIN; location / { resolver 127.0.0.11; set \$searxng_upstream http://searxng:8080; proxy_pass \$searxng_upstream; 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 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; @@ -221,27 +156,19 @@ server { } EOF ln -sfn "$NGINX_SEARCH_CONF" "/etc/nginx/sites-enabled/$SEARCH_DOMAIN" -else - echo "▶️ [8/11] Skipping Nginx config for SearXNG." fi -# --- Step 9: Obtain SSL Certificates --- -echo "▶️ [9/11] Finalizing Nginx and obtaining SSL certificates..." +# --- 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 - -# Get cert for UI Domain -if [[ "${UI_INCLUDE_WWW,,}" == "y" ]]; then UI_DOMAINS="-d $UI_DOMAIN -d www.$UI_DOMAIN"; else UI_DOMAINS="-d $UI_DOMAIN"; fi -certbot --nginx $UI_DOMAINS $CERTBOT_STAGING_FLAG --non-interactive --agree-tos -m "$EMAIL" --redirect - -# Get cert for Search Domain if deployed +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 - -# --- Step 10: Configure Automations --- -echo "▶️ [10/11] Configuring system and service automations..." +NGINX_UI_LOG="/var/log/nginx/$UI_DOMAIN.access.log" +touch $NGINX_UI_LOG && chown www-data:adm $NGINX_UI_LOG cat < /etc/fail2ban/filter.d/open-webui.conf [Definition] failregex = ^ .* "POST /api/v1/auths/signin.*" 400 @@ -257,39 +184,23 @@ 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 # Weekly reboot for system health" > /etc/cron.d/weekly-reboot +echo "0 9 * * 5 root /sbin/reboot" > /etc/cron.d/weekly-reboot -# --- Step 11: Finalization --- -echo "▶️ [11/11] Finalizing..." +# --- Step 9: Finalization --- +echo "▶️ [9/9] Finalizing..." systemctl restart nginx -systemctl restart fail2ban -echo "---" -echo "✅🎉 **DEPLOYMENT COMPLETE!** 🎉✅" -echo "" +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 +if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then echo " - SearXNG: https://$SEARCH_DOMAIN (user: admin)"; fi echo "" echo "--- NEXT STEPS: ADDING THE RESEARCH TOOL ---" if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then echo "1. Go to Open WebUI -> Settings -> Tools." - echo "2. Click 'Add Tool' and paste the Python code below into the editor." - echo "3. Open the 'Settings' tab in the tool editor." - echo "4. In the 'Environment Variables' section, add:" - echo " - Key: SEARXNG_BASE_URL" - echo " - Value: http://searxng:8080" - echo "5. Click 'Save' to finish." - echo "" - echo "--- Python Code for Research Tool ---" - if [[ -n "$RESEARCH_TOOL_URL" ]]; then - echo "Paste the content from your custom URL: $RESEARCH_TOOL_URL" - else - echo "Paste the default code from here: https://github.com/iamarcel/open-webui-utils/blob/main/research_tool.py" - fi -else - echo "SearXNG was not deployed, so no research tool was configured." + echo "2. Paste the Python code from https://github.com/iamarcel/open-webui-utils/blob/main/research_tool.py" + echo "3. Go to the Settings tab in the tool editor." + echo "4. Add Environment Variable: Key: SEARXNG_BASE_URL, Value: http://searxng:8080" + echo "5. Click 'Save'." fi echo "---" \ No newline at end of file