278 lines
6.2 KiB
Markdown
278 lines
6.2 KiB
Markdown
# MinIO Security Guide
|
|
|
|
## Console Access Security
|
|
|
|
### Production Console Access Options
|
|
|
|
#### ✅ Option 1: SSH Tunnel (Most Secure - RECOMMENDED)
|
|
|
|
**Don't expose console to internet at all.** Access via SSH tunnel:
|
|
|
|
```bash
|
|
# From your local machine
|
|
ssh -L 9001:localhost:9001 user@your-server
|
|
|
|
# Then access: http://localhost:9001
|
|
```
|
|
|
|
**Pros:**
|
|
- No public exposure
|
|
- No additional authentication needed
|
|
- Protected by SSH security
|
|
|
|
**Cons:**
|
|
- Requires SSH access
|
|
- Not convenient for multiple team members
|
|
|
|
---
|
|
|
|
#### ✅ Option 2: Domain with Traefik BasicAuth (Recommended for Teams)
|
|
|
|
Expose console via HTTPS with double authentication:
|
|
|
|
**Setup Steps:**
|
|
|
|
1. **Generate BasicAuth credentials:**
|
|
```bash
|
|
# Install htpasswd (if not installed)
|
|
sudo apt-get install apache2-utils # Ubuntu/Debian
|
|
# OR
|
|
brew install httpd # macOS
|
|
|
|
# Generate password hash
|
|
htpasswd -nb admin YourStrongPassword123
|
|
|
|
# Output example:
|
|
# admin:$apr1$xyz123$abc...def
|
|
```
|
|
|
|
2. **Add to production `.env`:**
|
|
```bash
|
|
# Double authentication: BasicAuth + MinIO login
|
|
TRAEFIK_CONSOLE_AUTH='admin:$$apr1$$xyz123$$abc...def' # Note: $$ for docker-compose
|
|
```
|
|
|
|
3. **Update docker-compose.prod.yml** (already done):
|
|
```yaml
|
|
- "traefik.http.routers.minio-console.middlewares=minio-auth"
|
|
- "traefik.http.middlewares.minio-auth.basicauth.users=${TRAEFIK_CONSOLE_AUTH}"
|
|
```
|
|
|
|
4. **Access:** https://console.crewsportswear.com
|
|
- First: Browser BasicAuth prompt (admin/YourStrongPassword123)
|
|
- Second: MinIO login (your MINIO_ROOT_USER/PASSWORD)
|
|
|
|
**Pros:**
|
|
- Double authentication layer
|
|
- Works from anywhere
|
|
- Can share with team
|
|
|
|
**Cons:**
|
|
- Console still publicly accessible (but protected)
|
|
- Need to manage two sets of credentials
|
|
|
|
---
|
|
|
|
#### ⚠️ Option 3: IP Whitelist (For Fixed IPs)
|
|
|
|
Add IP restriction to BasicAuth:
|
|
|
|
```yaml
|
|
# In docker-compose.prod.yml labels
|
|
- "traefik.http.middlewares.minio-ipwhitelist.ipwhitelist.sourcerange=YOUR_IP/32,OFFICE_IP/32"
|
|
- "traefik.http.routers.minio-console.middlewares=minio-auth,minio-ipwhitelist"
|
|
```
|
|
|
|
---
|
|
|
|
#### ❌ Option 4: Public Console (NOT RECOMMENDED)
|
|
|
|
**Never do this in production:**
|
|
- Exposed to brute force attacks
|
|
- Admin panel publicly accessible
|
|
- Single point of failure if credentials leaked
|
|
|
|
---
|
|
|
|
## S3 API Endpoint Security
|
|
|
|
The S3 API endpoint (`minio.crewsportswear.com`) **should remain public** for:
|
|
- Application file uploads/downloads
|
|
- Direct image access
|
|
- S3 API operations
|
|
|
|
**Why it's safe:**
|
|
- Requires valid access keys
|
|
- Bucket policies control access
|
|
- Can't browse/delete without credentials
|
|
|
|
**Example public URL:**
|
|
```
|
|
https://minio.crewsportswear.com/crewsportswear/images/product.jpg
|
|
```
|
|
|
|
Only publicly readable paths (like `/images/`) are accessible. Private uploads require auth.
|
|
|
|
---
|
|
|
|
## Production Security Checklist
|
|
|
|
### 1. Strong Credentials
|
|
```bash
|
|
# Generate strong password
|
|
openssl rand -base64 32
|
|
|
|
# Update .env
|
|
MINIO_ROOT_USER=admin_$(date +%s) # Unique username
|
|
MINIO_ROOT_PASSWORD=<generated_password>
|
|
```
|
|
|
|
### 2. Console Access
|
|
- [ ] Use SSH tunnel OR
|
|
- [ ] Enable Traefik BasicAuth
|
|
- [ ] Consider IP whitelist
|
|
- [ ] Never expose without protection
|
|
|
|
### 3. Bucket Policies
|
|
```bash
|
|
# Only make necessary paths public
|
|
mc anonymous set download crewminio/crewsportswear/images/
|
|
|
|
# Keep uploads private
|
|
mc anonymous set none crewminio/crewsportswear/uploads/
|
|
```
|
|
|
|
### 4. Application Access Keys
|
|
|
|
Create separate access keys per app (don't use root credentials):
|
|
|
|
```bash
|
|
# Access MinIO console → Administrator → Users → Create User
|
|
# Or via mc:
|
|
mc admin user add crewminio crewsportswear-app <password>
|
|
mc admin policy attach crewminio readwrite --user crewsportswear-app
|
|
```
|
|
|
|
Then use in app:
|
|
```bash
|
|
MINIO_KEY=crewsportswear-app
|
|
MINIO_SECRET=<password>
|
|
```
|
|
|
|
### 5. Network Segmentation
|
|
```yaml
|
|
# Apps should access MinIO via internal network
|
|
MINIO_ENDPOINT=http://crew-minio:9000 # Internal
|
|
# Not: https://minio.crewsportswear.com (external)
|
|
```
|
|
|
|
### 6. HTTPS Only
|
|
```yaml
|
|
environment:
|
|
- MINIO_SERVER_URL=https://minio.crewsportswear.com # Force HTTPS
|
|
```
|
|
|
|
### 7. Regular Backups
|
|
```bash
|
|
# Automated daily backup
|
|
mc mirror crewminio/ /var/backups/minio/$(date +%Y%m%d)/
|
|
```
|
|
|
|
### 8. Monitor Access Logs
|
|
```bash
|
|
# Enable audit logging
|
|
docker exec crew-minio-prod mc admin trace crewminio
|
|
```
|
|
|
|
---
|
|
|
|
## Recommended Production Setup
|
|
|
|
### For Solo Developer:
|
|
```yaml
|
|
# Don't expose console publicly
|
|
# Remove console Traefik labels
|
|
# Access via SSH tunnel only
|
|
```
|
|
|
|
### For Small Team (2-5 people):
|
|
```yaml
|
|
# Use BasicAuth + MinIO login (double auth)
|
|
# IP whitelist to office/VPN
|
|
# Strong passwords (32+ chars)
|
|
```
|
|
|
|
### For Larger Team:
|
|
```yaml
|
|
# Use VPN (Tailscale/WireGuard) + internal console
|
|
# Separate access keys per app/user
|
|
# Audit logging enabled
|
|
# Regular security reviews
|
|
```
|
|
|
|
---
|
|
|
|
## Quick Setup Commands
|
|
|
|
### Secure Console (BasicAuth)
|
|
|
|
```bash
|
|
# 1. Generate password
|
|
htpasswd -nb admin $(openssl rand -base64 16)
|
|
|
|
# Output: admin:$apr1$xyz...
|
|
# Copy this to .env
|
|
|
|
# 2. Update .env
|
|
cat >> .env << EOF
|
|
TRAEFIK_CONSOLE_AUTH='admin:\$\$apr1\$\$xyz...' # Escape $ with $$
|
|
EOF
|
|
|
|
# 3. Restart
|
|
docker-compose -f docker-compose.prod.yml up -d
|
|
```
|
|
|
|
### SSH Tunnel (No Public Console)
|
|
|
|
```bash
|
|
# 1. Remove console Traefik labels from docker-compose.prod.yml
|
|
# 2. Don't expose port 9001
|
|
# 3. Access via SSH:
|
|
ssh -L 9001:localhost:9001 user@server
|
|
# Then: http://localhost:9001
|
|
```
|
|
|
|
---
|
|
|
|
## Emergency: Credentials Compromised
|
|
|
|
```bash
|
|
# 1. Immediately change root password
|
|
docker exec crew-minio-prod mc admin user update crewminio minioadmin --password NewPassword123
|
|
|
|
# 2. Revoke leaked access keys
|
|
docker exec crew-minio-prod mc admin user disable crewminio leaked-user
|
|
|
|
# 3. Review access logs
|
|
docker exec crew-minio-prod mc admin trace crewminio
|
|
|
|
# 4. Rotate application keys
|
|
# Update all apps with new credentials
|
|
|
|
# 5. Check for unauthorized files
|
|
docker exec crew-minio-prod mc ls --recursive crewminio/
|
|
```
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
| Access Method | Security Level | Use Case |
|
|
|--------------|----------------|----------|
|
|
| SSH Tunnel | ⭐⭐⭐⭐⭐ | Solo dev, maximum security |
|
|
| BasicAuth + IP | ⭐⭐⭐⭐ | Small team, fixed IPs |
|
|
| BasicAuth Only | ⭐⭐⭐ | Remote team, can't use VPN |
|
|
| Public Console | ⭐ | **NEVER USE** |
|
|
|
|
**Recommendation:** Start with SSH tunnel. Add BasicAuth only if multiple people need access.
|