Cấu hình này em đang sử dụng, nếu có gì sai sót, anh em chỉ bảo để em fix lại hoặc tối ưu thêm: 0. Bài toán test1.com => site chính sử dụng php sub1.test1.com => xử lý vào ra sử dụng nodejs sub2.test1.com => xử lý vào ra sử dụng nodejs ... 1. Cloudflare: thêm các sub domain tương tự như đối với sub1 **note**: thậm chí các ipv4 có thể khác nhau nếu như có nhiều vps 2. apache/nginx: Cài đặt apache hoặc nginx, ở đây em dùng apache Đối với apache, cần kích hoạt chế độ proxy (với nginx thì không cần) Code: sudo a2enmod proxy sudo a2enmod proxy_http sudo a2enmod proxy_balancer sudo a2enmod lbmethod_byrequests Q1: Tại sao app chạy rồi mà ta vẫn phải cần apache hoặc nginx? Vì: apache hoặc nginx là phần mềm web server, có tính toán sẵn các cơ chế cân bằng, giúp vận hành website của một cách ổn định so với việc chạy nodejs hoặc php 1 cách thẳng thừng, nhất là đối với nodejs, 1 vài đánh giá trên mạng nói rằng tích hợp apache cho phép nodejs xử lý các truy nhập cùng lúc tốt hơn. Q2: Tại sao lại cấu hình proxy cho apache hay nginx? Vì: Đối với các phiên bản hiện tại của apache hay nginx, chưa có cách cấu hình nào để tích hợp với ứng dụng nodejs ngoài chế độ proxy. Q3: Chế độ proxy này hiểu như thế nào? Hiểu là: khi user tạo 1 request (req) A hợp lệ kết nối tới vps, apache phụ trách phân tích req A này và gửi 1 req B khác tới nodejs, sau đó trả lại thông tin cho user. Các headers trong req A và req B có sự ràng buộc, ví dụ ở A: req.headers.host = 'sub1.test1.com', ở B: req.headers.host = 'localhost' còn req.headers['x-forwarded-host']= 'sub1.test1.com'. Tuy nhiên khi sử dụng nginx, tôi có thể cấu hình để req A và req B giống nhau 1 cách tương đối: ví dụ như ở đây reqA.header.host= reqB.header.host, ip của user có thể lấy trực tiếp trên headers của reqB 'X-Real-IP' thông qua cấu hình: Code: location / { proxy_pass http://localhost:<port_của_app>/; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # ..... } 3. Chạy thử Cài đặt nodejs, php ... và chạy thử trên localhost, nếu như vps ko có vncserver, có thể cài đặt apache và cấu hình nhanh, rồi vào http://<ip_của_vps>/ để kiểm thử Code: <VirtualHost *:80> ServerName <ip_của_vps> ServerAlias <ip_của_vps> ProxyRequests on ProxyPass / http://localhost:<port_của_app>/ #có thể thay localhost bằng 127.0.0.1 </VirtualHost> Đối với app chạy php, chưa vội thiết lập dạng Directory, cứ thiết lập kiểu proxy như trên, và "cd <thư_mục_app>", rồi chạy app dạng "php artisan serve". Đối với app chạy nodejs, "cd <thư_mục_app>", rồi chạy "node <file_app.js>" 4. Triển khai mã: mã php để ở: /var/www/html/app_php_1/ mã nodejs để ở /home/app1/ Với php, cấu hình dạng Directory, không cần chạy app, chỉ cần chạy apache, app tự bật Với nodejs, cấu hình dạng ProxyPass, do đó app phải chạy sẵn, sử dụng npmjs[dot]com/package/forever để nodejs chạy dạng service 5. Cấu hình apache: Code: sudo nano /etc/apache2/sites-available/cau_hinh_1.conf Nội dung file: cau_hinh_1.conf Code: <VirtualHost *:80> <Directory /var/www/html/app_php_1/> Options FollowSymlinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory /var/www/html/app_php_1/> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*) index.php [PT,L] </Directory> DocumentRoot /var/www/html/app_php_1 ServerName test1.com ServerAlias test1.com </VirtualHost> <VirtualHost *:80> ServerName test1.com ServerAlias sub1.test1.com ProxyRequests on ProxyPass / http://localhost:<port_của_app>/ </VirtualHost> <VirtualHost *:80> ServerName test1.com ServerAlias sub2.test1.com ProxyRequests on ProxyPass / http://localhost:<port_của_app>/ </VirtualHost> Kích hoạt cau_hinh_1.conf, khởi động lại apache Code: cd /etc/apache2/sites-available/ sudo a2ensite cau_hinh_1.conf sudo a2enmod rewrite sudo systemctl restart apache2.service Tuy cấu hình giống nhau ở ServerAlias sub1.test1.com và sub2.test1.com, nhưng trong app của nodejs, ta tách ra: Cách 1: tách theo path url, ví dụ sub1.test1.com/sub1/...., sub2.test1.com/sub2/.... Code: // in app.js app.use('/sub1', require('./routes/sub1.js')); app.use('/sub2', require('./routes/sub2.js')); // in ./routes/sub1.js router.use('*', function(req, res, next){ if(req.headers['x-forwarded-host']!= 'sub1.test1.com') res.redirect(301, 'https://test1.com/'); else next(); }) // in ./routes/sub2.js router.use('*', function(req, res, next){ if(req.headers['x-forwarded-host']!= 'sub2.test1.com') res.redirect(301, 'https://test1.com/'); else next(); }) Cách 2: Không tách theo path url Code: // in app.js app.use('*', function(req, res, next){ if(req.headers['x-forwarded-host']!= 'sub1.test1.com') { // luật logic 1 ... res.end('sub1 here'); } else if(req.headers['x-forwarded-host']!= 'sub2.test1.com') { // luật logic 2 ... res.end('sub2 here'); } else next(); }); 6. Lưu ý: mặc định apache triển khai mã từ: /var/www/html/, ta để mã php ở /var/www/html/app_php_1/, nên ở thư mục /var/www/html/, có thể tạo nhanh file index.php để tránh các truy cập bất cần đời như http:// <ip_của_vps> / Code: <?php header("HTTP/1.1 301 Moved Permanently"); header("Location: https://google.com/"); ?>