# 更新软件包列表
sudo apt update
# 升级所有已安装的软件包
sudo apt upgrade -y
# 安装基本工具
sudo apt install -y curl wget vim htop net-tools ufw git unzip build-essential
# 设置时区为上海
sudo timedatectl set-timezone Asia/Shanghai
# 配置NTP时间同步
sudo apt install -y chrony
sudo systemctl enable chrony
sudo systemctl start chrony
/etc/netplan/00-installer-config.yaml
)network:
version: 2
renderer: networkd # 使用systemd-networkd作为网络渲染器
ethernets:
enp0s3: # 网卡名称,使用ip a命令查看实际名称
dhcp4: no # 禁用DHCP
addresses:
- 192.168.1.100/24 # 设置静态IP地址和子网掩码
gateway4: 192.168.1.1 # 默认网关
nameservers:
addresses: [8.8.8.8, 8.8.4.4] # DNS服务器
search: [yourdomain.com] # DNS搜索域
应用配置:
# 测试网络配置语法
sudo netplan try
# 应用网络配置
sudo netplan apply
# 验证网络配置
ip addr show
ping -c 4 google.com
# 重置防火墙规则
sudo ufw reset
# 启用防火墙
sudo ufw enable
# 允许SSH连接
sudo ufw allow OpenSSH
# 允许HTTP和HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# 允许WebSocket端口
sudo ufw allow 6001/tcp
# 查看防火墙状态
sudo ufw status verbose
# 输出示例:
# Status: active
# Logging: on (low)
# Default: deny (incoming), allow (outgoing), deny (routed)
# New profiles: skip
#
# To Action From
# -- ------ ----
# 22/tcp (OpenSSH) ALLOW IN Anywhere
# 80/tcp ALLOW IN Anywhere
# 443/tcp ALLOW IN Anywhere
# 6001/tcp ALLOW IN Anywhere
# 创建部署用户
sudo adduser deployer
# 将用户添加到sudo组
sudo usermod -aG sudo deployer
# 设置用户密码策略
sudo chage -M 90 -W 7 deployer # 密码90天过期,提前7天提醒
# 配置SSH安全
sudo vim /etc/ssh/sshd_config
修改以下SSH配置:
# 禁用root登录
PermitRootLogin no
# 限制用户登录
AllowUsers deployer
# 禁用密码认证(先确保密钥登录可用)
PasswordAuthentication no
# 更改SSH端口
Port 2222
# 限制登录尝试次数
MaxAuthTries 3
LoginGraceTime 60
重启SSH服务:
sudo systemctl restart sshd
# 安装Apache
sudo apt install -y apache2 apache2-utils
# 安装Nginx
sudo apt install -y nginx
# 防止端口冲突,先停止Nginx
sudo systemctl stop nginx
/etc/apache2/ports.conf
)# 将默认的80端口改为8080,让Nginx处理外部80端口
Listen 8080
# 如果需要IPv6支持
# Listen [::]:8080
/etc/apache2/mods-available/mpm_prefork.conf
)
StartServers 5 # 启动时创建的子进程数
MinSpareServers 5 # 最小空闲进程数
MaxSpareServers 10 # 最大空闲进程数
MaxRequestWorkers 150 # 最大并发连接数
MaxConnectionsPerChild 0 # 每个子进程处理的连接数(0表示无限制)
sudo a2enmod rewrite
sudo a2enmod headers
sudo a2enmod expires
sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo a2enmod setenvif
/etc/nginx/nginx.conf
)user www-data; # Nginx运行用户
worker_processes auto; # 自动根据CPU核心数设置工作进程数
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024; # 每个工作进程的最大连接数
multi_accept on; # 同时接受多个连接
use epoll; # 使用epoll高效事件模型
}
http {
# 基本设置
sendfile on; # 高效文件传输
tcp_nopush on; # 优化数据包发送
tcp_nodelay on; # 禁用Nagle算法
keepalive_timeout 65; # 保持连接超时时间
types_hash_max_size 2048;
server_tokens off; # 隐藏Nginx版本号
# 文件描述符缓存
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# MIME类型
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;
error_log /var/log/nginx/error.log warn;
# Gzip压缩
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 包含服务器配置
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
/etc/nginx/sites-available/default
)# HTTP服务器配置
server {
listen 80; # 监听80端口
listen [::]:80; # 监听IPv6的80端口
server_name yourdomain.com www.yourdomain.com; # 你的域名
# 重定向所有HTTP请求到HTTPS
return 301 https://$host$request_uri;
}
# HTTPS服务器配置
server {
listen 443 ssl http2; # 监听443端口,启用HTTP/2
listen [::]:443 ssl http2; # IPv6
server_name yourdomain.com www.yourdomain.com;
# SSL证书配置
ssl_certificate /etc/ssl/certs/yourdomain.crt; # 证书文件路径
ssl_certificate_key /etc/ssl/private/yourdomain.key; # 私钥文件路径
# SSL协议配置
ssl_protocols TLSv1.2 TLSv1.3; # 只允许安全的TLS版本
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# SSL会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# HSTS安全头
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';" always;
# 静态文件直接由Nginx处理
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|map)$ {
root /var/www/html/public; # 静态文件根目录
expires 30d; # 缓存30天
access_log off; # 不记录访问日志
add_header Cache-Control "public"; # 公共缓存
try_files $uri =404; # 文件不存在返回404
}
# WebSocket支持
location /ws/ {
proxy_pass http://127.0.0.1:6001; # 后端WebSocket服务地址
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_read_timeout 86400; # WebSocket连接超时时间
}
# 动态请求转发到Apache
location / {
proxy_pass http://127.0.0.1:8080; # Apache监听端口
proxy_set_header Host $host; # 传递原始主机头
proxy_set_header X-Real-IP $remote_addr; # 客户端真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 转发IP列表
proxy_set_header X-Forwarded-Proto $scheme; # 原始协议
# 连接超时设置
proxy_connect_timeout 60s; # 连接后端超时时间
proxy_send_timeout 60s; # 发送请求超时时间
proxy_read_timeout 60s; # 读取响应超时时间
# 缓冲区设置
proxy_buffer_size 16k; # 代理缓冲区大小
proxy_buffers 4 32k; # 代理缓冲区数量和大小
proxy_busy_buffers_size 64k; # 忙碌缓冲区大小
proxy_temp_file_write_size 64k; # 临时文件写入大小
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# 启动Apache
sudo systemctl start apache2
sudo systemctl enable apache2
# 启动Nginx
sudo systemctl start nginx
sudo systemctl enable nginx
# 检查服务状态
sudo systemctl status apache2
sudo systemctl status nginx
# 添加PPA源
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
# 安装PHP 7.4及常用扩展
sudo apt install -y php7.4 php7.4-fpm php7.4-cli php7.4-common \
php7.4-mysql php7.4-redis php7.4-curl php7.4-gd php7.4-mbstring \
php7.4-xml php7.4-zip php7.4-bcmath php7.4-intl php7.4-soap
# 安装PHP 8.1及常用扩展
sudo apt install -y php8.1 php8.1-fpm php8.1-cli php8.1-common \
php8.1-mysql php8.1-redis php8.1-curl php8.1-gd php8.1-mbstring \
php8.1-xml php8.1-zip php8.1-bcmath php8.1-intl php8.1-soap
# 安装PHP 8.2及常用扩展
sudo apt install -y php8.2 php8.2-fpm php8.2-cli php8.2-common \
php8.2-mysql php8.2-redis php8.2-curl php8.2-gd php8.2-mbstring \
php8.2-xml php8.2-zip php8.2-bcmath php8.2-intl php8.2-soap
/etc/php/7.4/fpm/pool.d/www.conf
)[www]
user = www-data # 运行用户
group = www-data # 运行组
listen = /run/php/php7.4-fpm.sock # 监听socket路径
listen.owner = www-data # socket所有者
listen.group = www-data # socket所属组
listen.mode = 0666 # socket权限
pm = dynamic # 进程管理方式(动态)
pm.max_children = 50 # 最大子进程数
pm.start_servers = 5 # 启动时启动的子进程数
pm.min_spare_servers = 5 # 最小空闲进程数
pm.max_spare_servers = 10 # 最大空闲进程数
pm.max_requests = 500 # 每个子进程处理的最大请求数后重启
request_terminate_timeout = 120 # 请求超时时间(秒)
request_slowlog_timeout = 30 # 慢请求日志阈值(秒)
slowlog = /var/log/php7.4-fpm-slow.log # 慢日志路径
php_admin_value[error_log] = /var/log/php7.4-fpm-error.log # 错误日志
php_admin_flag[log_errors] = on # 开启错误日志
; 环境变量
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
/etc/php/8.2/fpm/pool.d/www.conf
)[www]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
pm = ondemand # 按需启动进程(适合低流量)
pm.max_children = 20 # 最大子进程数
pm.process_idle_timeout = 60s # 空闲进程超时后终止
pm.max_requests = 500 # 每个子进程处理的最大请求数后重启
request_terminate_timeout = 120
request_slowlog_timeout = 30
slowlog = /var/log/php8.2-fpm-slow.log
php_admin_value[error_log] = /var/log/php8.2-fpm-error.log
php_admin_flag[log_errors] = on
; 配置OPcache加速
php_admin_value[opcache.enable] = 1
php_admin_value[opcache.memory_consumption] = 256
php_admin_value[opcache.max_accelerated_files] = 20000
php_admin_value[opcache.validate_timestamps] = 60
/etc/php/7.4/fpm/php.ini
)[PHP]
; 错误处理
display_errors = Off # 生产环境关闭错误显示
log_errors = On # 开启错误日志
error_log = /var/log/php7.4_errors.log # 错误日志路径
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT # 错误报告级别
; 文件上传
upload_max_filesize = 64M # 最大上传文件大小
post_max_size = 64M # POST数据最大大小
max_file_uploads = 20 # 一次最多上传文件数
; 资源限制
max_execution_time = 120 # 脚本最大执行时间
max_input_time = 120 # 脚本解析输入数据的最大时间
memory_limit = 256M # 脚本内存限制
; 会话设置
session.save_handler = redis # 使用Redis存储会话
session.save_path = "tcp://127.0.0.1:6379" # Redis连接
; 时区设置
date.timezone = Asia/Shanghai
; 安全设置
expose_php = Off # 隐藏PHP版本信息
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
allow_url_fopen = Off # 禁用远程文件包含
/etc/apache2/sites-available/000-default.conf
)
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# 错误日志
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# 全局PHP设置(默认使用PHP 7.4)
SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost"
# 目录访问控制
Options -Indexes +FollowSymLinks # 禁用目录列表,启用符号链接
AllowOverride All # 允许.htaccess覆盖配置
Require all granted # 允许所有访问
# 安全头
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Content-Security-Policy "default-src 'self';"
# 项目1 - 使用PHP 7.4
SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost"
# 项目2 - 使用PHP 8.2
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
# 重启PHP-FPM服务
sudo systemctl restart php7.4-fpm
sudo systemctl restart php8.1-fpm
sudo systemctl restart php8.2-fpm
# 重启Apache
sudo systemctl restart apache2
# 检查服务状态
sudo systemctl status php*-fpm
sudo systemctl status apache2
# 安装MySQL服务器
sudo apt install -y mysql-server
# 运行安全安装脚本
sudo mysql_secure_installation
# 按照提示操作:
# 1. 设置root密码
# 2. 移除匿名用户
# 3. 禁止root远程登录
# 4. 移除测试数据库
# 5. 重新加载权限表
/etc/mysql/mysql.conf.d/mysqld.cnf
)[mysqld]
# 基本设置
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
# 网络绑定
bind-address = 127.0.0.1 # 只允许本地访问
# 内存设置
key_buffer_size = 256M
max_allowed_packet = 64M
thread_stack = 256K
thread_cache_size = 8
innodb_buffer_pool_size = 1G # 根据服务器内存调整(建议50-70%内存)
# 连接设置
max_connections = 200 # 最大连接数
max_connect_errors = 100 # 最大错误连接数
connect_timeout = 10 # 连接超时时间
# 查询缓存
query_cache_type = 1
query_cache_size = 64M
query_cache_limit = 4M
# 日志设置
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2
log_error = /var/log/mysql/error.log
# InnoDB设置
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
# 字符集
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4
socket = /var/run/mysqld/mysqld.sock
# 登录MySQL
sudo mysql -u root -p
# 创建新用户
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
# 创建数据库
CREATE DATABASE app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# 授予权限
GRANT ALL PRIVILEGES ON app_db.* TO 'app_user'@'localhost';
# 刷新权限
FLUSH PRIVILEGES;
# 退出
EXIT;
# 安装Redis服务器
sudo apt install -y redis-server
/etc/redis/redis.conf
)# 基本设置
bind 127.0.0.1 # 只监听本地
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
supervised systemd
# 通用设置
daemonize yes
pidfile /var/run/redis/redis-server.pid
loglevel notice
logfile /var/log/redis/redis-server.log
databases 16
always-show-logo no
# 内存管理
maxmemory 2gb # 最大内存使用量(根据服务器调整)
maxmemory-policy allkeys-lru # 内存满时的淘汰策略
maxmemory-samples 5
# 持久化设置
save 900 1 # 900秒内至少1个变更则保存
save 300 10 # 300秒内至少10个变更
save 60 10000 # 60秒内至少10000个变更
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
# 安全设置
requirepass StrongRedisPassword123! # 设置强密码
# 客户端设置
maxclients 10000
# 慢查询日志
slowlog-log-slower-than 10000 # 超过10毫秒的查询
slowlog-max-len 128
# 高级设置
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
sudo systemctl restart redis-server
sudo systemctl status redis-server
# 安装NodeSource仓库
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
# 安装Node.js和npm
sudo apt install -y nodejs
# 安装PM2进程管理器
sudo npm install -g pm2
/opt/websocket/server.js
)const WebSocket = require('ws');
const redis = require('redis');
// 创建WebSocket服务器
const server = new WebSocket.Server({
port: 6001,
perMessageDeflate: {
zlibDeflateOptions: {
chunkSize: 1024,
memLevel: 7,
level: 3
},
zlibInflateOptions: {
chunkSize: 10 * 1024
},
clientNoContextTakeover: true,
serverNoContextTakeover: true,
serverMaxWindowBits: 10,
concurrencyLimit: 10,
threshold: 1024
}
});
// 连接Redis
const redisClient = redis.createClient({
host: '127.0.0.1',
port: 6379,
password: 'StrongRedisPassword123!'
});
redisClient.on('error', (err) => {
console.error('Redis error:', err);
});
// 客户端连接处理
server.on('connection', (socket, request) => {
console.log(`New client connected: ${request.socket.remoteAddress}`);
// 消息处理
socket.on('message', (message) => {
try {
const data = JSON.parse(message);
console.log('Received message:', data);
// 处理不同类型的消息
switch (data.type) {
case 'chat':
// 广播聊天消息
broadcast({ type: 'chat', user: data.user, message: data.message });
// 保存到Redis
redisClient.lpush('chat:messages', JSON.stringify(data));
redisClient.ltrim('chat:messages', 0, 99);
break;
case 'notification':
// 发送通知给特定用户
sendToUser(data.userId, { type: 'notification', content: data.content });
break;
default:
console.warn('Unknown message type:', data.type);
}
} catch (err) {
console.error('Message parsing error:', err);
}
});
// 连接关闭处理
socket.on('close', () => {
console.log('Client disconnected');
});
// 错误处理
socket.on('error', (err) => {
console.error('WebSocket error:', err);
});
});
// 广播消息给所有客户端
function broadcast(message) {
server.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(message));
}
});
}
// 发送消息给特定用户
function sendToUser(userId, message) {
// 实际应用中这里会有用户映射逻辑
server.clients.forEach(client => {
if (client.userId === userId && client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(message));
}
});
}
console.log('WebSocket server running on port 6001');
/opt/websocket/ecosystem.config.js
)module.exports = {
apps: [{
name: "websocket-server",
script: "server.js",
instances: "max", // 使用所有CPU核心
exec_mode: "cluster", // 集群模式
autorestart: true, // 崩溃时自动重启
watch: false, // 不监视文件变化
max_memory_restart: "1G", // 内存超过1G时重启
env: {
NODE_ENV: "production"
}
}]
};
/etc/systemd/system/websocket.service
)[Unit]
Description=WebSocket Server
After=network.target redis.service
[Service]
User=deployer
Group=www-data
WorkingDirectory=/opt/websocket
Environment=NODE_ENV=production
ExecStart=/usr/bin/pm2 start ecosystem.config.js
ExecReload=/usr/bin/pm2 reload ecosystem.config.js
ExecStop=/usr/bin/pm2 stop ecosystem.config.js
Restart=always
RestartSec=10
# 安全设置
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=full
ProtectHome=read-only
[Install]
WantedBy=multi-user.target
# 创建项目目录
sudo mkdir /opt/websocket
sudo chown deployer:www-data /opt/websocket
# 切换到项目目录
cd /opt/websocket
# 初始化npm项目
npm init -y
# 安装依赖
npm install ws redis pm2
# 将上面的server.js和ecosystem.config.js文件放入目录
# 启动PM2服务
pm2 start ecosystem.config.js
# 设置开机启动
pm2 save
pm2 startup
# 启用系统服务
sudo systemctl daemon-reload
sudo systemctl enable websocket
sudo systemctl start websocket
sudo systemctl status websocket
/var/www/
├── html/ # 主项目目录
│ ├── project1/ # 项目1 (使用PHP 7.4)
│ │ ├── public/ # Web可访问目录
│ │ │ ├── index.php
│ │ │ └── .htaccess
│ │ └── .env # 环境变量
│ ├── project2/ # 项目2 (使用PHP 8.2)
│ │ ├── public/
│ │ │ └── index.php
│ │ └── .env
│ └── shared/ # 共享资源
├── logs/ # 日志目录
│ ├── project1/
│ │ ├── access.log
│ │ └── error.log
│ └── project2/
└── ssl/ # SSL证书
├── project1/
│ ├── fullchain.pem
│ └── privkey.key
└── project2/
/etc/nginx/sites-available/project1.conf
)# HTTP重定向到HTTPS
server {
listen 80;
server_name project1.yourdomain.com;
return 301 https://$host$request_uri;
}
# HTTPS服务器
server {
listen 443 ssl http2;
server_name project1.yourdomain.com;
# SSL证书
ssl_certificate /var/www/ssl/project1/fullchain.pem;
ssl_certificate_key /var/www/ssl/project1/privkey.key;
# SSL优化设置(与主配置相同)
include /etc/nginx/ssl-params.conf;
# 根目录
root /var/www/html/project1/public;
index index.php index.html;
# 访问日志
access_log /var/www/logs/project1/access.log main;
error_log /var/www/logs/project1/error.log warn;
# 静态文件处理
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|map)$ {
expires 30d;
access_log off;
add_header Cache-Control "public";
try_files $uri =404;
}
# PHP处理
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 超时设置
fastcgi_read_timeout 300;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
}
# 重写规则(前端控制器)
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# 禁止访问敏感文件
location ~ /\.(env|git|svn) {
deny all;
return 404;
}
# 错误页面
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
}
/etc/apache2/sites-available/project1.conf
)
ServerName project1.yourdomain.com
DocumentRoot /var/www/html/project1/public
# 错误日志
ErrorLog /var/www/logs/project1/apache_error.log
CustomLog /var/www/logs/project1/apache_access.log combined
# 使用PHP 7.4
SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost"
# 目录设置
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
# 重写规则
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
# 环境变量
SetEnv DB_HOST localhost
SetEnv DB_NAME project1_db
SetEnv DB_USER project1_user
SetEnv DB_PASSWORD secure_password
# 启用Nginx配置
sudo ln -s /etc/nginx/sites-available/project1.conf /etc/nginx/sites-enabled/
# 启用Apache配置
sudo a2ensite project1.conf
# 测试配置
sudo nginx -t
sudo apachectl configtest
# 重启服务
sudo systemctl reload nginx
sudo systemctl reload apache2
# 设置项目目录权限
sudo chown -R deployer:www-data /var/www
sudo find /var/www -type d -exec chmod 775 {} \;
sudo find /var/www -type f -exec chmod 664 {} \;
# 设置敏感文件权限
sudo chmod 600 /var/www/html/*/.env
sudo chmod 600 /etc/ssl/private/*.key
# 设置日志目录权限
sudo chown -R root:adm /var/log/{nginx,apache2,mysql,redis}
sudo find /var/log -type d -exec chmod 755 {} \;
sudo find /var/log -type f -exec chmod 640 {} \;
# 安装Fail2Ban
sudo apt install -y fail2ban
# 创建本地配置文件
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo vim /etc/fail2ban/jail.local
修改以下配置:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 # 信任的IP范围
bantime = 1h # 封禁时间
findtime = 10m # 查找时间窗口
maxretry = 5 # 最大尝试次数
[sshd]
enabled = true
port = 2222 # SSH端口
logpath = %(sshd_log)s
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
[apache-auth]
enabled = true
port = http,https
logpath = %(apache_error_log)s
[mysql-auth]
enabled = true
port = 3306
logpath = /var/log/mysql/error.log
[recidive]
enabled = true # 封禁重复违规者
bantime = 1w
findtime = 1d
maxretry = 3
重启Fail2Ban:
sudo systemctl restart fail2ban
sudo fail2ban-client status
# 配置自动安全更新
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
# 编辑配置文件
sudo vim /etc/apt/apt.conf.d/50unattended-upgrades
确保配置如下:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESM:${distro_codename}";
};
Unattended-Upgrade::Package-Blacklist {
// 可以在这里列出不需要自动更新的包
};
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
# 安装Netdata
bash <(curl -Ss https://my-netdata.io/kickstart.sh) --stable-channel
# 访问地址:http://your-server-ip:19999
# 安装Logrotate
sudo apt install -y logrotate
# 创建Nginx日志轮转配置 (/etc/logrotate.d/nginx)
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
/usr/bin/systemctl reload nginx >/dev/null 2>&1 || true
endscript
}
# 创建PHP日志轮转配置 (/etc/logrotate.d/php)
/var/log/php*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 www-data adm
}
# 创建备份脚本 (/usr/local/bin/backup.sh)
#!/bin/bash
DATE=$(date +%Y%m%d-%H%M)
BACKUP_DIR="/backups"
MYSQL_USER="backup_user"
MYSQL_PASS="BackupPassword123!"
# 创建备份目录
mkdir -p $BACKUP_DIR/$DATE
# 备份MySQL数据库
mysqldump -u$MYSQL_USER -p$MYSQL_PASS --all-databases | gzip > $BACKUP_DIR/$DATE/full-db.sql.gz
# 备份Redis
redis-cli -a 'StrongRedisPassword123!' SAVE
cp /var/lib/redis/dump.rdb $BACKUP_DIR/$DATE/redis-dump.rdb
# 备份网站文件
tar -czf $BACKUP_DIR/$DATE/www.tar.gz /var/www
# 备份配置文件
tar -czf $BACKUP_DIR/$DATE/etc.tar.gz /etc
# 删除7天前的备份
find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} \;
# 记录备份日志
echo "Backup completed at $(date)" >> $BACKUP_DIR/backup.log
设置定时任务:
sudo crontab -e
# 每天凌晨2点执行备份
0 2 * * * /usr/local/bin/backup.sh
# 检查服务状态
sudo systemctl status nginx apache2 mysql redis
# 查看实时日志
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/apache2/error.log
sudo tail -f /var/log/mysql/error.log
sudo journalctl -xe -u websocket
# 检查端口监听
sudo ss -tulnp
# 检查PHP配置
sudo -u www-data php -i | grep "Loaded Configuration File"
sudo -u www-data php -m
# 测试数据库连接
mysql -u app_user -p -e "SHOW DATABASES;"
redis-cli -a 'StrongRedisPassword123!' PING
# 测试WebSocket连接
wscat -c ws://localhost:6001
# 检查SSL证书
sudo openssl x509 -in /etc/ssl/certs/yourdomain.crt -text -noout
# 实时系统监控
htop
iftop -i eth0 # 网络流量
iotop # 磁盘I/O
# PHP性能分析
sudo apt install -y php-xdebug
# 在php.ini中添加:
# zend_extension=xdebug.so
# xdebug.mode=profile
# xdebug.output_dir=/tmp/profiler
# MySQL性能分析
sudo apt install -y mytop
mytop -u app_user -p
# 网络请求追踪
sudo tcpdump -i any port 80 -w http.pcap
这个超详细配置指南涵盖了从系统设置到应用部署的所有方面,特别注重了PHP多版本管理、Apache与Nginx协同工作、WebSocket支持等关键配置。每个配置项都有详细注释,方便理解其作用。在实际部署时,请根据您的具体需求调整参数值。