build
Perfect! Let’s design a production-ready setup for multiple Node/Vite apps on a single EC2 instance using subdomains + Nginx + HTTPS + PM2. This will allow you to host multiple apps like op1.evolo.fr, op2.evolo.fr, etc., efficiently.
1️⃣ Folder Structure
Section titled “1️⃣ Folder Structure”On your EC2 instance, create a structure like:
/home/ubuntu/apps/├── op1│ ├── dist/ # built Vite project│ ├── package.json│ └── ecosystem.config.js # PM2 config├── op2│ └── ...- Each app has its own folder.
- Vite projects must be built first (
npm run build) intodist/.
2️⃣ Install PM2 (process manager)
Section titled “2️⃣ Install PM2 (process manager)”sudo npm install -g pm2pm2 startup systemd- PM2 keeps Node apps alive after reboots.
- You can manage apps individually:
pm2 start index.js --name op1pm2 start index.js --name op2pm2 save3️⃣ Install and configure Nginx
Section titled “3️⃣ Install and configure Nginx”sudo apt updatesudo apt install nginx -y- Nginx will serve multiple apps via subdomains.
4️⃣ Nginx config for multiple subdomains
Section titled “4️⃣ Nginx config for multiple subdomains”Create a config file:
sudo nano /etc/nginx/sites-available/evoloExample config:
# OP1server { listen 80; server_name op1.evolo.fr;
root /home/ubuntu/apps/op1/dist; index index.html;
location / { try_files $uri /index.html; }}
# OP2server { listen 80; server_name op2.evolo.fr;
root /home/ubuntu/apps/op2/dist; index index.html;
location / { try_files $uri /index.html; }}Enable the site:
sudo ln -s /etc/nginx/sites-available/evolo /etc/nginx/sites-enabled/sudo nginx -tsudo systemctl reload nginx5️⃣ Enable HTTPS for all subdomains
Section titled “5️⃣ Enable HTTPS for all subdomains”Install Certbot:
sudo apt install certbot python3-certbot-nginx -yRun for each subdomain:
sudo certbot --nginx -d op1.evolo.frsudo certbot --nginx -d op2.evolo.fr- Certbot auto-configures Nginx for SSL.
- Certificates auto-renew every 90 days.
6️⃣ Optional: Node API Backend
Section titled “6️⃣ Optional: Node API Backend”If you have a Node.js backend (Express/Nest/etc.):
- Run with PM2:
pm2 start server.js --name api-op1pm2 save- Add reverse proxy in Nginx:
server { listen 80; server_name api.op1.evolo.fr;
location / { proxy_pass http://localhost:3000; # Node API port 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; }}- HTTPS via Certbot as above.
7️⃣ Deployment workflow (recommended)
Section titled “7️⃣ Deployment workflow (recommended)”- Pull repo / sync files (
rsyncorgit pull) - Install dependencies (
npm install) - Build Vite app (
npm run build) - PM2 restart Node backend (if any)
- Nginx serves
dist/automatically
✅ Can also be scripted into a one-command deploy script.
8️⃣ Notes / Best Practices
Section titled “8️⃣ Notes / Best Practices”- Each subdomain points to a different folder
- Frontend Vite apps go in
dist/ - Node backends run via PM2 on separate ports
- Nginx handles HTTPS + routing
- Optional CDN for static assets improves performance
I can make a full ready-to-use template including:
- Folder structure
- PM2
ecosystem.config.jsfor multiple apps - Nginx config with SSL for all subdomains
- One-command deployment script
This would let you deploy and serve multiple Node/Vite apps on EC2 with HTTPS immediately.
Do you want me to create it?
✅ copy direct build
Section titled “✅ copy direct build”Create the folder with sudo, then give ubuntu write access
sudo mkdir -p /var/www/test1sudo chown -R ubuntu:ubuntu /var/www/test1rsync -avz \-e "ssh -i ~/.ssh/web1.pem" \./dist/ \ubuntu@op1.evolo.fr:/var/www/test1/ --rsync-path="sudo rsync"enable site:
sudo ln -s /etc/nginx/sites-available/test1 /etc/nginx/sites-enabled/restart
sudo nginx -tsudo systemctl reload nginxAh — you want to “push” your local build to EC2, and avoid accidentally deleting or overwriting files in the destination that aren’t in your local folder.
By default, your command:
rsync -avz -e "ssh -i ~/.ssh/web1.pem" ./dist/ ubuntu@op1.evolo.fr:/var/www/test1/- Copies all files from
./dist/to/var/www/test1/ - Overwrites files with the same name
- Does not delete extra files on the server
So in rsync terms, this is already a “push”, not a full sync.
✅ If you want to ensure no files are deleted on the server
Section titled “✅ If you want to ensure no files are deleted on the server”- Do NOT use
--delete - Your current command is fine:
rsync -avz -e "ssh -i ~/.ssh/web1.pem" ./dist/ ubuntu@op1.evolo.fr:/var/www/test1/This pushes your local files but keeps existing files on the server.
⚡ Optional: Dry-run first
Section titled “⚡ Optional: Dry-run first”To be extra safe, you can see what would happen without actually copying:
rsync -avzn -e "ssh -i ~/.ssh/web1.pem" ./dist/ ubuntu@op1.evolo.fr:/var/www/test1/-n→ dry run- You can check the output, then run the command without
-nto actually push.
✅ Extra tips
Section titled “✅ Extra tips”- Use a trailing slash on local folder
./dist/→ copies contents, not the folder itself. - Always check permissions on the server after pushing:
sudo chown -R www-data:www-data /var/www/test1sudo chmod -R 755 /var/www/test1This ensures NGINX can serve the files.
✅ Explication
Section titled “✅ Explication”1️⃣ sudo chown -R www-data:www-data /var/www/test1
Section titled “1️⃣ sudo chown -R www-data:www-data /var/www/test1”-
sudo: Runs the command as the superuser (root), which is required to modify files owned by other users. -
chown: Stands for change owner. It changes the owner and group of a file or directory. -
-R: Means recursive, so the command applies to/var/www/test1and everything inside it. -
www-data:www-data:- The first
www-datais the user owner. - The second
www-datais the group owner. www-datais the typical user/group used by web servers like Apache or Nginx.
- The first
-
/var/www/test1: The target directory whose ownership you want to change.
✅ Effect: All files and directories under /var/www/test1 will now be owned by the www-data user and group. This is essential for a web server to read/write files safely.
2️⃣ sudo chmod -R 755 /var/www/test1
Section titled “2️⃣ sudo chmod -R 755 /var/www/test1”chmod: Stands for change mode. It modifies file permissions.-R: Recursive, applies to the directory and all its contents.755: A numeric representation of permissions:
| Digit | Meaning | Example |
|---|---|---|
| 7 | Owner can read, write, execute (4+2+1) | rwx |
| 5 | Group can read and execute (4+0+1) | r-x |
| 5 | Others can read and execute (4+0+1) | r-x |
/var/www/test1: Target directory.
✅ Effect:
- Owner (
www-data) can read/write/execute. - Group and others can read and execute, but cannot modify files.
- This is a common setting for web directories so the server can serve files, but users can’t modify them.
💡 Summary
Section titled “💡 Summary”chown→ sets who owns the files (user & group).chmod→ sets what permissions everyone has.
These two commands together make /var/www/test1 owned by the web server and readable/executable for it and visitors, but only writable by the server.
check owner and permissions
Section titled “check owner and permissions”You can check both the owner and permissions of a file or directory using the ls command. Here’s how:
1️⃣ Check a single file or directory
Section titled “1️⃣ Check a single file or directory”ls -l /var/www/test1Example output:
drwxr-xr-x 5 www-data www-data 4096 Nov 16 17:00 test1Breaking it down:
| Part | Meaning |
|---|---|
drwxr-xr-x | File type & permissions (d = directory, rwx = read/write/execute for owner, r-x = read/execute for group and others) |
5 | Number of hard links |
www-data | Owner of the file/directory |
www-data | Group of the file/directory |
4096 | Size in bytes |
Nov 16 17:00 | Last modification date |
test1 | File/directory name |
2️⃣ Check recursively (all files inside)
Section titled “2️⃣ Check recursively (all files inside)”ls -lR /var/www/test1This will list all files and folders inside test1 with their owners and permissions.
3️⃣ Alternative: using stat
Section titled “3️⃣ Alternative: using stat”stat /var/www/test1Example output:
File: /var/www/test1 Size: 4096 Blocks: 8 IO Block: 4096 directoryDevice: 802h/2050d Inode: 123456 Links: 5Access: (0755/drwxr-xr-x) Uid: ( 1001/www-data) Gid: ( 1001/www-data)Access: 2025-11-16 17:00:00.000000000Modify: 2025-11-16 17:00:00.000000000Change: 2025-11-16 17:00:00.000000000Uid= OwnerGid= GroupAccess= Permissions in octal and symbolic (0755 / drwxr-xr-x)
If you want, I can also show a super quick one-liner to see just owner and permissions for all files under /var/www/test1 in a readable format.
Do you want me to do that?