This is the correct and most efficient way if you want to keep it all in one server block:
server { listen 80; listen [::]:80; listen 443 defaultdefault_server ssl; server_name www.example.com; ssl_certificate /path/to/my/cert; ssl_certificate_key /path/to/my/key; if ($scheme = http) { return 301 https://$server_name$request_uri; } } Everything else above, using "rewrite" or "if ssl_protocol" etc is slower and worse.
Here is the same, but even more efficient, by only running the rewrite on the http protocol it avoids having to check the $scheme variable on every request. But seriously, it's such a minor thing that you don't need to separate them.
server { listen 80; listen [::]:80; server_name www.example.com; return 301 https://$server_name$request_uri; } server { listen 443 defaultdefault_server ssl; server_name www.example.com; ssl_certificate /path/to/my/cert; ssl_certificate_key /path/to/my/key; }