Nginx setup for your (CakePHP) apps

Quite some time ago, I linked already to the cakephp-config-for-nginx/ blog post.
And my post about Apache setup is also now almost 10 years old.
It is time to update also my blog about the latest configuration here, and in particular about Nginx setup for both local and production environments.

Basics

You should always point your domain (or subdomain) to your public directory "webroot", as shown below.

Local setup

For a local setup, you don’t necessarily need HTTPS config.
So for a more simple setup, you can for example do:

server {
    listen 80;
    server_name sandbox.local;
    client_max_body_size 64M;

    # root directive should be global
    root /home/vagrant/Apps/sandbox/webroot;
    index index.php;

    access_log /var/log/nginx/sandbox.access.log;
    error_log /var/log/nginx/sandbox.error.log;

    location / {
        try_files $uri \$uri /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass    unix:/var/run/php/php7.4-fpm.sock; # Specify your PHP version here
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

Then you can browse your app as http://sandbox.local for example.

Production setup

Here, we definitely want to do HTTPS.

server {
        listen 443 ssl;
        listen [::]:443 ssl;
        server_name www.sandbox.de;
        root /var/www/dereuromark/sandbox/webroot;
        index index.php;
        location / {
                index index.php;
                try_files $uri $uri/ /index.php?$args;
        }
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass  unix:/var/run/php/php7.4-fpm.sock;
                fastcgi_index index.php;
        }
        location ~ /\.ht {
                deny all;
        }

        ssl on;
        ssl_certificate     /etc/letsencrypt/live/sandbox.de/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/sandbox.de/privkey.pem;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        access_log /var/log/nginx/sandbox.access.log;
        error_log /var/log/nginx/sandbox.error.log;
        # CloudFlare real IP (if behind cloudfare)
        include /etc/nginx/cloudflare-real-ip.conf;
}

The example also includes the SSL example using the free "letsencrypt" service.
This is optional but will render your website "safe" and also speeds it up by caching already a lot of resources out of the box.

Cloudflare is optional, as well. It helps to keep the site a bit more safe from attacks and speeds up asset delivery.
If you include this, you might want to use a real IP config to proxy the visitors IP through. Otherwise, you would only see the cloudflare IP.

Check their docs for details, it usually contains something along the lines of

set_real_ip_from ...;
real_ip_header     CF-Connecting-IP;

Redirects

You want your website to be only available through one main URL.
In my case, my websites usually always available only using https://www.DOMAIN or subdomains such as https://subdomain.DOMAIN.

Add a server based redirect to the canonical version of your domain, so either with or without www. prefix:

server {
        listen 443 ssl;
        listen [::]:443 ssl;
        server_name dereuromark.de;
        return 301 https://www.dereuromark.de$request_uri;
}

This snippet always adds a www. prefix. And to simplify, it also directly targets HTTPS.

Also a HTTP to HTTPS (force) redirect makes a lot of sense:

server {
        listen 80;
        listen [::]:80;
        server_name dereuromark.de www.dereuromark.de;
        return 301 https://$server_name$request_uri;
}

Note: If you want to avoid one redirect, you could split the last example into both 80 and 443 snippets. But the browser caches 301s anyway, so not too much gain here.

Now search engines won’t index multiple domains/versions, and it also doesn’t allow anyone to browse it through unsafe HTTP access.
Double-check that the browser displays the green "lock" icon and confirms that your site is using HTTPS-only connection/traffic now no matter what domain you type in.

More

Anything left out? Do you have other useful tips, tricks, addons, or tools around Nginx setup?
Add them as comments below.

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.