Hướng dẫn
Quảng cáo

Cấu hình nhiều subdomain trên NGINX + SSL Let's Encrypt

Hướng dẫn chi tiết cấu hình server NGINX tối ưu cho nhiều subdomain bằng cách dùng một file cấu hình nginx duy nhất và một chứng chỉ SSL Let's Encrypt.

Trong bài đăng này, tôi sẽ trình bày chi tiết cấu hình máy chủ web NGINX tối ưu cho nhiều tên miền phụ bằng cách sử dụng một file cấu hình nginx duy nhất và một chứng chỉ SSL Let's Encrypt.

NGINX là gì?

NGINX là ứng dụng máy chủ web hàng đầu cung cấp cho hơn 50% các trang web bận rộn nhất trên internet. Nó có thể cấu hình cao và có khả năng xử lý hàng nghìn yêu cầu đồng thời. 

Let's Encrypt là gì?

Let's Encrypt là một cơ quan cấp chứng chỉ và dịch vụ chứng chỉ SSL tự động, miễn phí. 

Bài đăng này mang tính kỹ thuật và hướng đến cộng đồng những người phát triên web. Tôi giả định rằng bạn đã quen với việc định cấu hình NGINX, cài đặt chứng chỉ SSL và dòng lệnh.

Tại sao lại đăng bài này?

Gần đây, tôi muốn cung cấp website miễn phí cho các thành viên với tên miền phụ dưới dạng https://subdomain.exampledomain.vn. Và trang chủ về dịch vụ đó (riêng biệt) tại https://exampledomain.vn và tôi đã thực hiện một số nghiên cứu để đi đến một giải pháp tối ưu. Thách thức là tài liệu được cung cấp đều là các giải pháp lỗi thời (bao gồm cả trên Stack Overflow).

Điều tôi đang muốn làm đó là:

  • Một chứng chỉ SSL Let's Encrypt duy nhất cho exampledomain.vn và tất cả các tên miền phụ sau này nếu phát sinh.
  • Một file cấu hình NGINX duy nhất cho exampledomain.vn và tất cả các tên miền phụ tham chiếu đến chứng chỉ SSL duy nhất đó.

