01.07 HTTPS and TLS Configuration
SimpleRisk relies on the web server (or reverse proxy) for TLS termination — the application doesn't enforce HTTPS itself, doesn't redirect HTTP to HTTPS, and doesn't emit HSTS headers. Here's the configuration pattern at the web server, the SimpleRisk-side settings that depend on HTTPS detection, and the production hardening checklist.
Why this matters
Production SimpleRisk should run over HTTPS. The application carries credentials (user passwords on login, API keys in headers, session cookies on every request), it carries sensitive content (risk descriptions, control evidence, incident details, document attachments), and it serves a customer-facing audience that increasingly expects basic transport security. Running SimpleRisk over plain HTTP in production is the kind of configuration mistake auditors flag in their first hour.
The honest scope of SimpleRisk's TLS handling: SimpleRisk doesn't terminate TLS itself. The application runs on top of a web server (Apache, Nginx, or whatever's in front of the Docker container in containerized deployments) and the web server handles TLS. This is conventional for PHP applications and matches the deployment patterns operators already use; the implication is that the TLS configuration lives at the web-server layer, not in SimpleRisk's settings.
The other things SimpleRisk specifically doesn't do that operators sometimes expect:
- No built-in HTTP-to-HTTPS redirect. The application doesn't notice that a request came in over HTTP and reply with a redirect to HTTPS. The redirect happens at the web server's level —
RedirectMatchin Apache, areturn 301in Nginx, or the cloud load balancer's redirect rule. - No HSTS, CSP, or other security headers. SimpleRisk doesn't add
Strict-Transport-Security,Content-Security-Policy,X-Frame-Options, or other security headers to its responses. Operators who want them add them at the web-server level. - No internal "force HTTPS" setting. There's no
force_https=trueconfiguration knob. The web-server-level enforcement is the only enforcement.
What SimpleRisk does do automatically is detect HTTPS based on the request's $_SERVER["HTTPS"] value. When the request came in over HTTPS:
- The session cookie is set with the
Secureflag (cookie won't be sent over plaintext HTTP). - The
simplerisk_base_urlsetting (set during the install wizard's Step 6) reflects thehttps://scheme. - The
ssl_certificate_check_simplerisksetting validates the install's own certificate during install.
So the configuration pattern is: terminate TLS at the web server (or reverse proxy), redirect HTTP to HTTPS at the web server, add security headers at the web server, run the installer over HTTPS so the SimpleRisk-side settings reflect the secure URL.
Before you start
Have these in hand:
- A SimpleRisk install that's reachable at a hostname (not just an IP), with the initial wizard completed.
- A TLS certificate for the SimpleRisk hostname. Common sources:
- Let's Encrypt via Certbot — free, auto-renewing, suitable for almost all production deployments. Requires the SimpleRisk hostname to be publicly resolvable for the HTTP-01 challenge (or DNS-controllable for the DNS-01 challenge).
- Organization-internal CA — for organizations with PKI infrastructure. The CA must be trusted by the browsers/clients that access SimpleRisk.
- Commercial CA certificate (DigiCert, Sectigo, GlobalSign, etc.) — for organizations that prefer commercial certs.
- Cloud-provider certificate manager — ACM on AWS, App Service Certificates on Azure, Google-managed SSL on GCP. Easiest path for cloud deployments where the cloud LB terminates TLS.
- Web server admin access — root or sudo to edit web server configuration, restart the web server, manage certificate files.
- DNS pointing the SimpleRisk hostname to the right IP/load balancer. TLS certificate issuance and validation require the hostname to resolve to the deployment.
Step-by-step
1. Decide where TLS terminates
Three common patterns for SimpleRisk:
- TLS at the SimpleRisk web server. Apache or Nginx running on the SimpleRisk host handles TLS. Appropriate for single-server deployments without a load balancer.
- TLS at a reverse proxy on the same host. Nginx in front of Apache (or in front of PHP-FPM for native installs, in front of the SimpleRisk container for Docker installs) terminates TLS. The proxy talks HTTP to SimpleRisk.
- TLS at a cloud load balancer. AWS ALB, Azure Application Gateway, GCP Load Balancer terminate TLS. The LB talks HTTP to the SimpleRisk hosts behind it.
The SimpleRisk-side configuration is mostly identical across the three patterns; the difference is where you put the TLS configuration.
2. Configure TLS at Apache (single-server pattern)
For Apache 2.4 with mod_ssl on Debian/Ubuntu:
sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d simplerisk.example.com
Certbot prompts for an email address and the terms-of-service confirmation, obtains a Let's Encrypt certificate, and updates the Apache vhost configuration to listen on 443 with the certificate. Certbot also offers to add an HTTP-to-HTTPS redirect; accept this to enforce HTTPS.
After Certbot completes, the Apache vhost looks roughly like:
ServerName simplerisk.example.com Redirect permanent / https://simplerisk.example.com/
ServerName simplerisk.example.com DocumentRoot /var/www/simplerisk SSLEngine on SSLCertificateFile /etc/letsencrypt/live/simplerisk.example.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/simplerisk.example.com/privkey.pem
AllowOverride All Require all granted
# Recommended security headers Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" Header always set X-Frame-Options "SAMEORIGIN" Header always set X-Content-Type-Options "nosniff" Header always set Referrer-Policy "strict-origin-when-cross-origin" ErrorLog ${APACHE_LOG_DIR}/simplerisk-error.log CustomLog ${APACHE_LOG_DIR}/simplerisk-access.log combined
The Redirect permanent / https://... block on the port 80 vhost handles the HTTP-to-HTTPS redirect. The Header always set directives add the security headers SimpleRisk doesn't add itself.
Restart Apache: sudo systemctl restart apache2.
Certbot automatically configures certificate renewal via a systemd timer or cron job; certificates renew without operator intervention.
3. Configure TLS at Nginx (single-server pattern)
For Nginx with PHP-FPM on Debian/Ubuntu:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d simplerisk.example.com
After Certbot completes, the Nginx server block looks roughly like:
server {
listen 80;
server_name simplerisk.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name simplerisk.example.com;
ssl_certificate /etc/letsencrypt/live/simplerisk.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/simplerisk.example.com/privkey.pem;
root /var/www/simplerisk;
index index.php index.html;
# Recommended security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
location ~ /\.ht {
deny all;
}
error_log /var/log/nginx/simplerisk-error.log;
access_log /var/log/nginx/simplerisk-access.log;
}
Restart Nginx: sudo systemctl reload nginx.
4. Configure TLS at a cloud load balancer (containerized or cloud pattern)
For AWS ALB:
- Provision an ALB in front of the SimpleRisk EC2/ECS/EKS deployment.
- Configure two listeners: - Port 80 with a default action of "redirect to HTTPS" (the ALB has a built-in redirect action). - Port 443 with the ACM certificate for the SimpleRisk hostname, forwarding to the SimpleRisk target group.
- Configure the target group to health-check
/on port 80 (the SimpleRisk container/host listens on HTTP). - Update DNS to point the SimpleRisk hostname at the ALB.
Equivalents for Azure Application Gateway and GCP Load Balancer follow the same pattern: TLS termination + redirect listener + forward to backend.
The security headers (HSTS, CSP, X-Frame-Options, etc.) can be added at the ALB level via response-header modification rules, or at the web-server level inside the SimpleRisk container, or at both. Adding them at the LB level is typical for cloud deployments because the LB is already in the request path.
5. Configure SimpleRisk to know it's running over HTTPS
If the install wizard ran over HTTPS, simplerisk_base_url was set to the https:// URL during Step 6 and no further action is needed.
If the install ran over HTTP first and HTTPS was added afterward, update the simplerisk_base_url setting:
- Sidebar: Configure → Settings.
- Find the Base URL field (or the equivalent label in your install).
- Update it to
https://simplerisk.example.com. - Save.
The setting affects:
- Email links (notifications, password reset, MFA-related emails) — these embed the base URL so recipients can click through to the install.
- The OpenAPI documentation rendering.
- Some cron-driven cross-references.
After updating, trigger a test notification or password-reset email to verify the embedded URL uses HTTPS.
6. Verify HTTPS is enforced
Test the configuration end-to-end:
- HTTP redirect: open
http://simplerisk.example.com/in a browser. The browser should land onhttps://simplerisk.example.com/after the redirect. - HTTPS connection: confirm the URL bar shows the secure-connection indicator (lock icon).
- HSTS header (if configured): use a browser developer tools' Network tab to confirm the response has the
Strict-Transport-Securityheader. - Cookie Secure flag: log in and check the session cookie in the browser developer tools' Application/Storage tab. The cookie should have the
SecureandHttpOnlyandSameSite=Strictflags set. - Certificate validity: use SSL Labs (https://www.ssllabs.com/ssltest/) to test the install's TLS configuration. Aim for an A or A+ grade; the typical issues are weak cipher suites or missing intermediate certificates, both of which are configurable at the web-server level.
7. Configure the database connection's TLS (optional)
For deployments where the SimpleRisk-to-MySQL connection traverses a network that needs encryption (separate-server installs, cloud-managed databases), the SimpleRisk install supports SSL/TLS to MySQL via the DB_SSL_CERTIFICATE_PATH constant in config.php.
To enable:
- Obtain the appropriate CA certificate for the MySQL server (RDS provides this; on-premise MySQL provides theirs through the MySQL admin).
- Place the certificate file on the SimpleRisk host at a known path, with read access for the web server user.
- Edit
simplerisk/includes/config.phpand setdefine('DB_SSL_CERTIFICATE_PATH', '/path/to/ca-cert.pem');. - Restart the web server (or PHP-FPM) so the new constant takes effect.
The PDO connection then uses TLS to MySQL. Verify by checking MySQL's connection logs or via the MySQL \\s status command from a mysql client connected with the same credentials.
8. Plan certificate renewal
Let's Encrypt certificates expire after 90 days. Certbot's automatic renewal handles this for the Apache and Nginx patterns documented above; verify the renewal timer is active (sudo systemctl status certbot.timer on systemd distributions) and that the renewal hooks reload the web server after renewal (sudo certbot renew --dry-run exercises the renewal end-to-end without actually renewing).
For commercial certificates with longer validity, set a calendar reminder for renewal at least 30 days before expiry. A certificate that expires in production produces a hard outage; the renewal process should never be the surprise.
For cloud-managed certificates (ACM, App Service Certificates, Google-managed), renewal is typically automatic — verify with the cloud provider that auto-renewal is enabled on the certificates in use.
Common pitfalls
A handful of patterns recur with HTTPS configuration.
-
Running the initial install wizard over HTTP and then adding HTTPS later. The
simplerisk_base_urlset during Step 6 reflects the URL the wizard ran on. If the wizard ran onhttp://simplerisk.example.com, the base URL is set to HTTP, and email notifications will embed HTTP URLs. Update the setting after enabling HTTPS (Step 5 above). -
Forgetting the HTTP-to-HTTPS redirect. Without the redirect, users typing
simplerisk.example.comin the browser get HTTP, which works (SimpleRisk responds) but doesn't enforce TLS. Browsers don't auto-upgrade unless HSTS is in play. Configure the redirect at the web server (ApacheRedirect, Nginxreturn 301, or LB redirect rule). -
HSTS configured before HTTPS is verified working. Setting
Strict-Transport-Securitywith a longmax-agecauses browsers to cache the HTTPS-only assertion for that duration. If HTTPS is then broken (certificate expires, web server misconfigured), users can't access the site at all because the browser refuses HTTP. For new HTTPS deployments, start HSTS with a short max-age (e.g.,max-age=300for 5 minutes), verify HTTPS is solid, then increase to the production value (max-age=31536000for one year). -
Mixing self-signed certificates with browser access. Self-signed certificates produce browser warnings users have to click through. Acceptable for development; not acceptable for production. Use Let's Encrypt or a real CA cert for production.
-
Certificate renewal failing silently. Certbot's auto-renewal can fail if the renewal hooks don't reload the web server, if the HTTP-01 challenge can't reach port 80 (firewall change, hostname change), or if the certificate file paths changed. Test renewal with
certbot renew --dry-runperiodically; check the certbot log for renewal failures. -
Forgetting that the SimpleRisk container talks HTTP to its own listener. In containerized deployments, the SimpleRisk container's internal Apache or Nginx typically listens on HTTP port 80; TLS is at the LB or reverse proxy in front. This is fine, but it means the internal traffic between LB and container is plaintext. For most deployments that's acceptable (the internal network is trusted); for high-sensitivity deployments, configure end-to-end TLS by terminating again at the container.
-
Using weak cipher suites. Browsers accept TLS connections with old, weak cipher suites for compatibility, but production deployments should disable them. Mozilla's SSL Configuration Generator (https://ssl-config.mozilla.org/) produces web-server config snippets for "modern", "intermediate", and "old" compatibility profiles; pick the strongest one your client base supports.
-
Not testing the configuration with SSL Labs. SSL Labs' free SSL Test grades the TLS configuration and identifies specific weaknesses. Run it after any TLS configuration change; aim for A or A+. The typical first-time score is B or C, which means the cipher suites need updating or the certificate chain has issues.
-
Database SSL configured without verifying it's actually being used. The
DB_SSL_CERTIFICATE_PATHconstant tells PDO to use TLS to MySQL, but if the MySQL server isn't actually configured to require TLS, the connection might fall back to plaintext. Verify MySQL is configured to require TLS (require_secure_transport = ONin MySQL's config) and verify the actual connection is encrypted (MySQL\\sstatus command). -
Adding security headers that break SimpleRisk functionality. A strict
Content-Security-Policyheader without the rightscript-srcandstyle-srcdirectives can block SimpleRisk's JavaScript and CSS, breaking the UI. CSP requires careful tuning; start withContent-Security-Policy-Report-Onlyto identify what would be blocked before enforcing.
Related
- System Requirements
- Installing on Linux
- Installing via Docker
- Installing on Cloud
- The Initial Configuration Wizard
- Securing the Database
- Securing the Web Server
- Session Management and Timeout
Reference
- Permission required: Server-side: root/sudo to edit web server configuration and manage certificates. SimpleRisk-side:
check_adminto update thesimplerisk_base_urlsetting via the admin UI. - Implementing files: Web-server configuration files (Apache:
/etc/apache2/sites-available/; Nginx:/etc/nginx/sites-available/); SimpleRisk's HTTPS detection:simplerisk/includes/authenticate.phpline 1052 (the session-cookiesecureflag is set fromisset($_SERVER["HTTPS"]));simplerisk/includes/install.phpline 959-972 (HTTPS verification during install Step 6);simplerisk/includes/config.php(theDB_SSL_CERTIFICATE_PATHconstant for database TLS). - Database tables:
settings(thesimplerisk_base_urlandssl_certificate_check_simpleriskkeys). config_settingskeys:simplerisk_base_url(the install's base URL, set during Step 6 from the request origin);ssl_certificate_check_simplerisk(boolean, set to '1' if HTTPS verification passed during install).- External dependencies: TLS certificate (Let's Encrypt, organization CA, commercial CA, or cloud certificate manager); web server with TLS support (Apache mod_ssl, Nginx with OpenSSL).