homelab-notes/proxmox1/searxng-lxc-notes.md
ilia d8e98b1aa2
All checks were successful
CI / skip-ci-check (pull_request) Successful in 1m27s
CI / markdown-lint (pull_request) Successful in 1m29s
CI / yaml-validate (pull_request) Successful in 1m30s
Refactor README and SearXNG notes for improved formatting and clarity
- Updated README.md to enhance the prompt structure for generating service documentation.
- Reformatted code blocks in searxng-lxc-notes.md for better readability and consistency.
2026-01-07 12:23:21 -05:00

10 KiB

SearXNG LXC Notes

Self-hosted SearXNG instance running in a Debian LXC, fronted by external Caddy VM, using Docker for SearXNG + Valkey/Redis.


Design

  • SearXNG runs in a Debian LXC (10.0.10.70) with Docker; only SearXNG and Valkey live in this container.
  • Caddy runs on a separate VM and is the single external reverse proxy for the homelab, including search.levkin.ca.
  • The SearXNG Docker setup uses "bring your own reverse proxy" mode from the official searxng-docker repo, so internal Caddy in the stack is removed.

Network and URLs

  • LXC IP: 10.0.10.70 (Proxmox container)
  • SearXNG container: Listens on 0.0.0.0:8080 on the LXC, published via Docker ports: - "8080:8080"
  • Public URL: https://search.levkin.ca via Caddy VM reverse proxy to 10.0.10.70:8080

Initial Setup

1. Create and Configure LXC Container

In Proxmox:

# Create Debian LXC container
# - Template: debian-12-standard
# - Storage: local-lvm
# - Network: Bridge vmbr0, IP 10.0.10.70/24
# - Resources: 2GB RAM, 1 CPU core minimum

2. Install Docker in LXC

SSH into the LXC container:

# Update system
apt update && apt upgrade -y

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

# Add current user to docker group (if needed)
usermod -aG docker $USER

# Verify installation
docker --version
docker compose version

3. Clone SearXNG Docker Repository

# Create directory
mkdir -p /opt/searxng-docker
cd /opt/searxng-docker

# Clone the official repository
git clone https://github.com/searxng/searxng-docker.git .

# Or download and extract if git is not available

Docker Compose Configuration

Location: /opt/searxng-docker/docker-compose.yaml inside the LXC.

Key Points

  • Only two services: redis (Valkey) and searxng
  • Internal Caddy service and volumes from the upstream searxng-docker example are removed
  • SearXNG base URL is set via env so generated links use the public domain

Complete docker-compose.yaml

