open-notebook/docs/deployment/security.md
2025-07-17 12:38:40 -03:00

481 lines
No EOL
13 KiB
Markdown

# Security Configuration
Open Notebook includes optional password protection and security features for users who need to deploy their instances publicly or in shared environments.
## 🔒 Password Protection
### When to Use Password Protection
Password protection is recommended for:
- **Public cloud deployments** - PikaPods, Railway, DigitalOcean, AWS, etc.
- **Shared network environments** - Corporate networks, shared servers
- **Team deployments** - Multiple users accessing the same instance
- **Production environments** - Any deployment accessible beyond localhost
### When NOT to Use Password Protection
Skip password protection for:
- **Local development** - Running on your personal machine
- **Private networks** - Secure, isolated network environments
- **Single-user setups** - Only you have access to the machine
- **Testing environments** - Temporary or development instances
## 🚀 Quick Setup
### Docker Deployment
For Docker deployments, add the password to your environment:
```yaml
# docker-compose.yml
services:
open_notebook:
image: lfnovo/open_notebook:latest-single
ports:
- "8502:8502"
environment:
- OPENAI_API_KEY=your_openai_key
- OPEN_NOTEBOOK_PASSWORD=your_secure_password
volumes:
- ./notebook_data:/app/data
restart: always
```
Or using a `.env` file:
```env
# .env file
OPENAI_API_KEY=your_openai_key
OPEN_NOTEBOOK_PASSWORD=your_secure_password
```
### Development Setup
For development installations, add to your `.env` file:
```env
# .env file in project root
OPEN_NOTEBOOK_PASSWORD=your_secure_password
```
## 🔐 Password Requirements
### Choosing a Secure Password
- **Length**: Minimum 12 characters, preferably 20+
- **Complexity**: Mix of uppercase, lowercase, numbers, and symbols
- **Uniqueness**: Don't reuse passwords from other services
- **Avoid**: Common words, personal information, predictable patterns
### Password Examples
```bash
# Good passwords
OPEN_NOTEBOOK_PASSWORD=MySecure2024!Research#Tool
OPEN_NOTEBOOK_PASSWORD=Notebook$Dev$2024$Strong!
# Bad passwords (don't use these)
OPEN_NOTEBOOK_PASSWORD=password123
OPEN_NOTEBOOK_PASSWORD=opennotebook
OPEN_NOTEBOOK_PASSWORD=admin
```
### Password Management
- **Use a password manager** to generate and store the password
- **Document the password** in your team's secure password vault
- **Rotate passwords** regularly for production deployments
- **Share securely** - Never send passwords via email or chat
## 🛡️ How Security Works
### Streamlit UI Protection
When password protection is enabled:
1. **Login form** appears on first visit
2. **Session storage** - Password stored in browser session
3. **Persistent login** - Users stay logged in until browser closure
4. **No logout button** - Clear browser data to log out
### API Protection
All API endpoints require authentication:
```bash
# API calls require Authorization header
curl -H "Authorization: Bearer your_password" \
http://localhost:5055/api/notebooks
```
### Excluded Endpoints
These endpoints work without authentication:
- **Health check**: `/health` - System status
- **API documentation**: `/docs` - OpenAPI documentation
- **OpenAPI spec**: `/openapi.json` - API schema
## 🔧 Configuration Examples
### Single Container with Security
```yaml
# docker-compose.single.yml
services:
open_notebook_single:
image: lfnovo/open_notebook:latest-single
ports:
- "8502:8502"
- "5055:5055"
environment:
- OPENAI_API_KEY=sk-your-openai-key
- OPEN_NOTEBOOK_PASSWORD=your_secure_password
- ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
volumes:
- ./notebook_data:/app/data
- ./surreal_single_data:/mydata
restart: always
```
### Multi-Container with Security
```yaml
# docker-compose.yml
services:
surrealdb:
image: surrealdb/surrealdb:latest
ports:
- "127.0.0.1:8000:8000" # Bind to localhost only
command: start --log warn --user root --pass root file:///mydata/database.db
volumes:
- ./surreal_data:/mydata
restart: always
open_notebook:
image: lfnovo/open_notebook:latest
ports:
- "8502:8502"
- "5055:5055"
environment:
- OPENAI_API_KEY=sk-your-openai-key
- OPEN_NOTEBOOK_PASSWORD=your_secure_password
- SURREAL_URL=ws://surrealdb:8000/rpc
- SURREAL_USER=root
- SURREAL_PASSWORD=root
volumes:
- ./notebook_data:/app/data
depends_on:
- surrealdb
restart: always
```
### Development with Security
```env
# .env file for development
OPEN_NOTEBOOK_PASSWORD=dev_password_2024
# Database
SURREAL_URL=ws://localhost:8000/rpc
SURREAL_USER=root
SURREAL_PASSWORD=root
SURREAL_NAMESPACE=open_notebook
SURREAL_DATABASE=development
# AI Providers
OPENAI_API_KEY=sk-your-openai-key
ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
```
## 🌐 Production Security
### HTTPS/TLS Configuration
**Always use HTTPS** in production. Here's an nginx reverse proxy example:
```nginx
# /etc/nginx/sites-available/open-notebook
server {
listen 80;
server_name your-domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
# Streamlit UI
location / {
proxy_pass http://127.0.0.1:8502;
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;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# API endpoints
location /api/ {
proxy_pass http://127.0.0.1:5055;
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;
}
}
```
### Firewall Configuration
Configure your firewall to restrict access:
```bash
# UFW (Ubuntu)
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 8502/tcp # Block direct access to Streamlit
sudo ufw deny 5055/tcp # Block direct access to API
sudo ufw enable
# iptables
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp --dport 8502 -j DROP
iptables -A INPUT -p tcp --dport 5055 -j DROP
```
### Docker Security
```yaml
# Production docker-compose.yml with security
services:
open_notebook:
image: lfnovo/open_notebook:latest
ports:
- "127.0.0.1:8502:8502" # Bind to localhost only
- "127.0.0.1:5055:5055"
environment:
- OPEN_NOTEBOOK_PASSWORD=your_secure_password
volumes:
- ./notebook_data:/app/data
restart: always
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
- /var/tmp
deploy:
resources:
limits:
memory: 2G
cpus: "1.0"
```
## 🔍 API Authentication
### Making Authenticated API Calls
```bash
# Get all notebooks
curl -H "Authorization: Bearer your_password" \
http://localhost:5055/api/notebooks
# Create a new notebook
curl -X POST \
-H "Authorization: Bearer your_password" \
-H "Content-Type: application/json" \
-d '{"name": "My Notebook", "description": "Research notes"}' \
http://localhost:5055/api/notebooks
# Upload a file
curl -X POST \
-H "Authorization: Bearer your_password" \
-F "file=@document.pdf" \
http://localhost:5055/api/sources/upload
```
### Python API Client
```python
import requests
class OpenNotebookClient:
def __init__(self, base_url: str, password: str):
self.base_url = base_url
self.headers = {"Authorization": f"Bearer {password}"}
def get_notebooks(self):
response = requests.get(
f"{self.base_url}/api/notebooks",
headers=self.headers
)
return response.json()
def create_notebook(self, name: str, description: str = None):
data = {"name": name, "description": description}
response = requests.post(
f"{self.base_url}/api/notebooks",
headers=self.headers,
json=data
)
return response.json()
# Usage
client = OpenNotebookClient("http://localhost:5055", "your_password")
notebooks = client.get_notebooks()
```
## 🚨 Security Considerations
### Important Limitations
Open Notebook's password protection provides **basic access control**, not enterprise-grade security:
- **Plain text transmission** - Passwords sent over HTTP (use HTTPS)
- **No password hashing** - Passwords stored in memory as plain text
- **No user management** - Single password for all users
- **No session timeout** - Sessions persist until browser closure
- **No rate limiting** - No protection against brute force attacks
- **No audit logging** - No security event logging
### Risk Mitigation
1. **Use HTTPS** - Always encrypt traffic with TLS
2. **Strong passwords** - Use complex, unique passwords
3. **Network security** - Implement proper firewall rules
4. **Regular updates** - Keep containers and dependencies updated
5. **Monitoring** - Monitor access logs and system resources
6. **Backup strategy** - Regular backups of data and configurations
### Enterprise Considerations
For enterprise deployments requiring advanced security:
- **SSO integration** - Consider implementing OAuth2/SAML
- **Role-based access** - Implement user roles and permissions
- **Audit logging** - Track all user actions and API calls
- **Rate limiting** - Implement API rate limiting
- **Database encryption** - Encrypt data at rest
- **Network segmentation** - Isolate services in secure networks
## 🔧 Troubleshooting
### Common Security Issues
#### Password Not Working
```bash
# Check environment variable is set
docker compose exec open_notebook env | grep OPEN_NOTEBOOK_PASSWORD
# Check container logs
docker compose logs open_notebook | grep -i auth
# Test API directly
curl -H "Authorization: Bearer your_password" \
http://localhost:5055/health
```
#### UI Shows Login Form but API Doesn't
```bash
# Environment variable might not be set for API
docker compose exec open_notebook env | grep OPEN_NOTEBOOK_PASSWORD
# Restart services
docker compose restart
# Check both services are using the same password
docker compose logs | grep -i password
```
#### 401 Unauthorized Errors
```bash
# Check authorization header format
curl -v -H "Authorization: Bearer your_password" \
http://localhost:5055/api/notebooks
# Verify password matches environment variable
echo $OPEN_NOTEBOOK_PASSWORD
# Check for special characters in password
echo "Password contains: $(echo $OPEN_NOTEBOOK_PASSWORD | wc -c) characters"
```
#### Cannot Access After Setting Password
```bash
# Clear browser cache and cookies
# Try incognito/private mode
# Check browser console for errors
# Verify password is correct
```
### Security Testing
```bash
# Test without password (should fail)
curl http://localhost:5055/api/notebooks
# Test with correct password (should succeed)
curl -H "Authorization: Bearer your_password" \
http://localhost:5055/api/notebooks
# Test health endpoint (should work without password)
curl http://localhost:5055/health
# Test documentation (should work without password)
curl http://localhost:5055/docs
```
## 📞 Getting Help
### Security Issues
If you discover security vulnerabilities:
1. **Do not open public issues** for security problems
2. **Contact the maintainer** directly via email
3. **Provide detailed information** about the vulnerability
4. **Allow time for fixes** before public disclosure
### Community Support
For security configuration help:
- **[Discord Server](https://discord.gg/37XJPXfz2w)** - Real-time help
- **[GitHub Issues](https://github.com/lfnovo/open-notebook/issues)** - Configuration problems
- **[Documentation](../index.md)** - Additional guides
### Best Practices
1. **Test security** thoroughly before production deployment
2. **Monitor logs** regularly for suspicious activity
3. **Keep updated** with security patches and updates
4. **Follow principle of least privilege** in network configuration
5. **Regular security reviews** of your deployment
---
**Ready to secure your deployment?** Start with the Quick Setup section above and always use HTTPS in production!