- 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.
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:8080on the LXC, published via Docker ports:- "8080:8080" - Public URL:
https://search.levkin.cavia Caddy VM reverse proxy to10.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) andsearxng - 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:8080broke access from the Caddy VM; use8080:8080so it listens on10.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
-
SSH to LXC and navigate to the directory:
cd /opt/searxng-docker -
Edit docker-compose.yaml to:
- Remove the caddy service and related volumes
- Ensure searxng has
ports: - "8080:8080"and the correctSEARXNG_BASE_URL
-
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 -
Start/restart stack:
docker compose up -d docker compose ps # Confirm searxng -> 0.0.0.0:8080->8080 -
Check logs:
docker compose logs -f searxng docker compose logs -f redis -
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
-
Secret Key: Always use a strong, randomly generated secret key in
settings.yml -
Network Isolation: SearXNG only needs to be accessible from the Caddy VM, not the entire network
-
Updates: Regularly update Docker images:
cd /opt/searxng-docker docker compose pull docker compose up -d -
Logging: Consider disabling or limiting logging for privacy:
# In settings.yml general: enable_metrics: false -
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
- Verify port binding:
docker compose psshould show0.0.0.0:8080->8080/tcp - Test from Caddy VM:
curl http://10.0.10.70:8080/ - Check firewall rules on LXC
- Verify network connectivity:
ping 10.0.10.70from Caddy VM
SearXNG Returns Errors
- Check Redis connectivity:
docker compose exec searxng ping redis - Verify settings.yml syntax:
docker compose exec searxng cat /etc/searxng/settings.yml - Check logs for specific errors:
docker compose logs searxng | grep -i error
Performance Issues
- Monitor resource usage:
docker stats - Check Redis performance:
docker compose exec redis valkey-cli info stats - Consider increasing LXC resources if needed
- 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
- Default search engine in browsers via
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.