API Tutorials

How to Add DNS, SSL, and Domain Checks to CI/CD Pipelines

Prevent DNS misconfigurations and certificate outages from reaching production. Practical pipeline examples for pre-deployment validation.

March 27, 202610 min readPlatform Engineering Team
3
Check types to automate
2
Pipeline examples included
50ms
Per-check latency

The Problem: Infrastructure Checks Happen Too Late

Most teams verify DNS records and SSL certificates manually, after deployment, or only when something breaks. A misconfigured CNAME in a Kubernetes ingress, an expired SSL certificate on a staging domain, or a lapsed domain registration all share the same root cause: infrastructure validation is disconnected from the deployment process.

Moving DNS record validation, SSL certificate checking, and WHOIS expiration monitoring into your CI/CD pipeline turns these checks into deployment gates. Configurations that would cause outages get caught before they reach production, not after users report the symptoms.

What to Validate and When

Check TypePipeline StageFailure Action
DNS record resolutionPre-deployBlock deployment
SSL certificate validityPre-deploy + nightly cronBlock deploy / alert
Domain expiration statusWeekly cronAlert only
DNS propagation verificationPost-deployRollback trigger

DNS Record Validation Before Deployment

The most common infrastructure deployment failures involve DNS: a CNAME pointing to the wrong load balancer, an MX record misconfigured after a mail provider migration, or a TXT record missing for domain verification. Checking DNS records programmatically before deployment catches these issues immediately.

Validation script

#!/bin/bash
# infra-check.sh — Run as a CI pipeline step
set -euo pipefail

API_KEY="${DOMAIN_API_KEY}"
DOMAIN="${DEPLOY_DOMAIN:-example.com}"
EXPECTED_IP="${EXPECTED_A_RECORD}"
API="https://api.ops.tools/v1"

echo "Checking DNS A record for ${DOMAIN}..."

DNS_RESPONSE=$(curl -sf "${API}/dns/lookup?domain=${DOMAIN}&recordType=A" \
  -H "x-api-key: ${API_KEY}")

RESOLVED_IP=$(echo "${DNS_RESPONSE}" | jq -r '.records[0].value // empty')

if [ "${RESOLVED_IP}" != "${EXPECTED_IP}" ]; then
  echo "FAIL: Expected ${EXPECTED_IP}, got ${RESOLVED_IP}"
  exit 1
fi

echo "PASS: DNS A record resolves to ${RESOLVED_IP}"

Tip: Store your API key in CI/CD secrets (GitHub Secrets, GitLab CI/CD Variables, or your vault). Never commit API keys to source control. Most CI platforms inject secrets as environment variables at runtime.

SSL Certificate Checks in the Pipeline

Deploying behind an expired or misconfigured certificate causes immediate browser warnings and service disruption. Certificate validation in CI/CD should check three things: whether the certificate is valid, how many days remain until expiration, and whether the chain of trust is complete.

Certificate validation script

#!/bin/bash
# ssl-check.sh — Validate certificate before deployment
set -euo pipefail

API_KEY="${DOMAIN_API_KEY}"
DOMAIN="${DEPLOY_DOMAIN:-example.com}"
MIN_DAYS=30
API="https://api.ops.tools/v1"

SSL_RESPONSE=$(curl -sf "${API}/ssl/check?domain=${DOMAIN}" \
  -H "x-api-key: ${API_KEY}")

VALID=$(echo "${SSL_RESPONSE}" | jq -r '.valid')
DAYS_LEFT=$(echo "${SSL_RESPONSE}" | jq -r '.daysUntilExpiration')
PROTOCOL=$(echo "${SSL_RESPONSE}" | jq -r '.protocol')

if [ "${VALID}" != "true" ]; then
  echo "FAIL: SSL certificate is invalid for ${DOMAIN}"
  exit 1
fi

if [ "${DAYS_LEFT}" -lt "${MIN_DAYS}" ]; then
  echo "WARN: Certificate expires in ${DAYS_LEFT} days (threshold: ${MIN_DAYS})"
  exit 1
fi

echo "PASS: Valid ${PROTOCOL} certificate, ${DAYS_LEFT} days remaining"

WHOIS Domain Expiration Monitoring

Domain expiration is a silent killer. Unlike SSL certificates, which browsers flag immediately, domain expiration causes complete loss of service with no user-facing warning. Adding WHOIS expiration checks to a scheduled pipeline catches this risk early.

Expiration check script

#!/bin/bash
# whois-check.sh — Verify domain registration is active
set -euo pipefail

API_KEY="${DOMAIN_API_KEY}"
DOMAIN="${DEPLOY_DOMAIN:-example.com}"
API="https://api.ops.tools/v1"

