mobile wallpaper 1
mobile wallpaper 2
mobile wallpaper 3
mobile wallpaper 4
1747 字
5 分钟
个人建站必学:Nginx 核心配置
2026-02-03

最近把自己的博客部署到了云服务器上,Nginx 这关躲不过去,折腾了几天总算把常用的东西摸熟了。网上教程大多是复杂的官方文档,许多功能个人建站根本用不上。我把实际用到的核心配置整理成这篇笔记,都是个人建站最需要的那部分。

一、核心骨架:一个最基础的虚拟主机#

先搞清楚一个问题:我在浏览器输入 www.example.com,敲下回车,Nginx 到底干了什么?

用大白话拆解一下:

  1. DNS 把域名解析到服务器的公网 IP,请求打到这台机器的 80 端口;
  2. Nginx 接到请求,先看请求头里的 Host 字段(也就是你输的域名),拿它去和所有 server 块的 server_name 逐个比对,找到匹配的那个 server 块。一台服务器可以挂好几个网站,靠的就是这个机制,所以叫「虚拟主机」;
  3. 匹配到之后,Nginx 从 root 指定的目录里找文件,路径是 root + 你访问的路径;
  4. 如果你访问的是 /(根路径),就按 index 列出的文件名挨个找,找到第一个为止。

下面是一个能跑起来的最简配置:

server {
# 监听 80 端口(HTTP)
# server_name 写你的域名,Nginx 靠它区分同一台机器上的不同网站
listen 80;
server_name www.example.com;
# 网站文件存放的目录,也就是博客打包后的输出目录
root /var/www/blog;
# 访问根路径时默认找哪个文件,按顺序找,找到第一个就返回
index index.html index.htm;
}

假设访问 www.example.com/,Nginx 就会去找 /var/www/blog/index.html,找到就返回给浏览器,找不到就是 404。就这么简单,一个静态博客站的最小配置完成了。

顺带一提,配置文件放哪:一般是 /etc/nginx/conf.d/你的站.conf 或者 /etc/nginx/sites-available/ 里建一个再软链到 sites-enabled/,看发行版本,效果一样。

二、反向代理:把本地服务代理出来#

静态站直接扔目录里就行,但很多博客程序是动态的。比如我跑了个 Node 服务或者 Docker 容器,它监听在 127.0.0.1:3000,这个端口外网访问不到。怎么让用户通过 80 端口的域名访问到它?

答案就是反向代理:Nginx 在前面收请求,转手塞给本地 3000 端口的服务,再把服务的响应转回给用户。用户全程只跟 Nginx 打交道,完全不知道背后还有个 3000 端口。

标准写法:

