Reverse Proxy Httpd Nodejs Pm2 - node.js

I'm trying to set up a reverse proxy to a Node.Js Express web server. Basically I'm trying to redirect any traffic coming to mywebsite.com and have httpd redirect them to node.js app endpoints. So if I would do mywebsite.com/test then it would run the /test function in my node app.
I'm running on EC2 (Amazon Linux 2 AMI)
My backend is at:
/home/ec2-user/mywebsite/mywebsite_backend/dist
I'm running the with pm2, which is a monitoring software for node.
Here's the configuration to /etc/httpd/conf.d/mywebsite.com.conf
<VirtualHost *:80>
ServerName mywebsite.com
ServerAlias www.mywebsite.com
ProxyPreserveHost On
ProxyPass /home/ec2-user/mywebsite/mywebsite_backend/dist http://localhost:8055/
ProxyPassReverse /home/ec2-user/mywebsite/mywebsite_backend/dist http://localhost:8055/
ErrorLog /etc/httpd/conf.d/error.log
CustomLog /etc/httpd/conf.d/custom.log combined
DocumentRoot /home/ec2-user/mywebsite/mywebsite_backend/dist
</VirtualHost>
When I try to open: https://mywebsite.com from a browser I get apache testpage.
When I try https: https://mywebsite.com/test' I get "Not Found". I'm guessing that this is because there's no :443 virtualhost?
When I try http aka non-secure: http://mywebsite.com I get "Forbidden".
Edit1: It seems that Apache is by default looking in /var/www/html. I added a index.html page there and now I can see it when visiting mywebsite.com.
Edit2:
When doing curl http://localhost:8055/test on the server the response is:
curl: (52) Empty reply from server
When doing curl https://localhost:8055/test on the server the response is:
curl: (60) SSL: no alternative certificate subject name matches target
host name 'localhost' More details here:
https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could
not establish a secure connection to it. To learn more about this
situation and how to fix it, please visit the web page mentioned
above.
I've made the SSL certificates for my express server with Let's encrypt and I'm pointing to the generated files in my code and it works locally, but it seems I have a problem with SSL with apache?
Edit3:
curl -k http://localhost:8055/test
Does not work.
I've tried now pingin my node app with
curl -k https://localhost:8055/test
It works.
Edit4: Looking at the error logs /etc/httpd/conf.d/error.log it seems that there are permission problems with the code being in /home directory. I will move it to /var/www/html/

Related

Proxy Error 502 on Apache2 for Reverse Proxy to NodeJs Subdomain App on Digital Ocean

Hello guys
Im trying to deploy my nodejs api on Digital Ocean, under subdomain https://api.host.com. Its has some path bellow, all starting by /v0.1.
For example https://api.host.com/v0.1/users
On this droplet the nodejs app is running over http://localhost:3000
At the same droplet i have got other app, a website hosted on Apache and responds at https://host.com it works fine.
Im using Apache for Reverse Proxy make all calls from https://api.host.com/ to http://localhost:3000.
Actually It works only for root path, i mean try to access https://api.host.com/ responds right but when i try to access other path i get error
Proxy Error
The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request
Reason: DNS lookup failure for: 127.0.0.1:3000v0.1
Apache/2.4.29 (Ubuntu) Server at api.host.com Port 443
HTTP Status Code: 502 Proxy Error
my vhost looks like...
<VirtualHost *:80>
...
...
ServerName api.host.com
ProxyPass /.well-unknown/ !
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
...
...
</VirtualHost>
Help please!
I am doing the same thing with an Apache server forwarding requests from a subdomain via a proxy to my nodeJS app listening on port 8080.
I believe that you only need to proxy pass the root to localhost:3000 and the nodeJS app is supposed to handle the routing.
For instance, if you are using express, something like.....
app.get('/v.01/users/', function (req, res) {
res.sendFile('/v.01/users/index.html'); });

Proxy a node/react application in an apache server

