---
title: 09.05 Securing the Web Server
description: SimpleRisk runs behind a web server (Apache or nginx); the web server is the front door. Harden it with TLS 1.2+ only, strong cipher suites, security…
---

[Skip to content](https://support.simplerisk.com/kb/09-05-securing-the-web-server#main-content)

English

Show submenu for translations

[Customer portal](https://support.simplerisk.com/tickets?hsLang=en)

[![SimpleRisk logo of a man walking a tight rope](https://support.simplerisk.com/hs-fs/hubfs/simplerisk_logo_long_small-4.png?width=377&height=72&name=simplerisk_logo_long_small-4.png)](https://www.simplerisk.com/)

Open main navigation

Close main navigation

- English
  
  Show submenu for translations
- [Customer portal](https://support.simplerisk.com/tickets)
- [Contact us](https://www.simplerisk.com/about-us/contact-us)

[Contact us](https://www.simplerisk.com/about-us/contact-us)

 How can we help you?

- There are no suggestions because the search field is empty.

1. [SimpleRisk Knowledge Base](https://support.simplerisk.com/kb?hsLang=en)
2. [Administrator Guide](https://support.simplerisk.com/kb/administrator-guide?hsLang=en)
3. [09 Encryption and Data Security](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#09-encryption-and-data-security)

# 09.05 Securing the Web Server

## SimpleRisk runs behind a web server (Apache or nginx); the web server is the front door. Harden it with TLS 1.2+ only, strong cipher suites, security headers (HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy), rate limiting, and a WAF if your environment warrants. The defaults from a fresh install are usually too permissive for production.

## Why this matters

The web server is the public-facing edge of every SimpleRisk install. Every authenticated session, every API call, every form submission goes through it before reaching PHP. A misconfigured web server exposes the application to attacks that the application code can't prevent: TLS downgrade attacks if old protocols are still enabled, cookie hijacking via missing security headers, clickjacking via missing X-Frame-Options, brute-force attacks via missing rate limiting.

SimpleRisk doesn't terminate TLS itself; the web server in front of it does. SimpleRisk doesn't send most security headers itself; the web server adds them. SimpleRisk doesn't enforce rate limits; if rate limiting is needed, the web server provides it. The web server's configuration is therefore the security boundary for everything that reaches the application.

The honest scope to know up front: **most of what's in this article is web server configuration, not SimpleRisk configuration**. SimpleRisk runs on Apache or nginx; you configure those tools. This article focuses on the configurations relevant to a SimpleRisk deployment; for general web server hardening, the official documentation for your web server is the authoritative source.

## Before you start

Have these in hand:

- **Root or sudo access** to the SimpleRisk server (or to the web server if it's separate, behind a load balancer).
- **The web server you're running** — Apache, nginx, or other. Examples in this article cover Apache and nginx; adapt for others.
- **A valid TLS certificate** for your SimpleRisk hostname. Either commercial (purchased) or free via Let's Encrypt — both work; commercial is appropriate for installs with strict procurement requirements; Let's Encrypt is operationally simpler.
- **A maintenance window** if you're changing TLS configuration in production; users may need to re-authenticate.
- **A test client** (browser, curl) to verify configuration changes from outside the server.

## Step-by-step

### 1. Use TLS 1.2 or TLS 1.3 only

Old TLS versions (TLS 1.0, TLS 1.1) and SSL (any version) have known vulnerabilities. Disable everything below TLS 1.2.

**nginx**:

```
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_ecdh_curve secp384r1;
```

**Apache** (in your virtual host or `ssl.conf`):

```
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
```

These configurations are based on Mozilla's "intermediate" recommendation (https://ssl-config.mozilla.org/), which balances modern security with broad client compatibility. If you can constrain to "modern" (TLS 1.3 only, no fallback), even better — but verify your client compatibility first.

Reload the web server after changes; test from outside:

```
# Test with openssl
openssl s_client -connect your-simplerisk.example.com:443 -tls1_2

# Or use online testers like ssllabs.com
```

Aim for an A or A+ rating on SSL Labs (https://www.ssllabs.com/ssltest/).

### 2. Enable HSTS

HSTS (HTTP Strict Transport Security) tells browsers to always use HTTPS, preventing TLS-stripping attacks.

**nginx**:

```
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
```

**Apache**:

```
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
```

`max-age=63072000` is two years (in seconds). `includeSubDomains` extends to subdomains. `preload` makes the entry eligible for the browser-preloaded HSTS list (https://hstspreload.org/) — but only enable preload if you're sure every subdomain is HTTPS-ready and you commit to keeping it that way.

### 3. Enable security headers

A baseline set of HTTP security headers:

**nginx**:

```
# Don't let MIME-type sniffing override declared types
add_header X-Content-Type-Options "nosniff" always;

# Don't let the page be framed (clickjacking protection)
add_header X-Frame-Options "SAMEORIGIN" always;

# Send a Referer only to same-origin requests
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# Enable XSS protection (legacy header; modern browsers use CSP)
add_header X-XSS-Protection "1; mode=block" always;

# Permissions-Policy (formerly Feature-Policy)
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
```

**Apache**:

```
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set X-XSS-Protection "1; mode=block"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
```

Verify with `curl -I https://your-simplerisk.example.com/` — the headers should appear in the response.

### 4. Configure Content Security Policy (CSP)

CSP is the strongest defense against XSS. SimpleRisk's UI uses inline scripts and styles in places, so a strict CSP requires careful tuning to avoid breaking the application.

A starting point that works with SimpleRisk's pattern (test thoroughly before committing):

**nginx**:

```
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'; form-action 'self';" always;
```

`'unsafe-inline'` and `'unsafe-eval'` weaken CSP's XSS protection but are needed for the current application. Tightening them requires application-side changes (using nonces or hashes); if your program needs strict CSP, file a feature request.

For starting out, **CSP-Report-Only** mode lets you see what would break without actually breaking it:

```
add_header Content-Security-Policy-Report-Only "default-src 'self'; ...; report-uri /csp-report" always;
```

The browser sends violation reports without blocking. Review the reports for a week, tune the policy, then switch to enforcing mode.

### 5. Configure cookie security

The session cookie should have the security flags. SimpleRisk sets `HttpOnly` by default; verify and add `Secure` and `SameSite`.

In `simplerisk/includes/config.php` (or PHP's session configuration):

```
ini_set('session.cookie_secure', '1');     // Only over HTTPS
ini_set('session.cookie_httponly', '1');   // Not accessible to JavaScript
ini_set('session.cookie_samesite', 'Lax'); // CSRF protection (or 'Strict' for tighter)
```

For SimpleRisk installs only accessed over HTTPS (which is what production deployments should be), `session.cookie_secure` should always be on.

### 6. Configure rate limiting

SimpleRisk has no native rate limiting. Web-server-level rate limiting protects against:

- Brute-force login attempts.
- API abuse from misbehaving integrations.
- Scraping of public-facing pages.

**nginx**:

```
http {
    # Define rate-limit zones
    limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

    server {
        # Rate-limit login attempts
        location ~* ^(/index\.php|/login)$ {
            limit_req zone=login_limit burst=5 nodelay;
            try_files $uri $uri/ /index.php?$args;
        }

        # Rate-limit API
        location /api/v2/ {
            limit_req zone=api_limit burst=20 nodelay;
            try_files $uri /api/v2/index.php?$args;
        }
    }
}
```

**Apache** (with `mod_evasive` or `mod_qos`):

`mod_evasive`:

```

    DOSHashTableSize 2048 DOSPageCount 5 DOSSiteCount 100 DOSPageInterval 1 DOSSiteInterval 1 DOSBlockingPeriod 60 
  
```

Tune to match your legitimate traffic patterns. Too tight and legitimate users get blocked; too loose and brute-force attempts succeed.

### 7. Restrict access to administrative paths (optional)

Some programs restrict access to administrative paths (`/admin/`, `/configure/`) to specific source IPs:

**nginx**:

```
location /admin/ {
    allow 10.0.0.0/8;          # Internal network
    allow 192.168.1.100;        # Specific admin workstation
    deny all;
    try_files $uri $uri/ /index.php?$args;
}
```

This is defense-in-depth — application-level admin permissions still apply, but the network layer prevents external access entirely. Appropriate for installs where admin access from outside specific networks is never legitimate.

### 8. Hide server software version

Default web server configurations expose the software version in the `Server` header. Hide it:

**nginx**:

```
server_tokens off;
```

**Apache**:

```
ServerTokens Prod
ServerSignature Off
```

Hiding the version doesn't substantively improve security (attackers fingerprint versions other ways), but it's a small step.

### 9. Disable unnecessary HTTP methods

SimpleRisk uses GET, POST, PUT, PATCH, DELETE. Methods like TRACE, OPTIONS (for non-CORS use), and CONNECT can be disabled if not needed.

**nginx**:

```
if ($request_method !~ ^(GET|POST|PUT|PATCH|DELETE|HEAD)$) {
    return 405;
}
```

**Apache**:

```

    Require all denied 
  
```

### 10. Configure a Web Application Firewall (WAF) (recommended for production)

A WAF inspects HTTP traffic and blocks known attack patterns. Options:

- **ModSecurity** with the OWASP Core Rule Set (OWASP CRS) — free, open-source, runs as an Apache or nginx module.
- **Cloudflare WAF** — managed, easy to configure, requires Cloudflare proxying.
- **AWS WAF** — managed, integrates with AWS infrastructure.
- **Imperva, F5, Akamai** — enterprise WAFs with broader feature sets.

A WAF in front of SimpleRisk catches:

- SQL injection attempts (which Phan and SimpleRisk's PDO-based DB layer should already prevent, but defense in depth).
- Cross-site scripting attempts.
- Path traversal attempts.
- Known CVE exploitation patterns.
- High-volume scraping or scanning behavior.

Tune the WAF carefully — overly-aggressive rules block legitimate behavior. Start in observation mode, review false positives, then enforce.

## Common pitfalls

A handful of patterns recur with web server hardening.

- **Allowing TLS 1.0 or TLS 1.1 for "compatibility."** Both are deprecated and have known vulnerabilities. Modern browsers don't need them; if a client does, that client is the security problem.
- **Setting HSTS without testing first.** Once browsers cache the HSTS header, they refuse HTTP for the entire `max-age` period. Test in non-production; start with a short `max-age` (e.g., 300 seconds) and increase as you gain confidence.
- **Configuring strict CSP without testing.** It will break the application in subtle ways. Use Report-Only mode first.
- **Skipping the `Secure` flag on session cookies.** Allows the cookie to transmit over HTTP, defeating HTTPS-only access patterns.
- **Leaving rate limits at the default (none).** Brute-force attempts against the login page are continuous on internet-exposed installs. Rate-limit them.
- **Restricting admin paths to "internal IPs" without verifying what "internal" means.** A wide internal range may include guest WiFi, vendor-accessible networks, or other untrusted segments. Tight allowlists.
- **Configuring a WAF in enforcing mode without observation period.** False positives during a release or workflow change cause user-impacting outages. Observe first, then enforce.
- **Hardening only the web server without the database and application.** All three layers matter. See [Securing the Database](https://support.simplerisk.com/kb/09-04-securing-the-database?hsLang=en) and the rest of this chapter.
- **Forgetting to test from outside the network.** Internal testing might not catch issues that only appear from external clients (firewall rules, certificate chains, etc.).
- **Not monitoring web server logs.** Logs without review produce no value. Forward to a SIEM or aggregator; alert on suspicious patterns (high 401 rate, scanning paths, etc.).
- **Trusting Cloudflare or your CDN as the only security layer.** WAFs can be bypassed; legitimate-looking traffic still hits the origin. The web server should be hardened as if no WAF were in front.
- **Using self-signed certificates in production.** Browsers reject them by default; users learn to click through the warning, which trains them to ignore certificate errors generally. Use a real certificate (Let's Encrypt is free).
- **Not redirecting HTTP to HTTPS.** A user typing `http://your-simplerisk.example.com` should be redirected to `https://`. Configure the redirect in the web server.

## Related

- [The Encryption Extra Overview](https://support.simplerisk.com/kb/09-01-the-encryption-extra-overview?hsLang=en)
- [Enabling Encryption](https://support.simplerisk.com/kb/09-02-enabling-encryption?hsLang=en)
- [Key Management and Rotation](https://support.simplerisk.com/kb/09-03-key-management-and-rotation?hsLang=en)
- [Securing the Database](https://support.simplerisk.com/kb/09-04-securing-the-database?hsLang=en)
- [HTTPS and TLS Configuration](https://support.simplerisk.com/kb/01-07-https-and-tls-configuration?hsLang=en)
- [Rate Limiting and Quotas](https://support.simplerisk.com/kb/08-04-rate-limiting-and-quotas?hsLang=en)
- [Session Management and Timeout](https://support.simplerisk.com/kb/04-08-session-management-and-timeout?hsLang=en)

- [FAQs](https://support.simplerisk.com/kb/faqs?hsLang=en)
- [SimpleRisk Extras](https://support.simplerisk.com/kb/simplerisk-extras?hsLang=en#main-content)

    - [Vulnerability Management Extra](https://support.simplerisk.com/kb/simplerisk-extras?hsLang=en#vulnerability-management-extra)
    - [Team Separation Extra](https://support.simplerisk.com/kb/simplerisk-extras?hsLang=en#team-separation-extra)
    - [Import-Export Extra](https://support.simplerisk.com/kb/simplerisk-extras?hsLang=en#import-export-extra)
- [Administrator Guide](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#main-content)

    - [00 About This Guide](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#00-about-this-guide)
    - [01 Installation and Deployment](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#01-installation-and-deployment)
    - [02 Upgrades and Maintenance](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#02-upgrades-and-maintenance)
    - [03 Users and Permissions](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#03-users-and-permissions)
    - [04 Authentication](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#04-authentication)
    - [05 Customization](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#05-customization)
    - [06 Configuring Risk and Compliance](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#06-configuring-risk-and-compliance)
    - [07 Integrations](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#07-integrations)
    - [08 The API](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#08-the-api)
    - [09 Encryption and Data Security](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#09-encryption-and-data-security)
    - [10 Workflows and Automation](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#10-workflows-and-automation)
    - [11 Reporting and Auditing](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#11-reporting-and-auditing)
    - [12 Operations](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#12-operations)
    - [13 Reference](https://support.simplerisk.com/kb/administrator-guide?hsLang=en#13-reference)
- [User Guide](https://support.simplerisk.com/kb/user-guide?hsLang=en#main-content)

    - [00 Foundations of GRC](https://support.simplerisk.com/kb/user-guide?hsLang=en#00-foundations-of-grc)
    - [01 Risk Management](https://support.simplerisk.com/kb/user-guide?hsLang=en#01-risk-management)
    - [02 Compliance Management](https://support.simplerisk.com/kb/user-guide?hsLang=en#02-compliance-management)
    - [03 Governance](https://support.simplerisk.com/kb/user-guide?hsLang=en#03-governance)
    - [04 Asset and Data Inventory](https://support.simplerisk.com/kb/user-guide?hsLang=en#04-asset-and-data-inventory)
    - [05 Threat and Vulnerability Management](https://support.simplerisk.com/kb/user-guide?hsLang=en#05-threat-and-vulnerability-management)
    - [06 Assessments](https://support.simplerisk.com/kb/user-guide?hsLang=en#06-assessments)
    - [07 Incident Management](https://support.simplerisk.com/kb/user-guide?hsLang=en#07-incident-management)
    - [08 Audit and Reporting](https://support.simplerisk.com/kb/user-guide?hsLang=en#08-audit-and-reporting)
    - [09 Day-to-Day SimpleRisk](https://support.simplerisk.com/kb/user-guide?hsLang=en#09-day-to-day-simplerisk)
    - [10 Continuous Improvement](https://support.simplerisk.com/kb/user-guide?hsLang=en#10-continuous-improvement)
- [SimpleRisk User Guides](https://support.simplerisk.com/kb/simplerisk-user-guides?hsLang=en)
- [Troubleshooting](https://support.simplerisk.com/kb/troubleshooting?hsLang=en)
- [SimpleRisk Hosted](https://support.simplerisk.com/kb/simplerisk-hosted?hsLang=en)
- [How To videos](https://support.simplerisk.com/kb/how-to-videos?hsLang=en)

[![favicon-1](https://support.simplerisk.com/hs-fs/hubfs/favicon-1.png?width=35&height=35&name=favicon-1.png "favicon-1")](https://www.simplerisk.com)

<https://www.facebook.com/simplerisk/> <https://www.twitter.com/simpleriskfree/> <https://www.linkedin.com/company/simplerisk/>

Copyright © 2026, SimpleRisk, Inc.