Mục lục
1. Chọn VPS
Để build strapi cần một vps 2GB ram trở lên, TH nếu ko sẽ bị lỗi. Thường thì dẽ chọn ubuntu 20.04 để cài đặt cho dễ quản lý
sudo apt-get update # Update
2. Cài đặt swap cho ubuntu
Tiến hành cài đặt swap để khi trường hợp không đủ ram để sử dụng có thể swap vào ổ cứng, hiện tại đều sử dụng SSD nên tốc độ sẽ khá tốt, nên chọn VPS Nvme.
Xem thêm: https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-20-04
Đối với EC2, dùng một volume mới như một vùng swap
# Chạy lsblk để xem danh sách ổ đĩa, trong đó có /dev/xvdf lsblk #Tạo swap cho ổ cứng vừa mount vào sudo mkswap /dev/xvdf # Enable swap sudo swapon /dev/xvdf # Thêm cấu hình vào file /etc/fstab để chạy swap khi khởi động sudo vi /etc/fstab #Thêm dòng bên dưới /dev/xvdf none swap sw 0 0 # Check swap sudo swapon --show
Đối với EC2 mount volumes sang một folder và tạo swap
https://aws.amazon.com/premiumsupport/knowledge-center/ec2-memory-partition-hard-drive/
Trong đó https://www.cyberciti.biz/faq/debian-ubuntu-reload-partition-table/
https://dev.to/hardiksondagar/how-to-use-aws-ebs-volume-as-a-swap-memory-5d15
https://www.bogotobogo.com/DevOps/AWS/aws_adding_swap_space_to_attached_volume_via_mkswap_and_swapon.php
3. Cài đặt vsftpd
Để cài đặt vsftp cần làm theo link bên dưới
https://www.digitalocean.com/community/tutorials/how-to-set-up-vsftpd-for-a-user-s-directory-on-ubuntu-20-04
Chú ý các bước sau:
Mở port cho vsftp
sudo ufw allow 20/tcp sudo ufw allow 21/tcp sudo ufw allow 40000:50000/tcp --> port này là dải port mở để truyền dữ liệu, phải đăng kí trong config vsftpd sudo ufw status
Sau khi tạo thành công user thì thêm vào file để cho phép user sử dụng ftp
echo "sammy" | sudo tee -a /etc/vsftpd.userlist
Config cho vsftp chuẩn /etc/vsftpd.conf
listen=NO listen_ipv6=YES anonymous_enable=NO local_enable=YES write_enable=YES local_umask=022 dirmessage_enable=YES use_localtime=YES xferlog_enable=YES connect_from_port_20=YES chroot_local_user=YES secure_chroot_dir=/var/run/vsftpd/empty pam_service_name=vsftpd force_dot_files=YES pasv_min_port=40000 pasv_max_port=50000 #user_sub_token=$USER #local_root=/home/$USER/public_html allow_writeable_chroot=YES ssl_enable=YES rsa_cert_file=/etc/ssl/private/vsftpd.pem allow_anon_ssl=NO force_local_data_ssl=YES force_local_logins_ssl=YES ssl_tlsv1=YES ssl_sslv2=NO ssl_sslv3=NO require_ssl_reuse=NO ssl_ciphers=HIGH port_enable=YES pasv_enable=YES pasv_address=3.1.142.167 pasv_addr_resolve=YES check_shell=NO passwd_chroot_enable=YES
4. Cài đặt nginx
Tiến hành cài đặt nginx theo link:
https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04
Trong đó chú ý /etc/nginx/sites-enable
và /etc/nginx/config.d
là 2 nơi để chứa config cho nginx
Cấu hình nginx mẫu: domain.conf
server { # Listen HTTP listen 80; server_name domain.com; # Redirect HTTP to HTTPS return 301 https://$host$request_uri; } server { # Listen HTTPS listen 443 ssl; server_name domain.com; # SSL config ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; # managed by Certbot ## Gzip config gzip on; client_max_body_size 512M; # .Netcore location / { proxy_pass https://frontend; proxy_http_version 1.1; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $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; proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_pass_request_headers on; } # Strapi API location /api/ { rewrite ^/api/?(.*)$ /$1 break; proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $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; proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_pass_request_headers on; } # Strapi Dashboard location /admin { proxy_pass http://backend/admin; proxy_http_version 1.1; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $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; proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_pass_request_headers on; } }
Và upstream.conf
upstream frontend { server 127.0.0.1:6300; } upstream backend { server 127.0.0.1:1337; }
5.Cài đặt .netcore
Cài đặt .netcore để chạy và build frontend theo link:
https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu
Thường thì sẽ cài theo source 3.1 hay 5.0.
6. Cài đặt node và npm
Tiến hành cài đặt node và npm, hãy xem requiredment của strapi mà cài đặt đúng version, sai khác sẽ gây ra lỗi.
https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04
7. Cài đặt pm2
Thông thường các .netcore hay strapi chạy sẽ là chạy trực tiếp, điều này sẽ gây ra một số vấn đề. Vì vậy cần đưa nó chạy dưới nền, để không ảnh hưởng tới các process khác. Trước kia sử dụng dùng các tool khác, hiện nay có thể sử dụng pm2, khá đơn giản.
Cài đặt pm2 ở đây
https://pm2.keymetrics.io/docs/usage/quick-start/
Với các câu lệnh thông dụng:
# Sẽ tạo ra file ecosystem.conf dùng để lưu cấu hình pm2 init # Lưu cấu hình pm2 lại pm2 save # Dùng để tạo ra câu command để bạn chạy nó để cho app chạy nền được gọi khi khởi động pm2 startup # Khơi chạy config pm2 start ecosystem.conf.js / pm2 start {tên config} # Dừng config pm2 stop {tên config} # Xem tất cả config của user pm2 status # Xem chi tiết logs một config pm2 logs {tên config} #pm2 del {tên config}/ {Số thứ tự config}
8. Cài đặt ssl dùng Let’s Encrypt
Cài đặt theo hướng dẫn, lưu ý backup config của nginx default.conf
trước khi chạy cerbot.
https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04
9. Cấu hình Strapi
Cấu hình s3 bucket
Tạo user để dùng đó làm clientid + secrect key kết nối s3
https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/amazon-aws.html#amazon-aws-install-requirements-and-creating-an-iam-non-root-user
Tạo s3 bucket
https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/amazon-aws.html#configure-s3-for-image-hosting
Đừng quên cấu hình Object Ownership
trong Permission
và cấu hình ACL enabled
chọn Object write
Cấu hình config cho strapi
Theo như đường dẫn:
https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/deployment/hosting-guides/amazon-aws.html#_3-install-the-strapi-aws-s3-upload-provider
Với config/plugins.js
module.exports = ({ env }) => ({ upload: { provider: 'aws-s3', providerOptions: { accessKeyId: env('AWS_ACCESS_KEY_ID'), secretAccessKey: env('AWS_ACCESS_SECRET'), region: env('AWS_REGION'), params: { Bucket: env('AWS_BUCKET_NAME'), }, cdn: env('AWS_CLOUDFRONT'), // CDN Url localServer: { maxage: 300000 } }, breakpoints: { xlarge: 1920, large: 1000, small: 500 } } });
Sử dụng thư viện:
https://www.npmjs.com/package/strapi-provider-upload-aws-s3-plus-cdn
Với config/plugins.js
module.exports = ({ env }) => ({ // ... upload: { provider: 'aws-s3-plus-cdn', providerOptions: { accessKeyId: env('AWS_ACCESS_KEY_ID'), secretAccessKey: env('AWS_ACCESS_SECRET'), region: env('AWS_REGION'), params: { Bucket: env('AWS_BUCKET'), }, cdnUrl: env("CDN_URL"), // Optional CDN URL - include protofol and trailing forward slash, e.g. 'https://assets.example.com/' }, }, // ... });
Cấu hình redis cache
Cài đặt strapi-middleware-cache
trong npm và cấu hình config/midleware.js
module.exports = ({ env }) => ({ settings: { cache: { enabled: true, type: 'redis', maxAge: 2600000, max: 400, cacheTimeout: 400, enableEtagSupport: true, logs: true, populateContext: false, models: ['blos'], // Models want to have cache redisConfig: { sentinels: [ { host: '192.168.10.41', port: 26379 }, { host: '192.168.10.42', port: 26379 }, { host: '192.168.10.43', port: 26379 }, ], name: 'redis-primary', } //or you can connect to redis lab with the command below. redisConfig: { host: 'localhost', port: 6379, password: 'secret_password', }, } } });
Xem thêm:
https://strapi.io/blog/caching-in-strapi-strapi-middleware-cache
Cấu hình backend strapi
File config/sever.js
module.exports = ({ env }) => ({ host: env('HOST'), port: env.int('PORT'), url: env('APP_URL'), admin: { url: env('APP_ADMIN_URL'), auth: { secret: env('ADMIN_JWT_SECRET'), }, }, cron: { enabled: env('CRON_JOB', false) }, });
File .env
Thường thì tạo config cho mỗi môi trường sẽ có config/env/{production}
– config/env/{stagging}
– config/env/{development}
Chép các file config và chỉnh sửa cho phù hợp.
File pm2 config
Thông thường file pm2 config cho strapi sẽ có thông tin sau:
module.exports = { apps: [ { name: 'strapi', cwd: '/home/strapi/public_html', script: 'npm', args: 'start', env: { NODE_ENV: 'production', DATABASE_HOST: 'database url', DATABASE_PORT: '3306', DATABASE_NAME: 'strapi', DATABASE_USERNAME: 'admin', DATABASE_PASSWORD: 'ciadmin123', 'DATABASE_SSL': 'true', AWS_ACCESS_KEY_ID: 'AKIAVL4SNFVVKZUU3IEX', AWS_ACCESS_SECRET: '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', // Find it in Amazon S3 Dashboard AWS_REGION: 'ap-southeast-1', AWS_BUCKET_NAME: 'ci-strapi-s3', }, }, ], }; // Các thông tin .env sẽ đè .env trong config
Qui trình build strapi
Thông thường sẽ là:
# Đăng nhập user su strapi # Về thư mục home/user vào backend cd ~ && cd backend # Dừng ứng dụng đang chạy pm2 stop {config} # Tải code về git pull # Cài package npm install # Build với môi trường production NODE_ENV=production npm run build # Khởi chạy ứng dụng pm2 start {config} #Xem logs hoạt động pm2 logs {config}
10. Cấu hình .netcore
Cấu hình để có thể build trên linux
Nguồn từ bài viết:
https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-5.0
Trong file SmartCsmNetCore.Site.csproj
thêm <RuntimeIdentifiers>win10-x64;linux-x64</RuntimeIdentifiers>
để thêm cấu hình build cho linux.
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework> <AssemblyName>SmartCsmNetCore.Site</AssemblyName> <RootNamespace>SmartCsmNetCore.Site</RootNamespace> <UserSecretsId>bb4bb8e8-7f9b-41cb-b4a9-2141b7337bea</UserSecretsId> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PlatformTarget>x64</PlatformTarget> </PropertyGroup> <PropertyGroup> <RuntimeIdentifiers>win10-x64;linux-x64</RuntimeIdentifiers> </PropertyGroup> <ItemGroup> <Content Remove="package.json" /> </ItemGroup>
File appsetting.json
{ "Logging": { "LogFilePath": "logs/ci-mvc/ci-mvc.txt", "LogFilePathError": "logs/ci-mvc-errors/ci-mvc.txt" }, "AllowedHosts": "*", "Tokens": { "Key": "6J1MNCBkG3yc7zj04c", "Issuer": "localhost", "TokenExpired": 15 }, "Urls": [ "https://localhost:6300" ], "Website": "http://localhost:6234", "CorsSettings": { "AllowOrigin": "*", "AllowMethod": "*", "AllowHeader": "*" }, "AppSettings": { "Item1": "Item1 value", "SampleSettings": { "SampleString": "SampleString value" } }, "WebAPI": "https://api", "TokenAPI": { "Key": "123", "Issuer": "localhost", "TokenExpired": 15 } } # Trong source cần cấu hình để tiếp nhận proxy header, cấu hình bảo mật + cấu hình để bắt chạy https mặc định.
Qui trình chạy
# Đăng nhập user su {user} # Về thư mục home/user/sources cd ~ && cd sources # Dừng ứng dụng pm2 stop {config} #Kéo source về hay upload ftp, về folder sources git pull # Build source .netcore dotnet publish /home/{user}/sources/SmartCsmNetCore.Site/SmartCsmNetCore.Site.csproj -r linux-x64 -o /home/{user}/public_html/ # Về thư mục đã build cd ~ && cd public_html # Khởi chạy ứng dụng pm2 start {config} # Trước đó phải chạy pm2 start dotnet 'dll file' {config } -i max # Hoặc tạo file config cho pm2
module.exports = { apps: [ { name: '{config-name}', cwd: '/home/{user}/public_html', script: 'dotnet ', args: '{dll file}', }, ], };
11. Firewall
Trên AWS muốn cho phép ứng dụng từ bên ngoài truy cập vào cần mở firewall, để mở firewall vào ứng dụng tìm Security Group để thêm tương ứng giao thức: TCP/UDP, IP và port.
Ngoài ra trên VPS EC2 còn có 1 firewall nữa, cấu hình theo link:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-20-04
Danh sách các port cần mở:
To Action From -- ------ ---- Nginx HTTP ALLOW Anywhere (:80) Nginx Full ALLOW Anywhere (:80 - :443) OpenSSH ALLOW Anywhere (:22) 40000:50000/tcp ALLOW Anywhere --> Port truyền dữ liệu FTP 990/tcp ALLOW Anywhere 6379/tcp ALLOW Anywhere 20:21/tcp ALLOW Anywhere 1338/tcp ALLOW Anywhere 1337/tcp ALLOW Anywhere Nginx HTTP (v6) ALLOW Anywhere (v6) Nginx Full (v6) ALLOW Anywhere (v6) OpenSSH (v6) ALLOW Anywhere (v6) 40000:50000/tcp (v6) ALLOW Anywhere (v6) --> Port truyền dữ liệu FTP 990/tcp (v6) ALLOW Anywhere (v6) 6379/tcp (v6) ALLOW Anywhere (v6) 20:21/tcp (v6) ALLOW Anywhere (v6) 1338/tcp (v6) ALLOW Anywhere (v6) 1337/tcp (v6) ALLOW Anywhere (v6)
12. Cấu hình s3 bucket
Để test s3 bucket, tốt nhất nên clone ra bucket mới
https://aws.amazon.com/premiumsupport/knowledge-center/move-objects-s3-bucket/