Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "irondrop"
version = "2.6.4"
version = "2.6.5"
edition = "2024"
license = "MIT"
description = "Drop files, not dependencies - a well tested fully featured & battle-ready server in a single Rust binary with support for indexing through 10M files."
Expand All @@ -11,15 +11,18 @@ readme = "README.md"
clap = { version = "4.6", features = ["derive"] }
glob = "0.3.3"
log = "0.4.29"
env_logger = "0.11.9"
env_logger = "0.11.10"
base64 = "0.22.1"
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "logging", "tls12"] }
rustls-pemfile = "2"


[dev-dependencies]
reqwest = { version = "0.13", features = ["blocking", "json"] }
serde_json = "1.0"
tempfile = "3.27"
threadpool = "1.8.1"
rcgen = "0.14"

[profile.release]
opt-level = 'z' # Optimize for size
Expand Down
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ IronDrop focuses on predictable behavior, simplicity, and low overhead. Use it t
- Search (standard and ultra-compact modes for large directories)
- Monitoring dashboard at `/monitor` and a JSON endpoint (`/monitor?json=1`)
- Basic security features: rate limiting, optional Basic Auth, path safety checks
- Native SSL/TLS support via `--ssl-cert` and `--ssl-key` (built-in HTTPS, no reverse proxy required)
- Single binary; templates and assets are embedded
- Pure standard library networking and file I/O (no external HTTP stack or async runtime)
- Ultra-compact search index option for very large directory trees (tested up to ~10M entries)
Expand All @@ -36,7 +37,7 @@ Designed to keep memory usage steady and to stream large files without buffering

## Security

Includes rate limiting, optional Basic Auth, basic input validation, and path traversal protection. See [RFC & OWASP Compliance](./doc/RFC_OWASP_COMPLIANCE.md) and [Security Fixes](./doc/SECURITY_FIXES.md) for details.
Includes native SSL/TLS (HTTPS), rate limiting, optional Basic Auth, basic input validation, and path traversal protection. See [RFC & OWASP Compliance](./doc/RFC_OWASP_COMPLIANCE.md) and [Security Fixes](./doc/SECURITY_FIXES.md) for details.

## 📦 Installation

Expand Down Expand Up @@ -145,6 +146,46 @@ irondrop -d /path/to/media \
irondrop --config-file ./config/production.ini
```

#### 🔒 HTTPS File Server
```bash
# Generate a self-signed certificate (for testing)
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'

# Serve files over HTTPS
irondrop -d ./files --ssl-cert cert.pem --ssl-key key.pem --listen 0.0.0.0

