When configuring Nginx upstream servers, many developers (myself included) instinctively include the http://
protocol prefix in the server definitions. This seems logical since we're dealing with HTTP services, but Nginx actually treats this as a configuration error.
# This will FAIL
upstream api_servers {
server http://192.168.49.4:49155;
server http://192.168.49.4:49156;
}
The proper way to define upstream servers is to simply use the IP:port combination without any protocol specification:
# Correct configuration
upstream api_servers {
server 192.168.49.4:49155;
server 192.168.49.4:49156;
}
Nginx upstream modules are designed to handle various types of backends, not just HTTP. The upstream directive is protocol-agnostic - it's the proxy_pass
directive that determines the protocol being used. When you specify http://
in the upstream definition, Nginx interprets this as part of the hostname, which violates its syntax rules.
Here's a complete working configuration for proxying to Docker containers:
upstream docker_backends {
server 192.168.49.4:49155;
server 192.168.49.4:49156;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://docker_backends;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
You can enhance your upstream configuration with additional parameters:
upstream load_balanced_servers {
server 192.168.49.4:49155 weight=3;
server 192.168.49.4:49156;
keepalive 32;
}
This configuration gives the first server more weight in load balancing and maintains persistent connections.
If you're still encountering issues:
- Always test your configuration with
nginx -t
- Check that your Docker containers are properly exposed on the specified ports
- Verify network connectivity between Nginx and your containers
- Examine Nginx error logs (
/var/log/nginx/error.log
) for detailed messages
When configuring Nginx as a reverse proxy for Docker containers, many developers (including myself) instinctively include http://
prefixes in upstream server definitions. However, this leads to configuration errors:
upstream api_servers {
server http://192.168.49.4:49155; # This will fail
server http://192.168.49.4:49156; # This will fail
}
Nginx responds with:
nginx: [emerg] invalid host in upstream "http://192.168.49.4:49155"
The upstream
directive in Nginx has specific syntax requirements:
- Server addresses should be specified as
host:port
or IP:port - Protocol prefixes (
http://
,https://
) are not supported in upstream blocks - Nginx automatically uses HTTP protocol for upstream connections
The working version simply removes the protocol prefix:
upstream api_servers {
server 192.168.49.4:49155;
server 192.168.49.4:49156;
}
Here are some common variations:
# With load balancing
upstream backend {
server 10.0.0.1:8080 weight=5;
server 10.0.0.2:8080;
server unix:/tmp/backend.sock;
}
# With failover settings
upstream resilient_backend {
server primary.example.com:80 max_fails=3 fail_timeout=30s;
server backup.example.com:80 backup;
}
For HTTPS upstreams, configure SSL separately:
upstream secure_backend {
server secure.example.com:443;
}
server {
location / {
proxy_pass https://secure_backend;
proxy_ssl_verify on;
proxy_ssl_name $proxy_host;
}
}
When encountering upstream issues:
- Always test configuration with
nginx -t
- Check error logs (
/var/log/nginx/error.log
) - Use
curl -v
to test direct connections to upstream servers - Verify network connectivity between Nginx and upstream