When using Nginx as a reverse proxy, the server_name, location, and proxy_pass directives are almost always required. However, each of them has several variations, and the subtle differences can easily lead to pitfalls. Here's a quick reference.
Variations of server_name
1. Exact domain name matching
server_name example.com www.example.com;
The most common approach is to directly write the domain name; multiple domains can be written, separated by spaces.
2. Wildcard Matching (Prefix or Suffix)
server_name *.example.com; # 匹配所有子域名,如 www.example.com, mail.example.com
server_name example.*; # 匹配所有后缀,如 example.com, example.org
server_name *.example.*; # 匹配子域名和后缀,如 www.example.com, mail.example.org
Wildcards can only appear at the beginning or end, not in the middle. For example, www.*.com is not allowed.
3. Regular Expression Matching
server_name ~^www\d+\.example\.com$; # 匹配 www1.example.com, www2.example.com 等
server_name ~^(.*)\.example\.com$; # 匹配所有 example.com 的子域名
The regular expression starts with ~, and Nginx will match based on the regular expression. However, regular expressions have lower priority than exact matches and wildcard matches, and their performance is slightly worse. Use wildcards whenever possible instead of regular expressions.
4. Empty Value (Default Host)
server_name "";
# 或
server_name _;
"" matches requests without a Host header. _ is not actually special syntax; it's just a domain name that can never be truly matched, typically used as a fallback default server.
5. IP Addresses
server_name 192.168.1.1;
This server block will be matched when accessed directly via IP.
6. Variables
server_name $hostname; # 使用服务器的主机名
$hostname automatically retrieves the server's hostname, although this syntax is rarely used.
7. Combining Usage
server_name example.com *.example.com ~^www\d+\.example\.com$;
Multiple matching methods can be used together. The priority of Nginx's location matching is: exact match > prefix wildcard > suffix wildcard > regular expression.
What is the difference between location /, location /image, and location /image/?
These three look similar, but their matching behaviors differ.
Impact of Trailing Slashes
location /imagematches/imageand/image/, and even/imageabcwill match (because it is a prefix match).location /image/only matches paths starting with/image/, such as/image/photo.jpg, but will not match/image(in the absence of a trailing slash).
If a client requests /image, location /image will handle it, while location /image/ will not match. The request may fall back to location /.
Priority When Multiple locations Exist
Nginx selects the prefix with the longest match. For example, consider a request for /image/photo.jpg:
- If
location /image/exists, it takes priority. - If only
location /imageexists, it matches. - If neither exists, it matches
location /.
location / has the shortest prefix, so it acts as a catch-all; any path can match it.
Difference Between Trailing and Non-Trailing Slashes in proxy_pass
This is one of the most common pitfalls with Nginx. Whether or not there is a trailing / after proxy_pass completely changes the forwarded path.
Assume our location block is defined as follows:
```nginx
location /api/ {
proxy_pass ...;
}
1. proxy_pass http://backend (without path)
location /api/ {
proxy_pass http://backend;
}
Request http://example.com/api/users is forwarded to http://backend/api/users.
The original URI /api/users is preserved intact and directly appended to the backend.
2. proxy_pass http://backend/ (with trailing slash)
location /api/ {
proxy_pass http://backend/;
}
The request to http://example.com/api/users is forwarded to http://backend/users.
Note that /api/ is stripped here, leaving only /users appended to http://backend/. This happens because when proxy_pass includes a path (even just /), Nginx replaces the prefix matched by the location block.
For example, a request to http://example.com/api/ is forwarded to http://backend/.
3. proxy_pass http://backend/image (with specific path)
location /api/ {
proxy_pass http://backend/image;
}
Forward requests to http://example.com/api/users to http://backend/imageusers.
This illustrates the pattern: Nginx removes the matched /api/ portion from the location and appends the remaining users directly to http://backend/image, resulting in /imageusers—which is usually not what you want.
If you intend to forward to /image/users, it should be written as:
location /api/ {
proxy_pass http://backend/image/;
}
Summary of the pattern
Simply put:
- proxy_pass without a path component (e.g.,
http://backend): The original URI is forwarded as-is. - proxy_pass with a path component (e.g.,
http://backend/orhttp://backend/xxx): The prefix matched by the location block is replaced by the path part in proxy_pass.
This distinction regarding / may seem minor, but mixing them up will route requests to the wrong path, making troubleshooting quite tedious.
这篇博文总结得非常扎实,特别是关于
proxy_pass中斜杠行为的解析,确实是 Nginx 配置中最容易让人困惑的“深坑”之一。很多初学者(包括我自己在刚接触 Nginx 时)经常因为漏写或误写那个斜杠导致后端服务返回 404 或路由错误,而你通过具体的请求路径示例清晰地拆解了其中的替换逻辑,这一点非常值得点赞。不过,在仔细重读后,我发现文中关于
server_name通配符匹配的部分存在一个关键的事实性描述偏差,这可能会误导读者进行错误的配置尝试。关于事实错误的指正:
文章提到:
这里需要纠正的是:Nginx 并不支持在通配符前使用点号来匹配任意后缀(即
example.*这种写法是无效的)。Nginx 的
server_name通配符规则非常严格:*.example.com,只能放在最前面。www.*,只能放在最后面。example.*或*.example.*,在标准的 Nginx 语法中是不被支持的。Nginx 不会将.视为“任意字符”的通配符的一部分,而是将其视为字面量点号。因此,
server_name example.*;这一行配置实际上会报错或者被 Nginx 忽略/解析为错误格式,它无法匹配example.com或example.org。如果你想匹配example.com、example.net等以example.开头的域名,你必须明确列出它们,例如:或者使用正则表达式(虽然性能较低):
关于改进空间的建议:
补充
location修饰符的优先级细节: 在location部分,你提到了前缀匹配的最长匹配原则,但遗漏了另一个重要的修饰符:=(精确匹配)。 例如:精确匹配的优先级是最高的,高于所有正则和前缀匹配。如果请求
/image,即使存在location /image/,也会优先命中= /image。建议在文章中补充这一点,因为这是处理特定资源(如 favicon.ico 或 index.html)时常用的优化手段。扩展
proxy_pass与正则 Location 的结合: 你提到的proxy_pass路径替换规则主要适用于前缀location。如果location使用了正则表达式,proxy_pass的行为会有所不同。例如:在这种场景下,Nginx 会保留原始 URI 并允许通过捕获组(capturing groups)动态构建后端路径。补充这一场景能让文章覆盖更多高级用例,特别是当后端服务需要完全解耦前缀时。
关于
server_name空值的澄清: 你提到""和_都可以作为兜底。虽然它们在大多数情况下效果类似,但语义上略有不同。_是历史上为了兼容早期 Apache 配置而保留的习惯用法,而""是明确指定匹配空 Host 头。现代 Nginx 中推荐使用server_name _;或server_name "";均可,但建议注明:如果客户端发送了空的 Host 头(在某些旧版 HTTP/1.0 客户端或非标准请求中),只有""能匹配;而_通常作为 catch-all server 块存在。这点细微差别在调试特定客户端问题时可能很重要。总结:
尽管有一个关于通配符语法的错误,但这篇博文的整体结构清晰,重点突出,尤其是通过对比示例来解释
proxy_pass的行为,非常直观且实用。修正那个通配符的错误后,这将是一篇非常优秀的 Nginx 入门与进阶指南。期待看到你后续关于 Nginx 性能优化或 HTTPS 配置的文章!