WHOIS_RESPONSE=$(curl -sf "${API}/whois/lookup?domain=${DOMAIN}" \
  -H "x-api-key: ${API_KEY}")

EXPIRY=$(echo "${WHOIS_RESPONSE}" | jq -r '.expirationDate // .expiresDate // empty')
REGISTRAR=$(echo "${WHOIS_RESPONSE}" | jq -r '.registrar // "unknown"')
STATUS=$(echo "${WHOIS_RESPONSE}" | jq -r '.status // empty')

if [ -z "${EXPIRY}" ]; then
  echo "WARN: No expiration date found for ${DOMAIN}"
  exit 1
fi

DAYS_LEFT=$(( ($(date -d "${EXPIRY}" +%s) - $(date +%s)) / 86400 ))

echo "Domain: ${DOMAIN}"
echo "Registrar: ${REGISTRAR}"
echo "Status: ${STATUS}"
echo "Expires: ${EXPIRY} (${DAYS_LEFT} days remaining)"

if [ "${DAYS_LEFT}" -lt 30 ]; then
  echo "WARN: Domain expires in ${DAYS_LEFT} days"
fi

GitHub Actions: Full Pre-Deploy Pipeline

Combine all three checks into a single GitHub Actions workflow that runs before every deployment.

name: Infrastructure Pre-Deploy Checks
on:
  deployment:
    types: [created]
  workflow_dispatch:
    inputs:
      domain:
        description: "Domain to validate"
        required: true
        default: "example.com"

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - name: DNS Record Validation
        run: |
          DNS=$(curl -sf "https://api.ops.tools/v1/dns/lookup?domain=${{ inputs.domain }}&recordType=A"             -H "x-api-key: ${{ secrets.DOMAIN_API_KEY }}")
          echo "DNS response: ${DNS}"
          IP=$(echo "${DNS}" | jq -r '.records[0].value // empty')
          [ -n "${IP}" ] || (echo "FAIL: No A record found" && exit 1)
          echo "PASS: A record resolves to ${IP}"

      - name: SSL Certificate Validation
        run: |
          SSL=$(curl -sf "https://api.ops.tools/v1/ssl/check?domain=${{ inputs.domain }}"             -H "x-api-key: ${{ secrets.DOMAIN_API_KEY }}")
          VALID=$(echo "${SSL}" | jq -r '.valid')
          DAYS=$(echo "${SSL}" | jq -r '.daysUntilExpiration')
          echo "SSL valid: ${VALID}, expires in ${DAYS}d"
          [ "${VALID}" = "true" ] || (echo "FAIL: Invalid certificate" && exit 1)
          [ "${DAYS}" -gt 30 ] || (echo "FAIL: Certificate expires soon" && exit 1)

      - name: WHOIS Domain Expiration Check
        run: |
          WHOIS=$(curl -sf "https://api.ops.tools/v1/whois/lookup?domain=${{ inputs.domain }}"             -H "x-api-key: ${{ secrets.DOMAIN_API_KEY }}")
          EXPIRY=$(echo "${WHOIS}" | jq -r '.expirationDate // empty')
          [ -n "${EXPIRY}" ] || (echo "FAIL: No WHOIS data" && exit 1)
          echo "Domain expires: ${EXPIRY}"
          echo "PASS: WHOIS data available and parseable"

GitLab CI: Infrastructure Validation Stage

The same checks work in GitLab CI with environment variables for secrets and multi-stage pipeline configuration.

# .gitlab-ci.yml
stages:
  - validate
  - deploy

variables:
  DOMAIN: "example.com"

infra-validate:
  stage: validate
  image: alpine:latest
  before_script:
    - apk add --no-cache curl jq
  script:
    - |
      DNS=$(curl -sf "https://api.ops.tools/v1/dns/lookup?domain=${DOMAIN}&recordType=A" \
        -H "x-api-key: ${DOMAIN_API_KEY}")
      IP=$(echo "${DNS}" | jq -r '.records[0].value // empty')
      [ -n "${IP}" ] && echo "DNS: OK (${IP})" || exit 1
    - |
      SSL=$(curl -sf "https://api.ops.tools/v1/ssl/check?domain=${DOMAIN}" \
        -H "x-api-key: ${DOMAIN_API_KEY}")
      VALID=$(echo "${SSL}" | jq -r '.valid')
      [ "${VALID}" = "true" ] && echo "SSL: OK" || exit 1
    - |
      WHOIS=$(curl -sf "https://api.ops.tools/v1/whois/lookup?domain=${DOMAIN}" \
        -H "x-api-key: ${DOMAIN_API_KEY}")
      EXPIRY=$(echo "${WHOIS}" | jq -r '.expirationDate // empty')
      [ -n "${EXPIRY}" ] && echo "WHOIS: OK" || exit 1
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Post-Deploy: DNS Propagation Verification

