• Dec. 4, 2025, 3:24 p.m.

    Introduction

    SearXNG is a free internet metasearch engine which aggregates results from more than 70 search services. Users are neither tracked nor profiled.

    This guide documents the specific method I used to install SearXNG on a YunoHost server using Docker. The challenge with YunoHost is that it already uses Nginx on ports 80/443. Therefore, standard Docker guides often fail or cause conflicts because they try to install "Caddy" (another web server) on the same ports.

    This method runs SearXNG locally on a specific port and uses the YunoHost "Redirect" app to proxy traffic safely.

    Prerequisites

    • A VPS running YunoHost.
    • Docker and Docker Compose installed (often standard on VPS images or installable via YunoHost).
    • SSH access to the server.
    • A subdomain configured in YunoHost (e.g., search.yourdomain.com).

    Step 1: Directory Structure & Docker Compose

    First, we create a clean workspace. We will place our files in /opt/searxng.

    mkdir -p /opt/searxng
    cd /opt/searxng
    

    Create the docker-compose.yml file:

    nano docker-compose.yml
    

    Paste the following configuration. Note that we have removed Caddy and bound the port to localhost (127.0.0.1) only. This is a security measure so the raw container isn't exposed to the public internet directly.

    version: '3.7'
    
    services:
      redis:
        container_name: redis
        image: redis:alpine
        command: redis-server --save "" --appendonly "no"
        networks:
          - searxng
        tmpfs:
          - /var/lib/redis
        cap_drop:
          - ALL
        cap_add:
          - SETGID
          - SETUID
          - DAC_OVERRIDE
    
      searxng:
        container_name: searxng
        image: searxng/searxng:latest
        networks:
          - searxng
        ports:
          - "127.0.0.1:8080:8080" # Binds locally. YunoHost will proxy here.
        volumes:
          - ./searxng:/etc/searxng:rw
        environment:
          - SEARXNG_BASE_URL=https://search.yourdomain.com/ # CHANGE THIS
        cap_drop:
          - ALL
        cap_add:
          - CHOWN
          - SETGID
          - SETUID
        logging:
          driver: "json-file"
          options:
            max-size: "1m"
            max-file: "1"
    
    networks:
      searxng:
    

    Step 2: Configuration & The "Nested Folder"

    This part is crucial and where many people make mistakes. We need to create a nested folder for the settings.

    Why a nested folder?

    In docker-compose.yml, we have the line:
    volumes: - ./searxng:/etc/searxng:rw

    This maps the folder ./searxng (on the host) to /etc/searxng (inside the container). If we put the settings.yml file directly in /opt/searxng, the container will see an empty directory and fail to start.

    Commands to setup config:

    # Create the nested directory
    mkdir searxng
    
    # Download the default configuration file into that folder
    curl -L https://raw.githubusercontent.com/searxng/searxng/master/searx/settings.yml > searxng/settings.yml
    

    Security: Generating the Secret Key

    SearXNG will not start without a unique secret key. Run this command to auto-generate one and inject it into your file:

    sed -i "s|ultrasecretkey|$(openssl rand -hex 32)|g" searxng/settings.yml
    

    Step 3: Enabling Safe Search (Optional)

    If you want "Safe Search" (filtering explicit content) enabled by default for all users, you need to edit the settings file manually.

    1. Open the file:
      bash nano searxng/settings.yml
    2. Find the search: section.
    3. Change safe_search to 2 (Strict) or 1 (Moderate).

    <!-- end list -->

    search:
      safe_search: 2
      autocomplete: ""
      default_lang: ""
    

    Step 4: Launching the Service

    Now we start the containers.

    docker compose up -d
    

    Check if it is running:

    docker ps
    

    You should see searxng running and listening on 127.0.0.1:8080.

    Note: Restarting the server later will not cause search errors. Redis is configured to not save data to disk (--save ""), so the cache is cleared on restart, but the configuration remains safe.


    Step 5: Exposing via YunoHost

    We do not use Nginx configurations manually. We use the YunoHost admin panel.

    1. Log in to the YunoHost web admin.
    2. Go to Applications > Install.
    3. Search for the Redirect app.
    4. Configure it as follows:
      • Domain: search.yourdomain.com
      • URL Path: /
      • Redirect Type: Proxy (Crucial setting!)
      • Destination URL: http://127.0.0.1:8080
    5. Click Install.

    Conclusion

    You now have a private, privacy-respecting search engine. YunoHost handles the SSL certificates (Let's Encrypt) and the firewall, while Docker handles the application logic.

    Key Takeaways learnt:

    • Always bind Docker ports to 127.0.0.1 when using a reverse proxy like Nginx/YunoHost to prevent bypassing the firewall.
    • Pay close attention to Docker volumes mappings—the folder structure on the host must match what the container expects.
    • Redis cache is temporary; it is okay to clear it on reboot.
  • edit

    Thread title has been changed from Self-Hosting SearXNG on YunoHost (via Docker).