Single End Point for Multipe Vuejs Applications Using Nginx
Tags: nginx, vue, express, node
Published: 2020-02-13 13:54:37

## Overview

To have a single point of entry into the multiple vue applications simplifies management. We allow one IP access into our Nginx server that makes calls deeper into our network to a single internal server that runs many vue applications.  This allows a single SSL certificate. Minimal firewall rule changes, we ask from small range increases at a time for new internal app ports. i.e. 8000-8010 then 8011-8020, etc.

## Vue

I'll cover the vue configuration first since this approach can back end agnostic. In our case, we will be using a node/express backend. To get this working you'll need to set a base path route for each application and map it to an internal port. For this example, we'll use /example and 8000. Start by setting up the base path within vue. This is managed by a file at the base level of your vue app, the same level as package.json. Create vue.config.js at the application base.

```js
module.exports = {
    publicPath: "/example/"
}
```

### dot env files

This section assumes you develop with a local server instance, it is running on a different port, it is running on port 8910. To this end I have two configuration files. 

```js
// .env.development
VUE_APP_API_BASE=http://localhost:8910/api/1.0
VUE_APP_MODE=development
Access_Control_Allow_Origin=http://localhost:8080
```

```js
// .env.production
VUE_APP_API_BASE=https://apps.western.edu/example/api/1.0
VUE_APP_MODE=production
Access_Control_Allow_Origin=https://apps.western.edu
```

The **VUE_APP_API_BASE** variable is picked up and used to route calls appropriately based on the **NODE_ENV** variable value, i.e. production or development. The **Access_Control_Allow_Origin** variable is so cors protection will allow us to access the server in either environment without having to change anything but the **NODE_ENV** variable. These files are also at the base of the vue application.

### vuex

I use a vuex file named store.js to provide an Axios base instance with the **VUE_APP_API_BASE**. This is done by creating an API getter in the store.js file. This uses the environment variables. Additionally, this is where I set my JWT value in the headers. I've removed it from this example but I have one more header __"Authorization": state.jwt__.

```js
...
getters: {
        api: function(state) {
            return axios.create({
            baseURL: process.env.VUE_APP_API_BASE,
            timeout: 5000,
            withCredentials: false,
            headers: {
                "Content-Type": "application/json;charset=UTF-8",
                "Accept": "application/json",
                "Access-Control-Allow-Origin": process.env.Access_Control_Allow_Origin
              }
            });
        }
...
```

## Node and Express Server

For the server, I'll use Node and Express. We again use configuration files. The key elements are two environment variables. 

```sh
# Make sure these are set appropriately in your environment before
# starting your server.
export express_port=8910
export cors_origin='http://localhost:8080'
```

In production, you'll set the express_port to the available port you have designated for the server. In our case 8000 on the server. You should not need cors_origin in production since we serve our vue instance through our node/express instance that also serves our API. Set this accordingly in production. In development, we assume the default __npm run serve__ port.

You need to configure express to use __process.env.express_port__ for the listening port. You will also need to set up your cors origin to __process.env.cors_origin__.

I also set the express to server a /public dirctory. This is where I copy everything generated from __npm run build__'s /dist directory. 

## Nginx

We will configure to route /example to the server and strip off the /example portion of the path when calling the internal API. In your Nginx configuration file, you'll need to configure the /example location.

```js
    location /example {
       # This is plain http not https.
       # This server, Nginx, has the SSL cert on 443
       rewrite ^/example/(.*) /$1 break;
       proxy_pass http://internal-server.example.con:8000/;
    }
```

The keys here are the location section which allows us to route based on the path. The second section is the rewrite wich allows us to strip off the /example/ portion of the url before proxying the connection back to the internal server actually running the application. You can setup as many locations as you need in this fashion and Nginx will route each one based on the path back to the appropriate path and port on our internal server.

## Conclusion

I use this to serve may applications. All come into the Nginx server and then get routed back to the internal server. The main advantages for me are one SSL certificate and external IP for all. Security is focused on the external/DMZ server first. This approach requires the setting of NODE_ENV, express_port, and cors_orign when working locally. Other than these changes the same code should work local and on the server.