Nginx 是一个异步框架的网页服务器,具有占用内存少、稳定性高、可大量并行处理等特点。截止 2018 年,全球有 30.46% 的网站使用 Nginx 作为代理。除了网页代理外,Nginx 也可作为反向代理、负载均衡等应用,本站使用的网页服务器就是 Nginx。
我的 Nextcloud 私有云是搭建在 HostHatch 洛杉矶数据中心的大容量机械硬盘 VPS 上。由于性能有限加上 HostHatch 没有对中国路由进行特别优化,导致国内直连的情况下丢包严重,连接状态极差。于是我用狗云圣何塞机房 4837 线路的 VPS 作为 Nextcloud 的中转来解决访问速度的问题,同时把本站也搭建在狗云的VPS上就不会有访问困难的问题了。这两种需求利用 Nginx 都能很好的满足。
我 Nginx 配置的基本架构:
- Nginx 提供本站的网页服务,并处理本站和 Nextcloud 的 HTTPS 加密。
- Nginx 为 Nextcloud 做反向代理,使客户端访问 Nextcloud 经过网络更好的 Nginx 所在的服务器来加速访问。
优化要点:
- 合理的配置本地缓存
- 开启压缩并做适当的配置
- 反向代理服务器不要缓存后端的数据,只作为一个桥梁来提供中转服务。这样数据传输更加直接,同时也能减轻反向代理服务器的压力。(我的反向代理服务器只有 5G 的硬盘,如果开启反向代理缓存的话,向后端传输数据的最大文件大小会受这个缓存的限制)
- HTTPS 加密方式的选择
我的nginx.conf配置
user site site; #用户和用户组
worker_processes auto; #CPU 核心数
worker_rlimit_nofile 8192; #最大打开文件数量
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
use epoll; #epoll事件模型
worker_connections 1024; #单个 worker 进程允许客户端最大连接数
multi_accept on; #worker 按串行方式来处理连接
}
http {
include /etc/nginx/mime.types; #媒体类型
default_type application/octet-stream; #媒体类型
charset UTF-8;
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;
# 安全
# add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# add_header X-Robots-Tag none;
# add_header X-Download-Options noopen;
# add_header X-Permitted-Cross-Domain-Policies none;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# add_header X-Frame-Options SAMEORIGIN; #不允许页面从框架 frame 或 iframe 中显示
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;
sendfile on; #开启高效文件传输模式
tcp_nopush on; #防止网路阻塞
keepalive_timeout 65; #客户端连接保持会话超时时间
tcp_nodelay on; #防止网络阻塞
types_hash_max_size 2048;
client_header_buffer_size 4096; #客户端请求头部的缓冲区大小,getconf PAGESIZE 命令查看
open_file_cache max=8192 inactive=20s; #打开文件指定缓存,建议和打开文件数一致,inactive 经过多长时间文件没被请求后删除缓存
open_file_cache_valid 30s; #多长时间检查一次缓存的有效信息
open_file_cache_min_uses 1; #open_file_cache 指令中的 inactive 时间内文件的最少使用次数,1次都没用,删除
client_header_timeout 15; #设置请求头的超时时间,超过这个时间没有发送任何数据,返回 request time out 错误
client_body_timeout 15; #设置请求体的超时时间
reset_timedout_connection on; #关闭不响应的 client 连接,释放那个 client 所占有的内存
send_timeout 15; #超过这个时间,客户端没有任何活动,nginx 关闭连接
server_tokens off; #关闭 Nginx 版本号
client_max_body_size 614400m; #上传文件大小限制
# 反向代理
proxy_buffering off;
proxy_max_temp_file_size 614400m; #反向代理上传文件大小限制
proxy_set_header X-Real_IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
proxy_pass_header X-CSRF-TOKEN;
proxy_set_header Upgrade $http_upgrade; #连接升级为 WebSocket
proxy_set_header Connection $connection_upgrade; #连接 map
proxy_connect_timeout 60s; #代理超时
proxy_read_timeout 60s; #读取超时
proxy_send_timeout 60s; #请求改善超时
#proxy_redirect off;
fastcgi_connect_timeout 600; #指定连接到后端 FastCGI 的超时时间
fastcgi_send_timeout 600; #向 FastCGI 传送请求的超时时间
fastcgi_read_timeout 600; #指定接收 FastCGI 应答的超时时间
fastcgi_buffer_size 64k; #指定读取 FastCGI 应答第一部分需要用多大的缓冲区
fastcgi_buffers 4 64k; #指定本地需要用多少和多大的缓冲区来缓冲 FastCGI 的应答请求
fastcgi_busy_buffers_size 128k; #建议设置为 fastcgi_buffers 的两倍
fastcgi_temp_file_write_size 128k; #在写入 fastcgi_temp_path 时将用多大的数据块,默认值是 fastcgi_buffers 的两倍
fastcgi_temp_path /tmp; #缓存临时目录
fastcgi_intercept_errors on; #指定是否传递 4xx 和 5xx 错误信息到客户端
fastcgi_cache_path /tmp/blog levels=1:2 keys_zone=cache_fastcgi:300m inactive=60m max_size=3584m; #fastcgi_cache 缓存目录
fastcgi_cache cache_fastcgi; #开启 FastCGI 缓存并为其指定一个名称
fastcgi_cache_valid 200 302 1h; #用来指定应答代码的缓存时间
fastcgi_cache_valid 301 1d; #将 301 应答缓存一天
fastcgi_cache_valid any 1m; #将其他应答缓存为1分钟
fastcgi_cache_min_uses 1; #设置经过多少次请求的相同 URL 将被缓存
fastcgi_cache_key http://$host$request_uri; #设置 web 缓存的 Key 值
#fastcgi_pass; #指定 FastCGI 服务器监听端口与地址
gzip on; #开启压缩
gzip_disable "msie6";
gzip_min_length 1k; #允许压缩的页面最小字节数
gzip_buffers 32 4k; #压缩缓冲区大小
gzip_http_version 1.1; #压缩版本
gzip_comp_level 9; #压缩比例(1-9)
gzip_proxied any; #对代理启用压缩
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on; #varyheader 支持
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
include /etc/nginx/conf.d/*.conf;
}
我的 conf.d 里面本站服务器配置
server {
listen 443 ssl;
#listen [::]:443 ssl ipv6only=on;
server_name sixdian.com;
root /home/site/sixdian.com;
ssl_certificate /etc/letsencrypt/live/sixdian.com-0001/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sixdian.com-0001/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
# expires 缓存调优
location ~* \.(ico|jpeg|gif|png|bmp|swf|flv)$ {
expires 30d;
#log_not_found off;
access_log off;
}
location ~* \.(js|css)$ {
expires 1d;
log_not_found off;
access_log off;
}
# 防盗链(未成功)
#location ~*^.+\.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {
#valid_referers sixdian.com;
#if($invalid_referer) {
#return 404;
#break;
#}
#access_log off;
#}
}
server {
listen 80;
#listen [::]:80 ipv6only=on;
server_name sixdian.com;
return 301 https://sixdian.com$request_uri;
}
server {
listen 80;
server_name www.sixdian.com;
return 301 https://sixdian.com$request_uri;
}
我 conf.d 里面 Nextcloud 服务器配置
server {
listen 443 ssl;
server_name drive.sixdian.com;
ssl_certificate /etc/letsencrypt/live/sixdian.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sixdian.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
location / {
proxy_pass http://s1.sixdian.com:****;
}
location = /.well-known/carddav {
return 301 $scheme://drive.sixdian.com/remote.php/dav/files/****/;
}
location = /.well-known/caldav {
return 301 $scheme://drive.sixdian.com/remote.php/dav/files/****/;
}
}
server {
listen 80;
server_name drive.sixdian.com;
return 301 https://drive.sixdian.com$request_uri;
location = /.well-known/carddav {
return 301 $scheme://drive.sixdian.com/remote.php/dav/files/****/;
}
location = /.well-known/caldav {
return 301 $scheme://drive.sixdian.com/remote.php/dav/files/****/;
}
}
我的 NextCloud 服务器 config.php 配置文件
位置在:/var/snap/nextcloud/current/nextcloud/config/config.php
<?php
$CONFIG = array (
'trusted_proxies' =>
array (
0 => '******',
),
'overwriteprotocol' => 'https',
'default_phone_region' => 'CN',
'apps_paths' =>
array (
0 =>
array (
'path' => '/snap/nextcloud/current/htdocs/apps',
'url' => '/apps',
'writable' => false,
),
1 =>
array (
'path' => '/var/snap/nextcloud/current/nextcloud/extra-apps',
'url' => '/extra-apps',
'writable' => true,
),
),
'supportedDatabases' =>
array (
0 => 'mysql',
),
'memcache.locking' => '\\OC\\Memcache\\Redis',
'memcache.local' => '\\OC\\Memcache\\Redis',
'redis' =>
array (
'host' => '/tmp/sockets/redis.sock',
'port' => 0,
),
'log_type' => 'file',
'logfile' => '/var/snap/nextcloud/current/logs/nextcloud.log',
'logfilemode' => 416,
'instanceid' => '******',
'passwordsalt' => '********',
'secret' => '******',
'trusted_domains' =>
array (
0 => 'drive.sixdian.com',
),
'datadirectory' => '/home/nextcloud',
'dbtype' => 'mysql',
'version' => '23.0.3.2',
'overwrite.cli.url' => 'https://drive.sixdian.com',
'dbname' => 'nextcloud',
'dbhost' => 'localhost:/tmp/sockets/mysql.sock',
'dbport' => '',
'dbtableprefix' => 'oc_',
'mysql.utf8mb4' => true,
'dbuser' => 'nextcloud',
'dbpassword' => '********',
'installed' => true,
'mail_smtpmode' => 'smtp',
'mail_smtpsecure' => 'ssl',
'mail_sendmailmode' => 'smtp',
'mail_from_address' => 'admin',
'mail_domain' => 'sixdian.com',
'mail_smtpauthtype' => 'LOGIN',
'mail_smtpauth' => 1,
'mail_smtphost' => 'smtp.exmail.qq.com',
'mail_smtpport' => '465',
'mail_smtpname' => 'admin@sixdian.com',
'mail_smtppassword' => '********',
'maintenance' => false,
'loglevel' => 2,
'overwritehost' => 'drive.sixdian.com',
);