# Force HTTPS

> Redirect plain HTTP to HTTPS per domain and per subdomain — applied only while the hostname has a valid certificate, so it can never take a site offline.

Source: https://www.corepanel.net/docs/web/https-redirect/
Last updated: 2026-07-30
Part of the CorePanel documentation — https://www.corepanel.net/docs

---

Every site CorePanel serves answers on both port 80 and port 443. Unless HTTP redirects
to HTTPS, a visitor who types the bare domain, an old bookmark, or a link from an email
signature keeps browsing over an unencrypted connection — and so does every form they
submit.

The **Force HTTPS** setting makes plain HTTP answer a permanent redirect to the same URL
over HTTPS. It is set per domain and per subdomain, and it is **on by default for new
domains**.

## What it does, exactly

A request that arrives over HTTP gets:

```
HTTP/1.1 308 Permanent Redirect
Location: https://www.example.com/checkout?step=2
```

The redirect preserves the **scheme change only** — path, query string and hostname stay
as they are. The status code is `308`, not `301`, and that difference matters: a `301`
allows the browser to turn a `POST` into a `GET`, which silently drops the body of a form
submitted over HTTP. `308` keeps the method and the body intact. Both are cached by
browsers the same way.

Requests under `/.well-known/` are never redirected, so ACME certificate challenges keep
working over HTTP.

## It only applies when there is a certificate

This is the part worth internalising, because it is what makes the setting safe:

**The redirect is evaluated per request, and only fires while that exact hostname has a
currently valid certificate.**

Three consequences follow:

- **Turning it on before a certificate exists is harmless.** The setting lies dormant and
  the site keeps serving over HTTP. As soon as the certificate is issued, the redirect
  starts working on its own — you do not have to come back and enable it.
- **A failed renewal degrades to HTTP instead of taking the site down.** Without this
  rule, an expired certificate plus a forced redirect is a site that answers "redirect to
  a URL the browser refuses to load" — an outage with no way back in through the browser.
- **An expired certificate counts as no certificate.** The check is validity, not
  presence of a file on disk.

Certificates come from the wildcard CorePanel issues for the domain (`*.example.com` +
`example.com`), or from the per-hostname certificate obtained on the first HTTPS request.
See [SSL Certificates](https://www.corepanel.net/docs/ssl-certificates) for how and when each is issued.

> **Two-level subdomains need their own certificate**
>
> A wildcard covers **one** label: `blog.example.com` is covered by `*.example.com`,
> `staging.blog.example.com` is not. On a two-level subdomain the redirect stays dormant
> until that hostname gets a certificate of its own.
## Where to change it

In the account workspace, open the **Domains** or **Subdomains** table and click the edit
button on the row. The dialog has an **HTTPS** section with the switch. Rows that redirect
show a shield next to their name.

The change is applied on the next configuration reload, with no downtime and no dropped
connections.

## Defaults, and why they differ

| How the domain was created | Force HTTPS |
|---|---|
| Added from the panel or the CLI | **On** |
| Created with a new account | **On** |
| Existing domain, upgraded to a version with this feature | **Off** |
| Imported from cPanel | **Off** |
| Restored from a backup | **Off** |

A brand-new domain has no traffic yet to break: no payment provider is calling an
`http://` webhook on it, and no application has an `http://` canonical URL stored in its
database. Turning the redirect on is what an operator would do by hand anyway.

A **migrated** site is the opposite case. It is live somewhere else right now, with
integrations registered against `http://` URLs at providers nobody is about to reconfigure.
Flipping a whole imported server to HTTPS-only on day one is how a migration goes wrong at
scale, so imports and restores leave it off and you enable it per domain once the site is
verified.

Upgrades leave existing domains alone for the same reason: changing how a live site
answers is an operator decision, not a side effect of installing a package.

## WordPress: the redirect loop to avoid

If WordPress still has an `http://` site URL, turning the redirect on creates a loop: the
server sends the browser to `https://`, WordPress sends it back to its `http://` canonical,
and the two bounce off each other until the browser gives up.

The panel checks for this before saving. When it finds a WordPress instance on the domain
with an `http://` site URL, it warns and offers to update the site URL in the same step —
and if that update fails, it **leaves the redirect off** rather than saving a
configuration it knows will loop.

The same trap exists for any application that stores its own absolute base URL (Nextcloud,
Matomo, a hardcoded `APP_URL` in a `.env`). Those the panel cannot see; check them before
enabling.

## Verifying it

```bash
# Should answer 308 with an https:// Location
curl -sI http://example.com/some/path?a=b | head -3

# Should NOT redirect — ACME challenges stay on HTTP
curl -sI http://example.com/.well-known/acme-challenge/test | head -1

# What certificate the hostname actually presents
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -subject -dates
```

If the first command returns `200` instead of `308`, the hostname has no valid certificate
yet — check the third command before looking anywhere else.
