Chuyện Gì Đã Xảy Ra
Tôi đang thêm một virtual host mới vào server Nginx đã có khoảng chục domain được cấu hình sẵn. Sau khi chạy nginx -t để kiểm tra config, tôi nhận được thông báo này:
nginx: [emerg] could not build the server_names_hash, you should increase server_names_hash_bucket_size: 64
nginx: configuration file /etc/nginx/nginx.conf test failed
Nginx từ chối reload. Site mới không lên được. Error log cũng không cung cấp thêm bất kỳ thông tin nào — chỉ có duy nhất một dòng đó. Hai dòng trong nginx.conf đã fix được, nhưng để biết hai dòng nào và tại sao thì cần phải tìm hiểu thêm.
Nguyên Nhân
Nginx lưu tất cả các giá trị server_name vào một hash table để tra cứu nhanh. Mỗi bucket trong bảng đó mặc định có kích thước 64 byte. Khi một tên domain — hoặc tổng trọng lượng của tất cả các tên domain — không vừa vào bucket 64 byte, Nginx sẽ không thể khởi tạo bảng khi startup và ném ra lỗi này.
Các nguyên nhân phổ biến:
- Tên domain dài như
some-very-long-subdomain.client-company-name.example.com(dễ dàng vượt 50+ ký tự) - Wildcard entry như
*.subdomain.example.com - Quá nhiều alias nhồi nhét vào một directive
server_name - Thêm vhost mới khiến tổng kích thước hash vượt giới hạn
Các Bước Debug
Bắt đầu bằng cách xác định config nào đang gây ra vấn đề:
nginx -T 2>&1 | grep server_name
Lệnh này sẽ dump toàn bộ config đã merge. Tìm những tên bất thường dài hoặc các server block chứa nhiều alias. Sau đó chạy kiểm tra config và đọc kỹ lỗi:
sudo nginx -t
Nếu lỗi hiển thị bucket_size: 64, tăng lên 128. Nếu đã là bucket_size: 128, tăng gấp đôi lên 256.
Muốn tìm server name dài nhất nhanh chóng? Chạy lệnh này:
grep -r 'server_name' /etc/nginx/sites-enabled/ | awk '{print length, $0}' | sort -rn | head -5
Tên nào có 60–70 ký tự chính là thủ phạm. Những tên dưới 50 ký tự thường vừa vặn với bucket size mặc định 64 byte.
Cách Sửa
Mở /etc/nginx/nginx.conf và thêm hoặc cập nhật các dòng sau bên trong block http:
http {
# Tăng hash bucket size cho server name dài
server_names_hash_bucket_size 128;
server_names_hash_max_size 512;
# ... phần còn lại của config
}
Hai directive này giải quyết các vấn đề khác nhau:
server_names_hash_bucket_size— kiểm soát kích thước từng bucket riêng lẻ. Phải là lũy thừa của 2: 64 → 128 → 256. Tăng giá trị này khi một tên domain quá dài không vừa bucket.server_names_hash_max_size— kiểm soát tổng số bucket. Mặc định là 512. Chỉ cần quan tâm khi bạn đang host hàng trăm domain — hầu hết mọi người không cần đụng đến cái này.
Với server thông thường gặp lỗi này, chỉ cần server_names_hash_bucket_size 128 là đủ. Đặt thẳng 256 từ đầu cũng không tốn kém gì và giúp bạn có thêm dư địa cho các domain trong tương lai.
Áp Dụng Fix
# Kiểm tra config trước — luôn luôn
sudo nginx -t
# Nếu test thành công, reload
sudo systemctl reload nginx
Xác Minh
Kết quả test sạch trông như thế này:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Sau đó xác nhận service đang chạy và vhost mới phản hồi được:
sudo systemctl status nginx
curl -I http://your-new-domain.com
Debug từ xa hoặc qua load balancer? Kiểm tra trực tiếp các worker process:
ps aux | grep nginx
Bạn sẽ thấy một master process và ít nhất một worker. Nếu chỉ có master mà không có worker nghĩa là vẫn còn thứ gì đó load thất bại.
Các Trường Hợp Đặc Biệt
Lỗi Vẫn Còn Sau Khi Đặt 128
Nếu lỗi bây giờ hiển thị bucket_size: 128, bạn đang có một tên domain thực sự rất dài. Nhảy thẳng lên 256:
server_names_hash_bucket_size 256;
Chỉ dùng lũy thừa của 2. Đặt giá trị như 192 sẽ không hoạt động — Nginx sẽ tự động làm tròn xuống hoặc ném ra một lỗi khác.
Config Nằm Trong File Include Riêng
Một số distro tách nginx.conf thành nhiều file include. Hãy đảm bảo directive nằm trong block http, không phải block server:
nginx -T 2>&1 | grep -A2 -B2 'server_names_hash'
Nếu vô tình đặt vào trong block server, directive sẽ bị bỏ qua hoàn toàn — lỗi cứ lặp lại và bạn sẽ mất cả tiếng đồng hồ tự hỏi tại sao.
Phòng Ngừa
Hiện tại, hai dòng này được thêm vào mọi cài đặt Nginx mới trước khi cấu hình bất kỳ vhost nào:
server_names_hash_bucket_size 128;
server_names_hash_max_size 1024;
Mất 10 giây. Tránh cho bạn khỏi một lần reload thất bại lúc 2 giờ sáng khi ai đó thêm domain kiểu như staging-api.long-client-name.internal.example.com.
Nếu bạn quản lý nhiều server Nginx và muốn kiểm tra config trước khi đẩy lên, nginx -t -c /path/to/test.conf cho phép bạn test bản sao local trước khi deploy. Để xác minh rằng config đã test khớp byte-for-byte với những gì đang chạy trên server, tôi dùng SHA-256 check với Hash Generator tại toolcraft.app — chạy trên trình duyệt, không có gì được upload lên.
Bài Học Rút Ra
- Luôn chạy
nginx -ttrước khisystemctl reload nginx. Reload với config lỗi sẽ thất bại âm thầm — config cũ vẫn chạy và bạn không nhận được cảnh báo nào. - Mặc định 64 byte ổn với các tên ngắn. Nhưng ngay khi ai đó thêm subdomain như
portal.north-america-region.client.example.com, bạn đã vượt giới hạn. Đặt 128 từ ngày đầu. - Thông báo lỗi hơi gây nhầm lẫn. Nó chỉ vào
bucket_size, nhưng nếu bạn đang host 300+ domain,max_sizemới là thứ thực sự cần điều chỉnh. Hãy kiểm tra cả hai. - Lỗi này chỉ xuất hiện lúc load config — khi khởi động hoặc reload. Server chạy ổn hàng tháng có thể đột ngột từ chối reload sau một thay đổi config duy nhất. Trước đó không có gì hỏng cả; chỉ là tên mới vừa đẩy vượt ngưỡng giới hạn.