server {
listen 80;
server_name www.example.com;
# 所有请求都代理到本地的 3000 端口
location / {
proxy_pass http://127.0.0.1:3000;
# 下面三个请求头非常重要,往下看解释
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 之后,Nginx 会把这几个字段改写后再转发给后端。

Host:后端程序经常要靠它判断用户访问的是哪个域名(比如生成绝对链接、路由分发)。不传的话,后端看到的 Host 是 127.0.0.1:3000,一些框架会直接懵掉。

X-Real-IP 和 X-Forwarded-For:这是新手最容易忽略的坑。TCP 连接是 Nginx 跟后端建立的,所以后端看到的「客户端 IP」永远是 127.0.0.1。日志里全是 127.0.0.1,想做 IP 封禁、统计地域分布,全都无从下手。而访客的真实 IP,Nginx 是知道的(它直接跟访客通信),这两个头就是把真实 IP 转交给后端的「快递单」:

  • X-Real-IP:直白,就一个值,当前这次请求的访客真实 IP;
  • X-Forwarded-For:会累积,格式是 访客IP, 第一层代理IP, ...,多层代理时能看出完整链路,后端日志程序一般认这个。

不传这两个头,你的后端日志里就只剩一片 127.0.0.1。

三、强制 HTTPS:SSL 证书配置#

个人站 HTTPS 已经是主流了,没有的话浏览器还会给标个「不安全」。证书用 Let’s Encrypt 免费申请就行(certbot 一条命令的事),拿到证书文件后配 443:

# 443 端口:真正的 HTTPS 服务
server {
listen 443 ssl;
server_name www.example.com;
# 证书文件路径(certbot 申请的证书就在这类位置)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 网站内容,和 80 那份一样
root /var/www/blog;
index index.html;
}
# 80 端口:只干一件事,把所有 HTTP 请求踢到 HTTPS
server {
listen 80;
server_name www.example.com;
# $host 是用户访问的域名,$request_uri 是路径加查询参数
# 比如 http://example.com/post/1?a=2 会跳到 https://example.com/post/1?a=2
return 301 https://$host$request_uri;
}

这里说一下为什么用 return 301 而不是 rewrite ^(.*)$ https://... permanent:

  • return 是 Nginx 官方推荐的做法,收到请求直接返回 301,简单直接;
  • rewrite 要先做正则匹配和捕获,纯属于多绕一圈,正则写错还会踩坑;
  • 301 是永久重定向,浏览器和搜索引擎会记住这个跳转,之后直接访问 HTTPS,省一次往返。

一句话总结:能用 return 就别用 rewrite。

四、图片防盗链:保护服务器的流量#

防盗链的原理一句话:HTTP 请求头里有个 Referer 字段,记录了「这个请求是从哪个网页发出来的」。正常读者在我的网页上看到图片,Referer 就是我的域名;被别人盗链时,Referer 是对方的域名。所以只要检查 Referer,不是自己家的就拒绝。

server {
listen 80;
server_name www.example.com;
root /var/www/blog;
# 只对图片类静态资源做防盗链
location ~* \.(jpg|jpeg|png|gif|webp|svg)$ {
# valid_referers 定义白名单:以下来源算合法
# none:浏览器直接输入图片地址打开(没有 Referer,比如地址栏直接访问、收藏夹)
# blocked:Referer 被防火墙之类的代理抹掉了
# server_names:所有 server_name 里写过的域名(含子域名)
valid_referers none blocked server_names;
# 如果 Referer 不在白名单里(invalid_referer 变量为真)
if ($invalid_referer) {
# 直接返回 403,拒绝访问,盗链网站上的图片就是裂图
return 403;
}
}
}

想更严的话,把 none 去掉,强制所有请求必须带合法 Referer。但副作用是别人把图片地址复制到浏览器地址栏直接打开也会被拦,一般还是留着 none 比较友好。

五、重定向#

常用重定向:裸域名跳 www#

很多人两个域名都解析了(example.com 和 www.example.com),但希望统一用一个,对 SEO 也好:

server {
listen 443 ssl;
server_name example.com; # 只匹配裸域名
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 统一跳到带 www 的域名,保留路径和参数
return 301 https://www.example.com$request_uri;
}

六、三个我遇到过的坑#

坑一:改完配置直接 reload

Nginx 的配置文件是纯文本,任何语法错误都起不来。如果改完直接 nginx -s reload,有错误会导致 reload 失败,运气差碰会直接挂掉。养成肌肉记忆:

# 第一步永远是测试语法,会精确告诉你哪一行错了
nginx -t
# 看到 syntax is ok 和 test is successful 才执行 reload
nginx -s reload

坑二:proxy_pass 末尾那个斜杠

# 情况 A:不带斜杠
location /blog/ {
proxy_pass http://127.0.0.1:3000;
}
# 访问 /blog/post/1 → 后端收到 /blog/post/1(完整路径原样传递)
# 情况 B:带斜杠
location /blog/ {
proxy_pass http://127.0.0.1:3000/;
}
# 访问 /blog/post/1 → 后端收到 /post/1(去掉 /blog 前缀再传递)

一个斜杠,决定了 URL 前缀要不要剥掉。后端路由怎么都匹配不上、页面能打开但静态资源全是 404,八成就是这个问题。记不住规则没关系,改完在浏览器里试一下,观察后端日志实际收到的路径。

坑三:静态文件 403 Forbidden

文件明明在,路径明明对,ls 都能看到,浏览器就是 403。九成是 Linux 权限问题,Nginx 的工作进程是用普通用户(一般是 nginx 或 www-data)跑的,它得一路都有权限才能读到文件,任何一级目录缺执行权限都不行。

排查命令:

# 1. 看看 Nginx 工作进程用哪个用户跑的
ps aux | grep nginx
# 2. 看 Nginx 配置里 user 指令
grep "^user" /etc/nginx/nginx.conf
# 3. 确认目录每一级都有执行权限(x),最省事的修法:
# 目录给 755,文件给 644,属主改成 Nginx 用户或加同组
chmod 755 /var/www/blog
chmod 644 /var/www/blog/index.html
chown -R www-data:www-data /var/www/blog

另外一个容易忽略的:SELinux(CentOS)。权限明明都对还是 403,setenforce 0 试一下如果立刻好了,就是 SELinux 的锅,再用 chcon 给目录改安全上下文做正式修复。

写在最后#

个人建站的 Nginx 配置,说穿了就是这几件事:server 块定位网站、proxy_pass 代理动态服务、443 加证书、防盗链守住流量。搞懂这些,一个博客站的 Nginx 部分就齐活了。至于负载均衡、限流、缓存那些大厂玩意,等哪天真有那泼天的流量再说🐶。

教程是折腾后靠回忆写的,可能会有说得不对的地方,仅供参考。

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

个人建站必学:Nginx 核心配置
https://www.vinceyun.com/posts/nginx-for-personal-site/
作者
Vince
发布于
2026-02-03
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录