> ## Documentation Index
> Fetch the complete documentation index at: https://www.checklyhq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# SslMonitor Construct

> Learn how to configure SSL monitors with the Checkly CLI.

> [!TIP]
>
> Learn more about SSL Monitors in [the SSL monitor overview](https://www.checklyhq.com/docs/detect/uptime-monitoring/ssl-monitors/overview.md).

Use SSL Monitors to verify the health and security posture of your TLS certificates. The examples below show how to configure monitoring for common scenarios.

> **Prerequisites**
>
> Before creating SSL Monitors, ensure you have:
>
> * An initialized Checkly CLI project
> * Network access to the HTTPS endpoint you want to monitor
> * The hostname (and optionally port) of the target server
>
> For additional setup information, see [CLI overview](https://www.checklyhq.com/docs/cli/overview.md).

```ts Basic Example theme={null}
import { Frequency, SslMonitor } from "checkly/constructs"

new SslMonitor("homepage-ssl", {
  name: "Homepage Certificate",
  description: "Monitors the TLS certificate for `example.com`.",
  frequency: Frequency.EVERY_1H,
  request: {
    hostname: "example.com",
    sslConfig: {
      alertDaysBeforeExpiry: 30,
    },
  },
})
```

```ts Advanced Example theme={null}
import {
  Frequency,
  SslAssertionBuilder,
  SslMonitor,
  TlsVersion,
} from "checkly/constructs"

new SslMonitor("api-ssl-advanced", {
  name: "API Certificate — strict baseline",
  description: "Enforces TLS 1.3, checks chain trust, and alerts 45 days before expiry.",
  activated: true,
  frequency: Frequency.EVERY_10M,
  locations: ["us-east-1", "eu-west-1"],
  degradedResponseTime: 1000,
  maxResponseTime: 5000,
  request: {
    hostname: "api.example.com",
    port: 443,
    sslConfig: {
      alertDaysBeforeExpiry: 45,
      handshakeTimeout: 5000,
      securityBaseline: {
        enabled: true,
        minTLSVersion: { value: "TLS1.2", severity: "fail" },
        recommendedTLSVersion: { value: "TLS1.3", severity: "degrade" },
        weakCipherSuite: { severity: "fail" },
        ocspMustStapleRespected: { severity: "degrade" },
      },
    },
    assertions: [
      SslAssertionBuilder.connection("chainTrusted").equals(true),
      SslAssertionBuilder.connection("hostnameVerified").equals(true),
      SslAssertionBuilder.connection("tlsVersion").equals(TlsVersion.TLS1_3),
      SslAssertionBuilder.certificate("daysUntilExpiry").greaterThan(45),
    ],
  },
})
```

## Configuration

SSL monitors have SSL-specific settings and inherit the standard monitor options shared across all check types.

**SSL Monitor Settings**

| Parameter | Type | Required | Default | Description |
| - | - | - | - | - |
| `request` | `object` | ✅ | - | SSL connection and certificate configuration |
| `degradedResponseTime` | `number` | ❌ | `3000` | Handshake time in milliseconds at which the monitor is marked degraded |
| `maxResponseTime` | `number` | ❌ | `10000` | Handshake time in milliseconds at which the monitor is marked failed |

**General Monitor Settings**

| Property | Type | Required | Default | Description |
| - | - | - | - | - |
| `name` | `string` | ✅ | - | Friendly name for your monitor |
| `description` | `string` | ❌ | `null` | A description of the monitor. Supports markdown. Max 500 characters |
| `activated` | `boolean` | ❌ | `true` | Whether the monitor is enabled |
| `alertChannels` | `Array<AlertChannel \| AlertChannelRef>` | ❌ | `[]` | Array of AlertChannel objects for notifications |
| `alertEscalationPolicy` | `AlertEscalationPolicy` | ❌ | - | Advanced alert escalation settings |
| `frequency` | `Frequency` | ❌ | `EVERY_10M` | How often to run your monitor |
| `group` | `CheckGroupV1` `CheckGroupV2` | ❌ | - | The CheckGroup this monitor belongs to |
| `locations` | `string[]` | ❌ | `[]` | Array of public location codes |
| `privateLocations` | `string[]` | ❌ | `[]` | Array of Private Location slugs |
| `muted` | `boolean` | ❌ | `false` | Whether alert notifications are muted |
| `tags` | `string[]` | ❌ | `[]` | Array of tags to organize monitors |
| `testOnly` | `boolean` | ❌ | `false` | Only run with test, not during deploy |
| `retryStrategy` | `RetryStrategy` | ❌ | [`noRetries()`](https://www.checklyhq.com/docs/constructs/retry-strategy#default-retry-strategy) | Strategy for configuring retries |
| `runParallel` | `boolean` | ❌ | `false` | Run monitors in parallel or round-robin |
| `triggerIncident` | `IncidentTrigger` | ❌ | - | Create and resolve an incident based on the check's alert configuration |

### `SslMonitor` Options

**request** `object` *required*

SSL connection configuration that defines the target host and all TLS-specific options.

**Usage:**

```ts theme={null}
new SslMonitor("my-ssl-monitor", {
  name: "Example SSL Monitor",
  request: {
    hostname: "example.com",
    sslConfig: {
      alertDaysBeforeExpiry: 30,
    },
  },
})
```

**Parameters:**

| Parameter | Type | Required | Default | Description |
| - | - | - | - | - |
| `hostname` | `string` | ✅ | - | The hostname to connect to and validate (no scheme or port) |
| `port` | `number` | ❌ | `443` | TCP port to connect to (1–65535) |
| `ipFamily` | `string` | ❌ | `'IPv4'` | IP family: `'IPv4'` \| `'IPv6'` |
| `sslConfig` | `SslConfig` | ✅ | - | TLS handshake and certificate options (see below) |
| `assertions` | `SslAssertion[]` | ❌ | `[]` | Certificate/handshake assertions using `SslAssertionBuilder` |

**degradedResponseTime** `number` (default: 3000)

TLS handshake time in milliseconds at or above which the monitor is marked as degraded (warning state). Range: 0–30,000 ms. Must be ≤ `maxResponseTime`.

**Usage:**

```ts highlight={3} theme={null}
new SslMonitor("my-ssl", {
  name: "Example SSL",
  degradedResponseTime: 1000,
  maxResponseTime: 5000,
  request: {
    hostname: "example.com",
    sslConfig: {},
  },
})
```

**maxResponseTime** `number` (default: 10000)

TLS handshake time in milliseconds at or above which the monitor is marked as failed. Range: 0–30,000 ms.

**Usage:**

```ts highlight={4} theme={null}
new SslMonitor("my-ssl", {
  name: "Example SSL",
  degradedResponseTime: 1000,
  maxResponseTime: 5000,
  request: {
    hostname: "example.com",
    sslConfig: {},
  },
})
```

### `SslConfig` Options

**alertDaysBeforeExpiry** `number` (default: 20)

Raise a degraded alert when the certificate is within this many days of expiry. Range: 1–365.

```ts theme={null}
sslConfig: {
  alertDaysBeforeExpiry: 30, // Warn 30 days before expiry
}
```

**serverName** `string`

SNI server name to send during the TLS handshake. Useful when a single IP hosts multiple certificates. Defaults to `hostname` when unset.

```ts theme={null}
sslConfig: {
  serverName: "tenant-a.example.com",
}
```

**handshakeTimeout** `number` (default: 10000)

Maximum milliseconds to wait for the TLS handshake to complete. Range: 1,000–30,000 ms.

```ts theme={null}
sslConfig: {
  handshakeTimeout: 5000,
}
```

**skipChainValidation** `boolean` (default: false)

When `true`, the certificate chain is not verified against system trusted roots. The certificate is still inspected for expiry and the security baseline. Use for internal or self-signed certificates.

```ts theme={null}
sslConfig: {
  skipChainValidation: true,
}
```

**clientCertificateMode** `'auto' | 'explicit'`

Enables mutual TLS by sending a client certificate during the handshake.

* `'auto'` — Checkly selects a stored client certificate automatically.
* `'explicit'` — uses the certificate referenced by `sslClientCertificateId`.

Omit to connect without a client certificate.

```ts theme={null}
sslConfig: {
  clientCertificateMode: "explicit",
  sslClientCertificateId: "9e83b6d8-a1e5-4c7b-8f0a-3d2e1c4b5a69",
}
```

**sslClientCertificateId** `string`

The UUID of the stored client certificate to present during the TLS handshake. Required when `clientCertificateMode` is `'explicit'`. Client certificates are managed under **Settings → Client Certificates** in the Checkly dashboard.

```ts theme={null}
sslConfig: {
  clientCertificateMode: "explicit",
  sslClientCertificateId: "9e83b6d8-a1e5-4c7b-8f0a-3d2e1c4b5a69",
}
```

**securityBaseline** `SecurityBaseline`

Override the default security baseline for this monitor. Omit to inherit the built-in default baseline.

```ts theme={null}
sslConfig: {
  securityBaseline: {
    enabled: true,
    minTLSVersion: { value: "TLS1.2", severity: "fail" },
    recommendedTLSVersion: { value: "TLS1.3", severity: "degrade" },
    weakCipherSuite: { severity: "fail" },
    weakSignatureAlgorithm: { severity: "fail" },
    knownBadCA: { severity: "fail" },
    ocspMustStapleRespected: { severity: "degrade" },
  },
}
```

**`SecurityBaseline` parameters:**

| Parameter | Type | Default severity | Description |
| - | - | - | - |
| `enabled` | `boolean` | `true` | Enable or disable baseline evaluation |
| `minTLSVersion` | `{ value?: string, severity? }` | `fail` | Minimum required TLS version (e.g. `'TLS1.2'`) |
| `minKeySizeBits` | `{ value?: number, severity? }` | `fail` | Minimum RSA key size in bits |
| `weakSignatureAlgorithm` | `{ severity? }` | `fail` | Reject weak signature algorithms (MD2-RSA, MD5-RSA, SHA1-RSA, DSA-SHA1, ECDSA-SHA1) on non-root certificates |
| `weakCipherSuite` | `{ severity? }` | `fail` | Reject known-weak cipher suites |
| `knownBadCA` | `{ severity? }` | `fail` | Reject distrusted certificate authorities |
| `recommendedTLSVersion` | `{ value?: string, severity? }` | `ignore` | Advisory minimum TLS version |
| `recommendedKeySizeBits` | `{ value?: number, severity? }` | `ignore` | Advisory minimum RSA key size |
| `ocspMustStapleRespected` | `{ severity? }` | `ignore` | Alert when must-staple cert is missing an OCSP staple |
| `sctPresent` | `{ severity? }` | `ignore` | Alert when no Signed Certificate Timestamp is observed |

Each rule's `severity` can be `'fail'` | `'degrade'` | `'ignore'`.

### `SslMonitor` Assertions

Define `assertions` using the `SslAssertionBuilder`. Five entry points map to the assertion sources — `certificate`/`connection` take a `property` (a field selector); `jsonResponse`/`textResponse` take a JSONPath/regex:

| Builder | Source | Description |
| - | - | - |
| `certificate(property)` | `CERTIFICATE` | Assert on a leaf-certificate field |
| `connection(property)` | `CONNECTION` | Assert on a TLS handshake / connection field |
| `responseTime()` | `RESPONSE_TIME` | TLS handshake duration in milliseconds |
| `jsonResponse(jsonPath)` | `JSON_RESPONSE` | Assert on any response field via a JSONPath expression |
| `textResponse(regex?)` | `TEXT_RESPONSE` | Extract a value from the serialized response with a regex, then compare |

`certificate(property)` properties: `daysUntilExpiry` / `keySizeBits` (number — `EQUALS` / `NOT_EQUALS` / `GREATER_THAN` / `LESS_THAN`), `subjectCN` / `issuerCN` (string — also `CONTAINS` / `NOT_CONTAINS`), `serialNumber` / `fingerprintSha256` / `issuerFingerprintSha256` / `keyAlgorithm` / `signatureAlgorithm` (exact — `EQUALS` / `NOT_EQUALS` only), `sans` (list — `CONTAINS` / `NOT_CONTAINS`), `selfSigned` / `isCA` (boolean — `EQUALS`).

`connection(property)` properties: `tlsVersion` (version — `EQUALS` / `NOT_EQUALS` / `GREATER_THAN` / `LESS_THAN`, ordered TLS1.0 \< TLS1.3), `cipherSuite` / `resolvedIp` (string — also `CONTAINS` / `NOT_CONTAINS`), `ocspStatus` (exact — `good` / `revoked` / `unknown`), `hostnameVerified` / `chainTrusted` / `ocspStapled` (boolean — `EQUALS`).

Examples:

```ts theme={null}
// Alert when fewer than 30 days remain before expiry
SslAssertionBuilder.certificate("daysUntilExpiry").greaterThan(30)
// Equivalent to: { source: 'CERTIFICATE', property: 'daysUntilExpiry', comparison: 'GREATER_THAN', target: '30' }

// The certificate chain must be trusted
SslAssertionBuilder.connection("chainTrusted").equals(true)
// Equivalent to: { source: 'CONNECTION', property: 'chainTrusted', comparison: 'EQUALS', target: 'true' }

// Assert an exact TLS version — tlsVersion is ordered, so greaterThan/lessThan also work
// (the security baseline's minTLSVersion is the usual way to enforce a "1.2-or-newer" floor)
SslAssertionBuilder.connection("tlsVersion").equals(TlsVersion.TLS1_3)
// Equivalent to: { source: 'CONNECTION', property: 'tlsVersion', comparison: 'EQUALS', target: 'TLS1.3' }

// Pin the cipher suite
SslAssertionBuilder.connection("cipherSuite").equals(CipherSuite.TLS_AES_256_GCM_SHA384)
// Equivalent to: { source: 'CONNECTION', property: 'cipherSuite', comparison: 'EQUALS', target: 'TLS_AES_256_GCM_SHA384' }

// Verify a specific issuer
SslAssertionBuilder.certificate("issuerCN").equals("Let's Encrypt")
// Equivalent to: { source: 'CERTIFICATE', property: 'issuerCN', comparison: 'EQUALS', target: "Let's Encrypt" }

// Reject weak keys (the security baseline's minKeySizeBits enforces a hard minimum)
SslAssertionBuilder.certificate("keySizeBits").greaterThan(1024)
// Equivalent to: { source: 'CERTIFICATE', property: 'keySizeBits', comparison: 'GREATER_THAN', target: '1024' }

// Assert on a nested chain field with a JSONPath expression
SslAssertionBuilder.jsonResponse("$.chain[0].keySizeBits").greaterThan(2048)
// Equivalent to: { source: 'JSON_RESPONSE', property: '$.chain[0].keySizeBits', comparison: 'GREATER_THAN', target: '2048' }
```

Use the `TlsVersion` and `CipherSuite` constants for type-safe comparisons:

```ts theme={null}
import {
  CipherSuite,
  SslAssertionBuilder,
  TlsVersion,
} from "checkly/constructs"

SslAssertionBuilder.connection("tlsVersion").equals(TlsVersion.TLS1_3)
SslAssertionBuilder.connection("cipherSuite").equals(CipherSuite.TLS_AES_128_GCM_SHA256)
```

Learn more in our docs on [Assertions](https://www.checklyhq.com/docs/detect/assertions.md).

### General Monitor Options

**name** `string` *required*

Friendly name for your SSL Monitor, displayed in the Checkly dashboard and used in notifications.

```ts highlight={2} theme={null}
new SslMonitor("my-ssl-monitor", {
  name: "Homepage Certificate",
  /* More options ... */
})
```

**frequency** `Frequency`

How often the SSL Monitor should run. Use the `Frequency` enum to set the check interval.

```ts highlight={3} theme={null}
new SslMonitor("my-ssl-monitor", {
  name: "Homepage Certificate",
  frequency: Frequency.EVERY_1H,
  /* More options ... */
})
```

**Available frequencies**: `EVERY_1M`, `EVERY_2M`, `EVERY_5M`, `EVERY_10M`, `EVERY_15M`, `EVERY_30M`, `EVERY_1H`, `EVERY_2H`, `EVERY_3H`, `EVERY_6H`, `EVERY_12H`, `EVERY_24H`. SSL monitors do not support sub-minute frequencies (`EVERY_10S` / `EVERY_20S` / `EVERY_30S`).

**locations** `string[]` (default: \[])

Array of [public location codes](https://www.checklyhq.com/docs/concepts/locations.md#public-locations) where the monitor should run from. Multiple locations provide geographic coverage.

```ts highlight={3} theme={null}
new SslMonitor("global-ssl", {
  name: "Global Certificate Monitor",
  locations: ["us-east-1", "eu-west-1", "ap-southeast-1"],
  /* More options ... */
})
```

**activated** `boolean` (default: true)

Whether the SSL Monitor is enabled and will run according to its schedule.

```ts highlight={3} theme={null}
new SslMonitor("my-ssl-monitor", {
  name: "Homepage Certificate",
  activated: false, // Disabled monitor
  /* More options ... */
})
```

## Examples

**Basic Expiry Alert**

```ts theme={null}
import { Frequency, SslMonitor } from "checkly/constructs"

new SslMonitor("homepage-ssl", {
  name: "Homepage Certificate",
  frequency: Frequency.EVERY_1H,
  locations: ["us-east-1", "eu-west-1"],
  request: {
    hostname: "example.com",
    sslConfig: {
      alertDaysBeforeExpiry: 30,
    },
  },
})
```

**Strict TLS Policy**

```ts theme={null}
import { Frequency, SslAssertionBuilder, SslMonitor, TlsVersion } from "checkly/constructs"

new SslMonitor("api-strict-tls", {
  name: "API — Strict TLS Policy",
  frequency: Frequency.EVERY_10M,
  locations: ["us-east-1", "eu-central-1"],
  request: {
    hostname: "api.example.com",
    sslConfig: {
      alertDaysBeforeExpiry: 45,
      securityBaseline: {
        enabled: true,
        minTLSVersion: { value: "TLS1.2", severity: "fail" },
        recommendedTLSVersion: { value: "TLS1.3", severity: "degrade" },
      },
    },
    assertions: [
      SslAssertionBuilder.connection("chainTrusted").equals(true),
      SslAssertionBuilder.connection("hostnameVerified").equals(true),
      SslAssertionBuilder.connection("tlsVersion").equals(TlsVersion.TLS1_3),
    ],
  },
})
```

**Internal / Self-Signed Cert**

```ts theme={null}
import { Frequency, SslAssertionBuilder, SslMonitor } from "checkly/constructs"

new SslMonitor("internal-ssl", {
  name: "Internal Service Certificate",
  frequency: Frequency.EVERY_6H,
  privateLocations: ["my-private-location"],
  request: {
    hostname: "internal.corp.example.com",
    port: 8443,
    sslConfig: {
      skipChainValidation: true,
      alertDaysBeforeExpiry: 14,
    },
    assertions: [
      SslAssertionBuilder.certificate("selfSigned").equals(true),
      SslAssertionBuilder.certificate("daysUntilExpiry").greaterThan(7),
    ],
  },
})
```

**mTLS Endpoint**

```ts theme={null}
import { Frequency, SslAssertionBuilder, SslMonitor } from "checkly/constructs"

new SslMonitor("mtls-endpoint", {
  name: "mTLS API Gateway",
  frequency: Frequency.EVERY_5M,
  request: {
    hostname: "mtls.api.example.com",
    sslConfig: {
      clientCertificateMode: "explicit",
      sslClientCertificateId: "9e83b6d8-a1e5-4c7b-8f0a-3d2e1c4b5a69",
      alertDaysBeforeExpiry: 30,
    },
    assertions: [
      SslAssertionBuilder.certificate("daysUntilExpiry").greaterThan(0),
      SslAssertionBuilder.connection("hostnameVerified").equals(true),
    ],
  },
})
```

**SNI Override**

```ts theme={null}
import { Frequency, SslMonitor } from "checkly/constructs"

// Monitor a certificate served for a specific SNI name
// on a shared IP (e.g. a CDN or multi-tenant server).
new SslMonitor("tenant-ssl", {
  name: "Tenant Certificate via SNI",
  frequency: Frequency.EVERY_1H,
  request: {
    hostname: "shared-cdn.example.net",
    sslConfig: {
      serverName: "tenant-a.example.com",
      alertDaysBeforeExpiry: 20,
    },
  },
})
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.