by Charles Oropallo | Jan 17, 2025 | Security, Technical Help
Recently, I encountered an issue while attempting to renew an SSL certificate for one of my domains, (let’s call it) testdomain.com, using Let’s Encrypt on a server running Virtualmin on Debian 12. The process was more complicated than I expected due to a small oversight that many others could easily make. This article details my experience, the errors I encountered due to Let’s Encrypt rate limits (which I didn’t know existed), and steps to avoid or resolve such issues.
The Problem: Let’s Encrypt Rate Limits for Failed Authorizations
A padlock that shows with an encrypted site using https in some browsers.
Let’s Encrypt provides free SSL certificates for securing websites. However, it enforces rate limits to ensure fair usage and prevent abuse. While attempting to renew the SSL certificate for testdomain.com, I discovered that the DNS settings were not pointed to my server, causing repeated failed validation attempts. By the time I fixed the DNS settings, I had hit Let’s Encrypt’s rate limit for failed authorizations.
This limit restricts requests for the same domain to 5 failed attempts per hour. Once you hit this limit, you must wait for the cooldown period to expire before trying again.
How the Error Appeared in Virtualmin
In the Virtualmin interface, I attempted to renew the certificate by navigating to:
- Virtualmin > Server Configuration > SSL Certificate
- Clicking on the Let’s Encrypt tab
- Ensuring the domain and subdomain (e.g.,
testdomain.com
and www.testdomain.com
) were selected
- Clicking the Request Certificate button
The renewal process failed with an error that Virtualmin reported as “an unknown issue.” Upon further investigation, I found the detailed error logs in the Let’s Encrypt log file located at:
/var/log/letsencrypt/letsencrypt.log
From the log, I saw this message:
urn:ietf:params:acme:error:rateLimited :: There were too many requests of a given type :: too many failed authorizations (5) for "testdomain.com" in the last 1h0m0s, retry after [time].
Understanding Let’s Encrypt Rate Limits
Let’s Encrypt enforces several types of rate limits. Here are the key ones:
- Failed Validation Limit:
- 5 failed validations per domain per hour.
- This applies to any validation failure, such as DNS misconfigurations or inaccessible
.well-known/acme-challenge
directories.
- Duplicate Certificate Limit:
- 5 identical certificates per week.
- If you request the same set of domains repeatedly, you’ll hit this limit.
- Certificates per Registered Domain:
- 50 certificates per registered domain per week.
- All subdomains count toward this limit.
- Account-Level Requests:
- 50 certificates per account per week.
These limits are described in detail at Let’s Encrypt’s rate limit documentation.
Diagnosing the Problem
If you encounter a similar issue, here are the steps to diagnose and resolve it:
1. Check DNS Settings
- Ensure the domain’s DNS A records correctly point to your server.
- Use tools like
dig
or online DNS propagation checkers to verify.
2. Verify Webroot Accessibility
3. Examine Let’s Encrypt Logs
4. Check Cooldown Period
- If you’ve hit the rate limit, the log will indicate a
Retry-After
time in UTC. Convert it to your local timezone to determine when you can retry.
5. Dry Run Your Request
Steps to Avoid Future Issues
1. Ensure DNS Settings Before Requesting Certificates
- Double-check that DNS records point to the correct server and have propagated globally before initiating an SSL request.
2. Test Webroot Configuration
- Verify that the
.well-known/acme-challenge/
directory is accessible for all domains you’re requesting.
3. Use the Dry-Run Option
- Always test with
--dry-run
before making a live request to avoid hitting limits.
4. Automate Renewals
- Virtualmin and Certbot support automated renewals. Ensure the cron job is configured correctly and DNS remains stable.
5. Avoid Forcing Duplicate Requests
- Options like
--duplicate
and --force-renewal
can lead to unnecessary requests. Only use them when absolutely necessary.
Conclusion
Hitting Let’s Encrypt’s rate limits can be frustrating, but understanding the causes and solutions can save time and effort. By checking DNS settings, verifying webroot accessibility, and using dry runs, you can prevent failed authorizations and avoid cooldown periods.
If you’re using Virtualmin, remember to check the Let’s Encrypt logs for detailed error messages, and plan your certificate renewals carefully to stay within the rate limits. Hopefully, my experience with testdomain.com helps you navigate and prevent similar issues.
As always, proactive testing and attention to detail go a long way in maintaining a secure and smoothly running server.









