From 00373de88644cae3eae43bdbfd51659ce1560657 Mon Sep 17 00:00:00 2001 From: first Date: Fri, 11 Jul 2025 06:15:12 +0000 Subject: [PATCH 1/7] Update onepush.sh --- onepush.sh | 283 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 199 insertions(+), 84 deletions(-) diff --git a/onepush.sh b/onepush.sh index 058b9dc..945860b 100644 --- a/onepush.sh +++ b/onepush.sh @@ -1,13 +1,12 @@ #!/bin/bash # ============================================================================== -# Automated Open WebUI Installer for Debian (v8 - Robust Cron Job) +# Automated Open WebUI & SearXNG Installer (v12 - GPG-Powered) # # This script will: -# 1. Use a robust /etc/cron.d file for the scheduled reboot, fixing a script hang. -# 2. Detect if UFW is active and handle it decisively. -# 3. Install all dependencies and deploy the full stack. -# 4. Configure all automations (updates, reboots, security). +# 1. Use `gpg` for random data generation, removing the `openssl` dependency. +# 2. Correctly configure Nginx to resolve Docker container names. +# 3. Deploy a complete, secure, and automated stack for Open WebUI and SearXNG. # ============================================================================== # --- Safety Checks --- @@ -15,7 +14,7 @@ set -euo pipefail # --- Pre-flight Checks --- if [[ "$EUID" -ne 0 ]]; then - echo "❌ This script must be run as root. Please use 'sudo ./setup-webui.sh'" + echo "❌ This script must be run as root. Please use 'sudo ./onepush.sh'" exit 1 fi if ! grep -qi "debian" /etc/os-release; then @@ -24,17 +23,16 @@ fi # --- User Input --- echo "---" -echo "Welcome to the Automated Open WebUI Installer." -echo "Please provide the following information:" +echo "Welcome to the Full Stack Open WebUI & SearXNG Installer." echo "---" - -read -p "Enter your domain or subdomain (e.g., webui.example.com): " DOMAIN -if [[ -z "$DOMAIN" ]]; then echo "❌ Domain name cannot be empty."; exit 1; fi +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.$DOMAIN)? [y/N]: " INCLUDE_WWW +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 "" @@ -45,69 +43,103 @@ 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 +fi + echo "---" -echo "✅ Thank you. Starting the setup for https://$DOMAIN" -echo "This process will take several minutes. Please do not interrupt it." +echo "✅ Thank you. Starting the setup." sleep 3 # --- Configuration Variables --- -CONTAINER_NAME="open-webui" -DATA_VOLUME="open-webui" -NGINX_CONF_PATH="/etc/nginx/sites-available/$DOMAIN" -NGINX_LOG_PATH="/var/log/nginx/$DOMAIN.access.log" +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" # --- Step 1: System Preparation and Dependencies --- -echo "▶️ [1/9] Updating system and installing dependencies..." +echo "▶️ [1/11] Updating system and installing dependencies..." export DEBIAN_FRONTEND=noninteractive apt-get update -apt-get install -y ca-certificates curl gnupg nginx certbot python3-certbot-nginx fail2ban unattended-upgrades - -# --- Step 2: Configure Firewall (Decisive Handling) --- -if [[ "${MANAGE_UFW,,}" != "n" ]]; then - echo "▶️ [2/9] Managing Firewall (UFW)..." - 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 +# 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 + +# --- Step 2: Configure Firewall --- +echo "▶️ [2/11] 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 else - echo "▶️ [2/9] Skipping firewall rule management as requested." if command -v ufw &> /dev/null && ufw status | grep -q "Status: active"; then - echo " - ⚠️ UFW is active but not managed by this script. Disabling it now to prevent cert issuance failure." + echo " - ⚠️ UFW is active but not managed. Disabling to prevent setup failure." ufw disable fi fi # --- Step 3: Install Docker --- -echo "▶️ [3/9] Installing Docker..." +echo "▶️ [3/11] Installing Docker..." 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 +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 -# --- Step 4: Run Open WebUI Container --- -echo "▶️ [4/9] Deploying Open WebUI container..." -if [ "$(docker ps -q -f name=$CONTAINER_NAME)" ]; then docker stop $CONTAINER_NAME > /dev/null; fi -if [ "$(docker ps -aq -f status=exited -f name=$CONTAINER_NAME)" ]; then docker rm $CONTAINER_NAME > /dev/null; 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 +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 $DATA_VOLUME:/app/backend/data \ - --name $CONTAINER_NAME \ + -v $UI_VOLUME:/app/backend/data \ + --name $UI_CONTAINER \ + --network open-webui-net \ --restart always \ ghcr.io/open-webui/open-webui:main -# --- Step 5: Configure Nginx Reverse Proxy --- -echo "▶️ [5/9] Configuring Nginx..." -if [[ "${INCLUDE_WWW,,}" == "y" ]]; then NGINX_SERVER_NAME="$DOMAIN www.$DOMAIN"; else NGINX_SERVER_NAME="$DOMAIN"; fi -cat < "$NGINX_CONF_PATH" +# --- 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 +cat < "$NGINX_UI_CONF" server { listen 80; listen [::]:80; - server_name $NGINX_SERVER_NAME; - access_log $NGINX_LOG_PATH; error_log /var/log/nginx/$DOMAIN.error.log; + server_name $NGINX_UI_SERVER_NAME; + access_log $NGINX_UI_LOG; error_log /var/log/nginx/$UI_DOMAIN.error.log; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; @@ -116,21 +148,100 @@ server { } } EOF -ln -sfn "$NGINX_CONF_PATH" "/etc/nginx/sites-enabled/$DOMAIN" -nginx -t && systemctl reload nginx +ln -sfn "$NGINX_UI_CONF" "/etc/nginx/sites-enabled/$UI_DOMAIN" -# --- Step 6: Obtain SSL Certificate --- -echo "▶️ [6/9] Obtaining SSL certificate with Certbot..." -if [[ "${INCLUDE_WWW,,}" == "y" ]]; then CERTBOT_DOMAINS="-d $DOMAIN -d www.$DOMAIN"; else CERTBOT_DOMAINS="-d $DOMAIN"; fi -CERTBOT_STAGING_FLAG="" -if [[ "${USE_STAGING,,}" == "y" ]]; then - echo " - Using Let's Encrypt STAGING environment for testing." - CERTBOT_STAGING_FLAG="--staging" +# --- 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 -certbot --nginx $CERTBOT_DOMAINS $CERTBOT_STAGING_FLAG --non-interactive --agree-tos -m "$EMAIL" --redirect -# --- Step 7: Configure Security Automations --- -echo "▶️ [7/9] Configuring Fail2Ban and automatic system updates..." +# --- 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; + 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 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" +else + echo "▶️ [8/11] Skipping Nginx config for SearXNG." +fi + +# --- Step 9: Obtain SSL Certificates --- +echo "▶️ [9/11] Finalizing Nginx and obtaining SSL certificates..." +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 +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..." cat < /etc/fail2ban/filter.d/open-webui.conf [Definition] failregex = ^ .* "POST /api/v1/auths/signin.*" 400 @@ -139,42 +250,46 @@ EOF cat < /etc/fail2ban/jail.d/open-webui.local [open-webui] enabled = true; port = http,https; filter = open-webui; -logpath = $NGINX_LOG_PATH; maxretry = 5; findtime = 3600; bantime = 86400; +logpath = $NGINX_UI_LOG; maxretry = 5; findtime = 3600; bantime = 86400; EOF systemctl restart fail2ban dpkg-reconfigure -plow unattended-upgrades - -# --- Step 8: Configure Service Automations --- -echo "▶️ [8/9] Deploying Watchtower and scheduling reboots..." 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 -# MODIFIED: Using a robust cron drop-in file instead of piping to crontab. -echo " - Scheduling weekly reboot for Friday at 09:00 UTC..." -echo "0 9 * * 5 root /sbin/reboot # Weekly reboot for system health" > /etc/cron.d/open-webui-reboot - -# --- Step 9: Finalization --- -echo "▶️ [9/9] Finalizing and cleaning up..." +# --- Step 11: Finalization --- +echo "▶️ [11/11] Finalizing..." systemctl restart nginx systemctl restart fail2ban -echo "" +echo "---" echo "✅🎉 **DEPLOYMENT COMPLETE!** 🎉✅" echo "" -echo "Open WebUI is now running and accessible at: https://$DOMAIN" +echo "--- ACCESS ---" +echo " - Open WebUI: https://$UI_DOMAIN" +if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then +echo " - SearXNG: https://$SEARCH_DOMAIN (user: admin)" +fi echo "" -echo "IMPORTANT NOTES:" -if [[ "${MANAGE_UFW,,}" == "n" ]]; then - echo " - ⚠️ UFW was detected and has been DISABLED to allow this script to complete." - echo " Your server's firewall is currently off. You are responsible for its configuration." +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." fi -if [[ "${USE_STAGING,,}" == "y" ]]; then - echo " - ⚠️ You used a STAGING certificate. Your site will show a browser security warning." - echo " To fix this, re-run this script after your rate limit expires and choose 'N' for staging." -fi -echo " - The Fail2Ban rule is active and will protect your login endpoint." -echo " - The first user to sign up will become the administrator." -echo " - Your system and the WebUI container will update automatically." -echo " - The server will reboot every Friday at 09:00 UTC." -echo "" \ No newline at end of file +echo "---" \ No newline at end of file From 816fc7e7ab5995d27e3cd6a93c744db70c724da3 Mon Sep 17 00:00:00 2001 From: first Date: Fri, 11 Jul 2025 06:53:44 +0000 Subject: [PATCH 2/7] progress --- onepush.sh | 245 +++++++++++++++++------------------------------------ 1 file changed, 78 insertions(+), 167 deletions(-) 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 From dd95fa27b2316fe8befc7c4153d1374a08fe3a02 Mon Sep 17 00:00:00 2001 From: first Date: Fri, 11 Jul 2025 18:08:55 +0000 Subject: [PATCH 3/7] working searxng --- onepush.sh | 80 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/onepush.sh b/onepush.sh index b8b095e..f4be09a 100644 --- a/onepush.sh +++ b/onepush.sh @@ -1,12 +1,17 @@ #!/bin/bash # ============================================================================== -# Automated Open WebUI & SearXNG Installer (v19 - The Definitive) +# Automated Open WebUI & SearXNG Installer (v26 - The Definitive Version) # -# This script will: -# 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. +# This script is the final, consolidated version incorporating all bug fixes +# and best practices discovered through our collaborative debugging process. +# +# Key Fixes: +# 1. Uses a robust "port-publishing" method for Nginx-to-Docker communication. +# 2. Uses environment variables to configure SearXNG, the correct method. +# 3. Uses a safe, non-blocking command to generate secrets. +# 4. Builds Docker commands safely in an array to prevent errors. +# 5. All previous logic (UFW, cron, etc.) is complete and verified. # ============================================================================== # --- Safety Checks --- @@ -47,17 +52,18 @@ echo "---"; echo "✅ Thank you. Starting the setup."; sleep 3 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" +# Add openssl for robust secret generation +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 @@ -85,31 +91,43 @@ 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..." + echo "▶️ [5/9] 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 + # 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" + # Publish port to localhost for Nginx to connect to + -p "127.0.0.1:8081:8080" + # Core settings via environment variables + -e "SEARXNG_SECRET=$SECRET_KEY" + -e "SEARXNG_BIND_ADDRESS=0.0.0.0" # Listen on all interfaces inside the container + -e "SEARXNG_BASE_URL=https://$SEARCH_DOMAIN" + --restart always + ) + + # Add optional Brave integration 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" + echo " - Enabling Brave engine with API key..." + docker_cmd+=( + -e "SEARXNG_ENGINES_BRAVE_API_KEY=$BRAVE_API_KEY" + -e "SEARXNG_ENGINES_BRAVE_DISABLED=false" + # Disable a noisy engine if a key is present + -e "SEARXNG_ENGINES_DUCKDUCKGO_DISABLED=true" + ) else - echo " - No Brave API key provided, using default settings." + echo " - No Brave API key provided, using default search engines." 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 + # Add the image name to the end of the command + docker_cmd+=(searxng/searxng) + + # Execute the final, safe command + "${docker_cmd[@]}" else echo "▶️ [5/9] Skipping SearXNG deployment." fi @@ -143,12 +161,12 @@ if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then server { listen 80; listen [::]:80; server_name $SEARCH_DOMAIN; location / { - resolver 127.0.0.11; - set \$searxng_upstream http://searxng:8080; - proxy_pass \$searxng_upstream; + # Proxy directly to the port we published on the host's localhost + 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 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; From aa33d9ceffbc19872338439822197824ee13621a Mon Sep 17 00:00:00 2001 From: first Date: Wed, 23 Jul 2025 02:31:40 +0000 Subject: [PATCH 4/7] json support --- onepush.sh | 69 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/onepush.sh b/onepush.sh index f4be09a..2ba841a 100644 --- a/onepush.sh +++ b/onepush.sh @@ -1,17 +1,12 @@ #!/bin/bash # ============================================================================== -# Automated Open WebUI & SearXNG Installer (v26 - The Definitive Version) +# Automated Open WebUI & SearXNG Installer (v27 - The Final) # -# This script is the final, consolidated version incorporating all bug fixes -# and best practices discovered through our collaborative debugging process. -# -# Key Fixes: -# 1. Uses a robust "port-publishing" method for Nginx-to-Docker communication. -# 2. Uses environment variables to configure SearXNG, the correct method. -# 3. Uses a safe, non-blocking command to generate secrets. -# 4. Builds Docker commands safely in an array to prevent errors. -# 5. All previous logic (UFW, cron, etc.) is complete and verified. +# 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 --- @@ -52,12 +47,12 @@ echo "---"; echo "✅ Thank you. Starting the setup."; sleep 3 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 -# Add openssl for robust secret generation 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 @@ -91,8 +86,19 @@ 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] Deploying SearXNG..." - + 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) @@ -101,11 +107,11 @@ if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then docker run -d --name "$SEARXNG_CONTAINER" --network "$NETWORK_NAME" - # Publish port to localhost for Nginx to connect to -p "127.0.0.1:8081:8080" - # Core settings via environment variables + -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" # Listen on all interfaces inside the container + -e "SEARXNG_BIND_ADDRESS=0.0.0.0" -e "SEARXNG_BASE_URL=https://$SEARCH_DOMAIN" --restart always ) @@ -116,17 +122,10 @@ if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then docker_cmd+=( -e "SEARXNG_ENGINES_BRAVE_API_KEY=$BRAVE_API_KEY" -e "SEARXNG_ENGINES_BRAVE_DISABLED=false" - # Disable a noisy engine if a key is present - -e "SEARXNG_ENGINES_DUCKDUCKGO_DISABLED=true" ) - else - echo " - No Brave API key provided, using default search engines." fi - # Add the image name to the end of the command docker_cmd+=(searxng/searxng) - - # Execute the final, safe command "${docker_cmd[@]}" else echo "▶️ [5/9] Skipping SearXNG deployment." @@ -161,7 +160,6 @@ if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then server { listen 80; listen [::]:80; server_name $SEARCH_DOMAIN; location / { - # Proxy directly to the port we published on the host's localhost proxy_pass http://127.0.0.1:8081; auth_basic "Private Search Instance"; auth_basic_user_file /etc/nginx/.htpasswd; @@ -213,12 +211,23 @@ 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: ADDING THE RESEARCH TOOL ---" +echo "--- NEXT STEPS: USING YOUR PRIVATE SEARCH ENGINE ---" if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then - echo "1. Go to Open WebUI -> Settings -> Tools." - 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'." + 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 "---" \ No newline at end of file From 83323c02ee4911b61f574fd4c8fe388d90a56be4 Mon Sep 17 00:00:00 2001 From: first Date: Wed, 23 Jul 2025 02:51:23 +0000 Subject: [PATCH 5/7] Update README.md --- README.md | 80 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index df99eeb..8c2e1ae 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,29 @@ -# Automated Open WebUI Installer for Debian +# Automated Open WebUI & SearXNG Installer ![Debian](https://img.shields.io/badge/OS-Debian-A81D33?style=for-the-badge&logo=debian)![License](https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge) -A single, robust, and intelligent shell script to fully automate the deployment of [Open WebUI](https://github.com/open-webui/open-webui) on a Debian server. This script transforms a manual setup process into a production-ready, one-shot command, complete with security hardening and full life-cycle automation. +A single, robust, and intelligent shell script to fully automate the deployment of [Open WebUI](https://github.com/open-webui/open-webui) and an optional, private [SearXNG](https://github.com/searxng/searxng) instance on a Debian server. This script transforms a manual setup process into a production-ready, one-shot command, complete with security hardening and full life-cycle automation. -This project was born from an iterative process of converting a manual guide into a fully automated script, adding features and fixing real-world deployment issues like Let's Encrypt rate limits, firewall pre-configurations, and fragile cron job commands. +This project was born from an iterative process of converting a manual guide into a fully automated script, adding features and fixing real-world deployment issues like Let's Encrypt rate limits, firewall pre-configurations, fragile cron jobs, and complex multi-container networking and configuration bugs. ## Features - **Fully Automated Deployment:** Runs non-interactively after an initial prompt for configuration details. +- **Optional SearXNG Stack:** + - Deploys a private SearXNG instance on a secure Docker network. + - Exposes it publicly on a separate subdomain with Basic Auth protection. + - Allows internal access from Open WebUI tools without authentication for fast, secure searching. + - Supports an optional Brave Search API key for enhanced, ad-free results. + - **Adds a custom JSON engine** to SearXNG for advanced integrations. - **Security First:** - - **Firewall Aware:** Intelligently detects and manages `UFW`, ensuring web ports are open or disabling it decisively to prevent silent failures. - - **Brute-Force Protection:** Installs and configures `Fail2Ban` with a precise filter to block IPs that repeatedly fail login attempts. -- **Robust Service Management:** Deploys Open WebUI via Docker, the recommended method, with the application port bound securely to the local interface. -- **Automatic HTTPS:** Uses Nginx as a reverse proxy and `Certbot` to automatically obtain and renew a free Let's Encrypt SSL certificate. + - **Firewall Aware:** Intelligently detects and manages `UFW`. + - **Brute-Force Protection:** Installs and configures `Fail2Ban` to protect the Open WebUI login. +- **Robust Service Management:** Deploys services via Docker on a shared private network, the recommended method. +- **Automatic HTTPS:** Uses Nginx as a reverse proxy and `Certbot` to automatically obtain and renew free Let's Encrypt SSL certificates. - **Production-Ready Automation:** - - **System Updates:** Configures `unattended-upgrades` to automatically apply system security patches. - - **Container Updates:** Deploys `Watchtower` to automatically update the Open WebUI container to the latest version. - - **Scheduled Reboots:** Implements a robust weekly reboot via a cron job for system health and to apply kernel updates. -- **Intelligent & Flexible:** - - Handles both root domains (with/without `www`) and subdomains correctly. - - Includes a **Let's Encrypt Staging Mode** to prevent rate-limiting during testing. - - Uses a reliable `cron.d` file for scheduling, avoiding common scripting pitfalls. + - **System Updates:** Configures `unattended-upgrades`. + - **Container Updates:** Deploys `Watchtower` for automatic container updates. + - **Scheduled Reboots:** Implements a robust weekly reboot via a `cron.d` file. ## Prerequisites @@ -29,27 +31,24 @@ Before running the script, you will need: 1. A server running **Debian 11 or 12**. 2. `sudo` or `root` access. -3. A domain or subdomain with a DNS **A record** pointing to your server's public IP address. +3. A domain for Open WebUI (e.g., `ai.example.com`) with a DNS **A record** pointing to your server's IP. +4. **If deploying SearXNG**, a second domain (e.g., `search.example.com`) also pointing to your server's IP. *(The script uses `search.example.com` by default but the variable can be changed)*. ## Usage -1. Clone this repository to your Debian server: +1. Download the script to your Debian server: ```bash curl -fsSL -o onepush.sh https://git.r21.io/primemover/onepush/raw/branch/master/onepush.sh ``` - 2. Make the script executable: ```bash chmod +x onepush.sh ``` - 3. Run the script with `sudo`: ```bash sudo ./onepush.sh ``` -The script will then prompt you for the necessary configuration details before proceeding with the automated installation. - ### The Interactive Prompts The script will ask you a few questions to configure your environment: @@ -67,11 +66,14 @@ The script will ask you a few questions to configure your environment: - Answer `Y` (the default) to have the script automatically add the `allow 'Nginx Full'` rule. - Answer `n` if you want to manage the firewall yourself. **If you choose 'n' and UFW is active, the script will disable UFW entirely** to guarantee the script can complete. +The script will then prompt you for the necessary configuration details before proceeding with the automated installation. + ## Post-Installation Once the script finishes, you will have a fully functional and secure Open WebUI instance. -- **Access Your Instance:** `https://your.domain.com` +- **Access Your Instance:** `https://ai.example.com` +- **Access SearXNG:** `https://search.example.com` (user: `admin`, with the password you set during installation). - **Admin Account:** The first user to register on the site will automatically be granted administrator privileges. - **Automations:** All automated services (system updates, container updates, reboots) are running in the background. No further action is needed. @@ -83,9 +85,43 @@ The most common reason to re-run the script is to get a production SSL certifica ## Security Considerations -- **Fail2Ban:** The jail `[open-webui]` is configured in `/etc/fail2ban/jail.d/open-webui.local`. It monitors the Nginx log file (`/var/log/nginx/your.domain.com.access.log`) for failed sign-in attempts (`POST /api/v1/auths/signin` with a `400` status code). After 5 failures, the offending IP is banned for 24 hours. +- **Fail2Ban:** The jail `[open-webui]` is configured in `/etc/fail2ban/jail.d/open-webui.local`. It monitors the Nginx log file (`/var/log/nginx/ai.example.com.access.log`) for failed sign-in attempts (`POST /api/v1/auths/signin` with a `400` status code). After 5 failures, the offending IP is banned for 24 hours. - **Firewall:** The script binds the Open WebUI Docker container to the localhost interface (`127.0.0.1:3000`), meaning it is not directly exposed to the internet. Only Nginx can access it. If you opt-out of UFW management, you are responsible for ensuring a firewall (either on the host or at the network level) is configured to allow traffic on ports 80 and 443. +### Using Your Private SearXNG Instance + +If you deployed SearXNG, you now have two powerful ways to enable web search for your models. + +#### Option A: Native Web Search (Recommended) + +This is the simplest and most integrated method. + +1. Log in to Open WebUI as an admin. +2. Go to the **Admin Panel** -> **Settings** -> **Web Search**. +3. Enable the **Web Search** toggle. +4. In the **SearXNG URL** field, enter: `http://searxng:8080` + *(This special URL works because the containers can talk to each other directly over their private Docker network).* +5. Click **Save**. + +You can now enable the "Web Search" capability for any model in the "Models" section of your settings. + +#### Option B: Advanced Python Research Tool + +This method provides more granular control and is useful for complex workflows. + +1. Go to **Settings** -> **Tools** and click **Add Tool**. +2. In the **Load from URL** field, paste the following link and click the load button: + ``` + https://raw.githubusercontent.com/iamarcel/open-webui-utils/main/research_tool.py + ``` +3. Click the **Settings** tab in the tool editor (the gear icon). +4. In the **Environment Variables** section, add the following key-value pair: + - **Key:** `SEARXNG_BASE_URL` + - **Value:** `http://searxng:8080` +5. Click **Save**. + +The tool is now installed and can be called in any chat using `@research`. + ## License This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. \ No newline at end of file From a5ab41ef099ad039692e1efb7c9712a78e3ed38c Mon Sep 17 00:00:00 2001 From: first Date: Wed, 23 Jul 2025 21:20:27 +0000 Subject: [PATCH 6/7] search domain prompt --- onepush.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/onepush.sh b/onepush.sh index 2ba841a..9b777b2 100644 --- a/onepush.sh +++ b/onepush.sh @@ -34,8 +34,12 @@ fi echo "" read -p "Deploy a private SearXNG instance for the research tool? [y/N]: " DEPLOY_SEARXNG BRAVE_API_KEY="" +SEARCH_DOMAIN="" if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then - SEARCH_DOMAIN="search.r21.io" + # MODIFIED: Prompt for the SearXNG domain instead of hardcoding it. + read -p "Enter the domain for SearXNG (e.g., search.example.com): " SEARCH_DOMAIN + if [[ -z "$SEARCH_DOMAIN" ]]; then echo "❌ SearXNG domain cannot be empty."; exit 1; fi + 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 @@ -222,7 +226,7 @@ if [[ "${DEPLOY_SEARXNG,,}" == "y" ]]; then 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 " OPTION B: Advanced Python Research 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" From 2a22b2ebb98b6de669a689b815a9cdc207ff52a5 Mon Sep 17 00:00:00 2001 From: first Date: Wed, 23 Jul 2025 21:33:43 +0000 Subject: [PATCH 7/7] remove openssl dependency --- onepush.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/onepush.sh b/onepush.sh index 9b777b2..5e0c598 100644 --- a/onepush.sh +++ b/onepush.sh @@ -57,7 +57,7 @@ SEARXNG_CONFIG_DIR="/srv/searxng" 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" +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 # --- Step 2: Firewall Management --- @@ -104,7 +104,9 @@ EOF sudo chown 1000:1000 "$SEARXNG_CONFIG_DIR/user.yml" # Generate a robust, shell-safe secret key - SECRET_KEY=$(openssl rand -hex 32) + set +o pipefail + SECRET_KEY=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 32) + set -o pipefail # Build the docker run command safely in an array docker_cmd=(