Documentation Index
Fetch the complete documentation index at: https://mintlify.com/questdb/questdb/llms.txt
Use this file to discover all available pages before exploring further.
Overview
QuestDB provides multiple security layers:
- HTTP Basic Authentication: Simple username/password authentication
- TLS/SSL Encryption: Encrypted connections for all protocols
- Access Control Lists (ACL): Fine-grained permissions (Enterprise)
- Read-Only Mode: Prevent data modification
- Network Binding: Restrict listening interfaces
Authentication
HTTP Basic Authentication
Protect the HTTP API and Web Console:
# server.conf
# Enable authentication
http.user=admin
http.password=quest
Access with authentication:
# Web Console
curl -u admin:quest http://localhost:9000/
# REST API
curl -u admin:quest -G http://localhost:9000/exec \
--data-urlencode "query=SELECT * FROM trades"
Disable authentication:
Comment out or remove the http.user and http.password lines.
PostgreSQL Authentication
Authenticate PostgreSQL wire protocol connections:
# server.conf
# Admin user (full access)
pg.user=admin
pg.password=quest
# Read-only user
pg.readonly.user.enabled=true
pg.readonly.user=viewer
pg.readonly.password=readonly_pass
Connect with authentication:
# psql
psql -h localhost -p 8812 -U admin -d qdb
# Connection string
postgresql://admin:quest@localhost:8812/qdb
Read-only user behavior:
- All
SELECT queries allowed
INSERT, UPDATE, DELETE, CREATE, ALTER, DROP rejected
ILP TCP Authentication
Authenticate InfluxDB Line Protocol connections:
# server.conf
# Authentication database file
line.tcp.auth.db.path=conf/auth.txt
auth.txt format:
# Format: username challenge_public_key user_private_key
alice Bpz3... uy2B...
bob xY7x... 3kKl...
Generate key pairs:
# Using QuestDB utility (if available)
java -cp questdb.jar io.questdb.cutlass.auth.AuthUtils \
generate-key-pair
# Output:
# Private key: uy2B...
# Public key: Bpz3...
Client authentication:
from questdb.ingress import Sender
with Sender('localhost', 9009, auth=(
'alice', # Username
'Bpz3...', # Challenge public key
'uy2B...' # Private key
)) as sender:
sender.row('trades', symbols={'symbol': 'BTC'}, columns={'price': 50000})
sender.flush()
Authorization (Enterprise)
Access Control Lists (ACL)
Fine-grained permissions for users and groups:
# server.conf
# Enable ACL
acl.enabled=true
# Admin user (full permissions)
acl.admin.user.enabled=true
acl.admin.user=admin
acl.admin.password=admin_pass
User Management
Create users (Enterprise SQL):
-- Create user
CREATE USER alice WITH PASSWORD 'alice_pass';
-- Grant permissions
GRANT SELECT ON trades TO alice;
GRANT INSERT ON trades TO alice;
-- Revoke permissions
REVOKE INSERT ON trades FROM alice;
-- Drop user
DROP USER alice;
Role-Based Access Control
-- Create role
CREATE ROLE analysts;
-- Grant permissions to role
GRANT SELECT ON trades TO analysts;
GRANT SELECT ON quotes TO analysts;
-- Assign role to users
GRANT ROLE analysts TO alice;
GRANT ROLE analysts TO bob;
-- Revoke role
REVOKE ROLE analysts FROM alice;
Permission Types
- SELECT: Read data from tables
- INSERT: Insert data into tables
- UPDATE: Update existing data (via ALTER TABLE)
- DELETE: Drop partitions
- CREATE: Create tables and schemas
- ALTER: Modify table structure
- DROP: Drop tables
- ALL: All permissions
Table-Level Permissions
-- Grant specific permissions
GRANT SELECT, INSERT ON trades TO alice;
-- Grant all permissions on table
GRANT ALL ON quotes TO alice;
-- Grant permissions on all tables
GRANT SELECT ON ALL TABLES TO alice;
Column-Level Permissions (Enterprise)
-- Grant access to specific columns
GRANT SELECT (timestamp, symbol, price) ON trades TO alice;
-- Deny access to sensitive columns
REVOKE SELECT (customer_id, email) ON trades FROM alice;
TLS/SSL Encryption
Generate Certificates
Self-signed certificate (development):
# Generate private key
openssl genrsa -out questdb-key.pem 2048
# Generate certificate signing request
openssl req -new -key questdb-key.pem -out questdb-csr.pem \
-subj "/CN=localhost"
# Generate self-signed certificate
openssl x509 -req -in questdb-csr.pem \
-signkey questdb-key.pem \
-out questdb-cert.pem -days 365
Certificate authority (production):
# Use Let's Encrypt
sudo certbot certonly --standalone -d questdb.example.com
# Certificates at:
# /etc/letsencrypt/live/questdb.example.com/fullchain.pem
# /etc/letsencrypt/live/questdb.example.com/privkey.pem
Global TLS Configuration
# server.conf
# Enable TLS for all protocols
tls.enabled=true
tls.cert.path=/path/to/questdb-cert.pem
tls.private.key.path=/path/to/questdb-key.pem
Protocol-Specific TLS
HTTP/HTTPS:
http.tls.enabled=true
http.tls.cert.path=/path/to/http-cert.pem
http.tls.private.key.path=/path/to/http-key.pem
Access via HTTPS:
curl -u admin:quest https://localhost:9000/
PostgreSQL TLS:
pg.tls.enabled=true
pg.tls.cert.path=/path/to/pg-cert.pem
pg.tls.private.key.path=/path/to/pg-key.pem
Connect with TLS:
psql "postgresql://admin:quest@localhost:8812/qdb?sslmode=require"
ILP TCP TLS:
line.tcp.tls.enabled=true
line.tcp.tls.cert.path=/path/to/ilp-cert.pem
line.tcp.tls.private.key.path=/path/to/ilp-key.pem
HTTP MIN TLS (separate health check endpoint):
http.min.tls.enabled=true
http.min.tls.cert.path=/path/to/min-cert.pem
http.min.tls.private.key.path=/path/to/min-key.pem
Read-Only Mode
Prevent all write operations:
# server.conf
# Global read-only mode
http.security.readonly=true
pg.security.readonly=true
Rejected operations:
INSERT
CREATE TABLE
ALTER TABLE
DROP TABLE
COPY
- ILP ingestion
Allowed operations:
SELECT
EXPLAIN
- System queries
Network Security
Bind to Specific Interfaces
Restrict which network interfaces QuestDB listens on:
# server.conf
# Bind HTTP to localhost only
http.net.bind.to=127.0.0.1:9000
# Bind PostgreSQL to private network
pg.net.bind.to=10.0.1.10:8812
# Bind ILP to all interfaces
line.tcp.net.bind.to=0.0.0.0:9009
Firewall Configuration
iptables (Linux):
# Allow HTTP from specific subnet
sudo iptables -A INPUT -p tcp --dport 9000 -s 10.0.0.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 9000 -j DROP
# Allow PostgreSQL from anywhere
sudo iptables -A INPUT -p tcp --dport 8812 -j ACCEPT
# Save rules
sudo iptables-save > /etc/iptables/rules.v4
ufw (Ubuntu):
# Allow HTTP from specific IP
sudo ufw allow from 10.0.0.100 to any port 9000
# Allow PostgreSQL
sudo ufw allow 8812/tcp
# Enable firewall
sudo ufw enable
Connection Limits
Prevent resource exhaustion:
# server.conf
# HTTP connection limits
http.net.connection.limit=256
http.ilp.connection.limit=100
http.json.query.connection.limit=150
http.export.connection.limit=25
# PostgreSQL connection limit
pg.net.connection.limit=64
# ILP TCP connection limit
line.tcp.net.connection.limit=256
Connection Timeouts
# HTTP idle timeout
http.net.connection.timeout=5m
http.net.connection.queue.timeout=5s
# PostgreSQL idle timeout
pg.net.connection.timeout=5m
pg.net.connection.queue.timeout=5m
# ILP TCP timeout (0 = no timeout)
line.tcp.net.connection.timeout=0
line.tcp.net.connection.queue.timeout=5s
Data Security
Encryption at Rest
QuestDB does not provide built-in encryption at rest. Use OS-level encryption:
LUKS (Linux):
# Create encrypted volume
sudo cryptsetup luksFormat /dev/sdb
sudo cryptsetup open /dev/sdb questdb_encrypted
# Create filesystem
sudo mkfs.ext4 /dev/mapper/questdb_encrypted
# Mount
sudo mount /dev/mapper/questdb_encrypted /var/lib/questdb
dm-crypt (Linux):
# Encrypt partition
sudo cryptsetup -y -v luksFormat /dev/sdb1
sudo cryptsetup open /dev/sdb1 questdb_data
sudo mkfs.ext4 /dev/mapper/questdb_data
Cloud provider encryption:
- AWS EBS: Enable encryption on volume
- Azure Disk: Enable encryption at rest
- GCP Persistent Disk: Automatic encryption
Sensitive Data Handling
Avoid storing secrets in server.conf:
Use environment variables:
export QDB_PG_PASSWORD="$(cat /run/secrets/pg_password)"
export QDB_HTTP_PASSWORD="$(cat /run/secrets/http_password)"
Reference in server.conf:
pg.password=${QDB_PG_PASSWORD}
http.password=${QDB_HTTP_PASSWORD}
Use secret files (Enterprise):
# Reference file containing password
http.password.file=/run/secrets/http_password
pg.password.file=/run/secrets/pg_password
Audit Logging (Enterprise)
# Enable audit logging
audit.enabled=true
audit.log.path=log/audit.log
Audit log captures:
- User authentication attempts
- Query execution (SELECT, INSERT, etc.)
- Schema changes (CREATE, ALTER, DROP)
- Permission changes (GRANT, REVOKE)
Security Best Practices
Production Checklist
Password Policy
Strong passwords:
- Minimum 20 characters
- Mix of uppercase, lowercase, numbers, symbols
- No dictionary words
- Unique per user/service
Rotation:
- Change passwords every 90 days
- Immediately after suspected compromise
- When employee leaves
Principle of Least Privilege
- Default deny: Start with no permissions
- Grant minimum: Only permissions needed
- Use read-only: For analytics and reporting
- Separate roles: Different users for different tasks
- Review regularly: Audit permissions quarterly
Network Segmentation
Recommended architecture:
Internet
|
[Load Balancer] -- TLS termination
|
[Application Tier] -- 10.0.1.0/24
|
[QuestDB] -- 10.0.2.0/24 (private subnet)
|
[Backup Storage] -- 10.0.3.0/24 (isolated subnet)
- Expose only HTTP/HTTPS publicly
- Keep PostgreSQL and ILP on private network
- Isolate backup storage
Incident Response
Suspected Breach
- Isolate: Disconnect from network
- Investigate: Review audit logs
- Contain: Revoke compromised credentials
- Remediate: Patch vulnerabilities
- Restore: From clean backup if needed
- Document: Record timeline and actions
Password Reset
# Stop QuestDB
systemctl stop questdb
# Edit server.conf
nano /var/lib/questdb/conf/server.conf
# Update passwords
http.password=new_secure_password
pg.password=new_secure_password
# Start QuestDB
systemctl start questdb
Revoke Access
-- Disable user (Enterprise)
ALTER USER alice DISABLE;
-- Drop user
DROP USER alice;
-- Revoke all permissions
REVOKE ALL ON ALL TABLES FROM alice;
Compliance
GDPR
- Right to erasure: Use
ALTER TABLE DROP PARTITION or filter exports
- Data minimization: Only store necessary data
- Access controls: Use ACL for fine-grained permissions
- Encryption: Enable TLS and encryption at rest
- Audit logging: Track data access
SOC 2
- Access control: Implement ACL and authentication
- Encryption: TLS in transit, disk encryption at rest
- Monitoring: Enable metrics and alerting
- Backup: Regular automated backups
- Audit: Comprehensive audit logging
HIPAA
- Encryption: Required for PHI
- Access controls: Strict user permissions
- Audit logging: Track all PHI access
- Backup and recovery: Tested disaster recovery plan
- Data retention: Implement TTL for old data
Security Updates
Stay informed:
- Subscribe to QuestDB security mailing list
- Monitor GitHub releases
- Review CVE databases
Update process:
- Test updates in staging environment
- Schedule maintenance window
- Backup database
- Apply update
- Verify functionality
- Monitor for issues
Emergency patches:
- Apply immediately for critical vulnerabilities
- Follow hotfix procedures
- Document changes