Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

The dependable way to install the MEAN stack on a Linux VPS is to use a supported Ubuntu LTS image, pin compatible Node.js, Angular CLI and MongoDB versions, run Express privately, serve the Angular build through NGINX on ports 80 and 443, and keep the API alive with PM2. You can self-host MongoDB or use MongoDB Atlas; in either case, keep the connection string in MONGODB_URI, not in source code.

What the MEAN stack contains

MEAN is a JavaScript and TypeScript web stack with four layers:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Component Layer Role in a VPS deployment
MongoDB Data Stores application documents and serves queries to the API.
Express.js Server and application Defines HTTP routes, validates requests, applies middleware and talks to MongoDB.
Angular Presentation Compiles the browser application into static HTML, CSS and JavaScript files.
Node.js Runtime Runs Express and the build tooling on the server.

In production, the browser normally reaches NGINX first. NGINX returns Angular’s compiled files and forwards an API prefix such as /api to Express on an internal loopback port. MongoDB should not be exposed to the public internet.

Decide versions and topology before installing

Write down the Ubuntu release, Node.js LTS release, Angular CLI version, MongoDB major version and Express port before creating the application. MEAN.JS documentation warns that unsupported preinstalled versions can break a project, and Angular, Node.js and MongoDB compatibility changes over time. Use one version policy for development and production rather than accepting whatever a package manager happens to provide.

Supported operating-system image

Choose an Ubuntu LTS image that is still supported by your VPS provider and by the MongoDB release you intend to install. A provider’s one-click image may use a different Ubuntu release or filesystem layout than a fresh VPS, so inspect its manifest before copying commands from a tutorial.

Node.js and Angular compatibility

Install the current Node.js LTS (or the exact version required by the application) and record the result of node --version and npm --version. MongoDB’s current framework quick start asks for Node.js and recommends the Latest LTS or Latest Release for that guide. Treat that recommendation as a starting point, not permission to mix arbitrary versions with an older Angular project.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the database location

You have two supported patterns:

  • MongoDB on the VPS: you control the service, disk, upgrades, backups and authentication.
  • MongoDB Atlas: the database is managed for you; you copy its URI, restrict network access to the VPS, and store the URI as MONGODB_URI.

Do not run both merely because both are easy to install. Select one connection target and test it from the VPS before putting the API behind NGINX.

Prepare the Linux VPS securely

Use a non-root deployment account for application work. Keep root access for system administration only, and use SSH keys rather than a password wherever the provider supports it.

  1. Connect as the initial administrator. Use the provider’s SSH details, then update the package index and installed packages:
    sudo apt update && sudo apt upgrade -y
  2. Create a deploy user. Replace deploy with your chosen account name:
    sudo adduser deploy
    sudo usermod -aG sudo deploy
  3. Install the deploy user’s SSH key. Copy the public key into /home/deploy/.ssh/authorized_keys, set ownership to deploy:deploy, and use mode 700 on the directory and 600 on the key file. Open a second SSH session as this user before changing the administrator’s access.
  4. Allow only required firewall ports. A typical web VPS needs SSH, HTTP and HTTPS:
    sudo ufw allow 22/tcp
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw enable
    sudo ufw status verbose

    Do not open MongoDB’s default port to the internet. If you use Atlas, allow the VPS’s outbound connection and add only the VPS address to the Atlas network-access list.
  5. Set a hostname and time zone. A stable hostname makes logs and TLS administration easier. Confirm the system clock is synchronized before issuing certificates.

The documented UFW pattern for a provider MEAN image allows 22, 80 and 443. Your provider may add rules, so inspect sudo ufw status numbered instead of assuming the image is hardened.

Install Node.js and npm

Use the installation method recommended for your selected Ubuntu release: the distribution package, a provider-supported Node repository, or a version manager approved by your operations policy. Avoid installing one Node version for the shell and a different one for PM2’s startup service.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Install Node.js and npm using the chosen method.
  2. Confirm the binaries resolve for the deploy user:
    node --version
    npm --version
  3. Record both versions in your deployment notes and in the project’s documentation.
  4. Log out and back in if the installer changed the user’s PATH.

