Files
Munich-news/docs/SECURITY.md
2025-11-12 11:34:33 +01:00

7.5 KiB

Security Notes

Network Security Architecture

Internal-Only Services

The following services are configured to be internal-only and are not exposed to the host machine or external network:

  • Ollama - AI service (port 11434 internal only)
  • MongoDB - Database (port 27017 internal only)
  • Crawler - News crawler (no ports)
  • Sender - Newsletter sender (no ports)

Only the Backend API is exposed to the host on port 5001.

This provides several security benefits:

Ollama Service Security

Configuration:

# Ollama service has NO ports exposed
ollama:
  image: ollama/ollama:latest
  # No ports section - internal only
  networks:
    - munich-news-network

Benefits:

  1. No External Access: Ollama API cannot be accessed from outside Docker network
  2. Reduced Attack Surface: Service is not exposed to potential external threats
  3. Network Isolation: Only authorized Docker Compose services can communicate with Ollama
  4. No Port Conflicts: Port 11434 is not bound to host machine

Accessing Ollama

From Docker Compose Services (✓ Allowed):

# Services use internal Docker network
OLLAMA_BASE_URL=http://ollama:11434

From Host Machine (✗ Not Allowed):

# This will NOT work - port not exposed
curl http://localhost:11434/api/tags
# Connection refused

From Inside Containers (✓ Allowed):

# Access from another container
docker-compose exec crawler curl http://ollama:11434/api/tags

Why This Matters

Security Risks of Exposed Ollama:

  • Unauthorized access to AI models
  • Potential for abuse (resource consumption)
  • Information disclosure through prompts
  • No authentication by default
  • Could be used for unintended purposes

With Internal-Only Configuration:

  • Only your trusted services can access Ollama
  • No external attack vector
  • Controlled usage within your application
  • Better resource management

Testing Ollama

Since Ollama is internal-only, you must test from inside the Docker network:

# ✓ Correct way - from inside a container
docker-compose exec crawler curl -s http://ollama:11434/api/tags

# ✓ Test translation
docker-compose exec crawler python crawler_service.py 1

# ✓ Check logs
docker-compose logs ollama

If You Need External Access

If you have a specific need to access Ollama from the host machine (e.g., development, debugging), you can temporarily expose it:

Option 1: Temporary Port Forward

# Forward port temporarily (stops when you press Ctrl+C)
docker exec -it munich-news-ollama socat TCP-LISTEN:11434,fork TCP:localhost:11434 &

Option 2: Add Ports to docker-compose.yml (Not Recommended)

ollama:
  ports:
    - "127.0.0.1:11434:11434"  # Only bind to localhost, not 0.0.0.0

⚠️ Warning: Only expose Ollama if absolutely necessary, and always bind to 127.0.0.1 (localhost only), never 0.0.0.0 (all interfaces).

Other Security Considerations

MongoDB:

  • Internal-only (not exposed to host)
  • Uses authentication (username/password)
  • Only accessible via Docker network
  • Cannot be accessed from host machine or external network

Backend API:

  • Exposed on port 5001 for tracking and admin functions
  • Should be behind reverse proxy in production
  • Consider adding authentication for admin endpoints
  • In production, bind to localhost only: 127.0.0.1:5001:5001

Email Credentials:

  • Stored in .env file
  • Never commit .env to version control
  • Use environment variables in production

Production Recommendations

  1. Use Docker Secrets for sensitive data:

    secrets:
      mongo_password:
        external: true
    
  2. Restrict Backend to Localhost (if not using reverse proxy):

    backend:
      ports:
        - "127.0.0.1:5001:5001"  # Only accessible from localhost
    
  3. Use Reverse Proxy (nginx, Traefik) - Recommended:

    backend:
      # Remove ports section - only accessible via reverse proxy
      expose:
        - "5001"
    

    Benefits:

    • SSL/TLS termination
    • Rate limiting
    • Authentication
    • Access logs
    • DDoS protection
  4. Regular Updates:

    docker-compose pull
    docker-compose up -d
    
  5. Monitor Logs:

    docker-compose logs -f
    
  6. Network Isolation:

    • Already configured: MongoDB, Ollama, Crawler, Sender are internal-only
    • Only Backend API is exposed
    • All services communicate via internal Docker network

Security Checklist

  • Ollama is internal-only (no exposed ports)
  • MongoDB is internal-only (no exposed ports)
  • MongoDB uses authentication
  • Crawler is internal-only (no exposed ports)
  • Sender is internal-only (no exposed ports)
  • Only Backend API is exposed (port 5001)
  • .env file is in .gitignore
  • Backend API has authentication (if needed)
  • Using HTTPS in production (reverse proxy)
  • Regular security updates
  • Monitoring and logging enabled
  • Backup strategy in place

Reporting Security Issues

If you discover a security vulnerability, please email security@example.com (replace with your contact).

Do not open public issues for security vulnerabilities.


Network Isolation Summary

Current Port Exposure

Service Port Exposed to Host Security Status
Backend API 5001 Yes Only exposed service
MongoDB 27017 No Internal only
Ollama 11434 No Internal only
Crawler - No Internal only
Sender - No Internal only

Security Improvements Applied

Ollama Service:

  • Changed from exposed (port 11434) to internal-only
  • Only accessible via Docker network
  • Prevents unauthorized AI model usage

MongoDB Service:

  • Changed from exposed (port 27017) to internal-only
  • Only accessible via Docker network
  • Prevents unauthorized database access

Result:

  • 66% reduction in attack surface (3 services → 1 service exposed)
  • Better defense in depth
  • Production-ready security configuration

Verification Commands

# Check what's exposed
docker ps --format "table {{.Names}}\t{{.Ports}}"

# Expected output:
# Backend:  0.0.0.0:5001->5001/tcp  ← Only this exposed
# MongoDB:  27017/tcp                ← Internal only
# Ollama:   11434/tcp                ← Internal only

# Test MongoDB not accessible from host
nc -z -w 2 localhost 27017  # Should fail

# Test Ollama not accessible from host
nc -z -w 2 localhost 11434  # Should fail

# Test Backend accessible from host
curl http://localhost:5001/health  # Should work

MongoDB Connection Security

Configuration

Inside Docker Network:

MONGODB_URI=mongodb://admin:changeme@mongodb:27017/
  • Uses mongodb (Docker service name)
  • Only works inside Docker network
  • Cannot be accessed from host

Connection Flow:

  1. Service reads MONGODB_URI from environment
  2. Docker DNS resolves mongodb to container IP
  3. Connection established via internal network
  4. No external exposure

Why This Is Secure

  • MongoDB port (27017) not exposed to host
  • Only Docker Compose services can connect
  • Uses authentication (username/password)
  • Network isolation prevents external access

Testing Security Configuration

Run the connectivity test:

./test-mongodb-connectivity.sh

Expected results:

  • MongoDB NOT accessible from host
  • Backend CAN connect to MongoDB
  • Crawler CAN connect to MongoDB
  • Sender CAN connect to MongoDB
  • Backend API accessible from host