Having issues with getting Nginx
to proxy_pass
with websockets and SSL (WSS).
NGINX Config
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name site.io www.site.io;
location / {
proxy_pass https://localhost:3000;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
location /ws {
proxy_pass http://localhost:8989/graphql;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/site.io/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/site.io/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 = www.site.io) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = site.io) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name site.io www.site.io;
return 404; # managed by Certbot
}
Server Code
const initApiServer = () => {
try {
const app = express();
// Allow CORS
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});
// Set security-related HTTPS headers
app.use(helmet());
// Setup for JSON and url encoded bodies
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/', apiRouter); // Apply API routes
const apollo = new ApolloServer({
typeDefs,
resolvers,
context: { db },
introspection: true, // enabled playground in prod
playground: true, // enabled playground in prod
});
apollo.applyMiddleware({ app });
const server = createServer(app);
apollo.installSubscriptionHandlers(httpServer);
server.listen(8989, () => {
getLogger().info(`API served at ${Config.PROTOCOL}://${Config.HOSTNAME}:${Config.PORT_API}`);
});
} catch (err) {
getLogger().error(`Error starting API Server: ${err.message}`);
require('../server').exit('SIGTERM'); // eslint-disable-line
}
};
I receive a variety of different errors:
WebSocket connection to 'wss://site.io:8989/ws' failed: WebSocket is closed before the connection is established.
WebSocket connection to 'wss://site.io:8989/ws' failed: Error during WebSocket handshake: Unexpected response code: 400
I have tested the server locally with non-SSL and it works fine. How can I get this to work?