by Charles Oropallo | Dec 16, 2024 | Do-It-Yourself, Technical Help, Website Development, WordPress
SimplePractice: Incorporating its Widget into your WordPress Divi Website
This article is about adding the SimplePractice widget to your WordPress website that uses the Divi theme. I’ll explain what SimplePractice is and get into how to install its widget into your WordPress Divi website.
Simplifying Practice Management for Mental Health Professionals
SimplePractice is a trusted all-in-one platform designed to make life easier for mental health professionals and other wellness practitioners. See https://SimplePractice.com for more details. It streamlines essential administrative tasks like scheduling, billing, documentation, and client communication, allowing practitioners to focus on what truly matters—their clients. With a user-friendly interface and powerful tools, it’s an ideal solution for solo practitioners and small group practices.
One of the standout features is its online scheduling tool, which lets clients book appointments through a secure, HIPAA-compliant client portal. This portal also allows clients to complete intake forms, sign documents, and even message their provider—all in one place. For therapists who offer virtual sessions, the telehealth integration enables seamless video appointments without the need for third-party apps.
SimplePractice also simplifies billing and insurance management. Providers can create invoices, process payments, and submit insurance claims directly through the system. Plus, its customizable progress notes and treatment plan templates make maintaining records both quick and efficient.
What makes SimplePractice shine is its simplicity. The platform is intuitive and easy to navigate, with minimal learning curves for both practitioners and their clients. The robust support team and extensive online resources ensure any questions are resolved quickly.
Whether it’s automating reminders, securely managing client data, or customizing a practice’s workflow, SimplePractice makes running a private practice straightforward and stress-free. It’s the tool busy professionals rely on to save time, stay organized, and provide exceptional care.
The SimplePractice appointment request widget can be incorporated into a development domain for your client’s pending Divi site and ultimately in the live site. Here’s how you can achieve this:
Step 1: Review the Widget Code
Once you have the widget code from the client, you need to verify its structure. Typically, it includes a <script>
tag provided by SimplePractice. For example:
The data-sp-client-id
is unique to your client’s SimplePractice account, so ensure that value matches.
Step 2: Add the Widget Code to the Divi Site
In Divi, you can embed custom code into the site using the Code Module or Theme Builder:
- Using the Divi Code Module:
- Open the page or section where you want to display the widget.
- Add a Code Module within the desired row or column.
- Paste the SimplePractice widget code into the module.
- Save the changes and preview to ensure the widget appears as expected.
- Using Divi Theme Builder (if the widget should appear site-wide):
- Navigate to Divi > Theme Builder in the WordPress dashboard.
- Create or edit a custom header, footer, or body section.
- Add a Code Module and paste the widget code.
- Assign the template to the desired pages or the entire site.
Step 3: Customize the Widget (Optional)
The Customizing Your Widget section in the SimplePractice documentation explains how you can:
- Change colors, fonts, and styles to match the Divi site’s design.
- Customize settings by modifying the
<script>
code parameters.
If your client’s code already includes customization, verify if it aligns with the new site’s look. For further adjustments, update the styles within the widget script.
Step 4: Use the Development Domain
SimplePractice widgets do not rely on a specific domain to function, as long as the data-sp-client-id
is correct. You can install and test the widget on the development domain without any issues. Once the site goes live on the actual domain, the widget should still work without changes.
However, after the site goes live, it’s good practice to:
- Confirm the widget works properly on the live domain.
- Recheck any customized URLs or redirects tied to the widget to ensure they match the live setup.
Step 5: Test the Integration
- Navigate to the development site.
- Test the widget to ensure it displays and works correctly (e.g., appointment requests can be submitted).
- Check for any conflicts with other scripts or plugins on the Divi site.