One provider MEAN image lists Node.js 22.22.3 on a page crawled in 2026. That is an image-specific figure, not a universal requirement; a different image or application may require another LTS release.

Install MongoDB or connect to Atlas

Self-hosted MongoDB

Follow MongoDB’s repository instructions for the exact Ubuntu release and MongoDB major version. The repository entry, package names and signing-key steps differ by release, so do not substitute an installation command intended for another Ubuntu version.

  1. Add the repository and signing key specified for your Ubuntu release.
  2. Install the MongoDB server package.
  3. Enable and start the service with the service name used by that package.
  4. Check its status and recent logs before creating application users.
  5. Enable authorization, create a least-privilege user for the MEAN application, and bind MongoDB to loopback or a private interface unless a documented private-network design requires otherwise.
  6. Plan backups and test restoring one. A running database is not a backup.

Keep the database port private in both UFW and any provider-level firewall. Store the database username, password and database name in environment configuration rather than in a committed file.

MongoDB Atlas

Atlas is a fully managed MongoDB service. Create a cluster, create a database user, restrict network access to the VPS address or private network, and copy the generated connection URI. Save it securely as MONGODB_URI; MongoDB’s quick start specifically demonstrates this environment-variable pattern and warns users to protect the connection string.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Test the URI from the VPS, not only from your laptop. A local workstation allowlist entry can make development appear successful while the production VPS remains blocked.

Environment file layout

Create an environment file outside the public Angular directory, for example /var/www/mean/server/.env:

MONGODB_URI=mongodb+srv://app_user:replace-with-a-secret@cluster.example.mongodb.net/appdb
PORT=5050
NODE_ENV=production

Replace the example URI with the real value, restrict the file to the deploy user, and ensure .env is listed in .gitignore. Never place this value in Angular source: anything compiled into dist can be downloaded by a browser.

Create the Express API

Keep the backend in a separate directory from the Angular project so that NGINX can expose only the compiled frontend.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Create the application directories and switch to the server directory:
    sudo mkdir -p /var/www/mean
    sudo chown -R deploy:deploy /var/www/mean
    cd /var/www/mean
    mkdir server
    cd server
  2. Initialize the package and install the dependencies used by MongoDB’s official example:
    npm init -y
    npm install mongodb express cors dotenv
    npm install -D typescript @types/node @types/cors @types/express tsx
  3. Create server.js (or use your TypeScript entry point) and load the environment before opening the database connection.

A minimal Express entry point can follow this shape:

import 'dotenv/config';
import express from 'express';
import cors from 'cors';
import { MongoClient } from 'mongodb';

const app = express();
const port = Number(process.env.PORT || 5050);
const client = new MongoClient(process.env.MONGODB_URI);

app.use(cors());
app.use(express.json());

app.get('/api/health', (_req, res) => {
  res.json({ ok: true });
});

app.listen(port, '127.0.0.1', () => {
  console.log(`API listening on ${port}`);
});

The example uses port 5050, matching MongoDB’s current Angular/Node framework guide. Connect to MongoDB during application startup in your real code, handle connection failures, and mount your routes below the same prefix that NGINX will proxy. Do not copy sample restaurant data or routes unless they belong to your application.

If your project uses CommonJS, use its existing module style rather than mixing import and require. Add a production script to package.json, for example "start":"node server.js", or use the command appropriate to your compiled TypeScript output.

Create and build the Angular frontend

  1. Install the Angular CLI version compatible with your project:
    sudo npm install -g @angular/cli
    For a project that pins a CLI locally, prefer npx ng after installing its declared dependencies.
  2. Create a new project or clone the existing repository into a directory separate from server, such as /var/www/mean/client.
  3. Install its dependencies:
    cd /var/www/mean/client
    npm ci

    Use npm install only when you intentionally need to resolve or update the lockfile.
  4. Set the production API base URL to the reverse-proxied path, such as /api, rather than http://127.0.0.1:5050. A browser interprets loopback as the user’s own computer, not the VPS.
  5. Build for production:
    npx ng build --configuration production

