Skip to main content
RapidDev - Software Development Agency
replit-integrationsStandard API Integration

How to Integrate Replit with Let's Encrypt

To use Let's Encrypt SSL certificates with a Replit app, deploy your app to a Replit Autoscale or Reserved VM deployment with a custom domain, then use Replit's built-in SSL provisioning which leverages Let's Encrypt automatically. For advanced use cases β€” generating certificates for external servers from Replit β€” use the acme.sh tool or the ACME protocol with DNS-01 challenge from a Node.js or Python script running on Replit.

What you'll learn

  • How Replit automatically handles Let's Encrypt SSL for custom-domain deployments
  • How to configure a custom domain on a Replit deployed app to get a free SSL certificate
  • How to use the ACME protocol from a Replit server to issue certificates for external domains
  • How to automate certificate renewal using Replit Scheduled deployments
  • How to store DNS provider credentials securely in Replit Secrets for DNS-01 challenges
Book a free consultation
4.9Clutch rating ⭐
600+Happy partners
17+Countries served
190+Team members
Intermediate12 min read25 minutesAuthMarch 2026RapidDev Engineering Team
TL;DR

To use Let's Encrypt SSL certificates with a Replit app, deploy your app to a Replit Autoscale or Reserved VM deployment with a custom domain, then use Replit's built-in SSL provisioning which leverages Let's Encrypt automatically. For advanced use cases β€” generating certificates for external servers from Replit β€” use the acme.sh tool or the ACME protocol with DNS-01 challenge from a Node.js or Python script running on Replit.

SSL Certificates and Replit: Two Approaches

Let's Encrypt revolutionized SSL certificate management by making it free and automated. For most Replit users, Let's Encrypt is already in use without any configuration: Replit's deployment infrastructure automatically provisions and renews Let's Encrypt certificates for all apps deployed with custom domains. You add a custom domain, Replit handles the certificate β€” no manual steps required.

The second use case for Let's Encrypt on Replit is more advanced: using Replit as a platform to run an ACME client that manages certificates for external servers. This is useful when you manage multiple servers (VPS instances, on-premise servers) that all need SSL certificates, and you want a centralized, cloud-accessible place to run certificate renewal automation. Replit's Scheduled deployment type makes it easy to run a certificate renewal script once a day or once a week.

The ACME protocol has two common challenge types: HTTP-01 (serve a file at a specific path on your server) and DNS-01 (create a DNS TXT record). For Replit-based automation, DNS-01 is more practical because it does not require the script to be running on the same server as the website, and it works for wildcard certificates.

Integration method

Standard API Integration

Replit automatically provisions Let's Encrypt certificates for all deployed apps on custom domains β€” you do not need to manage certificates manually for Replit-hosted apps. For external server certificate management, you can run an ACME client script on Replit that uses the DNS-01 challenge to issue and renew certificates, storing DNS provider credentials in Replit Secrets and outputting the certificate files.

Prerequisites

  • A Replit account with a deployed app on Autoscale or Reserved VM (for the custom domain HTTPS use case)
  • A custom domain registered with a DNS registrar you can configure (for adding CNAME records)
  • For ACME scripting: a DNS provider with an API (Cloudflare, Route53, etc.) and API credentials
  • Basic understanding of DNS records (CNAME, TXT) and SSL/TLS certificates

Step-by-step guide

1

Get HTTPS on Your Replit App with a Custom Domain

The simplest Let's Encrypt integration on Replit is the automatic one. When you deploy a Replit app with a custom domain, Replit's infrastructure handles Let's Encrypt certificate issuance and renewal automatically β€” you get HTTPS at no cost with no certificate management. To set this up: 1. In your Replit project, click the 'Deploy' button (rocket icon) in the top bar. 2. Choose 'Autoscale' (or 'Reserved VM' for always-on apps). 3. In the deployment settings, find the 'Custom Domain' section. 4. Enter your domain name (e.g., myapp.com or app.mycompany.com). 5. Replit will show you a target URL (e.g., your-repl.replit.app) or IP address. 6. Go to your DNS registrar (Cloudflare, Namecheap, GoDaddy, etc.) and create a CNAME record pointing your domain to the Replit target URL. 7. DNS propagation takes 5-60 minutes. Once propagated, Replit automatically provisions a Let's Encrypt certificate for your domain. After provisioning, your app is accessible at https://yourdomain.com with a valid Let's Encrypt certificate. Replit renews the certificate automatically before it expires (Let's Encrypt certificates expire every 90 days). Note: Custom domains require a paid Replit plan (Core $25/mo or higher). The free plan does not support custom domains.