by Charles Oropallo | Nov 26, 2024 | Do-It-Yourself, Technical Help
Resolving Default Page Mismatches
We had a website transferred to us for hosting by a client who did not know about resolving default page mismatches. This occurs, for example, the a page not found error happens when a site visitor is clicking on your navigation trying to get back to the home page. When hosting a website, ensuring that the correct default page is served when visitors navigate to the root domain (e.g., exampledomain.com
) is critical. A mismatch between menu navigation items and the actual default page can confuse visitors and lead to a poor user experience. Below, I’ve outlined several methods to address such issues. Each method depends on the tools and access available on your hosting environment.
1. Redirect Default Page Using a New default.htm
File
The simplest solution is to create a default.htm
file that redirects visitors to the correct index.html
file.
Steps:
- Create a new file named
default.htm
in the root directory of the website.
- Add the following HTML code to the file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="refresh" content="0;url=index.html">
<title>Redirecting...</title>
</head>
<body>
<p>If you are not redirected, <a href="index.html">click here</a>.</p>
</body>
</html>
- Save and upload the file to the server.
When visitors access exampledomain.com/default.htm
, they will be automatically redirected to index.html
.
2. Set Default Pages in Virtualmin
If your hosting server uses Virtualmin, you can configure the default pages it prioritizes when serving the site.
Steps:
- Log in to Virtualmin.
- Navigate to the specific domain by selecting it from the dropdown.
- Go to Server Configuration > Website Options.
- Locate the option for “Default index file names” or similar.
- Add
default.htm
to the list if it is not already present. For example:
index.html index.htm default.htm
- Save the changes and reload the website.
With this configuration, default.htm
will be recognized as a valid default page alongside index.html
.
3. Use an .htaccess
File
You can also use an .htaccess
file to specify which files should be served as default pages.
Steps:
- Access the root directory of the website via FTP or the file manager.
- Open or create a file named
.htaccess
.
- Add the following lines to the file:
DirectoryIndex default.htm index.html index.htm
- Save the file and upload it to the server.
This tells the server to prioritize default.htm
as the default page. If default.htm
is not found, it will fall back to index.html
or other specified files.
4. Update Navigation Links in the Website’s Code
If all navigation menu items point to default.htm
, you can update the site’s HTML files to point to index.html
instead.
Steps:
- Download the HTML files that contain navigation links.
- Search for
default.htm
in the code and replace it with index.html
.
- Save and upload the updated files to the server.
This ensures that navigation links point to the correct file and prevents further confusion.
5. Configure the Web Server Directly
For advanced users with root access to the server, you can modify the web server’s configuration files to set the default page order.
Apache Servers:
- Edit the Apache configuration file (e.g.,
/etc/httpd/conf/httpd.conf
or /etc/apache2/apache2.conf
).
- Find the
DirectoryIndex
directive and modify it:
DirectoryIndex default.htm index.html index.htm
- Save the file and restart Apache:
systemctl restart apache2
Nginx Servers:
- Edit the server block configuration file (e.g.,
/etc/nginx/sites-available/exampledomain.com
).
- Modify the
index
directive:
index default.htm index.html index.htm;
- Save the file and restart Nginx:
systemctl restart nginx
6. Combine Redirect and Navigation Fixes
For maximum compatibility and user experience, you can combine several methods. For example:
- Use the
.htaccess
file or Virtualmin to prioritize default.htm
.
- Add a redirect in
default.htm
for edge cases.
- Update all navigation links to
index.html
.
Final Thoughts on Resolving Default Page Mismatches
Choosing the right method depends on your hosting setup and access level. If you’re looking for a quick fix, creating a redirect in default.htm
is the easiest option. For a more permanent and scalable solution, consider updating the server configuration or .htaccess
file.
Always remember to test changes thoroughly to ensure they work as expected before making them live. This will prevent any disruptions for your website’s visitors.
And, finally, at CharlesWorks we take care of these types of issues for you.









