When setting up SSL certificate validation (like Comodo/Digicert), many developers struggle with proper Nginx configuration for HTTP-based domain verification. The key requirement is making a specific validation file (e.g., HASHHASH.txt) accessible at /.well-known/pki-validation/
path while maintaining other site routes.
The typical mistake is using root
directive incorrectly for nested paths. Your current approach:
location /.well-known/pki-validation/HASHHASH.txt {
root /var/www/comodo;
}
fails because Nginx constructs the full path as: /var/www/comodo/.well-known/pki-validation/HASHHASH.txt
, which likely doesn't match your file structure.
Here are three proven methods:
Method 1: Using alias directive
location ^~ /.well-known/pki-validation/HASHHASH.txt {
alias /var/www/comodo/HASHHASH.txt;
}
Method 2: Correct root-based approach
Place file in proper subdirectory structure:
# Directory structure:
# /var/www/comodo/.well-known/pki-validation/HASHHASH.txt
location /.well-known/pki-validation/ {
root /var/www/comodo;
}
Method 3: Full path rewrite
location = /.well-known/pki-validation/HASHHASH.txt {
rewrite ^ /HASHHASH.txt break;
root /var/www/comodo;
}
After making changes:
sudo nginx -t # Test configuration
sudo systemctl reload nginx # Apply changes
Verify with:
curl -I http://website.com/.well-known/pki-validation/HASHHASH.txt
1. Check file permissions: sudo chmod 644 /var/www/comodo/HASHHASH.txt
2. Verify SELinux contexts if applicable
3. Ensure no other location blocks are intercepting the request
4. Check error logs: tail -f /var/log/nginx/error.log
For environments with frequent certificate renewals:
location ~ ^/\.well-known/pki-validation/(.*\.txt)$ {
alias /var/www/ssl-validation/$1;
}
This regex pattern handles any .txt file in the validation directory.
When setting up SSL certificates with providers like Comodo or Let's Encrypt, you often need to prove domain ownership by serving a specific validation file at a precise URL path. The challenge is configuring Nginx to serve just this one file without affecting other routes.
The most frequent mistakes I see in these configurations are:
- Incorrect path concatenation between
location
androot/alias
- Missing file permissions
- Not accounting for hidden directories (.well-known)
- Forgetting to reload Nginx after changes
Here's the correct way to set this up:
server {
listen 80;
server_name example.com www.example.com;
location = /.well-known/pki-validation/HASHHASH.txt {
alias /var/www/comodo/HASHHASH.txt;
}
# Alternative using root directive
location /.well-known/pki-validation/ {
root /var/www/comodo;
}
}
Notice the important details:
- Using
alias
instead ofroot
when you want an exact file match - The equals sign (
=
) for exact location matching - File permissions must allow Nginx (usually www-data user) to read the file
After making changes:
sudo nginx -t
sudo systemctl reload nginx
curl http://example.com/.well-known/pki-validation/HASHHASH.txt
If you need to handle multiple validation files:
location ~ ^/\.well-known/pki-validation/(.*\.txt)$ {
alias /var/www/comodo/validation_files/$1;
}
This regex pattern will match any .txt file in the validation directory and serve it from the corresponding location in your filesystem.
If it's still not working:
- Check Nginx error logs:
tail -f /var/log/nginx/error.log
- Verify file exists:
ls -la /var/www/comodo/HASHHASH.txt
- Test permissions:
sudo -u www-data cat /var/www/comodo/HASHHASH.txt