Angular writes the compiled files beneath dist; the exact nested project directory depends on the Angular workspace. Find the directory containing index.html and use that directory as NGINX’s root. Keep source maps and development files out of a public directory unless you deliberately need them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configure NGINX as the public entry point

Install NGINX from the Ubuntu package repository, then create a server block for your domain. The public listener uses ports 80 and 443; Express remains on its internal port.

sudo apt install nginx -y
sudo nano /etc/nginx/sites-available/mean

Use a configuration like this, changing the domain and Angular path:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/mean/client/dist/client;
    index index.html;

    location /api/ {
        proxy_pass http://127.0.0.1:5050/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location / {
        try_files $uri $uri/ /index.html;
    }
}

The trailing slash behavior in proxy_pass matters. With the example above, NGINX removes the matching /api/ prefix before forwarding. If your Express routes include /api themselves, adjust the location and proxy target deliberately and test the resulting path.

  1. Enable the site:
    sudo ln -s /etc/nginx/sites-available/mean /etc/nginx/sites-enabled/mean
  2. Disable the default site if it conflicts:
    sudo rm -f /etc/nginx/sites-enabled/default
  3. Check syntax:
    sudo nginx -t
  4. Reload only after a successful test:
    sudo systemctl reload nginx

The try_files fallback is required for Angular’s single-page routing. Without it, loading a bookmarked route such as /orders/42 directly can return a 404 even though navigation from the home page works.

Issue HTTPS certificates

Point DNS at the VPS, confirm that port 80 reaches NGINX, then use the Certbot workflow supported by your Ubuntu image and provider. Configure the certificate for the same server block, redirect HTTP to HTTPS, and renew it automatically. Verify renewal with the provider’s documented dry-run command. Do not close port 80 if your chosen ACME validation method needs it.

Run Express with PM2

Closing SSH should not stop the API. PM2 daemonizes the Node process, records its state and can generate a system-startup unit.

  1. Install PM2 globally:
    sudo npm install pm2@latest -g
  2. Start the API from the directory containing its entry point:
    cd /var/www/mean/server
    pm2 start server.js --name mean-api
  3. Save the current process list:
    pm2 save
  4. Generate the startup command:
    pm2 startup
  5. Run the exact command printed by pm2 startup with the required privileges. It binds PM2’s saved process list to the system’s boot process.
  6. Check the result:
    pm2 ls
    pm2 logs mean-api

When the application is updated, install dependencies, rebuild if needed, then restart the named process and save the list again:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
cd /var/www/mean/server
npm ci
pm2 restart mean-api --update-env
pm2 save

Use a PM2 ecosystem file when you need several processes, a working directory, environment sets or a non-default interpreter. Keep secrets in the environment or a protected file rather than committing them to that file.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Verify the complete deployment

Perform checks from both the VPS and an external network. A green PM2 status alone does not prove that DNS, TLS, NGINX routing and MongoDB authentication work together.

  • API locally: run curl http://127.0.0.1:5050/api/health and confirm the expected JSON response.
  • Angular through NGINX: request the domain and confirm that the returned document is the production Angular shell, not the NGINX welcome page.
  • API through NGINX: request https://example.com/api/health and confirm that the request reaches Express.
  • Browser calls: open developer tools and confirm that Angular uses the relative /api path and that responses do not fail because of an incorrect CORS origin.
  • Database authentication: exercise a read and a write using the application account, then check that a bad credential fails.
  • Firewall: from another network, confirm only SSH, HTTP and HTTPS are reachable; MongoDB must not be publicly exposed.
  • Process recovery: run pm2 restart mean-api, then reboot the VPS and verify that PM2 restores the process.
  • TLS and DNS: test the hostname over HTTPS from outside the VPS and confirm the certificate covers the hostname users enter.

