NGINX Plus R35 for Federal Environments: FIPS-Compliant algorithms with ACME Certificates in AWS

NGINX Plus R35 offers a fantastic combination of built-in ACME support and also supports using FIPS-compliant cryptographic algorithms. This guide walks through configuring a setup of Nginx to use Let's Encrypt for automatic certificate generation and renewal with FIPS approved algorithms.  I should clarify that if you do not want to use FIPS approved algorithms, it is very simple to change the cipher suite lines to meet your particular needs.

This is an easy setup thanks to the relatively new AWS based Nginx offering. See the link below. 

nginx FIPS Offering on Red Hat Enterprise Linux

 

Why ACME + FIPS Algorithms help

The ACME (Automatic Certificate Management Environment) protocol revolutionizes SSL/TLS certificate lifecycle management. It does this by eliminating manual processes. Meanwhile, FIPS 140-2 compliance remains mandatory for government agencies and many enterprise environments. NGINX Plus R35's native ACME module finally brings these capabilities together in a single, streamlined solution.

 

A note on the use of Let's Encrypt for Federal Organizations

Federal organizations can use Let's Encrypt, but with important considerations:

Legitimate Use Cases:

  • Public-facing websites and services that need to be accessible to citizens
  • Development and testing environments where FIPS compliance isn't required
  • Non-sensitive public information portals like agency news, public documents, or general information sites
  • External collaboration platforms that interface with the public or other organizations

Key Limitations for Federal Use:

  • Not FIPS 140-2 validated - Let's Encrypt’s certificates don't meet federal cryptographic standards required for sensitive systems
  • Internet dependency - Certificate issuance requires external connectivity, which may conflict with air-gapped or highly secure networks
  • Limited control - Less oversight compared to internal Certificate Authorities or approved federal PKI providers
  • Compliance gaps - May not satisfy requirements like FedRAMP, FISMA, or other federal security frameworks

Better Federal Alternatives:

  • DoD PKI certificates for defense-related systems
  • Federal PKI (FPKI) for cross-agency authentication
  • Internal Certificate Authorities with FIPS-validated hardware security modules
  • Commercial providers that offer FIPS-compliant certificate services

Most federal organizations use Let's Encrypt only for low-sensitivity public websites. They use FIPS-compliant solutions for systems handling sensitive data or requiring federal security certifications

Let's look at how this could be set up.

 

Prerequisites

Before starting, ensure you have deployed your nginx FIPS Red Hat enterprise Liinux to AWS this gives you the following:

  • NGINX Plus R35 or later with a valid license (notably, to get to R35, you need to perform a 'sudo yum upgrade' to get to 35 in the version that I deployed)
  • Red Hat Enterprise Linux 8+ (or compatible distribution)
  • OpenSSL 3.0+ with FIPS provider support
  • Public domain with DNS pointing to your server (for a quick test I used DuckDNS)
  • Ports 80 (HTTP) and 443 (HTTPS) accessible from the internet

Also make sure you have the acme module installed. In my case, I retrieved that with a 

sudo yum install nginx-plus-module-acme

And that module should be located in the

/etc/nginx/modules directory

Step 1: Enable SELinux Network/File Permissions

The most common stumbling block with NGINX Plus ACME is SELinux blocking outbound connections:

Allow NGINX to make network connections to ACME servers 

# Allow NGINX to make network connections to ACME servers
sudo setsebool -P httpd_can_network_connect on

# Verify the setting persists
sudo getsebool httpd_can_network_connect

Also there is an acme state directory that I created in the /etc/nginx directory. I performed a chown on this directory so that nginx had permissions. This is the directory defined in my test nginx.conf file - see test nginx.conf below.

 

sudo chown nginx:nginx /etc/nginx/acme

Further troubleshooting

If you have other issues with acme, please note you can troubleshoot with

sudo tail -f /var/log/nginx/error.log

and 

sudo tail -f /var/log/audit 

and also you can use

nginx -t #this tests the nginx.conf file to see if it is good

