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 in how they can be written, and the subtle differences between these variations can easily lead to pitfalls. I am documenting these details here.
What are the different ways to write server_name
1. Exact Domain Matching
server_name example.com www.example.com;
The most common way is to write the domain directly. You can write multiple domains, 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 the end; they cannot be placed 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 的子域名
Regex patterns start with ~, and Nginx will match them using regular expressions. However, regex matching has lower priority than exact matching and wildcard matching, and it is also slightly less performant. Use wildcards whenever possible instead of regex.
4. Null Value (Default Host)
server_name "";
# 或
server_name _;
"" indicates a request without a Host header. _ is not actually any special syntax; it is simply a domain name that can never truly be matched, typically used as a fallback default server.
5. IP Address
server_name 192.168.1.1;
Accessing directly via IP will match this server block.
6. Variables
server_name $hostname; # 使用服务器的主机名
$hostname automatically retrieves the server's hostname, although this notation is less commonly used.
7. Combined Usage
server_name example.com *.example.com ~^www\d+\.example\.com$;
Multiple syntaxes can be used together. Nginx's matching priority 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 behavior differs.
Impact of Trailing Slashes
location /imagematches/imageand/image/, and even/imageabcwill match (because it is a prefix match).location /image/only matches paths that start with/image/, such as/image/photo.jpg, but it will not match/image(the case without a trailing slash).
If a client requests /image, location /image will handle it, while location /image/ will not match. The request may then fall back to location /.
Priority When Multiple Locations Exist
Nginx selects the longest matching prefix. For example, for a request to /image/photo.jpg:
- If
location /image/exists, it takes priority. - If only
location /imageexists, it matches that. - If neither exists, it matches
location /.
location / is the shortest prefix, so it acts as a fallback, matching any path.
The Difference of Whether or Not to Include a Trailing Slash in proxy_pass
This is the part of Nginx that I think is most prone to causing issues: whether or not you include a / after proxy_pass results in completely different forwarded paths.
Assume our location block looks like this:
location /api/ {
proxy_pass ...;
}
1. proxy_pass http://backend (without path)
location /api/ {
proxy_pass http://backend;
}
Request http://example.com/api/users, forwarding it to http://backend/api/users.
The original URI /api/users is fully preserved and directly appended to the backend.
2. proxy_pass http://backend/ (with a slash)
location /api/ {
proxy_pass http://backend/;
}
A 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 proxy_pass includes a path (even if it is just /), causing Nginx to replace the matched location prefix.
For another example, a request to http://example.com/api/ is forwarded to http://backend/.
3. proxy_pass http://backend/image (with a specific path)
location /api/ {
proxy_pass http://backend/image;
}
Request http://example.com/api/users, forwarded to http://backend/imageusers.
The pattern becomes clear here: Nginx strips the /api/ part matched by the location and directly appends the remaining users to http://backend/image, resulting in /imageusers—which is usually not the desired outcome.
If you want to forward to /image/users, it should be written as:
location /api/ {
proxy_pass http://backend/image/;
}
Summary of Patterns
In short:
proxy_passhas no path component (e.g.,http://backend): The original URI is forwarded unchanged.proxy_passhas a path component (e.g.,http://backend/orhttp://backend/xxx): The prefix matched by thelocationblock is replaced with the path component specified inproxy_pass.
This difference in the / may seem minor, but mixing it up can cause requests to be routed to the wrong path, which can be quite difficult to troubleshoot.
Comments (0)
No comments yet. Be the first to leave one!