Security hardening guide for RAGFlow deployments including authentication, network security, code execution sandbox, and data protection.
RAGFlow handles sensitive documents, API keys, and potentially confidential business data. Proper security configuration is essential for production deployments.
By default, RAGFlow requires authentication for:
# Edit service configuration
nano docker/service_conf.yaml.template
# Set admin credentials
admin:
username: admin
password: your-secure-password
# In service_conf.yaml.template
api:
keys:
- name: production-key
key: sk-your-api-key-here
permissions:
- read
- write
RAGFlow supports Python/JavaScript code execution in workflows. Without proper isolation, this could compromise the host system.
Install gVisor:
# Ubuntu/Debian
curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor -o /usr/share/keyrings/gvisor.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/gvisor.gpg] https://storage.googleapis.com/gvisor/releases stable main" | sudo tee /etc/apt/sources.list.d/gvisor.list
sudo apt-get update && sudo apt-get install runsc
Configure Docker:
# Edit Docker daemon config
sudo nano /etc/docker/daemon.json
# Add gVisor runtime
{
"runtimes": {
"runsc": {
"path": "/usr/bin/runsc"
}
}
}
# Restart Docker
sudo systemctl restart docker
Use gVisor in Docker Compose:
services:
ragflow:
runtime: runsc
# ... other config
# In service_conf.yaml.template
code_executor:
enabled: true
sandbox: gvisor
allowed_packages:
- numpy
- pandas
- requests
blocked_packages:
- os
- subprocess
- socket
timeout: 30 # seconds
max_memory: 512 # MB
0.0.0.0:80 inside containerOption 1: Bind to Specific Interface
# docker-compose.yml
services:
ragflow:
ports:
- "127.0.0.1:80:80" # Localhost only
Option 2: Use Reverse Proxy
# docker-compose.yml
services:
ragflow:
expose:
- "80" # Internal only
# No ports mapping
# Allow only necessary ports
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw deny 3306/tcp # Block MySQL from external
sudo ufw deny 6379/tcp # Block Redis from external
sudo ufw enable
server {
listen 443 ssl http2;
server_name ragflow.example.com;
ssl_certificate /etc/ssl/certs/ragflow.crt;
ssl_certificate_key /etc/ssl/private/ragflow.key;
# Strong SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000" always;
location / {
proxy_pass http://localhost:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Rate limiting
limit_req zone=onepersecond burst=10 nodelay;
}
}
# Rate limiting zone
http {
limit_req_zone $binary_remote_addr zone=onepersecond:10m rate=1r/s;
}
ragflow.example.com {
reverse_proxy localhost:80
tls your-email@example.com
}
# Change root password
docker compose exec mysql mysql -u root -p -e "ALTER USER 'root'@'%' IDENTIFIED BY 'new-secure-password';"
# Remove anonymous users
docker compose exec mysql mysql -u root -p -e "DELETE FROM mysql.user WHERE User='';"
# Remove test database
docker compose exec mysql mysql -u root -p -e "DROP DATABASE IF EXISTS test;"
# Restrict remote access
docker compose exec mysql mysql -u root -p -e "UPDATE mysql.user SET Host='localhost' WHERE User='root';"
# Set Redis password
docker compose exec redis redis-cli CONFIG SET requirepass "your-secure-password"
# Disable dangerous commands
docker compose exec redis redis-cli CONFIG SET rename-command FLUSHALL ""
docker compose exec redis redis-cli CONFIG SET rename-command FLUSHDB ""
docker compose exec redis redis-cli CONFIG SET rename-command CONFIG ""
# Edit .env file
nano .env
# Set secure credentials
MINIO_USER=ragflow-admin
MINIO_PASSWORD=your-very-secure-password-32chars
# docker-compose.yml
services:
minio:
environment:
MINIO_ROOT_USER: ragflow-admin
MINIO_ROOT_PASSWORD: your-secure-password
command: server /data --console-address ":9001"
volumes:
- minio_data:/data
# Create private bucket
docker compose exec minio mc mb mybucket
# Set private access
docker compose exec minio mc policy set private mybucket
# In service_conf.yaml.template
knowledge_base:
access_control:
enabled: true
default_permission: private
roles:
- name: admin
permissions:
- read
- write
- delete
- share
- name: user
permissions:
- read
- write
storage:
encryption:
enabled: true
algorithm: aes-256-gcm
key_rotation: true
# In service_conf.yaml.template
audit:
enabled: true
log_level: info
outputs:
- file
- stdout
retention_days: 90
events:
- login
- logout
- api_call
- document_upload
- document_delete
- config_change
# View audit logs
docker compose logs ragflow | grep "AUDIT"
# Find failed logins
docker compose logs ragflow | grep "login_failed"
# Find API calls
docker compose logs ragflow | grep "api_call"
#!/bin/bash
# backup-ragflow.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/ragflow_$DATE"
mkdir -p $BACKUP_DIR
# Backup MySQL
docker compose exec -T mysql mysqldump -u root -pYOUR_PASSWORD ragflow > $BACKUP_DIR/mysql.sql
# Backup MinIO
docker compose exec -T minio mc cp -r mybucket $BACKUP_DIR/minio
# Backup configuration
cp docker/.env $BACKUP_DIR/
cp docker/service_conf.yaml.template $BACKUP_DIR/
# Compress
tar czf $BACKUP_DIR.tar.gz $BACKUP_DIR
rm -rf $BACKUP_DIR
# Upload to remote storage (optional)
# rsync -av $BACKUP_DIR.tar.gz backup-server:/backups/
# In service_conf.yaml.template
data_retention:
enabled: true
max_age_days: 365
auto_delete: true
exclude_important: true
Any questions?
Feel free to contact us. Find all contact information on our contact page.