# HTTPS with authentication
irondrop -d ./files --ssl-cert cert.pem --ssl-key key.pem \
--username admin --password secret --listen 0.0.0.0
```

#### 🌐 Reverse Proxy (Nginx)
For production deployments, it is recommended to run IronDrop behind Nginx.

**Root Domain Configuration:**
```nginx
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 0; # Enable large uploads
proxy_buffering off; # Enable streaming
}
```

**Subpath Configuration (e.g., `/webstorage/`):**
```nginx
location /webstorage/ {
proxy_pass http://127.0.0.1:8080/;
proxy_redirect / /webstorage/;
sub_filter 'href="/"' 'href="/webstorage/"';
sub_filter_once off;
# ... see deployment guide for full sub_filter list
}
```

See the [Deployment Guide](./doc/DEPLOYMENT.md#nginx-reverse-proxy-deployment) for full configuration examples and optimization settings.

### 🛠️ Configuration Options

#### **Command Line Options**
Expand All @@ -160,6 +201,8 @@ IronDrop offers extensive customization through command-line arguments:
| `-a, --allowed-extensions` | Restrict file types | `-a "*.pdf,*.doc,*.zip"` |
| `-t, --threads` | Worker threads (default: 8) | `-t 16` |
| `--config-file` | Use INI configuration file | `--config-file prod.ini` |
| `--ssl-cert` | SSL certificate file (PEM) for HTTPS | `--ssl-cert cert.pem` |
| `--ssl-key` | SSL private key file (PEM) for HTTPS | `--ssl-key key.pem` |
| `-v, --verbose` | Debug logging | `-v true` |

#### **📄 Configuration File (Recommended for Production)**
Expand Down Expand Up @@ -197,6 +240,7 @@ Once IronDrop is running, these endpoints are available:

- Use authentication (`--username`/`--password`) when exposing to untrusted networks
- Adjust `--threads` based on workload
- Use `--ssl-cert` and `--ssl-key` for native HTTPS without a reverse proxy

### ❓ Need Help?

Expand Down
30 changes: 30 additions & 0 deletions config/irondrop.ini
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,31 @@ allowed_extensions = *.pdf,*.doc,*.zip,*.txt
username = testuser
password = testpass123

# ===============================================================================
# 🔒 SSL/TLS CONFIGURATION
# ===============================================================================

[ssl]
# 🔐 Native HTTPS Support - Serve files over encrypted connections
# • Requires both cert and key to be specified
# • Supports PEM format certificates and private keys
# • Uses TLS 1.2 and TLS 1.3 (via rustls - pure Rust TLS)
# • No OpenSSL runtime dependency required
#
# 🔧 How to generate a self-signed certificate (for testing):
# openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \
# -days 365 -nodes -subj '/CN=localhost'
#
# 🏢 For production, use certificates from a trusted CA (Let's Encrypt, etc.)
#
# ⚠️ Both cert and key must be provided together. Omit both for plain HTTP.

# SSL Certificate - Path to PEM certificate file
# cert = /etc/irondrop/cert.pem

# SSL Private Key - Path to PEM private key file
# key = /etc/irondrop/key.pem

# ===============================================================================
# 📝 LOGGING CONFIGURATION
# ===============================================================================
Expand Down Expand Up @@ -230,6 +255,10 @@ detailed = true
# port = 443
# directory = /var/company-files
# threads = 16
#
# [ssl]
# cert = /etc/letsencrypt/live/files.example.com/fullchain.pem
# key = /etc/letsencrypt/live/files.example.com/privkey.pem
#
# [upload]
# enable_upload = true
Expand Down Expand Up @@ -273,6 +302,7 @@ detailed = true
# ✅ 5. Enable uploads if needed (set enable_upload = true)
# ✅ 6. Add authentication for network access (set username/password)
# ✅ 7. Configure allowed file extensions for security
# ✅ 7b. (Optional) Add SSL cert and key for HTTPS
# ✅ 8. Run: irondrop --config-file my-config.ini
# ✅ 9. Open browser: http://localhost:8080 (or your chosen port)
# ✅ 10. Enjoy blazing-fast file sharing! 🚀
Expand Down
46 changes: 23 additions & 23 deletions doc/API_REFERENCE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# IronDrop API Reference v2.6.4
# IronDrop API Reference v2.6.5

## Overview

Expand Down Expand Up @@ -31,7 +31,7 @@ User-Agent: <client-identifier>
#### Response Headers
```http
# Standard headers
Server: IronDrop/2.6
Server: IronDrop/2.6.5
Content-Type: <mime-type>
Content-Length: <content-length>
Connection: keep-alive
Expand Down Expand Up @@ -193,9 +193,9 @@ Content-Type: text/html; charset=utf-8
#### `POST /_irondrop/upload`
Uploads files using direct binary streaming for optimal performance and unlimited file size support.

**Direct Upload Features (v2.6.4):**
**Direct Upload Features (v2.6.5):**
- **Direct Binary Streaming**: No multipart parsing overhead
- **Automatic Mode Selection**: Small uploads (≤2MB) processed in memory, large uploads (>2MB) streamed to disk
- **Automatic Mode Selection**: Small uploads (≤64MB) processed in memory, large uploads (>64MB) streamed to disk
- **Constant Memory Usage**: ~7MB RAM usage regardless of file size
- **Unlimited File Sizes**: No artificial size restrictions
- **Atomic Operations**: Complete uploads or clean failure with automatic cleanup
Expand All @@ -211,8 +211,8 @@ X-Filename: document.pdf
```

**Processing Modes:**
- **Memory Mode** (≤2MB): Direct processing in memory for minimal latency
- **Streaming Mode** (>2MB): Direct streaming to disk with constant ~7MB memory usage
- **Memory Mode** (≤64MB): Direct processing in memory for minimal latency
- **Streaming Mode** (>64MB): Direct streaming to disk with constant ~7MB memory usage

**Success Response (JSON):**
```json
Expand Down Expand Up @@ -292,7 +292,7 @@ Content-Type: text/html

