SSl works for frontend but not for backend - express

I have a MERN stack website which i use nginx to serve. My backend server is running on port 5000 over http. SSL works fine for my frontend, but i cant make https requests to my express server. How can i solve this issue? Should i use another SSL for my backend?
This is how my express server.js looks like:
const express = require("express");
const dotenv = require("dotenv");
const routers = require("./routers/index");
const connectDatabase = require("./helpers/database/connectDatabase");
const path = require("path");
const cors = require("cors");
// Environment Variables
dotenv.config({
path: "./config/env/config.env",
});
// MongoDb Conenction
connectDatabase();
const app = express();
// Express - Body Json
app.use(express.json());
const PORT = process.env.PORT;
// CORS
app.use(cors());
// Router Middleware
app.use("/api", routers);
app.listen(PORT, () => {
console.log(
`App Started on PORT: ${process.env.PORT} : ${process.env.NODE_ENV}`
);
});
and this is how nginx/sites-avaliable/my-site.com looks like:
server {
root /var/www/my-site.com/html;
index index.html index.htm index.nginx-debian.html;
server_name my-site.com www.my-site.com;
location / {
try_files $uri /index.html;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/my-site.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/my-site.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 = www.my-site.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = my-site.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name my-site.com www.my-site.com;
return 404; # managed by Certbot
}

Related

Using socket.io with ejs on Express/Nginx

I'm working on a app with socket.io, ejs, express & nginx on a Node JS server.
I have managed to get the socket.io working withthout use of ejs.
But when I try to implement it with ejs I get error 400 on client.js.
Here is my code for server.js :
var express = require('express');
var app = require('express')();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var ejs = require('ejs');
// WITHOUT EJS : WORKS FINE
app.get('/', function(req, res) {
res.sendFile(index.html');
});
// WITH EJS : GET HTTP ERR 400 IN CLIENT.JS CONSOLE
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
res.render('pages/index');
});
io.on('connection', function(socket) {
console.log('a user connected');
socket.on('chat message', function(msg){
console.log('message: ' + msg);
});
});
server.listen(process.env.PORT || 8080, function(){
console.log('app running');
});
My nginx code looks like this :
# HTTP — redirect all traffic to HTTPS
server {
listen 80;
listen [::]:80 default_server ipv6only=on;
return 301 https://$host$request_uri;
}
# HTTPS — proxy all requests to the Node app
server {
# Enable HTTP/2
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
# Use the Let’s Encrypt certificates
ssl_certificate /.../;
ssl_certificate_key /.../;
location ~* \.io {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy false;
proxy_pass http://example.com:8080;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Here is my client.js :
var socket = io();
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
What could be the issue here ?

Nginx upstream to express server - 502 error

Heyo, I have a nginx server on digital ocean. I used to host on AWS with PM2 but tweaked this to run it with nginx.
The problem is that it seems I get a 502. Something just isn't configured right. Originally I had the client just being served and that worked but when i switched to the server doing it 502's as well.
The client and server folders are in the same parent directory.
Here is my current var/nginx/sites-available/default
# Main Content Delivery Block (SSL)
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name quakeviz.app;
ssl on;
ssl_certificate /etc/ssl/certs/mpaccione_ssl.crt;
ssl_certificate_key /etc/ssl/private/mpaccione_ssl.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
add_header Content-Security-Policy upgrade-insecure-requests;
location / {
root /var/www/html/usgs_viz/server;
proxy_pass https://quakeviz.app:8080/;
proxy_ssl_session_reuse on;
#try_files $uri $uri/ /;
}
#location /bufferLength {
# root /var/www/html/usgs_viz/server;
# proxy_pass https://quakeviz.app:8080/;
# proxy_ssl_session_reuse on;
#}
#location /quakeData {
# root /var/www/html/usgs_viz/server;
# proxy_pass https://quakeviz.app:8080/;
# proxy_ssl_session_reuse on;
#}
}
# Redirect
#server {
# listen 80 default_server;
# listen [::]:80 default_server;
# listen 443 ssl;
# listen [::]:443 ssl;
#
# return 301 https://quakeviz.app$request_uri;
#}
Here is the index.js in the server folder. I get a 502 now (updated question) on the client and the api.
// Modules
const cors = require('cors'),
express = require('express'),
expressStaticGzip = require('express-static-gzip'),
fs = require('fs'),
path = require('path'),
app = express(),
// Globals
getDirectories = (source) => {
return fs
.readdirSync(source, { withFileTypes: true })
.filter((dir) => dir.isDirectory())
.map((dir) => dir.name)
}
// CORS for Local Testing
app.use(cors())
// Compression
app.use(
'/',
expressStaticGzip(path.join(__dirname, '../client/build'), {
enableBrotli: true,
orderPreference: ['br', 'gz'],
})
)
// Routes
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '../client/build', 'index.html'))
})
app.get('/.well-known(/*)?', function (req, res) {
res.sendFile(path.join(__dirname, '../.well-known', 'assetlinks.json'))
})
app.get('/privacy-policy', function (req, res) {
res.sendFile(path.join(__dirname, '../privacy_policy.html'))
})
// API
app.get('/bufferLength', function (req, res) {
const encoding = req.headers['accept-encoding'],
compArr = getDirectories(
path.join(__dirname, '/api-data/compressed/')
).sort(function sortNum(a, b) {
return b - a
})
if (compArr.length < 2) {
console.warn('ByteLength Not Available')
res.status(500).send(new Error('ByteLength Not Available'))
} else {
console.log('BUFFER LENGTH RES')
fs.readFile(
path.join(
__dirname,
`/api-data/compressed/${compArr[1]}/byteLength.json`
),
(err, data) => {
if (err) {
console.warn(err)
res.status(500).send(new Error(err))
} else {
console.log(data)
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(data)
}
}
)
}
})
app.get('/quakeData/:index', function (req, res) {
const encoding = req.headers['accept-encoding'],
index = req.params.index,
compArr = getDirectories(
path.join(__dirname, '/api-data/compressed/')
).sort(function sortNum(a, b) {
return a - b
})
// Send Second Newest Dataset as Latest May hvae Read/Writes
if (compArr.length <= 1) {
console.warn('Unsupported Content Encoding Headers')
res.status(500).send(new Error('Dataset Not Currently Available'))
} else {
if (encoding.includes('br')) {
console.log('BROTLI RES')
fs.readFile(
path.join(
__dirname,
`/api-data/compressed/${compArr[1]}/brotliData${index}.txt.br`
),
(err, data) => {
if (err) {
console.warn(err)
res
.status(500)
.send(new Error('Brotli Compression Data Read Error'))
} else {
res.writeHead(200, {
'Content-Type': 'application/json',
'Content-Encoding': 'br',
})
res.end(data)
}
}
)
} else if (encoding.includes('gzip')) {
console.log('GZIP RES')
fs.readFile(
path.join(
__dirname,
`/api-data/compressed/${compArr[1]}/gzipData${index}.txt.gz`
),
(err, data) => {
if (err) {
console.warn(err)
res.status(500).send(new Error('Gzip Compression Data Read Error'))
} else {
res.writeHead(200, {
'Content-Type': 'application/json',
'Content-Encoding': 'gzip',
})
res.end(data)
}
}
)
} else {
console.warn('Unsupported Content Encoding Headers')
res.status(415).send(new Error('Unsupported Requested Encoding Type'))
}
}
})
// Listen
app.listen(8080, () => console.log('API listening on 8080'))
Didn't understand why you are trying to proxy each to route of your service, why didn't you let your app route the request for you?
Example:
location / {
root /var/www/html/usgs_viz/server;
proxy_pass https://quakeviz.app:8080/;
proxy_ssl_session_reuse on;
}
other thing I notice was the https on the proxy_pass I don't think that would work, try replacing with http.
I changed things to this. I also ran the server with PM2.
I am starting to get more into the fullstack sysadmin bit and so I didn't actually know I needed to run this on PM2 as well as route it with Nginx. I had the notion that Nginx would run it if I pointed to it. Kind of a silly thing but I do think the nginx config here is better. See below.
# Main Content Delivery Block (SSL)
server {
listen 443 ssl;
server_name quakeviz.app;
ssl on;
ssl_certificate /etc/ssl/certs/mpaccione_ssl.crt;
ssl_certificate_key /etc/ssl/private/mpaccione_ssl.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
add_header Content-Security-Policy upgrade-insecure-requests;
location / {
root /var/www/html/usgs_viz/server;
proxy_pass http://localhost:8080;
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;
}
}

