NewHalo Edge 3 is here: HTTP/3 everywhere and 42 edge locations.Learn more
Docs / Web servers

Redirect HTTP to HTTPS and www to non-www

Web servers6 min readUbuntu 24.04 LTS

Once HTTPS works, send every visitor to one secure address. This guide redirects plain HTTP to HTTPS and redirects www to the bare domain, so search engines, bookmarks and shared links all point at a single canonical URL.

Before you begin

  • A working HTTPS certificate covering example.com and www.example.com. See Enable HTTPS with free TLS certificates.
  • nginx or Apache already serving your site.
  • A sudo user, such as deploy, and SSH access to the server.

Step 1: Choose your canonical address

Pick one form of your domain and use it everywhere. This guide uses https://example.com, without the www. Search engines treat the two forms as separate addresses, so choosing one keeps your ranking signals in one place.

Step 2: Record the current responses

Before changing anything, check how each address responds. The -I option shows headers only, and -s hides the progress meter.

curl -sI http://example.com | head -n 1
curl -sI https://www.example.com | head -n 1
HTTP/1.1 301 Moved Permanently
HTTP/2 200

Step 3: Write the nginx redirects

Certbot may already have added an HTTP redirect. Open your site file with sudo nano /etc/nginx/sites-available/example.com and make it match the structure below. The HTTPS blocks reuse the certificate files Certbot created. Those files already cover both names.

# Plain HTTP: send everything to the secure canonical domain
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 302 https://example.com$request_uri;
}

# HTTPS for www: send visitors to the bare domain
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    return 302 https://example.com$request_uri;
}

# HTTPS for the canonical domain: your real site
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    root /var/www/example.com/html;
    index index.html;
}

The redirects use 302 for now. Switch them to 301 after you have confirmed the behavior, as explained in the warning below.

Careful: A 301 redirect is cached by browsers for a long time, sometimes permanently. Test with 302 first. Change to 301 only when you are sure the destination is right.

Step 4: Write the Apache redirect

On Apache, enable the rewrite module with sudo a2enmod rewrite. Then add this virtual host to your HTTP site file, so every plain HTTP request goes to the canonical HTTPS address:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    RewriteEngine On
    RewriteRule ^ https://example.com%{REQUEST_URI} [R=302,L]
</VirtualHost>

For the www-to-bare redirect over HTTPS, add a VirtualHost *:443 block for www.example.com that reuses the SSL lines Certbot wrote into your HTTPS site, and redirects to https://example.com.

Step 5: Test and reload

Check the configuration, then reload the web server.

sudo nginx -t
sudo systemctl reload nginx

For Apache, use sudo apache2ctl configtest and sudo systemctl reload apache2.

Step 6: Verify each address

Check the status and the Location header for each address. The expected results are a redirect for http://example.com and for www.example.com, and a 200 for the canonical HTTPS address.

curl -sI http://www.example.com | grep -iE "^HTTP|^location"
HTTP/1.1 302 Found
location: https://example.com/
curl -sI https://example.com | head -n 1
HTTP/2 200

Troubleshooting

  • "Too many redirects" in the browser. Two rules send traffic back and forth, usually an HTTPS block that redirects to HTTP. Make sure only the www block and the HTTP block redirect, and the canonical block serves the page.
  • The browser still shows the old behavior. Browsers cache 301 responses. Test with curl or a private window, and switch to 302 while you work.
  • A certificate warning on www.example.com. The certificate does not include the www name. Run sudo certbot --nginx -d example.com -d www.example.com again.
  • The path is lost after the redirect. Check that the redirect ends with $request_uri in nginx, or %{REQUEST_URI} in Apache.

Next steps

With one canonical address in place, check your site's speed with Enable compression and browser caching. If you later add more domains, repeat these redirects for each one.

Something not working? Chat or email our support team and we will help you get unstuck.

Contact support