Pro tip: Use a subdomain for your Replit app rather than an apex domain (e.g., app.yourdomain.com instead of yourdomain.com) to allow CNAME configuration. Apex domains require ANAME or ALIAS records, which not all DNS providers support.

Expected result: Your Replit app is accessible at https://yourdomain.com with a padlock icon. Replit handles SSL certificate issuance and renewal automatically.

2

Check Certificate Expiry from Replit (Node.js)

Build a certificate monitoring script in Node.js that checks when SSL certificates expire for a list of domains. This is useful for tracking certificates you manage outside of Replit, or for validating that auto-renewal is working correctly. Node.js's built-in TLS module can connect to any HTTPS server and read the certificate details, including the expiry date. No external packages are needed for basic certificate inspection. This script can be run as a Scheduled Replit deployment to send daily or weekly alerts when certificates are approaching expiry.

check-certs.js
1// check-certs.js β€” SSL certificate expiry checker
2const tls = require('tls');
3
4function checkCertExpiry(hostname, port = 443) {
5 return new Promise((resolve, reject) => {
6 const socket = tls.connect({ host: hostname, port, servername: hostname }, () => {
7 const cert = socket.getPeerCertificate();
8 socket.destroy();
9
10 if (!cert || !cert.valid_to) {
11 return reject(new Error(`No certificate found for ${hostname}`));
12 }
13
14 const expiryDate = new Date(cert.valid_to);
15 const now = new Date();
16 const daysRemaining = Math.floor((expiryDate - now) / (1000 * 60 * 60 * 24));
17
18 resolve({
19 hostname,
20 subject: cert.subject?.CN || hostname,
21 issuer: cert.issuer?.O || 'Unknown',
22 expiryDate: expiryDate.toISOString(),
23 daysRemaining,
24 isExpired: daysRemaining < 0,
25 isExpiringSoon: daysRemaining < 30
26 });
27 });
28
29 socket.on('error', reject);
30 socket.setTimeout(10000, () => {
31 socket.destroy();
32 reject(new Error(`Timeout connecting to ${hostname}:${port}`));
33 });
34 });
35}
36
37async function checkAllDomains(domainsEnv) {
38 const domains = (domainsEnv || 'example.com').split(',').map(d => d.trim());
39 const results = [];
40
41 for (const domain of domains) {
42 try {
43 const result = await checkCertExpiry(domain);
44 results.push(result);
45 const status = result.isExpired ? 'EXPIRED' : result.isExpiringSoon ? 'EXPIRING SOON' : 'OK';
46 console.log(`[${status}] ${domain} β€” ${result.daysRemaining} days remaining (expires ${result.expiryDate})`);
47 } catch (err) {
48 console.error(`[ERROR] ${domain}: ${err.message}`);
49 results.push({ hostname: domain, error: err.message });
50 }
51 }
52
53 return results;
54}
55
56const DOMAINS = process.env.DOMAINS || 'example.com,google.com';
57checkAllDomains(DOMAINS)
58 .then(results => {
59 const alerts = results.filter(r => r.isExpiringSoon || r.isExpired || r.error);
60 if (alerts.length > 0) {
61 console.log('\nAlerts requiring attention:');
62 alerts.forEach(a => console.log(' -', a.hostname, a.error || `expires in ${a.daysRemaining} days`));
63 process.exit(1); // Non-zero exit signals failure in Replit Scheduled jobs
64 }
65 })
66 .catch(console.error);

Pro tip: Store your domain list as a DOMAINS environment variable in Replit Secrets (comma-separated). This way you can update the monitored domains without changing your script code.