by Charles Oropallo | Jan 3, 2021 | Do-It-Yourself, Technical Help, The CW Corner, Website Development, WordPress
I wanted to create a custom HTML code function, so made one that will generate a line feed. I tested it to neaten up the output from my favorite WordPress statistics plugin: WP-Statistics by Verona Labs.
This shortcode gives the ability to add line feeds to WordPress page, post or report outputs to improve their readability. The function can easily be modified to generate any HTML output by doing this:
- rename “newline” in the “add_shortcode” line to whatever you’d like the shortcode to be named
- adjust the HTML code inside the quotes in the “return” line
In this example, we’ll create the line break shortcode.
Creating the Line Break Shortcode
Adding shortcodes in WordPress is easily accomplished by simply inserting the appropriate coding for the shortcode into your child theme’s functions.php file.
Note: Child themes should always be used. Changes made directly to the parent theme’s files are usually overwritten each time the parent theme is updated.
To add the code, first back up your site and then do the following:
- Log into the WordPress Dashboard as an administrator
- Navigate to Appearance > Theme Editor
- Select Theme Functions (functions.php) under Theme Files in the right column
- Add the short function code lines below
/* -- Start of line breaks shortcode --*/
function line_break_shortcode() {
return '<br />';
}
add_shortcode( 'newline', 'line_break_shortcode' );
/* -- End of line break shortcode --*/
Adding Line Breaks
Once the code has been added to your functions.php file, all you have to do is add the
shortcode in your text to generate a line feed at that point. The beauty of doing this as a shortcode is that it can be inserted in places that do not normally allow you to add them – like in the email output of the WP-Statistics plugin.
Note: When testing your output from the WP-Statistics plugin, there is a convenient feature that allows you to send output every minute to see what you will be sending. As a rule I normally have the report set to send daily.
A Working Example
There were a couple of WP-Statistics report items that were of particular interest to me. One is the last post date. This is handy as a reminder when one should add one or more posts to a site – especially a blog – so the site content doesn’t appear stale (or as an alternative, simply do not show blog post creation dates). Even if you are not displaying the post dates on the site, it is good to know when you last posted something.
An example of the report pattern I used was this (note that in some WordPress themes the “[” and “]” characters in the example below display as repeated – there should only be one “[” opening shortcode character and one “]” closing shortcode character surrounding the shortcode itself when you use it):
WP Statistics report for https://CWCorner.com WordPress site:
[newline]
_______________________________________________
[newline]
[newline]
Last post date: [wpstatistics stat=lpd]
[newline]
Total Site Posts: [wpstatistics stat=postcount]
[newline]
Total Site Pages: [wpstatistics stat=pagecount]
[newline]
Total Site Users: [wpstatistics stat=usercount]
[newline]
Online Users at Report Time: [wpstatistics stat=usersonline]
[newline]
_______________________________________________
[newline]
[newline]
Today's Visitors so far: [wpstatistics stat=visitors time=today]
[newline]
Today's Visits so far: [wpstatistics stat=visits time=today]
[newline]
Yesterday's Visitors: [wpstatistics stat=visitors time=yesterday]
[newline]
Yesterday's Visits: [wpstatistics stat=visits time=yesterday]
[newline]
_______________________________________________
[newline]
[newline]
Total Visitors: [wpstatistics stat=visitors time=total]
[newline]
Total Visits: [wpstatistics stat=visits time=total]
[newline]
_______________________________________________
[newline]
[newline]
End of WP Statistics Report.
[newline]
I used the underline characters to separate various parts of the output for clarity. This report pattern generated a nicer, more readable report that even looked great when viewing it on my cell phone.
While I initially added this function as a way to neaten up the output of the WP-Statistics email report – the function should work just about anyplace in WordPress except in the PHP coding itself.









