Install Varnish & Nginx for CentOS 7/8
# CentOS 7
sudo yum install -y epel-release
sudo rpm --nosignature -i https://packagecloud.io/varnishcache/varnish73/gpgkey
sudo curl -L https://packagecloud.io/varnishcache/varnish73/config_file.repo?os=el&dist=7 -o /etc/yum.repos.d/varnishcache_varnish73.repo
# CentOS 8
sudo dnf install -y epel-release
sudo rpm --nosignature -i https://packagecloud.io/varnishcache/varnish73/gpgkey
sudo curl -L https://packagecloud.io/varnishcache/varnish73/config_file.repo?os=el&dist=8 -o /etc/yum.repos.d/varnishcache_varnish73.repo
# Install packages
sudo yum install -y varnish nginx policycoreutils-python-utils
Configure Nginx
- Change Nginx port:
sudo nano /etc/nginx/nginx.conf
Modify:
Contents
server {
listen 8080 default_server;
listen [::]:8080 default_server;
server_name _;
root /usr/share/nginx/html;
# ... rest of config
}
- Create WordPress config:
sudo nano /etc/nginx/conf.d/wordpress.conf
server {
listen 8080;
server_name yourdomain.com;
root /var/www/wordpress;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
- Restart Nginx:
sudo systemctl restart nginx
SSL Configuration
- Install Certbot:
sudo yum install -y certbot python3-certbot-nginx
- Generate Certificates:
sudo certbot certonly --nginx -d yourdomain.com
- Create Combined PEM:
sudo bash -c "cat /etc/letsencrypt/live/yourdomain.com/fullchain.pem /etc/letsencrypt/live/yourdomain.com/privkey.pem > /etc/varnish/yourdomain.com.pem"
sudo chown varnish:varnish /etc/varnish/yourdomain.com.pem
Configure Varnish
- Edit systemd service:
sudo nano /etc/systemd/system/varnish.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/sbin/varnishd \
-a :80 \
-a :443,PROXY \
-p feature=+http2 \
-p ssl_cert=/etc/varnish/yourdomain.com.pem \
-p ssl_key=/etc/varnish/yourdomain.com.pem \
-s malloc,4G \
-f /etc/varnish/default.vcl
- Reload systemd:
sudo systemctl daemon-reload
Optimized VCL File
sudo nano /etc/varnish/default.vcl
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
.first_byte_timeout = 300s;
.probe = {
.url = "/";
.interval = 10s;
.timeout = 5s;
.window = 5;
.threshold = 3;
}
}
sub vcl_recv {
# Redirect HTTP → HTTPS
if (req.http.X-Forwarded-Proto !~ "(?i)https" && req.url !~ "^/\.well-known/acme-challenge/") {
return (synth(750, "Moved Permanently"));
}
# Bypass cache for admin/dynamic content
if (
req.url ~ "^/(wp-admin|wp-login|cart|checkout|my-account|add-to-cart|logout|xmlrpc.php|rest-api/|graphql)" ||
req.method != "GET"
) {
return (pass);
}
# Strip cookies for static files
if (req.url ~ "\.(css|js|jpe?g|png|gif|webp|svg|ico|woff2?|ttf|eot|mp4|webm)(\?.*)?$") {
unset req.http.Cookie;
}
# Clean remaining cookies
if (req.http.Cookie) {
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_wpnonce|comment_author|woocommerce_(.*)|wordpress_(.*))[^;]*", "");
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
set req.http.Cookie = regsub(req.http.Cookie, ";\s*$", "");
if (req.http.Cookie == "") {
unset req.http.Cookie;
} else {
return (pass);
}
}
}
sub vcl_backend_response {
# Cache static files 1 year
if (beresp.url ~ "\.(css|js|jpe?g|png|gif|webp|svg|ico|woff2?|ttf|eot|mp4|webm)(\?.*)?$") {
set beresp.ttl = 365d;
unset beresp.http.Set-Cookie;
}
# Cache HTML 2 hours
else if (beresp.http.Content-Type ~ "text/html") {
set beresp.ttl = 2h;
set beresp.grace = 1h;
}
# Bypass REST API
if (bereq.url ~ "^/(wp-json|api)") {
set beresp.uncacheable = true;
}
}
sub vcl_synth {
if (resp.status == 750) {
set resp.status = 301;
set resp.http.Location = "https://" + req.http.Host + req.url;
return (deliver);
}
}
sub vcl_deliver {
# Cache headers
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT (" + obj.hits + ")";
} else {
set resp.http.X-Cache = "MISS";
}
# Security headers
set resp.http.X-Content-Type-Options = "nosniff";
set resp.http.X-Frame-Options = "SAMEORIGIN";
set resp.http.Referrer-Policy = "strict-origin-when-cross-origin";
unset resp.http.Server;
unset resp.http.X-Powered-By;
}
WordPress Configuration
Install Varnish HTTP Purge Plugin: Use the Varnish HTTP Purge plugin to clear cache automatically.
SELinux & Firewall
# Allow Varnish to bind to ports
sudo semanage port -a -t http_port_t -p tcp 80
sudo semanage port -a -t http_port_t -p tcp 443
# Firewall rules
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Finalize & Test
sudo systemctl restart varnish nginx
# Test SSL
curl -I https://yourdomain.com
# Verify cache
curl -I http://yourdomain.com | grep X-Cache
# Check Varnish logs
sudo journalctl -u varnish -f
Key CentOS-Specific Notes
- SELinux Contexts:
- If encountering permission issues:
sudo setsebool -P httpd_can_network_connect 1
sudo restorecon -Rv /etc/varnish
- PHP-FPM Configuration:
Ensure PHP-FPM is listening on correct socket:
sudo nano /etc/php-fpm.d/www.conf
listen = /run/php-fpm/www.sock
listen.owner = nginx
listen.group = nginx
- Varnish Logs:
CentOS uses journalctl for logging:
sudo journalctl -u varnish --since "5 minutes ago"
This CentOS version achieves identical performance to the Ubuntu setup while respecting Red Hat ecosystem conventions. The main differences are in package management and SELinux integration.