Using forever to forever run the node server on the virtual machine, I am unable to get the app to run without explicitly adding the port in the url like so: URL.com:8080
If I don't use the port in the URL, I do load up the file structure of the application.
Steps to reproduce: I have a create-react-app application.On the virtual server I run 'npm run build' to make sure I have a build to serve. I then run forever start on the root of the application.
The code below should give all the necessary details. I can provide more if you need.
I have spent so much time tweaking the .conf file to try different configurations but I can't seem to get it. I am using it and successfully hosting two static html sites but not this node application.
Package.json:
...
"main":"server/index.js",
"proxy":"http://localhost:8080"
...
Apache url.conf:
<VirtualHost *:80>
ServerName URL.com
ServerAlias URL.com:8080/
DocumentRoot /var/www/nameOfApp/
<Directory />
Options -Indexes +FollowSymLinks
AllowOverride All
</Directory>
<Directory /var/www/nameOfApp/public>
Options +Indexes +FollowSymLinks +MultiViews
AllowOverride All
</Directory>
</VirtualHost>
Node server file using express:
app.use(express.static(`${__dirname}/../build`));
I've also made sure I have the modules enabled to allow for proxying. So I think essentially, what I need is to request this site and not need the :8080 at the end.
Apache and NodeJS are 2 different and separate application.
You interact with them by sending request to the port that they are listening to. In your case here,
Apache is listening at port 80
Your NodeJS application is listening at port 8080
So all request to port 80 will be handled by Apache, and since you do not has an index.html, Apache will default to just list out the files and directory (Options Indexes). Up until this point, your node application do not know anything about your request.
So what you need to do is define some endpoint, say url.com/node, and tell Apache to forward all request of this endpoint to port 8080 and let your node application to do the job.
How to do this?
http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass
Best practices when running Node.js with port 80 (Ubuntu / Linode)
Node.js + Nginx - What now?
Hope this points you to the right direction.
The configuration that eventually worked was as simple as this:
<VirtualHost *:80>
ServerName yourdomain.com
ProxyPreserveHost on
ProxyPass / http://localhost:8080/
</VirtualHost>
Looks like I was over complicating it trying to create a complicated proxy but the solution was very simply adding this to the config for the node application and then running sudo systemctl restart apache2 and everything worked beautifully.

Apache Reverse Proxy and localhost - "Mixed content, the content must be served over HTTPS"

I have created a reverse proxy for my node server that runs on localhost, so that it can be served over HTTPS.
The forwarding works grate, however when the app tries to make requests I get:
Mixed Content: The page at 'https://foo.com/' was loaded over HTTPS,
but requested an insecure XMLHttpRequest endpoint
'http://localhost:8888/graphql?query=%7Bnotifications(userid)%7Bid%2C…
This request has been blocked; the content must be served over HTTPS.
Vhost config:
<VirtualHost *:443>
ServerName www.foo.com
ServerAlias foo.com
DocumentRoot /var/www/foo/
ErrorLog /var/www/foo/error.log
CustomLog /var/www/foo/requests.log combined
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
SSLCertificateFile "/etc/letsencrypt/live/foo.com/cert.pem"
SSLCertificateKeyFile "/etc/letsencrypt/live/foo.com/privkey.pem"
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / http://localhost:8888/
ProxyPassReverse / http://localhost:8888/
</VirtualHost>
What is missing from my setup?
You are openning the page on https://foo.com/, but URLs within your page contain hardcoded localhost domain and port. While rendering the page, client browser will try to fetch 'http://localhost:8888/graphql effectively skipping apache (which is running on port 80, on server foo.com) and hitting directly your node app, which will 1) work only if you run the browser from the very same machine where you have your node app running, and 2) even then, you will get the above error since some page assets are loaded using http.
When you use relative URLs (for example URL that begins with /), browser will prepend the base URL, resulting in https://foo.com/graphql.
Absolute vs relative URLs
You need to add a SSL certificate to your node.js app. Enabling it on apache won't help since the apache is forwarding the requests to your node.js app on port 8888 (which communicates on plain http and not https). That's why you get the mixed content error. The initial request is on https on apache then forwarded to http to node.js
Steps to configure node.js app with a SSL certificate (you can use a self-signed certificate or a commercial one).
First you have to use ssl-root-cas available via npm. The configure it as follows:
'use strict';
var https = require('https')
, cas
;
// This will add the well-known CAs
// to `https.globalAgent.options.ca`
require('ssl-root-cas').inject();
cas = https.globalAgent.options.ca;
cas.push(fs.readFileSync(path.join(__dirname, 'ssl', '01-ssl-intermediary-a.pem')));
cas.push(fs.readFileSync(path.join(__dirname, 'ssl', '02-ssl-intermediary-b.pem')));
cas.push(fs.readFileSync(path.join(__dirname, 'ssl', '03-ssl-site.pem')));
Try and see if that works!

