> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Configure URL Redirect

> Guide to configure NGINX to permanently redirect HTTP traffic to HTTPS, enable TLS with certificates, update firewall rules, and serve the same site over secure port 443.

In this lesson you'll configure NGINX to redirect all HTTP traffic to HTTPS using the simple and efficient `return` directive. This enforces encrypted connections and a consistent canonical URL for your site.

Goals

| Goal | Details |
| - | - |
| Redirect HTTP → HTTPS | Redirect all traffic arriving on port 80 to HTTPS (port 443) with a permanent redirect (HTTP 301). |
| Serve site over TLS | Provide an SSL-enabled server block on port 443 that uses the same site root and TLS certificate/key. |

Prerequisites / initial state

| Requirement | Current state / notes |
| - | - |
| App location | A simple "Diner" app is served from `/var/www/diner` on port 80. |
| Firewall (UFW) | UFW is active and currently allows SSH and HTTP. |
| Certificates | TLS certificate and key are required for port 443 (self-signed OK for testing). |

Check current UFW status:

```bash theme={null}
root@ubuntu-host:~# ufw status
Status: active

To                         Action  From
--                         ------  ----
22/tcp                     ALLOW   Anywhere
80/tcp                     ALLOW   Anywhere
22/tcp (v6)                ALLOW   Anywhere (v6)
80/tcp (v6)                ALLOW   Anywhere (v6)
```

Allow HTTPS through the firewall:

```bash theme={null}
root@ubuntu-host:~# ufw allow 443/tcp
```

Note: If you try to access `https://<host>` before NGINX is configured to listen on 443 and before TLS certificates are in place, your client will see a connection error (for example, connection refused or a browser/network TLS error) because no process is handling TLS yet.

Why this pattern?

* A minimal server block on port 80 that issues `return 301 https://$host$request_uri;` gives a fast, SEO-friendly permanent redirect.
* A separate server block on port 443 terminates TLS and serves the same content from the same `root`.
* Keeping the port 80 block short avoids unnecessary processing and ensures every HTTP request is canonicalized to HTTPS.

Examine the current non-HTTPS NGINX site configuration

* Typical HTTP-only site file: `/etc/nginx/sites-available/diner`

```nginx theme={null}
# /etc/nginx/sites-available/diner
server {
    listen 80;

    server_name diner.com;

    root /var/www/diner;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }
}
```

Create a combined configuration that redirects HTTP to HTTPS and serves HTTPS

* Create a new site file (example: `/etc/nginx/sites-available/diner-https`) containing two server blocks:
  * Port 80: issues a permanent redirect to the equivalent HTTPS URL.
  * Port 443: listens with `ssl` enabled and serves the same site content.

Example `diner-https` configuration:

```nginx theme={null}
# /etc/nginx/sites-available/diner-https
server {
    listen 80;

    server_name diner.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;

    server_name diner.com;

    ssl_certificate /etc/ssl/certs/diner.com.pem;
    ssl_certificate_key /etc/ssl/certs/diner.com-key.pem;

    root /var/www/diner;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }
}
```

Configuration details and best practices

* `return 301 https://$host$request_uri;` issues a permanent (301) redirect. `$host` preserves the hostname (including ports if present) and `$request_uri` preserves path and query string (for example, `/reservations?time=7pm`).
* The port 443 block must have `ssl_certificate` and `ssl_certificate_key` pointing to valid files so NGINX can terminate TLS.
* Obtain production certificates from a trusted CA (e.g., [Let's Encrypt](https://letsencrypt.org/)) and ensure the certificate matches `server_name` (DNS must point to your server).
* If you use multiple names (aliases), consider `server_name diner.com www.diner.com;` and ensure certificates cover all names (SAN or wildcard as appropriate).

Enable the HTTPS configuration

* Remove or disable any old HTTP-only symlink, then create the new symlink:

```bash theme={null}
# Remove existing site link if present (optional)
root@ubuntu-host:~# rm /etc/nginx/sites-enabled/diner

# Create the symlink for the HTTPS-enabled site
root@ubuntu-host:~# ln -s /etc/nginx/sites-available/diner-https /etc/nginx/sites-enabled/diner-https
```

Validate the NGINX configuration and reload

* Always test NGINX config before reloading:

```bash theme={null}
root@ubuntu-host:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

* If the test succeeds, reload NGINX to apply the changes:

```bash theme={null}
root@ubuntu-host:~# nginx -s reload
```

Verify the redirect behavior

* Test the HTTP endpoint to confirm it now responds with a 301 redirect:

```bash theme={null}
root@ubuntu-host:~# curl -I http://localhost
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0 (Ubuntu)
Date: <date>
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://localhost/
```

* A plain `curl localhost` (non-HEAD) will show the HTML body NGINX sends for the redirect:

```bash theme={null}
root@ubuntu-host:~# curl localhost
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>
```

Once NGINX listens on 443 with valid TLS certificates and UFW allows 443, clients can access the site securely over HTTPS. Visitors who request `http://diner.com` will be redirected to `https://diner.com` and served the site over TLS.

![A restaurant website landing page with a large hero photo of a plated dish and the bold headline "let's MEAT!" across the center. The page shows navigation links at the top and an embedded Google map (Banff area) and a video thumbnail below.](https://mintcdn.com/kodekloud-c4ac6d9a/ij3FNIPjp1w0Myd0/images/Nginx-for-Beginners/Intermediate-Config/Demo-Configure-URL-Redirect/restaurant-landing-hero-lets-meat-banff.jpg?fit=max\&auto=format\&n=ij3FNIPjp1w0Myd0\&q=85\&s=2870ac784f8b8411edfa891c1dc4d851)

Recap

* Use a minimal server block on port 80 to perform a permanent redirect: `return 301 https://$host$request_uri;`.
* Use a second server block on port 443 to terminate TLS and serve content, specifying `ssl_certificate` and `ssl_certificate_key`.
* Allow port 443 in your firewall (UFW) and always `nginx -t` before reloading.

If you are testing locally and using self-signed certificates, your browser will warn about the certificate. For production, obtain certificates from a trusted CA (for example, [Let's Encrypt](https://letsencrypt.org)) and ensure DNS for `server_name` points to your server IP.

Further reading and references

* NGINX documentation: [https://nginx.org/en/docs/](https://nginx.org/en/docs/)
* Let's Encrypt: [https://letsencrypt.org/](https://letsencrypt.org/)
* UFW (Uncomplicated Firewall) guide: [https://help.ubuntu.com/community/UFW](https://help.ubuntu.com/community/UFW)

> **[Watch Video](https://learn.kodekloud.com/user/courses/nginx-for-beginners/module/c78ff9cb-c15d-4f85-92fc-abee5ed98b20/lesson/4335a4b8-d404-4150-9001-09851f436e4a)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.