RustFS S3 Storage (NOT IN USE)
Note: RustFS was evaluated as a lower-memory alternative to MinIO in December 2025. However, presigned URLs generated via AWS SDK v3 failed signature validation (HTTP 403) when accessed through Cloudflare Tunnel, despite correct configuration. MinIO is the current recommended solution. See MinIO Storage.
RustFS provides S3-compatible object storage for the Signal bot’s file sharing functionality. It was intended to replace MinIO with a more memory-efficient Rust-based implementation.
Overview
Section titled “Overview”| Component | Value |
|---|---|
| Service | RustFS (S3-compatible, Rust-based) |
| Public URL | https://s3.irregular.chat |
| Console URL | https://s3-console.irregular.chat (if enabled) |
| Bucket | irregularchat |
| Link Expiration | 24 hours |
Why RustFS over MinIO?
Section titled “Why RustFS over MinIO?”| Metric | MinIO | RustFS |
|---|---|---|
| Memory (idle) | ~16 GiB | ~74 MiB |
| Memory % | 13% | 0.06% |
| Language | Go | Rust |
| License | AGPL v3 | Apache 2.0 |
Key Finding: RustFS uses ~220x less memory than MinIO in idle state.
Note: RustFS is currently alpha software. Monitor stability and have rollback plan ready.
How It Works
Section titled “How It Works”- User searches for files with
!files <query> - Bot returns search results from local file index
- User replies with a file number to get download link
- Bot generates a RustFS presigned URL:
- Constructs S3 path from category + filename
- Signs URL with AWS4-HMAC-SHA256 algorithm
- Sets 24-hour expiration
- Uses public URL for signature so it matches external access
- User receives direct download link
Architecture
Section titled “Architecture”┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐│ Signal User │─────▶│ Signal Bot │─────▶│ RustFS Server ││ !files drone │ │ minio-client.ts │ │ irregularchat │└─────────────────┘ └──────────────────┘ │ bucket │ │ │ └─────────────────┘ │ │ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ Presigned URL │ │ │ │ https://s3... │◀─────────────┘ │ │ ?X-Amz-... │ │ └──────────────────┘ │ │ ◀─────────────────────────┘ Download link (24 hour expiry)Docker Configuration
Section titled “Docker Configuration”Signal Bot compose.yml
Section titled “Signal Bot compose.yml”The signal-bot container connects to RustFS via the minio-network:
services: signal-bot: networks: - signal-bot-network - minio-network # For RustFS access (network name kept for compatibility)
networks: minio-network: external: trueRustFS docker-compose.yml
Section titled “RustFS docker-compose.yml”Located at /home/minio-irregularchat/docker-compose.yml:
version: '3.8'
services: rustfs: image: rustfs/rustfs:latest container_name: rustfs-production restart: unless-stopped ports: - "0.0.0.0:9002:9000" # S3 API port - "0.0.0.0:9003:9001" # Console port environment: RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY:-rustfs-test-admin} RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY} RUSTFS_CONSOLE_ENABLE: "true" RUSTFS_ADDRESS: ":9000" RUSTFS_CONSOLE_ADDRESS: ":9001" # CRITICAL: Required for presigned URLs to work via reverse proxy RUSTFS_EXTERNAL_ADDRESS: https://s3.irregular.chat RUSTFS_CORS_ALLOWED_ORIGINS: "*" RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS: "*" volumes: - /datadrive/rustfs-data:/data:rw - /datadrive/rustfs-logs:/logs:rw # REQUIRED: RustFS needs /logs writable healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 10s retries: 3 networks: - minio-network
networks: minio-network: name: minio-networkKey Differences from MinIO
Section titled “Key Differences from MinIO”| Feature | MinIO | RustFS |
|---|---|---|
| Credentials | MINIO_ROOT_USER_FILE (supports _FILE suffix) | RUSTFS_ACCESS_KEY (no _FILE suffix) |
| User ID | root | uid 10001 (rustfs user) |
| Logs Volume | Not required | Required - /logs must be writable |
| Console | Built-in | Enabled via RUSTFS_CONSOLE_ENABLE |
| File Serving | Serves mounted files directly | Only serves files uploaded via S3 API |
Environment Variables
Section titled “Environment Variables”Add these to the signal-bot .env file:
# RustFS S3 Configuration (uses MINIO_ prefix for code compatibility)MINIO_ENDPOINT=http://rustfs-production:9000MINIO_ACCESS_KEY=<your-access-key>MINIO_SECRET_KEY=<your-secret-key>MINIO_BUCKET=irregularchatMINIO_REGION=us-east-1MINIO_PUBLIC_URL=https://s3.irregular.chat| Variable | Description |
|---|---|
MINIO_ENDPOINT | Internal Docker network endpoint (used by bot) |
MINIO_ACCESS_KEY | S3-compatible access key |
MINIO_SECRET_KEY | S3-compatible secret key |
MINIO_BUCKET | Bucket containing files |
MINIO_REGION | AWS region (required for S3 signing) |
MINIO_PUBLIC_URL | Public URL for presigned links |
Note: Environment variables use MINIO_ prefix for code compatibility with existing minio-client.ts.
URL Shortening (Shlink)
Section titled “URL Shortening (Shlink)”RustFS presigned URLs can be very long (~300+ characters) which can cause issues in Signal messages:
- URLs get truncated by “Read More” in long messages
- URLs may get cut off when copying
- Long URLs are hard to share manually
The bot optionally integrates with Shlink (self-hosted URL shortener) to create short, memorable URLs:
| Component | Value |
|---|---|
| Long URL | https://s3.irregular.chat/irregularchat/...?X-Amz-... (~300 chars) |
| Short URL | https://irregular.chat/abc12 (~27 chars) |
| Expiration | Same as RustFS presigned URL (24 hours) |
Shlink Configuration
Section titled “Shlink Configuration”Add these to the signal-bot .env file:
# Shlink URL Shortener (optional)SHLINK_API_URL=http://shlink-api:8080SHLINK_API_KEY=<your-shlink-api-key>SHLINK_PUBLIC_URL=https://irregular.chatFile Path Mapping
Section titled “File Path Mapping”The bot maps local file paths to RustFS S3 keys:
| Local Path | S3 Key |
|---|---|
/app/irregularchat/UnmannedSystems/Documents/drone.pdf | UnmannedSystems/Documents/drone.pdf |
/app/irregularchat/Research/Reports/analysis.pdf | Research/Reports/analysis.pdf |
The minio-client.ts utility strips the base path and constructs the S3 key.
Data Synchronization
Section titled “Data Synchronization”Important: RustFS only serves files uploaded via S3 API. Unlike MinIO which can serve mounted files, RustFS requires files to be uploaded.
Initial Data Migration
Section titled “Initial Data Migration”Files are uploaded using mc mirror:
# Set up aliasRUSTFS_KEY=$(cat /home/minio-irregularchat/secrets/rustfs_access_key.txt)RUSTFS_SECRET=$(cat /home/minio-irregularchat/secrets/rustfs_secret_key.txt)mc alias set rustfs http://127.0.0.1:9002 "$RUSTFS_KEY" "$RUSTFS_SECRET"
# Mirror files (initial upload)mc mirror /datadrive/IrregularChat/ rustfs/irregularchat/Ongoing Synchronization
Section titled “Ongoing Synchronization”The Signal bot uploads files directly to RustFS when users use !save command. No separate sync cron is needed since:
- New files uploaded via bot go directly to RustFS
- rclone bisync with pCloud handles backup
Cloudflare Tunnel
Section titled “Cloudflare Tunnel”RustFS is exposed via Cloudflare Tunnel (not direct port exposure):
- API:
s3.irregular.chat→localhost:9002 - Console:
s3-console.irregular.chat→localhost:9003
This provides:
- SSL/TLS termination
- DDoS protection
- No exposed ports
Fallback Behavior
Section titled “Fallback Behavior”If RustFS is not configured (missing env vars), the bot falls back to pCloud:
// In file-search.tsif (isMinioConfigured()) { // Use RustFS presigned URL return await getFileLink(s3Key);} else { // Fallback to pCloud return await getPCloudLink(filePath);}Troubleshooting
Section titled “Troubleshooting”Check RustFS Configuration
Section titled “Check RustFS Configuration”docker compose exec signal-bot node -e "const { isMinioConfigured, getMinioConfig } = require('./dist/utils/minio-client.js');console.log('Configured:', isMinioConfigured());console.log('Config:', JSON.stringify(getMinioConfig(), null, 2));"Test Presigned URL Generation
Section titled “Test Presigned URL Generation”docker compose exec signal-bot node -e "const { getFileLink } = require('./dist/utils/minio-client.js');getFileLink('UnmannedSystems/Documents/test.pdf').then(console.log);"Check RustFS Health
Section titled “Check RustFS Health”curl -f http://localhost:9002/minio/health/liveView RustFS Logs
Section titled “View RustFS Logs”docker logs rustfs-production --tail 50Presigned URLs Return 403 Forbidden
Section titled “Presigned URLs Return 403 Forbidden”If presigned URLs work internally but fail via Cloudflare Tunnel:
-
Check RUSTFS_EXTERNAL_ADDRESS is set:
Terminal window docker exec rustfs-production env | grep EXTERNAL# Should show: RUSTFS_EXTERNAL_ADDRESS=https://s3.irregular.chat -
Generate presigned URLs using PUBLIC endpoint:
Terminal window # Use public URL in mc alias for presigned URL generationmc alias set rustfs-pub https://s3.irregular.chat "$RUSTFS_KEY" "$RUSTFS_SECRET"mc share download --expire=1h "rustfs-pub/irregularchat/path/to/file.pdf" -
Why this matters: Presigned URL signatures include the host header. If the URL is signed with
127.0.0.1:9002but accessed vias3.irregular.chat, the signature won’t match. -
Restart RustFS after config change:
Terminal window cd /home/minio-irregularchatdocker compose down --remove-orphansdocker compose up -d rustfs
Check File Upload Status
Section titled “Check File Upload Status”# Set up mc aliasmc alias set rustfs http://127.0.0.1:9002 "$RUSTFS_KEY" "$RUSTFS_SECRET"
# Check bucket sizemc du rustfs/irregularchat/
# List filesmc ls rustfs/irregularchat/ --recursive | head -20Maintenance
Section titled “Maintenance”Restart RustFS
Section titled “Restart RustFS”cd /home/minio-irregularchatdocker compose restart rustfsUpdate RustFS
Section titled “Update RustFS”cd /home/minio-irregularchatdocker compose pull rustfsdocker compose up -d rustfsVerify Restart Policy
Section titled “Verify Restart Policy”RustFS and Signal Bot have restart: unless-stopped, ensuring automatic restart after server reboot.
Credentials
Section titled “Credentials”Credentials are stored in /home/minio-irregularchat/secrets/:
# Access Keycat /home/minio-irregularchat/secrets/rustfs_access_key.txt
# Secret Keycat /home/minio-irregularchat/secrets/rustfs_secret_key.txtRelated Documentation
Section titled “Related Documentation”- File Management - Complete file search documentation
- All Commands - Bot command reference
- Self-Hosting Guide - Deployment instructions