Linux服务器部署踩坑记录 用TencentOS 3.1(基于RHEL 8/CentOS 8.x兼容)部署Node.js服务时踩了不少坑,记录一下完整的配置流程。
系统初始配置 登录与基础检查 1 2 3 4 5 6 7 8 9 passwd root top df -h free -h uname -a cat /etc/os-release
系统更新 1 2 3 4 5 yum update -y yum install -y vim wget curl net-tools
安全配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 systemctl start firewalld systemctl enable firewalld firewall-cmd --permanent --add-port=80/tcp firewall-cmd --permanent --add-port=443/tcp firewall-cmd --permanent --add-port=22/tcp firewall-cmd --permanent --add-port=3000/tcp firewall-cmd --reload useradd -m deploy passwd deploy usermod -aG wheel deploy
MongoDB安装与配置 添加YUM源 1 2 vim /etc/yum.repos.d/mongodb-org-4.4.repo
添加内容:
1 2 3 4 5 6 [mongodb-org-4.4] name =MongoDB Repositorybaseurl =https://repo.mongodb.org/yum/redhat/8 Server/mongodb-org/4.4 /x86_64 /gpgcheck =1 enabled =1 gpgkey =https://www.mongodb.org/static/pgp/server-4.4 .asc
安装MongoDB 1 2 3 4 5 6 7 8 9 10 11 yum install -y mongodb-org systemctl start mongod systemctl enable mongod systemctl status mongod
基础配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 mongo use admin db.createUser({ user: "admin" , pwd : "your_password" , roles: [{ role: "root" , db: "admin" }] }) exit vim /etc/mongod.conf security: authorization: enabled systemctl restart mongod
Node.js环境部署 安装Node.js 1 2 3 4 5 6 7 8 9 curl --silent --location https://rpm.nodesource.com/setup_16.x | sudo bash - yum install -y nodejs node -v npm -v
配置npm 1 2 3 4 5 6 7 8 9 10 11 npm install -g cnpm --registry=https://registry.npmmirror.com npm config set registry https://registry.npmmirror.com npm install -g pm2 yum install -y pcre-devel zlib-devel openssl openssl-devel unzip
PM2配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 pm2 startup pm2 start app.js --name "myapp" pm2 start app.js --name "myapp" --max-memory-restart 300M pm2 save pm2 list pm2 logs pm2 logs myapp pm2 monit pm2 restart myapp pm2 stop myapp pm2 delete myapp
PM2配置文件(ecosystem.config.js) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 module .exports = { apps : [{ name : 'myapp' , script : './app.js' , instances : 'max' , exec_mode : 'cluster' , max_memory_restart : '300M' , env : { NODE_ENV : 'production' , PORT : 3000 }, env_development : { NODE_ENV : 'development' , PORT : 3000 }, log_date_format : 'YYYY-MM-DD HH:mm:ss Z' , error_file : './logs/err.log' , out_file : './logs/out.log' , log_file : './logs/combined.log' , time : true }] };
Redis安装与配置 安装Redis 1 2 3 4 5 6 7 8 9 10 11 12 yum install -y redis systemctl start redis systemctl enable redis redis-cli ping
基础配置 1 2 3 4 5 6 7 8 9 10 11 12 13 vim /etc/redis.conf bind 127.0.0.1 port 6379 requirepass your_password databases 16 maxmemory 256mb maxmemory-policy allkeys-lru systemctl restart redis
Nginx安装与配置 使用官方源安装 1 2 vim /etc/yum.repos.d/nginx.repo
添加内容:
1 2 3 4 5 6 7 [nginx-stable] name =nginx stable repobaseurl =http://nginx.org/packages/centos/$releasever /$basearch /gpgcheck =1 enabled =1 gpgkey =https://nginx.org/keys/nginx_signing.keymodule_hotfixes =true
安装Nginx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 yum install -y gcc gcc-c++ autoconf pcre pcre-devel make automake httpd-tools yum-utils yum clean all yum makecache yum list nginx --showduplicates yum install -y nginx nginx -V systemctl enable --now nginx systemctl status nginx netstat -ltnp | grep nginx ss -nltp | grep nginx
基础配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 user nginx;worker_processes auto;error_log /var/log/nginx/error .log warn ;pid /var/run/nginx.pid;events { worker_connections 1024 ; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local ] "$request " ' '$status $body_bytes_sent "$http_referer " ' '"$http_user_agent " "$http_x_forwarded_for "' ; access_log /var/log/nginx/access.log main; sendfile on ; tcp_nopush on ; tcp_nodelay on ; keepalive_timeout 65 ; types_hash_max_size 2048 ; gzip on ; gzip_vary on ; gzip_proxied any; gzip_comp_level 6 ; gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml; include /etc/nginx/conf.d/*.conf ; }
Node.js反向代理配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 upstream nodejs_backend { server 127.0.0.1:3000 weight=5 ; server 127.0.0.1:3001 weight=5 ; keepalive 64 ; } server { listen 80 ; server_name yourdomain.com; location ~ ^/(images|javascript|js|css|flash|media|static)/ { root /var/www/static; expires 30d ; } location / { proxy_pass http://nodejs_backend; proxy_http_version 1 .1 ; proxy_set_header Upgrade $http_upgrade ; proxy_set_header Connection 'upgrade' ; 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 ; proxy_cache_bypass $http_upgrade ; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
HTTPS配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 server { listen 443 ssl http2; server_name yourdomain.com; ssl_certificate /etc/nginx/ssl/yourdomain.crt; ssl_certificate_key /etc/nginx/ssl/yourdomain.key; ssl_protocols TLSv1.2 TLSv1.3 ; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on ; ssl_session_cache shared:SSL:10m ; ssl_session_timeout 10m ; location / { proxy_pass http://nodejs_backend; } } server { listen 80 ; server_name yourdomain.com; return 301 https://$server_name $request_uri ; }
解决403 Forbidden错误 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 tail -f /var/log/nginx/error.logchmod -R 755 /var/wwwchown -R nginx:nginx /var/wwwsetenforce 0 vim /etc/selinux/config setsebool -P httpd_can_network_connect 1
系统参数优化 文件描述符限制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ulimit -nsysctl -n -e fs.file-max cp /etc/security/limits.conf /etc/security/limits.conf.backupvim /etc/security/limits.conf * soft nofile 65535 * hard nofile 65535 root soft nofile 65535 root hard nofile 65535
内核参数优化 1 2 3 4 5 6 7 8 9 10 11 12 13 vim /etc/sysctl.conf net.core.somaxconn = 65535 net.core.netdev_max_backlog = 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_keepalive_time = 1200 net.ipv4.tcp_max_tw_buckets = 5000 sysctl -p
监控与告警 使用mailx配置邮件告警 安装mailx 1 2 3 4 5 6 7 8 chkconfig postfix off service postfix stop chkconfig sendmail off service sendmail stop yum -y install mailx
配置邮件 1 2 3 4 5 6 7 8 9 10 11 vim /etc/mail.rc set from=your_qq@qq.comset smtp=smtps://smtp.qq.com:465set smtp-auth-user=your_qq@qq.comset smtp-auth-password=your_auth_code set smtp-auth=loginset ssl-verify=strictset nss-config-dir=/etc/pki/nssdb
获取SSL证书 1 2 3 4 5 6 echo -n " " | openssl s_client -connect smtp.qq.com:465 | \ sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /etc/pki/nssdb/qq.crt certutil -A -n 'qq' -t "P,P,P" -d /etc/pki/nssdb -i /etc/pki/nssdb/qq.crt
测试邮件发送 1 2 3 4 5 6 7 8 echo "邮件正文内容" | mail -s "邮件主题" recipient@example.comecho "邮件正文" | mail -s "主题" -A attachment.txt recipient@example.comcat report.txt | mail -s "每日报告" recipient@example.com
API监控脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #!/bin/bash API_URL="http://your-api.com/api/health" CHECK_INTERVAL=60 MAIL_LIST=("admin@example.com" "ops@example.com" ) send_alert () { local subject="$1 " local body="$2 " local now=$(date "+%Y-%m-%d %H:%M:%S" ) for email in "${MAIL_LIST[@]} " ; do echo -e "$body \n\n时间: $now " | mail -s "$subject " "$email " done } check_api () { local result=$(curl -k -s --max-time 10 "$API_URL " ) local http_code=$(curl -k -s -o /dev/null -w "%{http_code}" --max-time 10 "$API_URL " ) if [ "$http_code " != "200" ]; then send_alert "API告警:HTTP $http_code " \ "API服务器返回异常状态码:$http_code \nURL: $API_URL " return 1 fi if [[ "$result " != *"success" * ]]; then send_alert "API告警:业务异常" \ "API返回结果异常\n返回结果: $result " return 1 fi return 0 } while true ; do check_api sleep $CHECK_INTERVAL done
系统资源监控脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #!/bin/bash CPU_THRESHOLD=80 MEM_THRESHOLD=80 DISK_THRESHOLD=90 check_cpu () { local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1) if (( $(echo "$cpu_usage > $CPU_THRESHOLD " | bc -l) )); then echo "CPU使用率告警: ${cpu_usage} %" | mail -s "服务器CPU告警" admin@example.com fi } check_memory () { local mem_usage=$(free | awk 'NR==2{printf "%.2f", $3*100/$2}' ) if (( $(echo "$mem_usage > $MEM_THRESHOLD " | bc -l) )); then echo "内存使用率告警: ${mem_usage} %" | mail -s "服务器内存告警" admin@example.com fi } check_disk () { local disk_usage=$(df -h / | awk 'NR==2 {print $5}' | cut -d'%' -f1) if [ "$disk_usage " -gt "$DISK_THRESHOLD " ]; then echo "磁盘使用率告警: ${disk_usage} %" | mail -s "服务器磁盘告警" admin@example.com fi } check_cpu check_memory check_disk
服务自动启动配置 1 2 3 4 5 6 7 8 9 10 11 12 13 systemctl enable nginx.service systemctl enable redis.service systemctl enable mongod.service reboot systemctl status nginx systemctl status redis systemctl status mongod pm2 list
安全加固 SSH安全配置 1 2 3 4 5 6 7 8 9 10 11 12 13 vim /etc/ssh/sshd_config Port 2222 PermitRootLogin no PasswordAuthentication no MaxAuthTries 3 ClientAliveInterval 300 ClientAliveCountMax 2 systemctl restart sshd
防火墙配置 1 2 3 4 5 6 firewall-cmd --permanent --remove-service=ssh firewall-cmd --permanent --add-port=2222/tcp firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --reload
Fail2ban安装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 yum install -y fail2ban vim /etc/fail2ban/jail.local [sshd] enabled = true port = 2222 filter = sshd logpath = /var/log/secure maxretry = 3 bantime = 3600 systemctl enable fail2ban systemctl start fail2ban
这些都是实际部署时用过的配置,从系统初始化到服务部署、监控告警、安全加固都有。重点注意Nginx反向代理配置和SELinux可能导致的403问题。
参考