### 4. Search API

#### `GET /api/search`
#### `GET /_irondrop/search`
Searches for files and directories within the served directory tree.

**Query Parameters:**
Expand All @@ -304,10 +304,10 @@ Searches for files and directories within the served directory tree.

**Examples:**
```http
GET /api/search?q=document
GET /api/search?q=report&limit=20&offset=10
GET /api/search?q=Config&case_sensitive=true
GET /api/search?q=readme&path=/docs
GET /_irondrop/search?q=document
GET /_irondrop/search?q=report&limit=20&offset=10
GET /_irondrop/search?q=Config&case_sensitive=true
GET /_irondrop/search?q=readme&path=/docs
```

**Success Response:**
Expand Down Expand Up @@ -413,20 +413,20 @@ Static asset not found

### 6. Health and Monitoring

#### `GET /_health`
#### `GET /_irondrop/health`
Basic health check endpoint.

**Response:**
```json
{
"status": "healthy",
"version": "2.6",
"version": "2.6.5",
"uptime_seconds": 3600,
"timestamp": "2024-01-01T12:00:00Z"
}
```

#### `GET /_status`
#### `GET /_irondrop/status`
Detailed server status and statistics.

**Response:**
Expand Down Expand Up @@ -472,7 +472,7 @@ Content-Type: text/html; charset=utf-8
</html>
```

#### `GET /_irondrop/monitor?json=1`
#### `GET /_irondrop/_irondrop/monitor?json=1`
Machine-readable JSON stats for integration with external monitoring / scripting.

**Response (JSON):**
Expand Down Expand Up @@ -539,12 +539,12 @@ API information and capabilities.
},
"health_check": {
"method": "GET",
"path": "/_health",
"path": "/_irondrop/health",
"description": "Basic health check"
},
"status": {
"method": "GET",
"path": "/_status",
"path": "/_irondrop/status",
"description": "Detailed server status"
}
},
Expand Down Expand Up @@ -709,7 +709,7 @@ if (result.status === 'success') {
**Search Files:**
```javascript
// Search for files
const searchResponse = await fetch('/api/search?q=document&limit=10');
const searchResponse = await fetch('/_irondrop/search?q=document&limit=10');
const searchData = await searchResponse.json();

if (searchData.status === 'success') {
Expand All @@ -723,7 +723,7 @@ if (searchData.status === 'success') {
**Health Check:**
```javascript
// Monitor server health
const health = await fetch('/_health').then(r => r.json());
const health = await fetch('/_irondrop/health').then(r => r.json());
console.log(`Server uptime: ${health.uptime_seconds}s`);
```

Expand All @@ -746,12 +746,12 @@ curl "http://localhost:8080/directory" -H "Accept: application/json" | jq .

**Search files:**
```bash
curl "http://localhost:8080/api/search?q=document&limit=5" | jq .
curl "http://localhost:8080/_irondrop/search?q=document&limit=5" | jq .
```

**Health check:**
```bash
curl http://localhost:8080/_health
curl http://localhost:8080/_irondrop/health
```

**With authentication:**
Expand Down Expand Up @@ -794,7 +794,7 @@ if response.status_code == 200:
```python
import requests

response = requests.get('http://localhost:8080/api/search',
response = requests.get('http://localhost:8080/_irondrop/search',
params={'q': 'document', 'limit': 10})
data = response.json()

Expand Down Expand Up @@ -827,4 +827,4 @@ All inputs are validated:
- File names for path traversal attempts
- HTTP headers for malformed content

This API reference covers all functionality available in IronDrop v2.6.4 and provides comprehensive examples for client integration.
This API reference covers all functionality available in IronDrop v2.6.5 and provides comprehensive examples for client integration.
Loading
Loading