# 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= ``` ### 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 mc admin policy attach crewminio readwrite --user crewsportswear-app ``` Then use in app: ```bash MINIO_KEY=crewsportswear-app MINIO_SECRET= ``` ### 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.