services:
  redis:
    container_name: redis
    image: docker.io/valkey/valkey:8-alpine
    command: valkey-server --save 30 1 --loglevel warning
    restart: unless-stopped
    networks:
      - searxng
    volumes:
      - valkey-data2:/data
    healthcheck:
      test: ["CMD", "valkey-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3

  searxng:
    container_name: searxng
    image: docker.io/searxng/searxng:latest
    restart: unless-stopped
    networks:
      - searxng
    ports:
      - "8080:8080"   # Must NOT be bound to 127.0.0.1, Caddy VM needs LAN access
    volumes:
      - ./searxng:/etc/searxng:rw
      - searxng-data:/var/cache/searxng:rw
    environment:
      - SEARXNG_BASE_URL=https://search.levkin.ca/
    depends_on:
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/"]
      interval: 30s
      timeout: 10s
      retries: 3

networks:
  searxng:
    driver: bridge

volumes:
  valkey-data2:
  searxng-data:

Important Notes

  • Port binding: Binding to 127.0.0.1:8080:8080 broke access from the Caddy VM; use 8080:8080 so it listens on 10.0.10.70
  • Volumes: Match the official documentation: config under /etc/searxng, cache under /var/cache/searxng
  • Health checks: Added to ensure services are ready before accepting traffic

SearXNG Configuration

Settings File

Location: /opt/searxng-docker/searxng/settings.yml

Key configuration options:

server:
  secret_key: "CHANGE_ME_TO_SOMETHING_RANDOM"  # Generate with: openssl rand -hex 32
  base_url: "https://search.levkin.ca/"
  bind_address: "0.0.0.0"
  port: 8080

search:
  formats:
    - html
    - json
    - csv
    - rss

engines:
  # Enable/disable specific engines as needed
  - name: google
  - name: bing
  - name: duckduckgo
  - name: wikipedia
  # Add more engines as desired

general:
  instance_name: "SearXNG"
  enable_metrics: false  # Set to true if you want metrics endpoint

ui:
  theme: simple  # Options: simple, oscar, courgette
  infinite_scroll: true
  results_on_new_tab: false

outgoing:
  max_request_timeout: 3.0
  pool_connections: 100
  useragent_suffix: "SearXNG"

redis:
  url: "redis://redis:6379/0"

Generate Secret Key

openssl rand -hex 32

Update the secret_key in settings.yml with the generated value.


Deployment Steps

  1. SSH to LXC and navigate to the directory:

    cd /opt/searxng-docker
    
  2. Edit docker-compose.yaml to:

    • Remove the caddy service and related volumes
    • Ensure searxng has ports: - "8080:8080" and the correct SEARXNG_BASE_URL
  3. Configure settings.yml (if customizing):

    # Copy default settings if not present
    cp searxng/settings.yml.example searxng/settings.yml
    
    # Edit settings.yml
    nano searxng/settings.yml
    
  4. Start/restart stack:

    docker compose up -d
    docker compose ps  # Confirm searxng -> 0.0.0.0:8080->8080
    
  5. Check logs:

    docker compose logs -f searxng
    docker compose logs -f redis
    
  6. Quick local test from another host on LAN:

    curl -v http://10.0.10.70:8080/ | head
    

Expected: HTML for SearXNG front page, status 200 from server granian.


Caddy VM Configuration

Caddy runs on a separate VM and handles HTTPS + public DNS.

Site Block

search.levkin.ca {
    encode gzip
    reverse_proxy 10.0.10.70:8080 {
        header_up Host {host}
        header_up X-Real-IP {remote}
        header_up X-Forwarded-For {remote}
        header_up X-Forwarded-Proto {scheme}
    }
}

Notes

  • Caddy handles TLS certificates and HTTPS for search.levkin.ca
  • Upstream is plain HTTP on LAN; change IP/port here if the LXC moves
  • This follows the "bring your own reverse proxy" approach recommended by the SearXNG Docker docs
  • Headers are forwarded to preserve client information

Firewall Configuration

LXC Container

Ensure port 8080 is accessible from the Caddy VM:

# If using ufw
ufw allow from 10.0.10.0/24 to any port 8080

# Or if using iptables directly
iptables -A INPUT -s 10.0.10.0/24 -p tcp --dport 8080 -j ACCEPT

Proxmox Host

Ensure the Proxmox firewall allows traffic between VMs/LXCs on the same network.


Security Considerations

  1. Secret Key: Always use a strong, randomly generated secret key in settings.yml

  2. Network Isolation: SearXNG only needs to be accessible from the Caddy VM, not the entire network

  3. Updates: Regularly update Docker images:

    cd /opt/searxng-docker
    docker compose pull
    docker compose up -d
    
  4. Logging: Consider disabling or limiting logging for privacy:

    # In settings.yml
    general:
      enable_metrics: false
    
  5. Rate Limiting: Configure rate limiting in Caddy if needed to prevent abuse


Backup and Restore

Backup

# Backup configuration
tar -czf searxng-backup-$(date +%Y%m%d).tar.gz \
  /opt/searxng-docker/searxng \
  /opt/searxng-docker/docker-compose.yaml

# Backup volumes (optional, for cache)
docker run --rm -v searxng-docker_searxng-data:/data -v $(pwd):/backup \
  alpine tar czf /backup/searxng-data-$(date +%Y%m%d).tar.gz /data

Restore

# Extract configuration
tar -xzf searxng-backup-YYYYMMDD.tar.gz -C /

# Restore volumes (if needed)
docker run --rm -v searxng-docker_searxng-data:/data -v $(pwd):/backup \
  alpine tar xzf /backup/searxng-data-YYYYMMDD.tar.gz -C /

Monitoring and Maintenance

Check Container Status

docker compose ps
docker compose logs --tail=50 searxng

View Resource Usage

docker stats searxng redis

Update Containers

cd /opt/searxng-docker
docker compose pull
docker compose up -d
docker compose image prune -f  # Remove old images

Clear Cache

docker compose exec searxng rm -rf /var/cache/searxng/*
docker compose restart searxng

Troubleshooting

Container Won't Start

# Check logs
docker compose logs searxng

# Verify configuration
docker compose config

# Test connectivity
docker compose exec searxng ping -c 3 redis

Can't Access from Caddy VM

  1. Verify port binding: docker compose ps should show 0.0.0.0:8080->8080/tcp
  2. Test from Caddy VM: curl http://10.0.10.70:8080/
  3. Check firewall rules on LXC
  4. Verify network connectivity: ping 10.0.10.70 from Caddy VM

SearXNG Returns Errors

  1. Check Redis connectivity: docker compose exec searxng ping redis
  2. Verify settings.yml syntax: docker compose exec searxng cat /etc/searxng/settings.yml
  3. Check logs for specific errors: docker compose logs searxng | grep -i error

Performance Issues

  1. Monitor resource usage: docker stats
  2. Check Redis performance: docker compose exec redis valkey-cli info stats
  3. Consider increasing LXC resources if needed
  4. Review search engine timeouts in settings.yml

Privacy and Usage Notes

  • SearXNG is a metasearch engine: It queries multiple search providers and aggregates results, instead of you talking to each provider directly
  • Self-hosting means:
    • No profiling or tracking by the instance; logs can be disabled or tightly controlled
    • You no longer have to trust a random public SearXNG operator with your search queries
  • Intended use in this homelab:
    • Default search engine in browsers via https://search.levkin.ca
    • Potential backend for LLM tools or scripts that need web search via SearXNG's APIs

API Usage

SearXNG provides a JSON API for programmatic access:

# Example search query
curl "https://search.levkin.ca/search?q=example&format=json" | jq

# RSS feed
curl "https://search.levkin.ca/search?q=example&format=rss"

Useful for automation, LLM integrations, or custom search tools.


Resource Limits

Recommended LXC container resources:

  • CPU: 1-2 cores
  • RAM: 2-4 GB
  • Disk: 10-20 GB (for cache and logs)
  • Network: Standard bridge connection

Adjust based on usage patterns and concurrent users.