and

sudo nginx -s reload #this will reload your configuration

and 

sudo systemctl status nginx #this will check the "status" of nginx to see that the daemon is running properly.

Also note that when you ssh into the instance, note that this is a fairly locked down instance.

 

NGINX Plus is secured using the SELinux 'httpd_t' context and exceptions are

logged to /var/log/audit/audit.log.  Edit or disable the SELinux policy to

allow NGINX Plus to access additional resources or ports.

More info on using SELinux with NGINX Plus is available at

https://www.nginx.com/blog/using-nginx-plus-with-selinux/

Register this system with Red Hat Insights: rhc connect

 

If you are not comfortable with linux on the command line, you can centrally manage your instances through the nginx one SaaS console. The Nginx one SaaS console makes the configuration and management of Nginx much easier, especially if you have a fleet of nginx servers. Also, your Nginx instances need internet connectivity you cannot manage Nginx from Nginx One in disconnected network environments.

 

Step 2: Basic NGINX Plus Configuration with ACME

Create a foundational configuration that establishes ACME connectivity:

My simple test configuration was as follows.

Nginx can also and is commonly configured as a reverse proxy to other resources with proxy_pass directives. This is a simple test setup, so I have put in a simple response if the test works.

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    # Required for ACME
    resolver 8.8.8.8;

    # ACME staging issuer (fake certificates)
    acme_issuer staging {
        uri https://acme-staging-v02.api.letsencrypt.org/directory;
        # contact mailto:youremail@domain.com;  # CHANGE THIS
        state_path /etc/nginx/acme;
        accept_terms_of_service;
    }


    acme_shared_zone zone=acme:1M;

    # HTTP server (required for challenges)
   server {
    # listener on port 80 is required to process ACME HTTP-01 challenges
    listen 80;

    location / {
        #Serve a basic 404 response while listening for challenges
        return 404;
    }
}

    # HTTPS server with ACME
    server {
        listen 443 ssl;
        http2 on;
        server_name secure.yourdomain.com;  # CHANGE THIS

        acme_certificate staging;
        ssl_certificate $acme_certificate;
        ssl_certificate_key $acme_certificate_key;

        # FIPS-compliant protocols
        ssl_protocols TLSv1.2 TLSv1.3;

        # FIPS-approved cipher suites
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:AES128-SHA256:AES256-SHA384;

        # FIPS-approved elliptic curves
        ssl_ecdh_curve prime256v1:secp384r1:secp521r1;

        ssl_prefer_server_ciphers off;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 1d;
        ssl_session_tickets off;


        location / {
            return 200 "ACME Test Works!\n";
            add_header Content-Type text/plain;
        }
    }
}

 

I am using staging for testing ACME. If you look at the nginx.conf I have added this directory, which allows me to play with test certificates.

 

# ACME staging issuer (fake certificates)
    acme_issuer staging {
        uri https://acme-staging-v02.api.letsencrypt.org/directory;
        # contact mailto:youremail@domain.com;  # CHANGE THIS
        state_path /etc/nginx/acme;
        accept_terms_of_service;
    }

 

For production, you would set it like this.

 

# ACME production issuer (real certificates)
acme_issuer production {
    uri https://acme-v02.api.letsencrypt.org/directory;
    # contact mailto:youremail@domain.com;  # CHANGE THIS
    state_path /etc/nginx/acme;
    accept_terms_of_service;
}

 

The change needed is replacing https://acme-staging-v02.api.letsencrypt.org/directory with https://acme-v02.api.letsencrypt.org/directory to use Let's Encrypt's production API endpoint instead of staging.

For more information about let's encrypt, you can check here, https://letsencrypt.org/

 

Step 3: FIPS-Compliant Configuration

The key to FIPS compliance lies in carefully selecting cryptographic algorithms and also the correct TLS version. 

       # FIPS-compliant protocols
        ssl_protocols TLSv1.2 TLSv1.3;

        # FIPS-approved cipher suites
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:AES128-SHA256:AES256-SHA384;

 