by Charles Oropallo | Dec 15, 2020 | Do-It-Yourself, Internet, Security, Technical Help, The CW Corner, Website Development, WordPress
Akismet provides a convenient and free way to protect your personal WordPress site or blog from spam.
Many times we’d like to allow comments to be left on our WordPress site. The hassle with this can be the tremendous amounts of spam that come through the forms on websites.
Akismet is a compact WordPress plugin that filters the incoming comments. It is pretty straightforward to use and pretty easy to set up as well.
Install the Akismet plugin
The first step in this process is to ensure that the Akismet plugin is installed in your WordPress website:
-
-
- Log into your WordPress website’s dashboard as an administrator
- Click on Plugins in the left dashboard navigation column
- Look and see if Akismet is listed – if it is – and it is not activated you can proceed to the Akismet Setup step below – otherwise
- Click on Add New under Plugins in the dashboard navigation column
- If you don’t see Akismet in the plugins, then in the text box to the right of the work Keyword in the row starting with Featured type in Akismet – then click on its Install Now button. Do not activate it yet.
Perform the Akismet Setup
To set up Akismet in your website, you will need an API code from the Akismet site. The first step in that process is to navigate to:
https://akismet.com/plans
This (as of the time of this writing) brings you to a page that should look similar to the screenshot below.
Akismet offering pricing page
To get the free version of Akismet comment spam protection, you will need to click on the Get Personal button on the above page.
Once you’ve done that, you should see a page similar to the one below. Before attempting to fill out anything on this page, we need to set that $36 / YEAR to $0 / YEAR. Click on the $36 / YEAR box and drag it to the left.
Akismet Default $36 per year page
Dragging that $36 / YEAR box to the left should change the page to display something like the one below showing 0$ / YEAR. You can also see that the information to fill in has changed.
Akismet $0 per year page
Akismet $0 per year page
Now fill in the information completely. Note that you need to be able to check all three checkboxes indicating the following:
-
-
- you don’t have ads on your site
- you don’t sell products/services on your site
- you don’t promote a business on your site
If these are the case, then you will qualify for a free, personal plan.
All you have to do once you have gotten this far is follow the directions on the page below.
Akismet signup complete page
Finally, it is suggested that while on that settings page in Akismet, you can choose to show the number of approved comments beside each comment author and choose whether to show a privacy notice or not. Then just click the Save Changes button and you are on your way!









by Charles Oropallo | Nov 15, 2020 | Do-It-Yourself, Technical Help, WordPress
Every piece of popular software gets updated over time. PHP is no different.
PHP 7.4 is the latest version of PHP 7 at the time of this writing. It was originally rolled out November 28, 2019 and will receive security support until November 28, 2022. It also appears that PHP 7.4 may be the last of the PHP 7 releases, as PHP 8.0 was rolled out on November 26, 2020.
This is all great news, since each newer PHP version so far has continued to provide:
- considerable (but not total) backward compatibility
- faster execution speeds
- greater security.
We’ve seen many PHP upgrades since running WordPress over many, many years. Our preliminary testing has always shown that many WordPress plugins and themes don’t work seamlessly with new versions of PHP as they are rolled out. As for PHP 7.4, the WordPress core and its latest default themes do. Unfortunately, many sites will simply break if caution isn’t taken to ensure all of their components – the core, the plugins and the themes – are PHP 7.4 compliant. For this reason, we usually don’t switch PHP to the later version until we are confident most things will work. When you think about the many thousands of themes and plugins out there for WordPress, it is no surprise that sometimes this takes longer than a year.
WordPress PHP notifications
PHP versions older than PHP 7.2 now trigger the red circle with an exclamation point PHP notification that administrative users see in the WordPress dashboard.
PHP update required notification
Site Health Status – Should be improved
Bear in mind that WordPress only issues a warning about 7.1 and lower. The red notice in the dashboard is not shown for higher versions. Navigating to Tools > Site Health yields more details about site health.
Site Health – Should be Improved
Site Health Status – 1 critical issue – running outdated version of PHP 7.1 requires an update
PHP 7.2 just went to end of life November 30, 2020 – hence the red PHP update required notice that shows in the dashboard for anything older than 7.2 doesn’t show if you are running PHP 7.2 and above.
Site Health Status – Good
PHP 7.2 which should be updated
If you are running PHP 7.3 (or newer) you will not get the red notice described above. However, in the site health you will see an indication stating “Your site is running an older version of PHP (7.3.x) which worries many when they see it.
Site Health – Good
Site Health Status – 1 recommended improvement – running an older version of PHP – PHP 7.3.25
The fact is that PHP 7.3 will be receiving security updates until December 6, 2021. Given that, there is plenty of time to get ready for PHP 7.4.
Site Health Status – Good
PHP 7.2 and above
The plan at CharlesWorks is to make PHP 7.4 available in the upcoming months. When that happens, you will notice that each of the PHP 7.x versions you see in the DirectAdmin interface will be bumped up by one version. So you will always still be able to go back to 7.3 if needed.
PHP 8.0 was released on November 26, 2020 with an expected security support date of October 26, 2023. There appears to be more incompatibility between it and PHP 7. CharlesWorks would not expect to roll this version out until nearer the end of 2021. Let’s give the world a chance to find all of the bugs for us.