Expected result: Running node check-certs.js logs the SSL certificate expiry status for each domain in DOMAINS. Domains expiring within 30 days are flagged with 'EXPIRING SOON'.

3

Python Certificate Monitoring Script

The Python ssl module provides equivalent functionality for checking certificate expiry. This version also demonstrates how to send a Slack alert when certificates are expiring, making it suitable for automated monitoring as a Replit Scheduled deployment. Install Flask if you need an HTTP interface, otherwise this script runs as a standalone job: pip install requests Store DOMAINS (comma-separated domain list), ALERT_WEBHOOK_URL (Slack webhook), and ALERT_DAYS_THRESHOLD (default 30) in Replit Secrets.

check_certs.py
1# check_certs.py β€” SSL certificate expiry checker with Slack alerts
2import os
3import ssl
4import socket
5import datetime
6import json
7import requests
8
9def check_cert_expiry(hostname, port=443):
10 context = ssl.create_default_context()
11 try:
12 with socket.create_connection((hostname, port), timeout=10) as sock:
13 with context.wrap_socket(sock, server_hostname=hostname) as ssock:
14 cert = ssock.getpeercert()
15 except Exception as e:
16 return {'hostname': hostname, 'error': str(e)}
17
18 # cert['notAfter'] format: 'Mar 15 12:00:00 2025 GMT'
19 expiry_str = cert.get('notAfter', '')
20 expiry_date = datetime.datetime.strptime(expiry_str, '%b %d %H:%M:%S %Y %Z')
21 days_remaining = (expiry_date - datetime.datetime.utcnow()).days
22
23 return {
24 'hostname': hostname,
25 'expiry_date': expiry_date.isoformat(),
26 'days_remaining': days_remaining,
27 'is_expired': days_remaining < 0,
28 'is_expiring_soon': days_remaining < int(os.environ.get('ALERT_DAYS_THRESHOLD', 30))
29 }
30
31def send_slack_alert(domains_at_risk):
32 webhook_url = os.environ.get('ALERT_WEBHOOK_URL')
33 if not webhook_url or not domains_at_risk:
34 return
35 message = 'SSL Certificate Alerts:\n' + '\n'.join(
36 f"- {d['hostname']}: {d.get('days_remaining', 'ERROR')} days remaining or error: {d.get('error', '')}"
37 for d in domains_at_risk
38 )
39 requests.post(webhook_url, json={'text': message}, timeout=10)
40
41def main():
42 domains_env = os.environ.get('DOMAINS', 'example.com')
43 domains = [d.strip() for d in domains_env.split(',')]
44 results = []
45
46 for domain in domains:
47 result = check_cert_expiry(domain)
48 results.append(result)
49 if result.get('error'):
50 print(f'[ERROR] {domain}: {result["error"]}')
51 else:
52 status = 'EXPIRED' if result['is_expired'] else ('EXPIRING SOON' if result['is_expiring_soon'] else 'OK')
53 print(f'[{status}] {domain} β€” {result["days_remaining"]} days remaining')
54
55 alerts = [r for r in results if r.get('is_expiring_soon') or r.get('is_expired') or r.get('error')]
56 if alerts:
57 send_slack_alert(alerts)
58 print(f'\n{len(alerts)} alert(s) sent.')
59
60if __name__ == '__main__':
61 main()

Pro tip: Configure this script as a Replit Scheduled deployment to run automatically every day. Set ALERT_WEBHOOK_URL to a Slack Incoming Webhook URL to receive direct Slack messages when certificates need attention.

Expected result: Running python check_certs.py checks all domains and logs their status. If any certificate is expiring within 30 days, it sends a Slack alert to ALERT_WEBHOOK_URL.

4

Store DNS Provider Credentials for DNS-01 Certificate Issuance