After deployment, verify that DNS changes have propagated to multiple regions. A post-deploy check that queries from distributed locations catches regional caching issues that would not appear in single-region pre-deploy validation.

#!/bin/bash
# propagation-check.sh — Run after deployment
API_KEY="${DOMAIN_API_KEY}"
DOMAIN="${DEPLOY_DOMAIN}"
EXPECTED_IP="${EXPECTED_A_RECORD}"

PROP_RESPONSE=$(curl -sf \
  "https://api.ops.tools/v1/dns/propagation?domain=${DOMAIN}&recordType=A" \
  -H "x-api-key: ${API_KEY}")

MISMATCHES=$(echo "${PROP_RESPONSE}" | jq \
  '[.locations[] | select(.value != "'${EXPECTED_IP}'")]')

MISMATCH_COUNT=$(echo "${MISMATCHES}" | jq 'length')

if [ "${MISMATCH_COUNT}" -gt 0 ]; then
  echo "WARN: ${MISMATCH_COUNT} locations still resolving to old IP"
  echo "${MISMATCHES}" | jq -r '.[] | "\(.location): \(.value)"'
  # Optionally trigger rollback or wait for propagation
fi

echo "Propagation: ${MISMATCH_COUNT} of $(echo "${PROP_RESPONSE}" | jq '.locations | length') locations updated"

Scheduled Monitoring: Beyond Deployment Gates

Pipeline gates only catch problems at deploy time. Certificate expiration and domain registration changes happen between deployments. A scheduled cron-based pipeline that runs daily or weekly provides continuous coverage.

1

Daily SSL scan

Schedule a pipeline that checks SSL validity for all production domains. Set alert thresholds at 30, 14, 7, and 1 day before expiration. Route alerts to your on-call channel. This catches certificates that expire between deployments.

2

Weekly WHOIS audit

Query WHOIS data for all managed domains weekly. Track expiration dates and flag domains approaching renewal within 60 days. This is especially important for teams managing large domain portfolios where individual expiration dates are easy to lose track of.

3

On-demand DNS audit

Trigger a full DNS record audit on demand via pipeline dispatch. After any DNS provider change, nameserver migration, or infrastructure switch, run the audit to verify all records resolve correctly across multiple regions before considering the change complete.

Common pitfalls

Hardcoding domains: Maintain a domain manifest file or environment variable that the pipeline reads. This avoids updating the pipeline script every time a domain is added or removed. Ignoring rate limits: When checking large domain portfolios, add delays between requests to stay within the API rate limit. Silent failures: Always use set -euo pipefail in bash scripts so that any failed API call fails the pipeline step.

For deeper detail on each API capability, see the DNS record query guide, SSL monitoring walkthrough, and domain expiration protection guide.

Frequently Asked Questions

Q: Why should DNS and SSL checks run in CI/CD pipelines?

Running these checks as deployment gates catches DNS misconfigurations, expired certificates, and domain registration risks before they affect production. Manual checks are inconsistent and usually happen too late.

Q: How do I call domain data APIs from GitHub Actions?

Store your API key in GitHub Secrets under the repository settings. Reference it in workflow steps usingsecrets.DOMAIN_API_KEY (using the $ syntax). Use curl to call the API endpoint, parse the JSON response with jq, and exit with a non-zero code to fail the step if validation does not pass.

Q: What infrastructure checks should run before deployment?

At minimum: verify DNS records resolve to expected values, confirm SSL certificates are valid with more than 30 days until expiration, and check WHOIS data shows active domain registration. Add DNS propagation verification as a post-deploy step for DNS changes.

Q: How often should SSL certificate checks run in CI/CD?

Run SSL validation on every deployment for domains affected by the release. Additionally, schedule a daily or nightly cron pipeline that checks all production domains. Set alert thresholds at 30, 14, 7, and 1 day before expiration.

Related Articles

API Tutorials12 min read

DNS Lookup API: How to Check DNS Records Programmatically

Complete developer guide to querying DNS records via API. Includes working code examples in Python, Node.js, Go, and PHP with caching best practices.

Read Article
API Tutorials13 min read

IP Geolocation API: Complete Developer Guide

Build location-aware applications with IP geolocation data. Get country, city, ISP, timezone, and VPN detection from any IP address. Code examples included.

Read Article
API Tutorials12 min read

WHOIS Lookup API: Domain Registration Data at Scale

Query WHOIS data programmatically for domain intelligence. Get registrar info, expiration dates, and ownership data. Python, Node.js, Go, and PHP examples.

Read Article

Start Automating Infrastructure Checks Today

Professional plans starting at $29/month. One API key for DNS, WHOIS, IP, and SSL validation.