To install Nginx on CentOS 7
First add the EPEL repository that hosts Nginx
sudo yum install epel-release
Then install Nginx
sudo yum install nginx
To start Nginx, run
sudo systemctl start nginx
To enable Nginx to start automatically when the system starts:
sudo systemctl enable nginx
For more information on installing Nginx, check out Digital Ocean’s walkthrough
Here are some other useful commands that you’ll probably be wanting as you learn how to use Nginx.
To view live error logs:
sudo tail -f /var/log/nginx/error.log
To restart Nginx (after every config change at least):
sudo systemctl restart nginx
To look at system logs:
journalctl -xe
To setup Nginx
First, you’ll need to setup some basic configuration in the nginx.conf file, in CentOS 7 this file is located at /etc/nginx/nginx.conf. Because I am used to Apache’s configuration, I split up the various server configs into separate files and included them in nginx.conf with include /etc/nginx/conf.d/*.conf;
I also wanted my Nginx server to be able to run PHP, so I could use WordPress. To be able to do this, you need to use a FastCGI instance and send PHP files to it.
1 2 3 |
upstream php { server 127.0.0.1:9000; } |
More information on FastCGI with Nginx
This is the full nginx.conf file, with other basic settings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
worker_processes 1; error_log /var/log/nginx/error.log; include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; client_max_body_size 13m; index index.php index.html index.html; include /etc/nginx/mime.types; default_type application/octet-stream; upstream php { server 127.0.0.1:9000; } include /etc/nginx/conf.d/*.conf; server_tokens off; } |
DigitalOcean has a great guide on Understanding the Nginx Configuration
Now, for each website you want to host, create a .conf file in the /etc/nginx/conf.d folder. This is what a simple reverse proxy server configuration file would look like if your other server was running on port 4000. I will include my full configuration file for tannerwj.com with all of these features and the modern security settings that I will address next at the end of this article.
1 2 3 4 5 6 7 8 |
server { listen 80; server_name mywebsite.com; location / { proxy_pass http://127.0.0.1:4000; } } |
For my websites, I generally use HTTP2 with HTTPS and IPv6. This is really easy to implement with Nginx. Simply replace listen 80; with listen [::]:443 ssl http2;
There are some great benefits for using HTTP2, and it is becoming more and more widely accepted. Learn more about HTTP2
To send all .php files to your FastCGI process, include this location block in whatever server block you will be using with PHP.
1 2 3 4 5 6 7 |
location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; fastcgi_pass php; } |
To redirect www requests to your non-www server block, add this server block:
1 2 3 4 |
server { server_name www.mywebsite.com; return 301 $scheme://mywebsite.com$request_uri; } |
To redirect non-HTTPS requests to your HTTPS server block, add this server block:
1 2 3 4 5 6 |
server { listen 80; listen [::]:80; server_name mywebsite.com; return 301 https://mywebsite.com$request_uri; } |
Modern Security Settings
I always make sure to be up to date on the current security best practices. This usually results in receiving an A+ rating from Qualys SSL Labs – something that I’d recommend to everyone. I’ll go over a few of the features that I added to my site in order to receive this A+ security rating.
I assume you already have an SSL certificate and key, but if you don’t there are a couple ways you can obtain one for free. Let’s Encrypt and Cloudflare both offer free SSLs, and I would recommend that you take advantage of them. Every website should use an SSL, regardless of the purpose of the website.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
listen 443 ssl http2 deferred; listen [::]:443 ssl http2 deferred; ssl_certificate /path/to/ssl/cer.pem; ssl_certificate_key /path/to/ssl/key.pem; ssl_session_cache shared:SSL:5m; ssl_session_timeout 1h; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH$ ssl_dhparam /path/to/ssl/dhparam.pem; add_header Strict-Transport-Security "max-age=15768000" always; add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; |
To learn more about these settings, I would recommend you check out a Gist by Diego Plentz. He fully explains these different settings, and you can decide from there whether or not you would like to implement them.
My full default.conf file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
server { server_name www.tannerwj.com; return 301 $scheme://tannerwj.com$request_uri; } server { listen 80; listen [::]:80; server_name tannerwj.com; return 301 https://tannerwj.com$request_uri; } server { listen 443 ssl http2 deferred; listen [::]:443 ssl http2 deferred; ssl_certificate /path/to/ssl/cer.pem; ssl_certificate_key /path/to/ssl/key.pem; ssl_session_cache shared:SSL:5m; ssl_session_timeout 1h; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH$ ssl_dhparam /path/to/ssl/dhparam.pem; add_header Strict-Transport-Security "max-age=15768000" always; add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; server_name tannerwj.com; root /var/www/html/wordpress/; location /static/ { root /var/www/html/; try_files $uri $uri/ =500; } error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location ~ \.php$ { rewrite ^/notes/(.*) /$1 break; fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; fastcgi_pass php; } location ~ /notes { rewrite ^/notes/(.*) /$1 break; try_files $uri $uri/ /index.php?$args; } location / { proxy_pass http://127.0.0.1:4000; } } |
As you can see, this includes all the modern security settings that I showed before, as well as how I implemented my various server blocks. It also includes my reverse proxy, as I redirect some incoming traffic to a Node.js server I have running on port 4000. I also include 5 other location blocks for specific control of those endpoints or file types. This allows me to serve static files as well as .php files from Nginx (this includes all of WordPress on the /notes route), but still allow for other routes to be forwarded to my Node.js server.
To host multiple websites on the same server with Nginx, simply add more server blocks to your configuration file, or add a new configuration file to the conf.d folder for each website that you host.
If this was helpful and you’d like to send a tip, send some Bitcoin to 1tannERvhK55jqoHhaydEbkc6rdo6iJ2i
Some helpful links:
https://stackoverflow.com/questions/34090577/wordpress-nginx-proxy-and-subdirectory-wp-login-php-redirects-to-domain
https://stackoverflow.com/questions/17413526/nginx-missing-sites-available-directory
https://codex.wordpress.org/Nginx
https://serverfault.com/questions/769444/nginx-wordpress-in-subdirectory
https://www.linode.com/docs/websites/lemp/lemp-server-on-centos-7-with-fastcgi
https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-nginx-on-centos-6–2
Leave a Reply