Why TCExam Behaves Differently Under HTTPS
TCExam is a PHP-based computer-based assessment system that stores an absolute site URL inside its configuration files and generates links, form actions, and AJAX endpoints from that stored value. When you install it over plain HTTP and later enable SSL, or when a certificate is issued but the application config never gets updated, the mismatch surfaces in very specific ways: login pages that reload endlessly, question media that silently fails to load, and timer scripts that stop firing because the browser blocks an insecure request mid-exam. These are not server faults. They are a direct result of the application still believing it lives at an http:// address while the browser arrives over https://.
The configuration that drives this lives in two files under your document root. The primary one is config/tce_config.php, which defines constants such as K_PATH_URL and K_PATH_HOST. These constants are concatenated into nearly every emitted URL, so a stale http:// prefix there is the usual root cause of mixed-content and redirect problems. The second relevant file is config/tce_authentication.php, where session and cookie behavior is defined. On the Hostiso stack you edit both through the cPanel Jupiter File Manager or DirectAdmin Evolution File Manager, since you are operating as an unprivileged hosting user with no SSH or root access.
There is a second layer that trips people up on LiteSpeed shared hosting: proxy awareness. LiteSpeed terminates TLS at the web server and hands the request to PHP. In most cases PHP sees $_SERVER['HTTPS'] correctly, but when a service such as Cloudflare or a reverse proxy sits in front, the TLS handshake happens upstream and your origin may receive the request on an internal HTTP connection. PHP then reports $_SERVER['HTTPS'] as empty, TCExam assumes it is on HTTP, and it issues a redirect to the HTTPS version. The proxy forwards that back, the origin redirects again, and you get a redirect loop. Recognizing which layer is misreporting the scheme determines which fix you apply.
Issuing and Verifying the Certificate First
Before touching any application file, confirm a valid certificate actually covers the hostname TCExam runs on. In cPanel Jupiter, open Security → SSL/TLS Status. Hostiso provisions AutoSSL (which uses Let's Encrypt or Sectigo depending on the account), so you should see a green lock beside your domain and any subdomain such as exam.yourdomain.com. If the entry shows as unsecured, click Run AutoSSL and wait for the queue to complete. In DirectAdmin Evolution the equivalent path is Account Manager → SSL Certificates, where you select Free & automatic certificate from ACME Provider, tick both the bare domain and the www or subdomain entries, and save.
A frequent cause of a half-working certificate is that TCExam lives on a subdomain or subfolder that was not included when the certificate was generated. AutoSSL covers document roots it can validate, so if you added exam.yourdomain.com after the last run, trigger a fresh issuance. Verify the result from the browser by loading https://yourdomain.com/tcexam/ directly and inspecting the padlock. A certificate that is valid but presents the wrong hostname (a mismatch warning) means the DNS record points at a document root whose certificate covers a different name, which no amount of application config will correct.
Only once the padlock is clean on a direct request should you move on to the application. Trying to debug redirect loops while the certificate itself is invalid wastes time, because the browser warnings mask the application-level symptoms you are actually trying to fix.
Updating TCExam Config and Enforcing HTTPS Cleanly
Open config/tce_config.php in File Manager and locate the URL constants. Set them explicitly to the HTTPS form so TCExam stops generating protocol-relative or HTTP links:
define ('K_PATH_HOST', 'https://exam.yourdomain.com/');
define ('K_PATH_URL', K_PATH_HOST.'tcexam/');Adjust the tcexam/ segment to match your actual install path, or remove it entirely if TCExam sits at the domain root. Save the file, then clear your browser cache and reload. This single change resolves the majority of mixed-content warnings, because the application now emits https:// for its stylesheets, question images, and AJAX calls instead of the stale scheme.
To force every visitor onto HTTPS, add a redirect at the web server layer through .htaccess in your document root rather than inside PHP. LiteSpeed reads .htaccess natively, so this is the correct place for a scheme redirect:
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]The second RewriteCond is what prevents redirect loops behind a proxy. When Cloudflare or a front-end proxy forwards an already-secure request, it sets the X-Forwarded-Proto header to https even though the origin connection is plain HTTP. By checking that header in addition to the native HTTPS variable, the rule stops redirecting requests that are already secure from the visitor's perspective. If you skip this condition on a proxied account, the origin keeps trying to upgrade a connection the browser already considers secure, and the result is the ERR_TOO_MANY_REDIRECTS page.
If you use Cloudflare, also set the SSL/TLS mode in the Cloudflare dashboard to Full or Full (strict), never Flexible. Flexible mode makes Cloudflare talk to your Hostiso origin over HTTP while serving the browser HTTPS, which guarantees the loop regardless of your .htaccess conditions. Full (strict) pairs cleanly with the AutoSSL certificate you issued earlier.
Proxy Awareness, Secure Cookies, and Residual Mixed Content
When PHP still reports HTTP behind a proxy and your config edits are not enough, you can hint the scheme without root by setting a server variable in .user.ini at the document root. The PHP Selector on CloudLinux reads .user.ini for your account:
; forces TCExam session cookies to be sent only over HTTPS
session.cookie_secure = On
session.cookie_httponly = On
session.cookie_samesite = "Lax"Setting session.cookie_secure matters during live exams. If cookies are not flagged secure while the site runs on HTTPS, some browsers refuse to persist the session across the exam's AJAX heartbeat, and candidates get logged out mid-test. After saving .user.ini, allow a few minutes for the CloudLinux PHP worker to recycle, or touch a PHP file to force a reload, since the file is cached per directory rather than read on every request.
For stubborn mixed-content warnings that survive the config change, inspect the browser console on the exam page. Each blocked request names the exact http:// asset. The usual offenders are hardcoded image paths inside question text that were pasted with an absolute HTTP URL, or a logo path stored in the TCExam admin under Modules → General → Configuration. Edit those entries in the TCExam AdminCP so they use relative paths or the HTTPS host. As a transitional safety net you can add an upgrade directive via .htaccess, which tells the browser to retry insecure subresources over HTTPS:
Header always set Content-Security-Policy "upgrade-insecure-requests"Treat that header as a stopgap rather than a cure, because it masks the underlying stale links instead of removing them, and it will not help assets served from a host that has no certificate. The durable fix remains correcting K_PATH_HOST and cleaning any absolute HTTP references inside question banks.
Finally, confirm the whole chain end to end. Load the exam login over HTTPS, start a sample test, submit an answer, and watch the console stay clean through the timer refresh. If PHP-level issues persist, your account's error_log in the document root records session and header warnings that point to the exact file and line, which is the fastest way to isolate a remaining HTTP reference without server-wide access. The same approach to resource and request handling applies across other PHP learning platforms, such as the Claroline migration and URL rewrite workflow, where stored absolute URLs drive the same class of HTTPS symptoms.