These are deployment acceptance checks, not a claim that any particular VPS image has already passed them. Provider images and package defaults change, so repeat them after rebuilding a server.

Manual installation versus a one-click MEAN image

Decision point Manual installation One-click image
Control You choose the Ubuntu image, package versions, ports and directory layout. The provider chooses image defaults, bundled versions and file locations.
Time to first page Longer because each layer is installed and configured. Usually faster because the provider bundles the stack and bootstrap scripts.
Maintenance You own updates, hardening, backups and compatibility testing. Bootstrap is simpler, but you still own application updates and must inspect the defaults.
Port assumptions You define the Express port and NGINX proxy path. Provider examples commonly use Express on 5000 and NGINX on public ports 80 and 443.
Migration Documented packages and paths are easier to reproduce on another VPS. Image-specific scripts and paths may require changes during migration.

Choose a one-click image when speed matters and you are willing to audit its users, firewall rules, service files, Node.js version and database exposure. Choose manual installation when you need repeatable infrastructure, a specific Ubuntu release, a private database network or a controlled upgrade schedule.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common failures and precise fixes

Angular loads, but every API call fails

Check the compiled environment value first. If it contains 127.0.0.1:5050, rebuild with a relative /api base URL. Then check the NGINX location prefix, the trailing slash on proxy_pass and the Express route path. Read /var/log/nginx/error.log and pm2 logs mean-api together so you can distinguish a proxy error from an application error.

Direct Angular routes return 404

Add or restore try_files $uri $uri/ /index.html; in the general location block, confirm that NGINX’s root is the directory containing index.html, run nginx -t, and reload NGINX.

PM2 works now but not after reboot

pm2 save alone is not enough. Run pm2 startup, execute the exact generated command, verify the process list with pm2 ls, reboot, and inspect both pm2 ls and the system journal if the process is missing.

MongoDB connections time out

For self-hosting, verify the service is running and bound to the interface Express uses; for Atlas, verify the VPS address is in the network-access list. Check DNS resolution, credentials, TLS requirements and outbound firewall rules. Do not solve a timeout by opening MongoDB to every internet address.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

NGINX reports a bad gateway

Confirm that Express is listening on the same port NGINX proxies to and that it is bound to 127.0.0.1. Use ss -ltnp and a local curl request. A stopped PM2 process, a wrong working directory or an environment file that PM2 cannot read are common causes.

Production maintenance checklist

  • Pin Node.js, Angular CLI, MongoDB and application dependencies; review upgrades in a staging environment.
  • Patch Ubuntu and NGINX regularly and remove unused packages and services.
  • Rotate database credentials and any application secrets without committing them to Git.
  • Back up MongoDB on a schedule and perform a restore test.
  • Monitor disk space, memory, PM2 restarts, NGINX errors and certificate expiry.
  • Keep MongoDB private and expose only the web ports required by the application.
  • Document the selected Express port, API prefix, Angular dist path, PM2 process name and recovery commands.
  • Recheck provider image manifests, Ubuntu support, Node.js versions, Angular compatibility, MongoDB packages and firewall defaults before rebuilding a server. These details can change within a short release cycle.

Frequently Asked Questions

Can the Angular frontend and Express API use different domains?

Yes, but a separate frontend domain requires an explicit CORS policy and usually additional cookie, CSRF and TLS configuration. Keeping both behind one NGINX hostname with an /api prefix avoids those cross-origin requirements.

Should I expose Express directly on port 5000 or 5050?

No. Those are example internal ports: provider examples use 5000, while MongoDB’s framework example uses 5050. Bind Express to loopback and let NGINX be the public entry point.

Can I install MongoDB and the Node application on the same VPS?

You can on a small deployment if the VPS has enough memory, disk and backup capacity, but the services then share one failure domain. A managed database or separate private database host provides stronger isolation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why does an environment variable work in Express but not in Angular?

Express reads environment variables at runtime on the server. Angular values are embedded when the application is built, so changing the VPS environment after ng build does not change the browser bundle; rebuild it and never embed secrets.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.