By bicycle
I am runnning into an SSL error when setting up Nginx as a reverse proxy for a Node.js app. This app uses Express to serve static content and Socket.io to manage Websocket connections.
The error occurs on the client side when attempting to connect to the socket.io server:
GET https://mywebsite.com:3000/socket.io/?EIO=3&transport=polling&t=NHqAzi7 net::ERR_SSL_PROTOCOL_ERROR
The steps I have taken to set this up are as follows:
/etc/nginx/sites-available/mywebsite.com for the default /socket.io/ socket pathMy Nginx configuration file looks like this:
server {
root /var/www/mywebsite.com/html;
index index.html index.htm index.nginx-debian.html;
server_name mywebsite.com www.mywebsite.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /socket.io/ {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = mywebsite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name mywebsite.com www.mywebsite.com;
return 404; # managed by Certbot
}
And my server setup follows these instructions and looks like this:
var express = require('express'),
http = require('http');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
app.use(express.static(__dirname + "/public"));
server.listen(3000, ()=>{
console.log('server listening on port 3000');
});
Finally, my client connects to the server like this:
socket = io('https://mywebsite.com:3000');
Any idea what else I could try to get this working?
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hi there @bicycle,
As you have already setup a reverse proxy for yourdomain.com/socket.io/ to proxy to port 3000, what you could do is update your client connects to the server like this:
socket = io('https://yourdomain.com/socket.io/');
That way as per your Nginx configuration the connection would get proxied to port 3000.
Hope that this helps! Regards, Bobby
Your setup seems mostly correct, but the issue likely arises from how you’re handling WebSockets in the Nginx configuration and the way the client is connecting to the server. Let’s address these points:
In your Nginx configuration, the location /socket.io/ block looks properly configured for handling WebSocket connections. However, there’s no need to use the port number in your client-side connection. Nginx is already listening on port 443 (HTTPS) and proxying those requests to your Node.js app on port 3000. The client should simply connect to:
socket = io('https://mywebsite.com');
Connecting directly to port 3000 (https://mywebsite.com:3000) in the client bypasses Nginx and tries to establish a direct connection to your Node.js app, which isn’t set up for HTTPS (and thus causes the SSL error).
Your Node.js server is currently set up with a regular HTTP server. This is fine since Nginx handles the SSL termination. Ensure that your server isn’t trying to handle SSL itself, as Nginx is already taking care of that.
Ensure both Nginx and your Node.js application are running:
sudo systemctl status nginxsudo lsof -i :3000Make sure your server’s firewall is not blocking relevant ports. Since you are using Nginx as a reverse proxy, external traffic should only need to access ports 80 and 443.
After making changes to your Nginx configuration, always test the configuration and reload if it’s successful:
sudo nginx -t
sudo systemctl reload nginx
On the client-side, make sure to connect to the WebSocket server via the Nginx proxy (as shown above). There’s no need to specify the port in the URL since Nginx handles the proxy to the correct port.
If it’s still not working:
/var/log/nginx/error.log) for any clues.Make sure your SSL certificates are up to date and correctly configured in Nginx.
By addressing these points, you should be able to resolve the SSL connection issue and properly route your WebSocket traffic through Nginx to your Node.js application.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.