Nhiều domain, subdomain có thể dùng cho một website, khi đó khai báo khối server sẽ lặp lại chỉ khác server_name và các khai báo SSL.
Có vài cách để tránh việc khai báo lại này:
- Lấy chứng chỉ SSL chung cho nhiều domain, subdomain (thí dụ SSL của example.com đã bao gồm SSL của example.org). Khi đó khai báo chung trong một khối server:
server {
listen 443 ssl http2;
server_name example.com example.org;
root /path/to/www;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include php.conf;
include ssl.conf;
location / {
try_files $uri $uri/ /index.php?$args =404;
}
}
- Khai báo SSL phụ thuộc vào một biến khác của Nginx
map $host $piCert {
example.com /etc/letsencrypt/live/example.com/fullchain.pem;
example.org /etc/letsencrypt/live/example.org/fullchain.pem;
}
map $host $piKey {
example.com /etc/letsencrypt/live/example.com/privkey.pem;
example.org /etc/letsencrypt/live/example.org/privkey.pem;
}
server {
listen 443 ssl http2;
server_name example.com example.org;
root /path/to/www;
ssl_certificate $piCert;
ssl_certificate_key $piKey;
include php.conf;
include ssl.conf;
location / {
try_files $uri $uri/ /index.php?$args =404;
}
}
Biến $host chứa đựng giá trị của server_name. Nhưng trong khai báo nhiều domain, $host chỉ lấy domain đầu tiên. Vì vậy cách trên thất bại, vẫn phải khai báo 2 khối server cho từng domain chỉ khác nhau ở server_name.
Thay vì dùng biến $host, có thể dùng biến $ssl_server_name phản ánh đúng domain đang dùng của server_name:
map $ssl_server_name $piCert {
example.com /etc/letsencrypt/live/example.com/fullchain.pem;
example.org /etc/letsencrypt/live/example.org/fullchain.pem;
}
map $ssl_server_name $piKey {
example.com /etc/letsencrypt/live/example.com/privkey.pem;
example.org /etc/letsencrypt/live/example.org/privkey.pem;
}
Một cách khác chính xác hơn là dùng biến $ssl_preread_server_name. Tuy nhiên cách này đòi hỏi Nginx được biên dịch có module ngx_stream_ssl_preread_module và khai báo cũng phức tạp hơn.
- Trường hợp backend của proxy
Nhờ tùy chọn proxy_set_header Host $host;
ở proxy server, biến $host
ở backend chứa tên domain và chúng ta có thể ứng dụng như sau:
server {
listen 443 ssl http2;
listen [::]:443;
include /etc/nginx/templates/ssl.tmpl;
server_name adminer.example.com
mailadmin.example.com
webmail.example.com;
return 301 https://mail.example.com/$sub_to_folder;
}
map $host $sub_to_folder {
adminer.example.com adminer;
mailadmin.example.com iredadmin;
webmail.example.com mail;
}
Chú thích
Trường hợp có nhiều domain và subdomain, cách dùng $ssl_server_name như trên tương đối rườm rà. Vì domain.com và *.domain.com có SSL trong cùng file nên có thể tìm cách bỏ subdomain trong $ssl_server_name để dùng SSL của domain.com
- *.example.com -> example.com
- *.example.org -> example.org
map $ssl_server_name $ssl_domain_name {
volatile;
hostnames;
default $ssl_server_name;
~^(\w+\.)?(?<basedomain>[^.]+\.[^.]+)$ $basedomain;
}
server {
listen 443 ssl http2;
server_name example.com example.org
cloud.example.com mail.example.org;
root /path/to/www;
ssl_certificate /etc/letsencrypt/live/$ssl_domain_name/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$ssl_domain_name/privkey.pem;
include php.conf;
include ssl.conf;
location / {
try_files $uri $uri/ /index.php?$args =404;
}
}