Tôi coi đây là một giải pháp tối ưu vì nó 'DRY' (Không lặp lại - Don't Repeat Yourself). Miền và các miền phụ của nó chia sẻ một khối cấu hình NGINX duy nhất cho một chứng chỉ SSL duy nhất, giúp việc bảo trì và gia hạn tự động dễ dàng hơn.

Những điều bạn nên biết trước:

  1. "www" trong "www.exampledomain.vn" thực sự là một miền phụ (như subdomain.exampledomain.vn). Với một vài lưu ý, exampledomain.vn có thể được coi là một miền riêng biệt - miền gốc .
  2. NGINX có tệp cấu hình chính có tên "nginx.conf". Tệp chính này thường tham chiếu đến các tệp cấu hình khác (thường là một tệp cho mỗi miền ảo).
  3. Chứng chỉ SSL của Let's Encrypt thường được cài đặt và gia hạn tự động bằng cách sử dụng 'certbot' của chúng (một tác nhân quản lý chứng chỉ chạy trên máy chủ web). Tác nhân này hỗ trợ và sử dụng NGINX để cài đặt chứng chỉ SSL.

Cấu hình NGINX

Tôi sẽ giả sử rằng NGINX đã được cài đặt và tệp cấu hình NGINX chính "nginx.conf" đã được định cấu hình (có thể bao gồm các tệp cấu hình riêng biệt cho từng miền ảo).

Trong bài đăng này, tôi tập trung vào việc định cấu hình tên miền exampledomain.vn và các tên miền phụ của nó.

Vì chúng ta sẽ sử dụng HTTPS, nên tôi sẽ bắt đầu bằng cách chuyển hướng tất cả HTTP (lưu lượng không an toàn trên cổng 80) sang HTTPS (an toàn):

Ví dụ

server{
    
    listen 80;           # IPv4
    server_name ~^(www\.)?(?<name>(.+\.)?exampledomain\.vn)$;
    return 301 https://$name$request_uri;
}

Đây là cấu hình NGINX đầy đủ của tôi:

Ví dụ

server{
    
    listen 80;           # IPv4
	server_name ~^(www\.)?(?<name>(.+\.)?exampledomain\.vn)$;
    return 301 https://$name$request_uri;
}
server {
	listen 443 ssl http2; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/exampledomain.vn-0001/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/exampledomain.vn-0001/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    server_name ~^www\.(?<name>(.+\.)?exampledomain\.vn)$;
    return 301 https://$name$request_uri;
}
server {
		server_name "~^(?<subdomain>\w+)\.exampledomain\.vn$";
		if ($https != 'on') {
                return 301 https://$subdomain.exampledomain.vn$request_uri;
        }
        set $checkfoldersubdomain "/$subdomain";
        set $foldersubdomain "/$subdomain";
        if ($checkfoldersubdomain = '/')
        {
        	set $foldersubdomain "";
        }
		root /home/exampledomain.vn/public_html$foldersubdomain;
        index index.php index.html index.htm;        
		location / { 
                try_files $uri $uri/ /index.php?$args;
                #return 200 $document_root;
        }       
    	# access_log off;
		access_log /home/exampledomain.vn/logs/access.log;
    	# error_log off;
    	error_log /home/exampledomain.vn/logs/error.log;
		# Custom configuration
		include /home/exampledomain.vn/public_html/*.conf;
 
    	location ~ \.php$ {
		fastcgi_split_path_info ^(.+\.php)(/.+)$;
        	include /etc/nginx/fastcgi_params;
        	fastcgi_pass 127.0.0.1:9000;
        	fastcgi_index index.php;
		fastcgi_connect_timeout 300;
		fastcgi_send_timeout 300;
		fastcgi_read_timeout 300;
		fastcgi_buffer_size 32k;
		fastcgi_buffers 8 16k;
		fastcgi_busy_buffers_size 32k;
		fastcgi_temp_file_write_size 32k;
		fastcgi_intercept_errors on;
        	fastcgi_param SCRIPT_FILENAME /home/exampledomain.vn/public_html$fastcgi_script_name;
    	}
	
	# Disable .htaccess and other hidden files
	location ~ /\.(?!well-known).* {
		deny all;
		access_log off;
		log_not_found off;
	}
	
	location = /favicon.ico {
		log_not_found off;
		access_log off;
	}
	
	location = /robots.txt {
		allow all;
		log_not_found off;
		access_log off;
	}
	
	location ~* \.(3gp|gif|jpg|jpeg|png|ico|wmv|avi|asf|asx|mpg|mpeg|mp4|pls|mp3|mid|wav|swf|flv|exe|zip|tar|rar|gz|tgz|bz2|uha|7z|doc|docx|xls|xlsx|pdf|iso|eot|svg|ttf|woff)$ {
		gzip_static off;
		add_header Pragma public;
		add_header Cache-Control "public, must-revalidate, proxy-revalidate";
		access_log off;
		expires 30d;
		break;
        }

        location ~* \.(txt|js|css)$ {
	        add_header Pragma public;
		add_header Cache-Control "public, must-revalidate, proxy-revalidate";
		access_log off;
		expires 30d;
		break;
        }

    listen 443 ssl http2 default_server;
    ssl_certificate /etc/letsencrypt/live/exampledomain.vn-0001/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/exampledomain.vn-0001/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
server {
    if ($host = www.exampledomain.vn) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
	listen 80;
	server_name www.exampledomain.vn;
    return 404; # managed by Certbot
}

Nó sử dụng một biểu thức chính quy để khớp với miền và các miền phụ của nó - và nó bắt tên miền phụ thành một biến: $subdomain. Sau đó, $subdomain được sử dụng để chỉ định các vị trí "root" riêng biệt cho từng tên miền phụ (cho vị trí của root index.html trong số các tệp khác). 

 

Mẹo: Nó hữu ích để định cấu hình nhiều tên miền phụ yêu cầu cấu hình tương tự nhưng yêu cầu một thư mục chung riêng biệt. Giải pháp thay thế là thiết lập các khối máy chủ riêng lẻ cho từng miền phụ.

Cài đặt một chứng chỉ SSL duy nhất cho nhiều tên miền phụ

Bạn sẽ cần phải cài đặt  Let's Encrypt  SSL agent (certbot) cho hệ thống cụ thể của mình (Linux, CentOS, Windows ...) trước khi tiến hành phần này. Đây là cách gọi certbot để tạo một chứng chỉ nhiều miền phụ duy nhất (từ dòng lệnh hoặc thiết bị đầu cuối):

Ví dụ

sudo certbot-auto certonly --server https://acme-v02.api.letsencrypt.org/directory  --manual --preferred-challenges dns  -d exampledomain.vn -d *.exampledomain.vn

Nếu bạn chỉ muốn tạo chứng chỉ cho 1 số tên miền phụ cụ thể thì dùng dòng lệnh sau:

Ví dụ

sudo certbot certonly -d exampledomain.vn -d www.exampledomain.vn -d web.exampledomain.vn

Cuối cùng, sau khi bạn hoàn tất việc định cấu hình NGINX và SSL, bạn có thể kiểm tra những gì bạn đã thực hiện bằng cách sử dụng:

Ví dụ

sudo  nginx -t

Hãy xem tệp nhật ký NGINX của bạn để tìm nhật ký có thể giúp bạn gỡ lỗi các vấn đề cụ thể trong khi kiểm tra các yêu cầu / chuyển hướng miền phụ của bạn trong thanh địa chỉ trình duyệt của bạn.

Bài viết này đã giúp ích cho bạn?

Bài viết mới

Advertisements