hlquery.conf - Main Server Configuration
The main configuration file (hlquery.conf) controls server behavior, networking, logging, and performance settings. This is the primary configuration file that hlquery loads on startup.
File Location
run/conf/hlquery.conf (dev layout)
/etc/hlquery/hlquery.conf (system/debian/rpm layouts)
Configuration Format
hlquery uses a custom XML-like configuration format for readability:
<log method="file" type="*" level="debug" target="/path/to/logfile.log">
<server name="hlquery.local" id="001">
<bind address="0.0.0.0" port="9200" type="http">
Logging Configuration
Configure logging for different components and levels. Multiple log entries can be defined for different purposes.
Log Entry Syntax
<log method="file" type="*" level="debug" target="/path/to/logfile.log"
rotate_size="128MB" rotate_interval="daily"
max_rotated_files="14" max_age_days="14">
Parameters
-
method: Output method
file: Write to fileconsole: Write to console (stdout/stderr)syslog: Write to syslog
-
type: Log type filter
*: All log typesstartup: Server startup and shutdown eventsdatabase: Database operations and RocksDB storagesearch: Search operations and queriesnetwork: Network and connection eventsauth: Authentication eventsquery: User search queries (for analytics)
-
level: Log verbosity level
debug: Detailed debugging information (most verbose)normal: Normal operational messages (recommended for production)verbose: Verbose loggingcritical: Critical errors only (least verbose)
-
target: Output target
- For
method="file": Path to log file - For
method="console": Ignored (uses stdout/stderr) - For
method="syslog": Ignored (uses system syslog)
- For
-
rotate_size: Rotate the file when it reaches this size
- Supports
KB,MB,GB,TB - Example:
"128MB" 0or omitted disables size-based rotation
- Supports
-
rotate_interval: Rotate on a time boundary
- Accepts seconds,
daily, orweekly - Example:
"86400"or"daily" - Omit to disable time-based rotation
- Accepts seconds,
-
max_rotated_files: Maximum number of rotated files to keep
- Example:
"14" - Omit to use the default retention count
- Example:
-
max_age_days: Delete rotated files older than this many days
- Example:
"7" - Omit or set to
0to disable age-based retention
- Example:
Example Logging Configurations
Basic Setup - Single Log File:
# Global server log capturing all events
<log method="file" type="*" level="normal" target="/var/log/hlquery/hlquery.log"
rotate_size="128MB" rotate_interval="daily" max_rotated_files="14" max_age_days="14">
Advanced Setup - Separate Log Files:
# Global server log
<log method="file" type="*" level="debug" target="/var/log/hlquery/hlquery.log">
# Startup and shutdown events
<log method="file" type="startup" level="normal" target="/var/log/hlquery/startup.log">
# Database operations
<log method="file" type="database" level="normal" target="/var/log/hlquery/database.log"
rotate_size="128MB" rotate_interval="daily" max_rotated_files="7" max_age_days="7">
# Search operations
<log method="file" type="search" level="normal" target="/var/log/hlquery/search.log">
# Query log for analytics (only user queries, not debug logs)
<log method="file" type="query" level="normal" target="/var/log/hlquery/queries.log"
rotate_size="64MB" rotate_interval="daily" max_rotated_files="3" max_age_days="3">
# Network events
<log method="file" type="network" level="normal" target="/var/log/hlquery/network.log">
# Authentication events
<log method="file" type="auth" level="normal" target="/var/log/hlquery/auth.log">
Development Setup - Console Logging:
# Development: log to console for immediate feedback
<log method="console" type="*" level="debug">
Production Setup - Syslog Integration:
# Production: integrate with system logging
<log method="syslog" type="*" level="normal">
Module Configuration
Use the <module> tag when you want to load optional runtime modules such as the ratelimit module.
Rate Limit Module
The ratelimit module wraps write- and admin-facing APIs with per-IP buckets so you can tone down traffic bursts while letting operators connect from trusted hosts.
<module name="ratelimit">
<ratelimit enabled="true" limit_per_minute="180" window_seconds="60" log="true">
<!-- Controls the default write-rate bucket (document/create/update/delete). -->
<ratelimit_rule name="default-write" limit_per_minute="120" window_seconds="60" operations="AddDocument,UpdateDocument,DeleteDocument,BulkImportDocuments" />
<!-- A stricter admin bucket for key/user/maintenance commands. -->
<ratelimit_rule name="admin" limit_per_minute="10" window_seconds="60" operations="CreateUser,DeleteUser,CreateKey,DeleteKey,Flush,Repair" />
<!-- Target only the "reports" collection for occasional bulk writes. -->
<ratelimit_rule name="reports-bulk" limit_per_minute="30" window_seconds="120" operations="BulkImportDocuments" collections="reports" />
<!-- Skip enforcement when requests originate from localhost. -->
<ratelimit_exception description="Local test harness" ips="localhost" />
</ratelimit>
</module>
You can define multiple <ratelimit_rule> entries to cover different scopes (collections, operations, IP ranges) and pair them with <ratelimit_exception> entries for trusted hosts such as 127.0.0.1/::1. Use the CLI helpers (hlquery-cli module ratelimit status|rules|exceptions) to verify the runtime buckets and exception lists while the server is running.
AI Query Module
The ai_query module wraps the natural-language query helpers that live in run/modules/m_ai_query. It now exposes multiple CLI and HTTP routes:
module ai_query ask <text>: smart route that infers intent and returns an answer with supporting evidencemodule ai_query collections <text>: ranks the collections most related to the promptmodule ai_query search <text>: searches documents and auto-picks the most likely collection when one is not suppliedmodule ai_query status: shows runtime availability, routes, and loaded collectionsmodule ai_query parse <text>: compatibility alias forask
This means prompts like module ai_query ask which collection talks about science? now resolve into ranked collection candidates instead of only doing a raw single-collection search. The module refuses to start unless a models directory exists (default run/models) and a configured model descriptor points to a present file.
<module name="ai_query">
<llm models_dir="run/models" auto_find="yes">
</module>
auto_find="yes" selects the first .gguf file in models_dir after sorting filenames. Use model_file to pin a specific GGUF file or model_name to resolve a built-in local model catalog preset. The shipped presets match tools/download: qwen_0_5, qwen_1_5, qwen_3, qwen_14, and qwen_coder_1_5. If you need to refresh the models bundle, place the files anywhere under run/models (the run/models/ directory is ignored by git), or use tools/download. The module now loads heuristics directly from run/modules/m_ai_query and no longer needs etc/ai/query.js.
Server Identity
Define the server's identity within the hlquery network.
Syntax
<server name="hlquery.local" id="001">
Parameters
-
name: Server name (FQDN)
- Used for identification in logs and monitoring
- Example:
"hlquery.local","search.example.com"
-
id: Unique numeric identifier
-
Used for server identification
-
Example:
"001","002" -
When
true: Only read and search operations allowed -
All write operations (create, update, delete) return 403 Forbidden
-
Useful for demo environments where data modification should be prevented
-
Example
<server name="hlquery.production.example.com" id="001">
Analytics
Configure optional outbound usage analytics. This tag is disabled by default and is intended for SaaS operators that want periodic usage summaries without adding latency to query handling.
Syntax
<analytics
active="false"
endpoint="http://127.0.0.1:8089/v1/analytics/hlquery"
flush_interval="300"
connect_timeout_ms="5000"
track_reads="true"
track_writes="true">
Parameters
-
active: Enable or disable outbound analytics
false: Analytics are fully disabledtrue: Analytics worker starts and sends startup and usage batches
-
endpoint: Remote HTTP endpoint that receives analytics payloads
- Example:
"http://127.0.0.1:8089/v1/analytics/hlquery" - Leave empty when analytics are disabled
- Example:
-
flush_interval: Flush interval in seconds
300means300 seconds, which is5 minutes- Controls how often in-memory usage counters are exported
-
connect_timeout_ms: Timeout for the outbound analytics HTTP request
- Value is in milliseconds
- Example:
"5000"means a 5 second timeout
-
track_reads: Track read-side activity
- Includes search, get, list, and similar read operations
trueenables read usage reporting
-
track_writes: Track write-side activity
- Includes insert, update, and delete operations
trueenables write usage reporting
Behavior
- Analytics are best-effort and non-blocking on the request path.
- When enabled, hlquery sends one startup payload shortly after boot.
- Regular usage data is aggregated in memory and flushed on the configured interval.
- On shutdown, hlquery attempts one final flush.
- If the analytics worker is contended, events may be dropped instead of blocking queries.
Example
<server name="hlquery.production.example.com" id="001">
<analytics
active="true"
endpoint="http://127.0.0.1:8089/v1/analytics/hlquery"
flush_interval="300"
connect_timeout_ms="5000"
track_reads="true"
track_writes="true">
Network Bindings
Configure network ports for client connections. Multiple bind entries can be defined for different interfaces or protocols.
HTTP Binding
<bind address="0.0.0.0" port="9200" type="http">
Parameters
-
address: IP address to bind to
0.0.0.0: Bind to all network interfaces (default)127.0.0.1: Bind to localhost only (more secure)- Specific IP:
192.168.1.100(bind to specific interface)
-
port: Port number
- Default:
9200 - Must be available and not in use by another process
- Default:
-
type: Connection type
http: Standard HTTP (unencrypted)https: HTTPS with SSL/TLS encryption
HTTPS Binding
Enable SSL/TLS for secure connections:
<bind address="0.0.0.0" port="9443" type="https"
ssl_cert="/path/to/server.crt"
ssl_key="/path/to/server.key"
ssl_protocols="TLSv1.2 TLSv1.3"
ssl_ciphers="HIGH:!aNULL:!MD5">
HTTPS Parameters
-
ssl_cert: Path to SSL certificate file (
.crtor.pem)- Required for HTTPS
- Example:
"/etc/ssl/certs/hlquery.crt"
-
ssl_key: Path to SSL private key file (
.key)- Required for HTTPS
- Must match the certificate
- Example:
"/etc/ssl/private/hlquery.key"
-
ssl_protocols: Allowed SSL/TLS protocols (optional)
- Default:
"TLSv1.2 TLSv1.3" - Example:
"TLSv1.3"(TLS 1.3 only)
- Default:
-
ssl_ciphers: Allowed cipher suites (optional)
- Default:
"HIGH:!aNULL:!MD5" - Example:
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256"
- Default:
Generate SSL Certificates
Use the provided script to generate self-signed certificates:
./scripts/create_ssl.sh
Certificates will be created in run/ssl/ directory:
server.crt: Certificate fileserver.key: Private key file
Multiple Bindings Example
# HTTP on all interfaces
<bind address="0.0.0.0" port="9200" type="http">
# HTTPS on all interfaces
<bind address="0.0.0.0" port="9443" type="https"
ssl_cert="/etc/ssl/certs/hlquery.crt"
ssl_key="/etc/ssl/private/hlquery.key">
# HTTP on localhost only (for local admin)
<bind address="127.0.0.1" port="9201" type="http">
Performance Settings
Configure thread and performance limits to control resource usage.
Syntax
<performance max_threads="10">
Parameters
- max_threads: Global maximum number of threads
- Default:
8 - Range:
1-256 - Larger values help saturate multi-core CPUs, but make sure your data is fully indexed and your database is on low-latency NVMe/SSD storage with a healthy RocksDB block cache before increasing this number.
- Default:
- search_pool_threads: Threads dedicated to executing search requests (0 = auto)
- Default:
0(auto distribution) - If there is spare CPU headroom, raise this (30+) so searches can run in parallel without waiting on the HTTP or write pools.
- Default:
- http_pool_threads: Threads handling HTTP requests and API work (0 = auto)
- Default:
0 - Keep this proportionally smaller than the search pool when the workload is query-heavy.
- Default:
- write_pool_threads: Threads that serve ingestion and write operations (0 = auto)
- Default:
0 - Reduce this when there is little ingestion traffic so search and HTTP pools can grab more threads.
- Default:
- management_pool_threads: Threads for background admin tasks (0 = auto)
- Default:
0 - Can remain small (4-6 threads) since management tasks are infrequent.
- Default:
Example
# High-throughput configuration for idle CPUs and NVMe storage
<performance
max_threads="64"
queue_size="32768"
max_candidates="1500"
snippet_step="20"
max_connections="2000"
search_pool_threads="36"
http_pool_threads="12"
write_pool_threads="6"
management_pool_threads="6">
Once you have confirmed that the collection is fully indexed and RocksDB is tuned (larger block cache, tuned compaction), set search_pool_threads high to keep the search pool saturated whenever queries arrive in bursts.
IP Allow Filtering
Configure IP address filtering to restrict access to the server. Supports IP addresses, CIDR subnets, hostnames (with DNS resolution), and wildcard hostnames.
Syntax
<allow allowed="*">
Parameters
- allowed: Comma-separated list of allowed IP addresses, CIDR ranges, and/or hostnames
- Use
"*"to allow all IPs - Use specific IPs:
"192.168.1.1,10.0.0.5" - Use CIDR subnets:
"192.168.1.0/24"(allows entire subnet) - Use hostnames:
"api.example.com"(DNS resolved at startup) - Use wildcard hostnames:
"*.example.com"(reverse DNS on connection) - Mix all types:
"192.168.1.1,192.168.1.0/24,api.example.com,*.internal.com"
- Use
DNS Resolution Strategy
The system intelligently uses DNS only when needed:
- IP-Only Configs: No DNS resolution (zero overhead)
- Hostnames in Config: Resolved at startup, cached
- Wildcard Hostnames: Reverse DNS on connection (cached)
- Client Hostnames: Resolved on connection (cached)
DNS Caching
- Forward DNS Cache: Hostname → IPs (up to 1024 entries)
- Reverse DNS Cache: IP → Hostname (up to 1024 entries)
- Automatic Flush: Cache flushed every 1 hour via TimerManager
- Cache Eviction: FIFO (oldest first when full)
Examples
# Allow all IPs (no DNS)
<allow allowed="*">
# Only localhost
<allow allowed="127.0.0.1">
# Specific IPs (no DNS)
<allow allowed="192.168.1.1,10.0.0.5">
# CIDR subnet (no DNS)
<allow allowed="192.168.1.0/24">
# Hostname (DNS at startup)
<allow allowed="api.example.com">
# Wildcard hostname (reverse DNS on connect)
<allow allowed="*.example.com">
# Mix everything
<allow allowed="192.168.1.0/24,*.internal.com,api.example.com,10.0.0.5">
Default Behavior
IMPORTANT: If <allow> tag is not provided or allowed is empty, ALL connections are DENIED (secure by default).
You must explicitly configure allowed IPs or use allowed="*" to allow all.
How DNS Resolution Works
-
Startup Resolution:
- Regular hostnames (e.g.,
api.example.com) are resolved at server startup - All resolved IPs are added to the allowed list
- Results are cached for performance
- Regular hostnames (e.g.,
-
Connection-Time Resolution:
- If client connects using a hostname, it's resolved using the cache
- Wildcard patterns (e.g.,
*.example.com) trigger reverse DNS lookup - Reverse DNS results are cached
-
Cache Management:
- Both forward and reverse DNS caches are limited to 1024 entries
- Cache is automatically flushed every 1 hour
- Oldest entries are evicted when cache is full (FIFO)
Performance
- IP-Only Configs: Zero DNS overhead
- Hostname Resolution: <5ms (cached after first)
- Reverse DNS: <10ms (cached after first)
- Connection Check: <0.1ms total
- Cache Hit Rate: >95% for repeated lookups
Logging and DNS Resolution
The system provides intelligent logging that automatically includes hostname information when DNS resolution is enabled:
DNS-Enabled Logging (when hostnames are configured):
- Log entries show both IP and hostname:
192.168.1.100 (api.example.com) - Reverse DNS lookup performed on connection (cached)
- Enhanced security visibility and troubleshooting
DNS-Disabled Logging (IP-only or wildcard "*" configs):
- Log entries show only IP addresses:
192.168.1.100 - No DNS overhead, optimal performance
- Suitable for static IP environments
Example Log Output:
# With DNS enabled (hostnames configured)
[ip_allow] IP allow filter initialized with 3 IP(s), 1 hostname(s) (DNS resolution enabled)
[httpserver] Connection blocked from IP: 192.168.1.200 (unauthorized.example.com) (IP not allowed)
[httpserver] Accepted HTTP connection from 192.168.1.100:54321 (api.example.com)
# Without DNS (IP-only configuration)
[ip_allow] IP allow filter initialized with 2 IP(s) (no DNS resolution needed)
[httpserver] Connection blocked from IP: 192.168.1.200 (IP not allowed)
[httpserver] Accepted HTTP connection from 192.168.1.100:54321
Important: DNS resolution is only enabled when hostnames are configured in the allowed parameter. For IP-only configurations or wildcard "*", DNS is completely disabled, and logs show only IP addresses.
Security
- Default Deny: No config = deny all (secure by default)
- HTTP 403 Response: Blocked connections receive proper HTTP error
- Thread-Safe: All operations are mutex-protected
- DNS Logging: Hostname information in logs when DNS is enabled (hostnames configured)
For detailed IP filtering documentation, see IP Filtering.
Configuration Layout
hlquery.conf is now the primary runtime configuration and contains merged sections for:
- authentication/users
- distributed links
- search settings
- storage/performance settings
Optional split files can still be used in some deployments, but they are legacy compared to the merged layout.
Query Settings
Use <query_settings> in hlquery.conf to control query parsing and lexical resources:
<query_settings
enable_synonyms="true"
enable_stopwords="true"
lexical_scope_preference="merge">
lexical_scope_preference="merge"combines global and collection synonyms/stopwords.lexical_scope_preference="local"lets collection synonyms override matching global synonym terms; collection stopwords replace global stopwords when present.lexical_scope_preference="global"lets global synonyms override matching collection synonym terms; global stopwords replace collection stopwords when present.
For synonyms, precedence is applied per normalized term. For example, if both global and local sets define phone, local uses the collection definition for phone, while unrelated global synonym terms still apply.
For stopwords, precedence is applied to the whole stopword scope because stopwords are simple term sets. With local, a collection stopword list replaces the global list for that collection; with global, the global list replaces the collection list.
Auth/User Section Example
<auth enabled="true">
<user name="admin" token="replace-with-strong-token" flags="admin">
<user name="service_api" token="replace-with-strong-token" flags="user">
<user name="dashboard" password="replace-with-strong-password" flags="user">
Complete Configuration Example
Here's a complete example configuration file:
# hlquery - Main Server Configuration
# https://www.hlquery.com
# LOGGING CONFIGURATION
# Global server log
<log method="file" type="*" level="normal" target="/var/log/hlquery/hlquery.log">
# Startup events
<log method="file" type="startup" level="normal" target="/var/log/hlquery/startup.log">
# Database operations
<log method="file" type="database" level="normal" target="/var/log/hlquery/database.log">
# Query log for analytics
<log method="file" type="query" level="normal" target="/var/log/hlquery/queries.log">
# SERVER IDENTITY
<server name="hlquery.production.example.com" id="001">
# NETWORK BINDINGS
# HTTP on all interfaces
<bind address="0.0.0.0" port="9200" type="http">
# HTTPS (optional, uncomment to enable)
# <bind address="0.0.0.0" port="9443" type="https"
# ssl_cert="/etc/ssl/certs/hlquery.crt"
# ssl_key="/etc/ssl/private/hlquery.key">
# PERFORMANCE SETTINGS
<performance max_threads="8">
# AUTH / USERS (merged in hlquery.conf)
<auth enabled="true">
<user name="admin" token="replace-with-strong-token" flags="admin">
<user name="dashboard" password="replace-with-strong-password" flags="user">
Production Configuration Recommendations
Security
-
Enable Authentication:
<auth enabled="true"> -
Use HTTPS:
<bind address="0.0.0.0" port="9443" type="https"ssl_cert="/etc/ssl/certs/hlquery.crt"ssl_key="/etc/ssl/private/hlquery.key"ssl_protocols="TLSv1.3"ssl_ciphers="HIGH:!aNULL:!MD5"> -
Restrict Network Access with IP Filtering:
<!-- Allow only specific IPs/subnets --><allow allowed="192.168.1.0/24,10.0.0.5"><!-- Or bind to specific interface --><bind address="192.168.1.100" port="9200" type="http"> -
Use Appropriate Log Levels:
<!-- Production: normal level --><log method="file" type="*" level="normal" target="/var/log/hlquery/hlquery.log">
Performance
-
Optimize Thread Count:
<!-- Match to CPU cores, but keep low --><performance max_threads="8"> -
Separate Log Files:
<!-- Separate logs for easier monitoring --><log method="file" type="database" level="normal" target="/var/log/hlquery/database.log"><log method="file" type="search" level="normal" target="/var/log/hlquery/search.log"> -
Enable Query Logging for Analytics:
<log method="file" type="query" level="normal" target="/var/log/hlquery/queries.log">
Hot Reload
hlquery supports hot-reloading configuration changes:
- Edit the configuration file
- Save the file
- The server automatically detects changes
- Configuration is reloaded without restarting the server
Note: Some changes require a server restart:
- Port number changes
- SSL certificate changes
- Network binding changes
Environment Variables
Some settings can be overridden with environment variables:
HLQUERY_DATA_DIR: Data directory pathHLQUERY_LOG_DIR: Log directory pathHLQUERY_PORT: HTTP port number (overrides config file)HLQUERY_CONFIG_DIR: Configuration directory path
Configuration Validation
hlquery validates the configuration file on startup. Invalid configurations will cause the server to fail to start with an error message indicating the problem.
Common validation errors:
- Invalid XML syntax
- Missing required parameters
- Invalid parameter values
- File permission issues
Troubleshooting
Configuration Not Loading
-
Check file permissions: Ensure the configuration file is readable
ls -l /etc/hlquery/hlquery.confchmod 644 /etc/hlquery/hlquery.conf -
Validate syntax: Check for XML syntax errors
# Look for unclosed tags, missing quotes, etc. -
Check logs: Review startup logs for configuration errors
tail -f run/logs/startup.log
Port Already in Use
-
Change port in configuration:
<bind address="0.0.0.0" port="9201" type="http"> -
Or stop the process using the port:
lsof -i :9200kill <PID>
SSL Certificate Issues
-
Verify certificate paths are correct
-
Check certificate permissions:
chmod 644 /path/to/server.crtchmod 600 /path/to/server.key -
Ensure certificates are valid and not expired:
openssl x509 -in server.crt -text -noout
Log Files Not Created
-
Check directory exists and is writable:
mkdir -p /var/log/hlquerychmod 755 /var/log/hlquery -
Check disk space:
df -h /var/log
Related Documentation
- Search Configuration - Search algorithm settings
- Database Configuration - RocksDB storage engine settings
- Users Configuration - Authentication settings
- Installation Guide - Server setup
- API Reference - API documentation