MEAN Stack
Overview
The MEAN Stack is MongoDB, Express, Angular and Node.js working together as a full-stack JavaScript platform. This image installs, configures and connects all four on a single Amazon EC2 instance. A small sample full-stack application is already running, so you can browse to port 80 as soon as the instance reaches the ready state and see the stack working end to end.
What you get:
- Node.js 22 LTS, installed from the official NodeSource Debian repository.
- MongoDB 7 Community, installed from the official mongodb.org Debian repository and running with SCRAM-SHA-256 authentication enabled.
- A sample Express 4 API server at
/opt/mean/sac, run by pm2 as a systemd service calledmean-app.serviceand listening on the loopback interface on port 3000. - nginx configured as a reverse proxy in front of Express, terminating port 80 and forwarding all requests to the Node.js application.
- A prebuilt Angular 18 single-page front end, served as static assets from
/opt/mean/sac/public. - MongoDB administrator, MongoDB application and Express session credentials generated on the first boot of every deployed instance.
Two instances launched from the same Amazon Machine Image never share passwords. The credentials are written to /root/mean-credentials.txt with mode 0600, so only the root user can read them.
You are expected to replace the sample application with your own MEAN application. The surrounding scaffolding stays the same: nginx, pm2 under systemd, MongoDB, and the first-boot credential rotation. Replace /opt/mean/sac with your own code, point mean-app.service at it, and ship.
Prerequisites
Before you deploy this image, make sure you have:
- An Amazon Web Services account where you can launch EC2 instances.
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products.
- An EC2 key pair in the target Region for SSH access to the instance.
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network and inbound port 80 from the networks your visitors will use.
- The AWS CLI (version 2) installed locally, if you plan to deploy from the command line.
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for MEAN Stack. Select the SecureAnyCloud listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger, because MongoDB and Node.js both benefit from extra memory under load. Choose your EC2 key pair under Key pair (login).
Under Network settings, select your VPC and subnet. Create or select a security group that allows inbound port 22 from your management network and inbound port 80 from the networks your visitors use. Leave the root volume at the default size or larger.
Select Launch instance. First-boot initialisation takes approximately one minute after the instance state becomes Running and the status checks pass.
Launch the Instance from the AWS CLI
The following command launches an instance from the SecureAnyCloud MEAN Stack Marketplace AMI into an existing subnet and security group.
Replace <ami-id> with the AMI ID shown on the Marketplace listing. Replace <key-name> with your EC2 key pair name and <subnet-id> with your subnet ID. Replace <security-group-id> with a security group that opens ports 22 and 80 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":20,"VolumeType":"gp3"}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=mean-stack-01}]'On success, the command prints a JSON document. Note the instance ID, then retrieve the instance's public address once it is running with aws ec2 describe-instances --instance-ids <instance-id> --query "Reservations[].Instances[].PublicIpAddress" --output text.
Connect and Retrieve Initial Credentials
Connect over SSH with the key pair you selected and the public IP address from step 2. The SSH login user depends on the operating system of the AMI variant you launched. For MEAN Stack on Ubuntu 24.04, the user is ubuntu.
This is an example for the Ubuntu 24.04 variant.
ssh -i <your-key>.pem ubuntu@<instance-public-ip>Once you have shell access, read the credentials file that first boot generated.
sudo cat /root/mean-credentials.txtThe file contains the per-instance MongoDB administrator user, the MongoDB application user, the database name and the Express app secret. Store the contents in a password manager and remove the file once you have recorded the values.
Browse the Sample Application
The sample application is served on port 80. Open a browser and visit the instance's public address.
http://<instance-public-ip>/You see the SecureAnyCloud MEAN Stack starter page. It shows the four components of the stack, reports the health of the Express API, and lists the documents currently in the sample collection. The API inserts a welcome document automatically the first time it runs.
The starter page renders an Angular front end, served as static assets from /opt/mean/sac/public. The front end calls the Express API at /api/items, which reads from and writes to the sac.items collection in MongoDB. Every page load exercises the full Angular -> Express -> MongoDB round trip.
Add Items Through the Sample UI
The starter page includes a form to add new items. Enter a name and an optional note, then choose Add.
The Angular front end issues an HTTP POST to /api/items, and nginx forwards the request to Express on 127.0.0.1:3000. Express inserts a document into MongoDB as the application MongoDB user, authenticated against the SecureAnyCloud database with SCRAM-SHA-256. The new item appears at the top of the list, which is ordered by creation time.
Delete items individually with the Delete button on each row. The front end issues DELETE /api/items/<id>, which Express routes to MongoDB.
Exercise the API Directly with curl
The sample API is also reachable directly. From the EC2 instance, check its health.
curl -s http://127.0.0.1/api/healthThis returns a small JSON document that confirms the API is up and that the Express app secret has been loaded from the environment file. The secretConfigured field should report true.
To list items, run the following.
curl -s http://127.0.0.1/api/itemsTo create an item from the command line, run the following.
curl -s -X POST http://127.0.0.1/api/items \
-H 'Content-Type: application/json' \
-d '{"name":"my first item","note":"created from the command line"}'Connect to MongoDB
The MongoDB shell mongosh is preinstalled. Use it with the application credentials from /root/mean-credentials.txt.
APP_PASS=$(sudo grep '^mongo.app.password=' /root/mean-credentials.txt | cut -d= -f2-) mongosh "mongodb://sac:${APP_PASS}@127.0.0.1:27017/sac?authSource=sac"Inside the shell, the items collection of the SecureAnyCloud database is the one that the sample API reads and writes.
use sac db.items.countDocuments({}) db.items.find().sort({createdAt: -1}).limit(5)For administrative work, use the administrator credentials from the same file.
ADMIN_PASS=$(sudo grep '^mongo.admin.password=' /root/mean-credentials.txt | cut -d= -f2-) mongosh "mongodb://marketplaceAdmin:${ADMIN_PASS}@127.0.0.1:27017/?authSource=admin"MongoDB listens on port 27017 on all interfaces by default, so only the AWS security group on the instance controls who can reach it. Open port 27017 in the security group only to the trusted networks that need direct database access.
Replace the Sample With Your Own MEAN Application
The image is a starting point. Replace the sample at /opt/mean/sac with your own MEAN application.
The mean-app.service unit expects this layout:
/opt/mean/sac/package.jsondeclaring your Node.js dependencies and amainentry point./opt/mean/sac/server.js(or whatevermainpoints to) as the Node.js process that pm2-runtime launches.- A static front end in
/opt/mean/sac/public/(the Angular build output) that Express serves.
The Express process reads the MongoDB connection string and the app secret from /etc/meanapp/sac.env. The keys are as follows.
NODE_ENV=production PORT=3000 MONGO_DB=sac MONGO_URI=mongodb://sac:<password>@127.0.0.1:27017/sac?authSource=sac APP_SECRET=<random>To deploy your own application, run the following.
# Stop the sample
sudo systemctl stop mean-app.service
# Replace the code (as ubuntu, then chown for the runtime user)
sudo rm -rf /opt/mean/sac
sudo mkdir -p /opt/mean/sac
sudo chown meanapp:meanapp /opt/mean/sac
sudo -u meanapp git clone <your-repo-url> /opt/mean/sac
# Install dependencies as the runtime user cd /opt/mean/sac
sudo -u meanapp env HOME=/var/lib/meanapp npm install --omit=dev --no-fund --no-audit
# If your Angular front end needs building, build it once here:
#
sudo -u meanapp env HOME=/var/lib/meanapp npm run build
# and copy the build output into /opt/mean/sac/public/
# Restart the service
sudo systemctl restart mean-app.serviceYour application now runs in place of the sample. The environment file, the MongoDB users, the nginx vhost and the systemd unit all continue to apply.
Operate the Stack
These systemd units make up the stack:
- mongod.service: MongoDB 7 Community, listening on 27017.
- mean-app.service: the Express API, run by pm2-runtime, on 127.0.0.1:3000.
- nginx.service: the reverse proxy, on port 80.
- mean-firstboot.service: a one-shot unit that rotates credentials on first boot.
Check the status of all services at once.
sudo systemctl is-active mongod.service mean-app.service nginx.serviceRestart the Node.js application after a code or environment change.
sudo systemctl restart mean-app.serviceApplication stdout and stderr are written to /var/log/meanapp/stdout.log and /var/log/meanapp/stderr.log respectively. Tail them while you debug.
sudo tail -f /var/log/meanapp/stdout.log /var/log/meanapp/stderr.logMongoDB logs go to /var/log/mongodb/mongod.log and nginx logs go to /var/log/nginx/.
Enable HTTPS With Let's Encrypt
The image ships with port 80 open and port 443 closed by default. To enable HTTPS, complete these steps:
- Open port 443 inbound in the EC2 security group on the instance.
- Point a DNS A record at the instance public IP and wait for propagation.
- Install certbot and request a certificate.
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.comCertbot reads the existing nginx vhost, requests a certificate, writes a new HTTPS server block and reloads nginx. The redirect from port 80 to port 443 is optional, and certbot offers to add it.
Backup and Restore
The MongoDB data directory is /var/lib/mongodb. The simplest way to back it up is mongodump to S3.
ADMIN_PASS=$(sudo grep '^mongo.admin.password=' /root/mean-credentials.txt | cut -d= -f2-) sudo mongodump --uri "mongodb://marketplaceAdmin:${ADMIN_PASS}@127.0.0.1:27017/?authSource=admin" \
--archive=/tmp/mean-$(date +%F).archive --gzip aws s3 cp /tmp/mean-*.archive s3://<your-backup-bucket>/mean/Restore in the reverse direction with mongorestore --archive=<file> --gzip.
Troubleshooting
The page reports API not reachable. The service mean-app.service is not running. Restart it with sudo systemctl restart mean-app.service and inspect /var/log/meanapp/stderr.log for the failure reason.
The page renders but /api/items returns 502 Bad Gateway: nginx is up but cannot reach Express. Confirm Express is listening with sudo ss -tlnp | grep 3000. If not, restart mean-app.service.
MongoDB authentication fails: the credentials file was generated on first boot. Confirm that /root/mean-credentials.txt exists, and check that the application user line matches the env file at /etc/meanapp/sac.env. The two should agree, because mean-firstboot.service writes both.
Credentials file is missing: first boot did not run successfully. Check sudo systemctl status mean-firstboot.service for the failure reason. Once you have fixed it, remove /var/lib/sac/data/mean-firstboot.done and start the service again.
Screenshots
The sample MEAN application welcome page, served on first boot with no manual setup.
The sample Angular front end listing documents read from MongoDB via the Express API.
Creating a new item: Angular POSTs to Express, which writes to MongoDB.
The MEAN Stack overview view showing the running service health.
Support
This image is sold on the AWS Marketplace by SecureAnyCloud, which provides 24x7 technical support by email and chat for installation, configuration, upgrades and tuning of the MEAN Stack.
Deploy on AWS
Launch MEAN Stack on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com