Apache reverse proxy configuration issue

i have a problem with setting up an apache reverse proxy server and hope you can help.
I have 3 ubuntu web servers, available on https://service1.domain.com, https://service2.domain.com:4433 and so on...
Now, i will access these servers without typing the port in the addressbar.
So my idea is to use an reverse proxy server, that i can type in service2.domain.com and it redirects to service2 (https).
I installed an ubuntu server with apache and enabled the modules:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests
Then i set up the 000-default.conf on the proxy with the following content:
<VirtualHost service1.domain.com:80>
ProxyPreserveHost On
ProxyPass / https://service1.domain.com/
ProxyPassReverse / https://service1.domain.com/
</VirtualHost>
<VirtualHost service2.domain.com:80>
ProxyPreserveHost On
ProxyPass / https://service2.domain.com/
ProxyPassReverse / https://service2.domain.com/
</VirtualHost>
The ports 80 and 443 on the router are forwarded to the proxy server.
On the service(1-3) servers, SSL is enabled with certificates from Lets Encrypt.
Now, if i try to open site service1.domain.com, i get an error (cert_name).
The sites now should not be accessible directly, because there is no port forwarding anymore.
My question is now, how is the right config for reverse proxies? Do i need to enable a certificate for each service also on the proxy server?
Thank you for your help!
Not exactly sure what your end goal is. The certificate is for the client facing server. If you want people to hit the site without having to set the port, you can use the Redirect statement in the virtual host config.
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://www.example.com
</VirtualHost>
Which would forward any non ssl traffic to use the ssl virtual host.

how to run multiple cross platform web application on the same server using different ports?

I am running a java web application on tomcat 7.0, which is setup on media temple Ubuntu 16.04 server. The application is running on port 8080, and I have a domain which is binded to the port.
e.g. public-ip-of-server:8080 xyz.com
Now, I want to run a node js application (rocket-chat) on the same Linux server using port 3000. I have configured the whole application, and the application is running on localhost:3000/ but when I am trying to access the application using public IP of the server (e.g. public-ip:3000/), I am not able to access it.
I have allowed the traffic on port 3000 using command,
ufw allow 3000
I also edited apache2.conf,
ProxyPass /rocketchat http://public-ip-of-server:3000/
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module
modules/mod_proxy_http.so
but after changing this parameter I am not able to restart the apache2 service.
so I revert back the changes.
what should I do to run both the application (java and node js) on the same Linux server ? can anyone please help me out.
Just bind nodejs app to interface 0.0.0.0 instead of 127.0.0.1.
In your Apache configuration, you should use the localhost instead of public ip. So instead of:
ProxyPass /rocketchat http://public-ip-of-server:3000/
use:
ProxyPass /rocketchat http://localhost:3000/
I am using Ubuntu server so httpd.conf is not present there, so I have created another file, in sites-available folder of apache2.(e.g xyz.conf).
I have two domain which pointing to the same media temple name server,
I used one domain for pointing tomcat application on port 8080 and another domain for node js application on port 3000, by making virtual host in xyz.conf
<VirtualHost *:80>
ServerName xyz.com
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
</VirtualHost>
<VirtualHost *:80>
ServerName abc.com
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
After this I enabled proxy mode using command :
sudo a2enmod proxy
And also make this xyz.conf file as site configuration file, using command,
sudo a2ensite xyz.conf
It will ask you to reload the apache2 service,
just reload it and restart,
e.g sudo systemctl restart apache2.service
The problem resolved by forwarding the request, which is received on port 80 of apache2, to tomcat:8080 and nodejs:3000, by creating virtual host.

Resources