For advanced users running ACME client scripts that issue certificates for external servers using the DNS-01 challenge, the script needs credentials for your DNS provider's API to automatically create and delete TXT records. Store your DNS provider API credentials in Replit Secrets (lock icon πŸ”’ in sidebar). The exact secret names depend on your DNS provider: For Cloudflare: CLOUDFLARE_API_TOKEN β€” a Cloudflare API token with Zone:DNS:Edit permission CLOUDFLARE_ZONE_ID β€” the Zone ID for the domain (found in Cloudflare dashboard β†’ domain β†’ Overview β†’ Zone ID) For Route53: AWS_ACCESS_KEY_ID β€” AWS access key with Route53 record permissions AWS_SECRET_ACCESS_KEY β€” corresponding secret key For other DNS providers: Check the documentation for your ACME client library (python-acme, acme-client for Node.js, or acme.sh) to see which environment variables it expects for each DNS provider. IMPORTANT: DNS-01 challenge-based certificate issuance requires that your Replit script can make API calls to your DNS provider AND that Let's Encrypt can verify the TXT record publicly. The actual certificate issuance process involves multiple round trips to the Let's Encrypt ACME server, so plan for the script to take 60-120 seconds to complete.

Pro tip: Use Cloudflare as your DNS provider if possible β€” its API is well-supported by virtually every ACME client, it has a generous free tier, and its API token system allows fine-grained permissions (DNS-only, no account control).

Expected result: DNS provider API credentials are stored in Replit Secrets and accessible to your ACME certificate issuance scripts via os.environ or process.env.

Common use cases

Custom Domain HTTPS on a Replit Deployed App

Deploy a Replit app with a custom domain and get automatic HTTPS via Let's Encrypt. Replit provisions the certificate when you add the custom domain in the deployment settings. No code changes are needed β€” just configure the DNS CNAME record and Replit handles the rest.

Replit Prompt

Deploy your Replit app using Autoscale deployment, configure a custom domain in deployment settings, then update your DNS registrar to point the domain to Replit's deployment URL using a CNAME record. SSL is provisioned automatically within minutes.

Copy this prompt to try it in Replit

Automated Certificate Renewal for External Servers

Run an ACME client script on Replit as a Scheduled deployment that renews Let's Encrypt certificates for your VPS or on-premise servers once every 60 days. The script uses the DNS-01 challenge with your DNS provider's API, and uploads renewed certificates to your servers via SSH or an API.

Replit Prompt

Write a Python script that uses the acme library to request a Let's Encrypt certificate for an external domain using DNS-01 challenge with Cloudflare DNS API. Store CLOUDFLARE_API_TOKEN and domain configuration in environment variables. Output the certificate and key files for upload to the target server.

Copy this prompt to try it in Replit

Certificate Health Monitor

Build a Replit server that monitors the SSL certificate expiry dates for a list of domains and sends an alert when any certificate is within 30 days of expiry. Run it daily as a Scheduled deployment to catch certificates before they expire and cause downtime.

Replit Prompt

Create a Node.js script that checks the SSL certificate expiry date for each domain in a DOMAINS environment variable (comma-separated), identifies any expiring within 30 days, and posts an alert to a Slack webhook URL. Schedule to run daily.

Copy this prompt to try it in Replit

Troubleshooting

Custom domain on Replit shows 'Not Secure' or 'Certificate Error' after adding the domain

Cause: DNS propagation is not complete yet, or the CNAME record does not point to the correct Replit deployment URL.

Solution: Wait 5-60 minutes for DNS propagation. Use a tool like whatsmydns.net to verify the CNAME record is resolving correctly worldwide. Once DNS propagates, Replit automatically triggers certificate provisioning. If the issue persists after an hour, check the deployment settings in Replit and confirm the custom domain is active.

Let's Encrypt rate limit error β€” 'too many certificates already issued for this domain'

Cause: Let's Encrypt enforces rate limits: 50 certificates per domain per week, and 5 duplicate certificates per week. This is usually triggered by running certificate issuance scripts too many times in testing.

Solution: Use Let's Encrypt's staging environment (acme-staging-v02.api.letsencrypt.org) while developing your ACME scripts. Staging has the same protocol but no rate limits and does not issue browser-trusted certificates. Switch to production only when your script works correctly.