Sub paths in url returning an internal server error with nginx and express server using react router

So basically I have an express server running on port 4000 that Nginx is redirecting to with a proxy_pass. When I access the root of my domain in the browser (https://www.buildingblockscms.tech/) everything works fine. But when I refresh any sub-routes I've navigated to or try to access them directly (https://www.buildingblockscms.tech/dashboard) I get an internal server error.
The react app running on my express server works absolutely fine with react-router-dom when ran locally but something is up with my Nginx config.
I've been trying to solve this all day, any help is GREATLY appreciated.
This is my sites-available/default file in Nginx.
server {
root /var/www/index.html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name buildingblockscms.tech www.buildingblockscms.tech;
location / {
proxy_pass http://localhost:4000/; #whatever port your app runs$
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;
proxy_set_header X-Forwarded-Host $server_name;
proxy_redirect off;
}
And this is my server file running on port 4000:
const express = require('express');
const mongoose = require('mongoose');
const graphqlHTTP = require('express-graphql');
const auth = require('./middleware/auth');
const app = express();
const fileUpload = require('express-fileupload');
app.use(express.json());
// enable files upload
// app.use(
// fileUpload({
// createParentPath: true
// })
// );
// DB Config
const db = process.env.mongoURI || require('./config/keys').mongoURI;
// Connect to Mongo
mongoose
.connect(db, { useUnifiedTopology: true, useNewUrlParser: true })
.then(() => console.log('MongoDB connected...'))
.catch((err) => console.log(err));
// Use Routes
app.use('/api/content-types', require('./routes/api/content-types'));
app.use('/api/sites', require('./routes/api/sites'));
app.use('/api/users', require('./routes/api/users'));
app.use('/api/pages', require('./routes/api/pages'));
app.use('/api/auth', require('./routes/api/auth'));
// GraphQL Route
app.use(
'/graphiql',
auth,
graphqlHTTP({
schema: require('./routes/client-graphql/schema'),
graphiql: true,
})
);
// Serve static assets if in production
if (process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
const port = process.env.PORT || 4000;
app.listen(port, () => console.log(`Server started on port ${port}`));

nginx proxy pass express routes

With the following config and code, if I goto https://domain.co/api/yo
it looks for a '/api/yo' route in the express app rather than just '/yo'
how do I config NGINX so that express sees https://domain.co/api/yo as '/yo'?
server {
listen 443 default_server;
listen [::]:443 default_server;
root /var/www/domain.co;
index index.html;
server_name domain.co www.domain.co;
ssl on;
ssl_certificate /etc/letsencrypt/live/domain.co/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.co/privkey.pem;
location / {
try_files $uri /index.html;
}
location /api {
proxy_pass http://127.0.0.1:8080;
}
}
app.js
const express = require('express')
const app = express()
app.get('/yo', (req, res) => res.send('Hello World!'))
app.listen(8080, () => console.log('Example app listening on port 8080!'))
The Nginx and Express route had to match for me
nginx:
location /api
express:
app.get('/api', ...)

express and nginx - loads html file but can't serve assets

I'm trying to run an express server at port 3000. When I visit my server's IP, I'm able to get the html page to load, however it doesn't seem to be able to find the assets (have a .js and .css file that I link to - this is in the same directory as the index.html inside of public). Am I missing something in my configs?
express setup
const express = require('express');
const path = require('path');
const app = express();
const PORT = 3000;
app.use('*',
express.static(path.join(__dirname, '..', 'public', 'index.html')));
app.get('*', (req, res) => {
res.sendFile((path.join(__dirname, '..', 'public', 'index.html')));
});
app.listen(PORT, () => {
console.log(`Listening on http://localhost:${PORT}...`)
});
nginx setup
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/my_site/public;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1: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;
}
}
In your nginx configuration,
try_files $uri $uri/ =404;
Means nginx will try to find a static resource in your root folder, then try it with a / at the end, if it hasn't found anything yet will give out a 404 (Not Found).
It never reaches the proxy_pass.
The proper way to configure it would be like this:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/my_site/public;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ #nodejs;
}
location #nodejs {
proxy_pass http://127.0.0.1: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;
}
}
Now, it will look for static files in your root folder, then pass it on to the node server.