I'm trying to set up multiple APIs on a single VPS and serve them through Nginx.
I want to have all of them in separate sub-locations like the example below:
Express remote paths:
[myhost].com/apps/app1/api
[myhost].com/apps/app2/api
Express local paths:
localhost:[app1 port]
localhost:[app2 port]
Socket.IO remote paths:
[myhost].com/apps/app1/api/socket.io
[myhost].com/apps/app2/api/socket.io
Socket.IO local paths:
localhost:[app1 port]/socket.io
localhost:[app2 port]/socket.io
Express works as desired, I am able to access it locally like this:
curl -ivL http://localhost:[app1 port]
But, because of Socekt.IO 'path' property, Socket.IO responses only on:
curl -ivL http://localhost:[app1 port]/apps/app1/api/socket.io/?EIO=4
Without Socket.IO 'path' I am not able to access it remotely.
const ioServer = new socketIo.Server(httpServer, {
.....
path: "/apps/app1/api/socket.io", <---- this 'path' property
});
Nginx configuration:
......
location /apps {
index _;
autoindex on;
location /apps/app1/api/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://localhost:[app1 port];
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /apps/app1 {
index index.html;
}
....
How can I get rid off /apps/app1/api part on localhost Socket.IO without losing the remote access?
Thanks
I'm just learning Nuxt JS, and it's fine on my local computer until i want to try to deploy it on the server,
It's just a simple App, just Image and Text, but when i deploy it on the server the image won't load.
I'm using PM2 to deploy my App on my Ubuntu VPS
You guys can look at the error on https://bappedabjn.id as it look like this
EDIT :
I'm sorry i didn't include detail
Here is where i put the image at static/img/logo.png
And here how i called the image
<nuxt-img src="/img/logo.png" width="100" class="mb-10" />
And lastly here is my nginx.conf for #Lykos94 asking it
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;
I tried to create a new NuxtJS project based on your information and added the #nuxt/image and I managed to reproduce your issue. You are currently using the target: 'server' (or none, and it's the default) option in your nuxt.config.js, which requires to have additional configuration for you to use the #nuxt/image module.
In particular you should follow the following guide at this link and add this to your plugins:
import { createIPX, createIPXMiddleware } from "ipx";
// https://github.com/unjs/ipx
const ipx = createIPX({
dir: "static/", // absolute path to images dir
});
export default createIPXMiddleware(ipx);
After following the guide I managed to run the npm run build and run my server in production, displaying correctly the image.
I've done this tutorial,
https://reactjs.org/tutorial/tutorial.html
Then uploaded it to production server, running on ubuntu nginx with SSL. Ran npm run build, created the build files and served static files with serve module serve -s -p 8083 build. It runs OK on port 8083.
But when I try to add it as a pm2 service pm2 serve ./build/ 8083 I get a 404 not found (when it's not running the error is 502 Bad Gateway)
I tried several ways, with pm2 serve ./ 8083, pm2 serve ./public/ 8083, etc.
Nginx config:
location ~* /.(js|jpg|png|css)$ {
access_log off;
expires max;
}
location = /react-game {
root /var/www/test.com/html/react-game/build;
proxy_pass http://localhost:8083;
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;
autoindex off;
}
Any ideas how to replicate serve -s -p 8083 build with pm2?
Thanks!
I think the main issue is serve is meant to serve static files and pm2 is meant to persistently run a script. Here is an article about serving react with pm2:
https://ygamretuta.xyz/deploy-create-react-app-with-pm2-16beb90ce52
But is there a reason you don't want to just make nginx listen on port 8083 and serve the build files statically by itself? Or is there a reason you're not serving the build files on port 80?
I am trying to enable HMR on my react front end which also uses nginx/php-fpm as backend. I read a few articles and questions on stackoverflow but I still cannot get it to work.
So first of all, If I understand It correctly It should work like this:
1.I have my docker nginx container(80) mapped to port 8080
I make request to localhost:8080 which then passes It into docker container to nginx which listens on port 80.
After that I should have two options, If I want to make a request to backend, which is just API, then everything with /api in URI will be redirected to php-fpm, otherwise everything else will be redirected to webpack-dev-server.
Currently I have my nginx configured like this:
upstream backend {
server app:9000;
}
server {
root /var/www/emailApp/public;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://localhost:8080;
}
location ~ ^\/api\/.+$ {
fastcgi_pass backend;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param DOCUMENT_ROOT $realpath_root;
}
}
I am not sure this works correctly, but If it matches something with '/' it should try to pass it into port 8080, If it matches something with /api/ then it should pass it to php backend.
Here is my webpack config
entry: './assets/index.jsx',
output: {
filename: 'main.js',
publicPath: "http://localhost:8080/public/"
},
devServer: {
contentBase: path.join(__dirname, 'public'),
host: '0.0.0.0',
compress: true,
port: 8080
},
I mainly did this from tutorials, but I don't think that I understand It. because right now I call index.php which calls controller that returns template which contains reference to main.js that is in public folder. But event after reading documentations I quite don't understand It. The devServer part maybe, It specifies server that will listen on 0.0.0.0:8080, but If I am not mistaken I would need to change the structure of my project so I have index.html file that will include my js file in public folder, right ?
Edit 1: Here is a mini code I made that reproduces the error. Please follow README.md to install.
Edit 2: Finally, I found one solution. Besides $locationProvider.html5Mode(true); ($locationProvider.hashPrefix('') is NOT necessary for me) and <base href="/" />, I need to add the follows in routes/index.js, rather than app.js. Then, we do NOT need to add anything more to app.js or nginx or apache like this thread mentions.
var express = require('express');
var router = express.Router();
var path = require('path');
... ...
router.get('*', function(req, res) {
res.sendfile('./views/index.html'); // load our public/index.html sendFile
// res.sendFile('index.html', { root: path.join(__dirname, 'views') }); // does not work
});
One problem is, in the server console, it gives express deprecated res.sendfile: Use res.sendFile instead routes/index.js:461:9. But res.sendFile('index.html', { root: path.join(__dirname, 'views') }); can not help, it returns 404 error.
My express version is ~4.14.0... does anyone know how to fix that?
OP:
I develop in Mac with Apache a MEAN-stack application that can be requested by
https://localhost:3000/#/home. In production with an NGINX server, the application can be requested by
https://www.myapp.io/#/home. The fragment-identifier # is needed in all cases because of angular ui-router.
So I wanted to make pretty url without # (eg, https://www.myapp.io/home, https://localhost:3000/home) work. I have done the following:
added $locationProvider.html5Mode(true); $locationProvider.hashPrefix('') in app.config(['$stateProvider'....
added <base href="/" /> in index.html
As a result, https://localhost:3000/#/home changes automatically to https://localhost:3000/home in the browser bar, similarly for https://www.myapp.io/#/home.
However, directly entering https://localhost:3000/home or https://www.myapp.io/home in the browser will raise an error (I don't know how to turn previous <h1><%= message %></h1><h2><%= error.status %></h2><pre><%= error.stack %></pre> in error.ejs to error.html, so I don't have more details).
So now, the goal is to make https://localhost:3000/home and https://www.myapp.io/home work.
By following this thread, I added the follows to app.js:
app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));
app.all('/*', function(req, res, next) {
res.sendFile('index.html', { root: __dirname });
});
And in Apache of Mac, here is my httpd-vhosts.conf, after restarting apache,
https://localhost:3000/home still returns an error.
<VirtualHost *:443>
ServerName localhost
DocumentRoot "/Users/SoftTimur"
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /etc/apache2/ssl/localhost.crt
SSLCertificateKeyFile /etc/apache2/ssl/localhost.key
<Directory "/Users/SoftTimur">
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
</VirtualHost>
In production, here is the NGINX server block. After restarting NGINX, https://www.myapp.io/home still returns an error.
server {
listen 443 ssl;
server_name myapp.io www.myapp.io;
ssl_certificate /etc/letsencrypt/live/myapp.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.io/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:EC$
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
index index.html;
root /opt/myapp;
location / {
try_files $uri $uri/ /index.html;
}
location ~ /.well-known {
allow all;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_set_header Proxy "";
proxy_pass https://127.0.0.1:3000;
# These three lines added as per https://github.com/socketio/socket.io/issues/1942 to remove sock$
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Could anyone help?
This might useful stuff,
AngularJS routing without the hash '#'
Also, use this line in your express server file.
app.use(express.static(path.join(__dirname, 'client folder')));
this will directly finds your index.html file in that views folder and loads it
try this in your express server
var express = require('express');
var app = express();
app.get('*', function (req, res) { res.sendFile(__dirname + '/views/index.html'); });
and in your angular app:
$locationProvider.hashPrefix('!').html5Mode({
enabled: true
});
$urlRouterProvider.otherwise('/');
and you still need the <base href="/"> in your index.html
let me know if this works for you
EDIT:
I just found your app in https://github.com/chengtie/mini-mean,
looks like your app.use order is wrong. Please copy paste this in your express server and check if it's okay now. pastebin
You don't need Apache or Nginx to run NodeJs in development, just node server.js is enough
Express gave you that error because you are using a deprecated API res.sendfile please use res.sendFile (capital F)
Some info for doing SPA:
When you have the '#' in your URL, the browser interpret it as a local reference and thus, won't send new request to the server
By enabling $locationProvider.html5Mode(true) you are now using html5 push state to navigate around your application history and (if I'm not mistaken you are happening to be using) angular effectively remove the '#' in url
Without the '#' (hash-bang) browser will interpret it as a new request and send it to server, so you have to map all requests from server to your SPA entry file
For exact steps of replicating this behavior, consult this article: https://scotch.io/tutorials/pretty-urls-in-angularjs-removing-the-hashtag (the base href in your entry file is important)
If it's just about the #. You can remove it in Angular itself.
Just inject locationProvider at your app entry and set htmlMode to true. In your index.html set the baseUrl.
$locationProvider.html5Mode(true)
And in you index.html add:
<base href="/" />
That will generate your urls without the #. Does that help?