typescript
1// Use Let's Encrypt staging URL in development
2const ACME_DIRECTORY = process.env.NODE_ENV === 'production'
3 ? 'https://acme-v02.api.letsencrypt.org/directory'
4 : 'https://acme-staging-v02.api.letsencrypt.org/directory';

Certificate monitor script shows ERROR for a domain that has a valid certificate in browser

Cause: The TLS connection attempt timed out, the domain requires SNI (Server Name Indication) and the socket is not configured with the servername option, or a firewall blocks outbound port 443 from Replit.

Solution: Ensure the TLS socket is created with the servername option set to the hostname for SNI support. Verify that Replit can reach the domain on port 443 by testing in the Shell: curl -v https://thedomain.com.

typescript
1// Node.js: ensure SNI is set
2const socket = tls.connect({
3 host: hostname,
4 port: 443,
5 servername: hostname // Critical for SNI β€” must match the hostname
6});

Replit custom domain shows 'This site can't be reached' after SSL setup

Cause: The app is not deployed (Replit Autoscale scaled to zero, or the deployment was stopped), or the deployment is running but not listening on the correct port.

Solution: Ensure your server listens on port 3000 with host '0.0.0.0' (not 'localhost'). Replit's deployment infrastructure routes external traffic to port 3000 internally. Check deployment logs for startup errors.

typescript
1// Correct server binding for Replit deployments
2app.listen(3000, '0.0.0.0', () => {
3 console.log('Server running on port 3000');
4});

Best practices

  • Use Replit's automatic SSL provisioning for custom-domain apps β€” it handles Let's Encrypt issuance and renewal without any code changes required
  • Store all DNS provider API tokens in Replit Secrets (lock icon πŸ”’) β€” never in code or configuration files
  • Always use Let's Encrypt's staging environment while developing ACME scripts to avoid hitting production rate limits
  • Use DNS-01 challenge for ACME automation from Replit since it does not require the script to run on the same server as the target website
  • Deploy certificate monitoring scripts as Replit Scheduled deployments to run daily and alert before certificates expire
  • Set your alert threshold to 30 days before expiry β€” Let's Encrypt certificates expire every 90 days, so you have plenty of time to renew before 30 days
  • Use subdomains (app.example.com) rather than apex domains on Replit to simplify CNAME configuration
  • If managing certificates for external servers, consider whether a dedicated certificate management service (Certbot on the server itself) is more appropriate than running ACME from Replit

Alternatives

Frequently asked questions

Does Replit automatically handle SSL/HTTPS for my app?

Yes. When you deploy a Replit app and add a custom domain, Replit automatically provisions a Let's Encrypt certificate for your domain and renews it before expiry. You do not need to write any SSL-related code. The *.replit.app subdomain also uses HTTPS by default.

How do I add HTTPS to my custom domain on Replit?

Deploy your app using Autoscale or Reserved VM deployment, then add your custom domain in the deployment settings. Replit shows you a CNAME target. Update your DNS registrar to point your domain to that target. Once DNS propagates (5-60 minutes), Replit provisions the Let's Encrypt certificate automatically.

Can I use Let's Encrypt for a server that is not on Replit?

Yes. You can run an ACME client script on Replit to issue and renew Let's Encrypt certificates for any server. Use the DNS-01 challenge type with your DNS provider's API so the script does not need to run on the target server. Then upload the certificate files to your external server via SSH, S3, or an API.

How do I store DNS credentials securely in Replit for Let's Encrypt DNS challenges?

Click the lock icon (πŸ”’) in the Replit sidebar to open Secrets. Add your DNS provider API token (e.g., CLOUDFLARE_API_TOKEN) as a secret. Access it in Python as os.environ['CLOUDFLARE_API_TOKEN'] or in Node.js as process.env.CLOUDFLARE_API_TOKEN. Never put DNS credentials in your code files.

Do Replit Autoscale deployments automatically renew SSL certificates?

Yes. Replit manages the full certificate lifecycle for custom domains on deployed apps, including automatic renewal before the 90-day Let's Encrypt certificate expiry. You do not need to do anything β€” renewal is handled transparently by Replit's infrastructure.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation β€” no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.