Other robust things to consider as part of a secure nginx configuration... though not strictly about setting up FIPS ciphers.

   # HSTS and security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;

 

Strict-Transport-Security: Forces browsers to only connect to your site using HTTPS (encrypted connections)  this is cached/remembered by the browser for 1 year, including all subdomains.

X-Frame-Options DENY: Prevents your website from being embedded in frames or iframes on other sites, protecting against clickjacking attacks.

X-Content-Type-Options nosniff: Stops browsers from guessing file types and forces them to respect the Content-Type header you set, preventing certain security vulnerabilities.

These headers help protect your website from common web security threats.

 

 

Step 4: Deployment and Validation

Create the ACME state directory and deploy:

# Create state directory with proper permissions 
sudo mkdir -p /etc/nginx/acme 
sudo chown nginx:nginx /etc/nginx/acme 
sudo chmod 755 /etc/nginx/acme 
# Test configuration 
sudo nginx -t 
# Deploy the configuration sudo systemctl reload nginx 

# Trigger certificate generation curl https://secure.yourdomain.com

 

Step 5: Verify Setup

Validate that your deployment uses only FIPS-approved algorithms:

# Check negotiated cipher suite 
openssl s_client -connect secure.yourdomain.com:443 -brief 
# Verify elliptic curve usage 
openssl s_client -connect secure.yourdomain.com:443 2>/dev/null | grep -E "(Cipher|Server Temp Key)" 
# Test against FIPS cipher list 
openssl ciphers -v 'ECDHE-RSA-AES256-GCM-SHA384' | head -5

 

Monitoring and Maintenance

The best part about NGINX Plus with ACME integration lies in its automation. Certificates automatically renew 30 days before expiration, with no manual intervention required. Monitor the process with:

# Watch ACME renewal activity 
sudo tail -f /var/log/nginx/error.log | grep -i acme 
# Verify certificate expiration 
echo | openssl s_client -connect secure.yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates

 

Key Considerations

FIPS vs. Performance:

FIPS-compliant cipher suites may have slight performance impacts compared to modern alternatives like ChaCha20-Poly1305. In high-throughput environments, monitor CPU usage and consider hardware acceleration.

Post-Quantum Readiness:

While no PQC algorithms are currently FIPS-approved, NIST has published the FIPS 203-205 standards. Plan for hybrid configurations in 2026-2027, when FIPS-validated PQC implementations become available.

Staging vs. Production:

Always test with Let's Encrypt's staging environment first to avoid rate limits. Simply change the ACME URI to https://acme-staging-v02.api.letsencrypt.org/directory during initial testing.

 

Nginx One!

Some of this involves linux command-line work that people may not be familiar with. I already mentioned Nginx One. It can simplify your life!

Nginx One Console is a centralized management platform that dramatically simplifies the administration of multiple Nginx instances. It does this by providing a unified web-based dashboard for monitoring, configuring, and managing all deployments from a single location. Instead of manually configuring each server through SSH and command-line interfaces, the console streamlines common tasks like SSL certificate management, load balancer updates, and security policy enforcement with features like automated configuration synchronization and one-click deployments. This eliminates the complexity of managing multiple configuration files, reduces human error, and provides real-time visibility into performance and health metrics. This allows teams to implement changes across hundreds of servers in minutes rather than hours while focusing on strategic initiatives instead of routine maintenance.

 

Conclusion

NGINX Plus R35's native ACME support eliminates the complexity traditionally associated with certificate management. By combining automated certificate lifecycle management with government-grade cryptography, organizations can maintain security and operational efficiency.

This configuration provides a solid foundation for production deployments, while automating one of the most error-prone aspects of SSL/TLS management. As PQC standards mature and achieve FIPS validation, this same framework will seamlessly adapt to quantum-resistant cryptography.

For more NGINX Plus configuration guides and best practices, visit the official NGINX documentation.

Published Sep 11, 2025
Version 1.0
No CommentsBe the first to comment