Couldnt verify ssl certificate: 404 unauthorized

I ran into a problem where i tried a lot but couldnt resolve please help !!

My domain is:

I ran this command: certbot certonly --webroot -w $WEBROOT_PATH -d $DOMAIN --non-interactive --agree-tos --email $EMAIL

It produced this output:
Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
Domain: stag-blogs.devcentrehouse.eu
Type: unauthorized
Detail: 54.159.226.253: Invalid response from http://stag-blogs.devcentrehouse.eu/.well-known/acme-challenge/zZgqYFZybE-mnGJx6bK9vTcrm40z9RMhToevb7QDyWU: 404

Hint: The Certificate Authority failed to download the temporary challenge files created by Certbot. Ensure that the listed domains serve their content from the provided --webroot-path/-w and that files created there can be downloaded from the internet.

My web server is (include version): apache2

The operating system my web server runs on is (include version): im running on aws fargate docker wordpress container

My hosting provider, if applicable, is: cloudflare

I can login to a root shell on my machine (yes or no, or I don't know): yes i can access to my container

I'm using a control panel to manage my site (no, or provide the name and version of the control panel):no

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you're using Certbot): certbot 2.1.0

currently im using wordpress container on aws fargate, i have allowed necessary inbound rules,
80,443 for my loadbalancer dns on 0.0.0.0/0 lb-sg
i have container-sg where 80,443 inbound access from my loadbalancer configured.

this is my default.conf file copying this to /etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName stag-blogs.devcentrehouse.eu
    DocumentRoot /var/www/html

    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    # Serve the challenge files from the .well-known directory
    Alias /.well-known/acme-challenge/ /var/www/html/.well-known/acme-challenge/
    <Directory "/var/www/html/.well-known/acme-challenge/">
        Options None
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # Redirect HTTP to HTTPS
    RewriteEngine on
    RewriteCond %{HTTPS} !=on
    RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/
    RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]
</VirtualHost>

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    ServerName stag-blogs.devcentrehouse.eu
    DocumentRoot /var/www/html

    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/stag-blogs.devcentrehouse.eu/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/stag-blogs.devcentrehouse.eu/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

i have checked necessary webroot folder under /var/www/html
there is /var/www/html/.well-known/acme-challenge with 775 permission too which i created manually using dockerfile.

I have forwarded 80 http loadbalancer port to container port too

what can be the problem as my apache2 is also running on port 80.
I tried to stop apache2 and install certificate using --standalone too but still not working.
the certificate file is not generated as i checked on /etc/letsencrypt/ there is no /live directory created.
Please suggest me some thing.

So how many Apache instances do you have behind the AWS ELB? The ELB itself has two IP addresses.

Because every Apache instance must be able to respond to the HTTP Challenge coming from the Let's Encrypt Server. Certbot, as the ACME Client, sets up the token on the system it runs on. But, the LE Server may send a request to either of the IP in your DNS and either must reply properly.

The "404" in the error message is an HTTP "Not Found" so your system said it did not have the token.

In a single instance setup this is usually because the --webroot-path (-w) given to Certbot is not the folder used as the DocumentRoot for this domain and challenge. But, multi instance setups are very different.

Depending on your config and needs could you just enable AWS ACM Certs in the load balancer and use HTTP between the ELB and your Apache instances?

Or, use a DNS Challenge instead of the HTTP Challenge with --webroot?

2 Likes

Currently im using only one instance behind ELB, when i checked on the webroot path there is no such key added. As i using the single instance i confirmed that the webroot path given to certbot
/var/www/html is same as DocumentRoot /var/www/html
In my loadbalancer i have just HTTP and didnt enabled AWS ACM as im trying to generate certificate manually and will import in ACM manually.
as i also created testfile under acme-challenge to test it shows 403 forbidden

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
<hr>
<address>Apache/2.4.61 (Debian) Server at stag-blogs.devcentrehouse.eu Port 80</address>
</body></html>

what kind of permission is needed? as i allowed inbound rules too and gave permission too.
I didnt try DNS challenge as i only use http challenge.
im using the default apache2.conf file

# configuration directives that give the server its instructions.
# See http://httpd.apache.org/docs/2.4/ for detailed information about
# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
# hints.
#
#
# Summary of how the Apache 2 configuration works in Debian:
# The Apache 2 web server configuration in Debian is quite different to
# upstream's suggested way to configure the web server. This is because Debian's
# default Apache2 installation attempts to make adding and removing modules,
# virtual hosts, and extra configuration directives as flexible as possible, in
# order to make automating the changes and administering the server as easy as
# possible.

# It is split into several files forming the configuration hierarchy outlined
# below, all located in the /etc/apache2/ directory:
#
#       /etc/apache2/
#       |-- apache2.conf
#       |       `--  ports.conf
#       |-- mods-enabled
#       |       |-- *.load
#       |       `-- *.conf
#       |-- conf-enabled
#       |       `-- *.conf
#       `-- sites-enabled
#               `-- *.conf
#
#
# * apache2.conf is the main configuration file (this file). It puts the pieces
#   together by including all remaining configuration files when starting up the
#   web server.
#
# * ports.conf is always included from the main configuration file. It is
#   supposed to determine listening ports for incoming connections which can be
#   customized anytime.
#
# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
#   directories contain particular configuration snippets which manage modules,
#   global configuration fragments, or virtual host configurations,
#   respectively.
#
#   They are activated by symlinking available configuration files from their
#   respective *-available/ counterparts. These should be managed by using our
#   helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
#   their respective man pages for detailed information.
#
# * The binary is called apache2. Due to the use of environment variables, in
#   the default configuration, apache2 needs to be started/stopped with
#   /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
#   work with the default configuration.


# Global configuration
#

#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# NOTE!  If you intend to place this on an NFS (or otherwise network)
# mounted filesystem then please read the Mutex documentation (available
# at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>);
# you will save yourself a lot of trouble.
#
# Do NOT add a slash at the end of the directory path.
#
#ServerRoot "/etc/apache2"

#
# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
#
#Mutex file:${APACHE_LOCK_DIR} default

#
# The directory where shm and other runtime files will be stored.
#

DefaultRuntimeDir ${APACHE_RUN_DIR}

#
# PidFile: The file in which the server should record its process
# identification number when it starts.
# This needs to be set in /etc/apache2/envvars
#
PidFile ${APACHE_PID_FILE}

#
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 300

#
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive On

#
# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We recommend you leave this number high, for maximum performance.
#
MaxKeepAliveRequests 100

#
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 5


# These need to be set in /etc/apache2/envvars
User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}

#
# HostnameLookups: Log the names of clients or just their IP addresses
# e.g., www.apache.org (on) or 204.62.129.132 (off).
# The default is off because it'd be overall better for the net if people
# had to knowingly turn this feature on, since enabling it means that
# each client request will result in AT LEAST one lookup request to the
# nameserver.
#
HostnameLookups Off

# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here.  If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog ${APACHE_LOG_DIR}/error.log

#
# LogLevel: Control the severity of messages logged to the error_log.
# Available values: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the log level for particular modules, e.g.
# "LogLevel info ssl:warn"
#
LogLevel warn

# Include module configuration:
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf

# Include list of ports to listen on
Include ports.conf


# Sets the default security model of the Apache2 HTTPD server. It does
# not allow access to the root filesystem outside of /usr/share and /var/www.
# The former is used by web applications packaged in Debian,
# the latter may be used for local directories served by the web server. If
# your system is serving content from a sub-directory in /srv you must allow
# access here, or in any related virtual host.
<Directory />
        Options FollowSymLinks
        AllowOverride None
        Require all denied
</Directory>

<Directory /usr/share>
        AllowOverride None
        Require all granted
</Directory>

<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

#<Directory /srv/>
#       Options Indexes FollowSymLinks
#       AllowOverride None
#       Require all granted
#</Directory>




# AccessFileName: The name of the file to look for in each directory
# for additional configuration directives.  See also the AllowOverride
# directive.
#
AccessFileName .htaccess

#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<FilesMatch "^\.ht">
        Require all denied
</FilesMatch>


#
# The following directives define some format nicknames for use with
# a CustomLog directive.
#
# These deviate from the Common Log Format definitions in that they use %O
# (the actual bytes sent including headers) instead of %b (the size of the
# requested file), because the latter makes it impossible to detect partial
# requests.
#
# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.
# Use mod_remoteip instead.
#
LogFormat "%v:%p %a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%a %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent

# Include of directories ignores editors' and dpkg's backup files,
# see README.Debian for details.

# Include generic snippets of statements
IncludeOptional conf-enabled/*.conf

# Include the virtual host configurations:
IncludeOptional sites-enabled/*.conf
ServerName stag-blogs.devcentrehouse.eu

only added ServerName at the bottom of configuration

I'd start by updating the client:

1 Like

But why would you use an ELB if you don't plan on having more instances? Getting a cert working with multiple instances will need a different solution.

Yes, but why have you chosen to do it this way? Seems unnecessarily difficult.

Your Apache system is rejecting HTTP Challenge requests with that. You need to find where in your config you do that. Perhaps there is something which denies any URI that has a period at the start.

You need to look at all the conf files you include from the base Apache conf file you showed. This command shows the overall VirtualHost setup

sudo apache2ctl -t -D DUMP_VHOSTS

You said you only added the one ServerName to the Apache conf. Have you created your VirtualHost config too?

4 Likes

sure will update this

Currently im testing behind the ELB, i have planned to attach EFS for every instance to mount the volume,
i did only added default.conf to /etc/apache2/sites-available/000-default.conf for VHOSTS.
sudo apache2ctl -t -D DUMP_VHOSTS from this i got only config from

*:80                   stag-blogs.devcentrehouse.eu (/etc/apache2/sites-enabled/000-default.conf:1)

Would you show contents of that file?

Somewhere you treat the ACME Challenge differently. We'll try to find that.

curl -I http://stag-blogs.devcentrehouse.eu/Test404
HTTP/1.1 404 Not Found
Server: Apache/2.4.61 (Debian)
X-Powered-By: PHP/8.2.21

curl -I http://stag-blogs.devcentrehouse.eu/.well-test/Test404
HTTP/1.1 404 Not Found
Server: Apache/2.4.61 (Debian)
X-Powered-By: PHP/8.2.21

# Your first post showed a 404 but this test shows a 403
curl -i http://stag-blogs.devcentrehouse.eu/.well-known/acme-challenge/Test404
HTTP/1.1 403 Forbidden
Server: Apache/2.4.61 (Debian)
2 Likes

yes the same content that i shared previously,

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName stag-blogs.devcentrehouse.eu
    DocumentRoot /var/www/html

    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    # Serve the challenge files from the .well-known directory
    Alias /.well-known/acme-challenge/ /var/www/html/.well-known/acme-challenge/
    <Directory "/var/www/html/.well-known/acme-challenge/">
        Options None
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # Redirect HTTP to HTTPS
    RewriteEngine on
    RewriteCond %{HTTPS} !=on
    RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/
    RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]
</VirtualHost>

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    ServerName stag-blogs.devcentrehouse.eu
    DocumentRoot /var/www/html

    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/stag-blogs.devcentrehouse.eu/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/stag-blogs.devcentrehouse.eu/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

Currently commented redirection to https and vhost:443 config as it throws an error

Yes, well, it is not exactly like that then :slight_smile:

You had to comment out the port 443 VHost because it refers to cert files that don't exist yet. And, of course not redirect people to a URL that isn't working.

We cross-posted. Please see the update to my post just before yours. I don't see why your system would throw the 403 given what you show. Something else must be happening.

Is there a .htaccess file involved at all?

2 Likes

yes currently its commented the commented code is

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName stag-blogs.devcentrehouse.eu
    DocumentRoot /var/www/html

    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    # Serve the challenge files from the .well-known directory
    Alias /.well-known/acme-challenge/ /var/www/html/.well-known/acme-challenge/
    <Directory "/var/www/html/.well-known/acme-challenge/">
        Options None
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # Redirect HTTP to HTTPS
    # RewriteEngine on
    # RewriteCond %{HTTPS} !=on
    # RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/
    # RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]
</VirtualHost>

# <VirtualHost *:443>
#     ServerAdmin webmaster@localhost
#     ServerName stag-blogs.devcentrehouse.eu
#     DocumentRoot /var/www/html

#     <Directory /var/www/html>
#         Options Indexes FollowSymLinks
#         AllowOverride All
#         Require all granted
#     </Directory>

#     ErrorLog ${APACHE_LOG_DIR}/error.log
#     CustomLog ${APACHE_LOG_DIR}/access.log combined

#     SSLEngine on
#     SSLCertificateFile /etc/letsencrypt/live/stag-blogs.devcentrehouse.eu/fullchain.pem
#     SSLCertificateKeyFile /etc/letsencrypt/live/stag-blogs.devcentrehouse.eu/privkey.pem
#     Include /etc/letsencrypt/options-ssl-apache.conf
# </VirtualHost>

and i also checked for .htaccess but couldnt found anywhere

I don't think that Apache system is the one handling requests from your ELB

Why?

Because in my previous post you will see two requests for 'Test404' were replied to by a PHP based system with a 404. But, there is no PHP config in what you show

Oddly, the test to the ACME Challenge path did not show PHP involved and got a 403.

Do you have rules in your ELB directing to multiple apache systems?

2 Likes

is this becaue i have defined url in wp-config.php ?

<?php
/**
 * The base configuration for WordPress
 *
 * The wp-config.php creation script uses this file during the installation.
 * You don't have to use the website, you can copy this file to "wp-config.php"
 * and fill in the values.
 *
 * This file contains the following configurations:
 *
 * * Database settings
 * * Secret keys
 * * Database table prefix
 * * ABSPATH
 *
 * @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/
 *
 * @package WordPress
 */

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', getenv('WORDPRESS_DB_NAME'));

/** Database username */
define('DB_USER', getenv('WORDPRESS_DB_USER'));

/** Database password */
define('DB_PASSWORD', getenv('WORDPRESS_DB_PASSWORD'));

/** Database hostname */
define('DB_HOST', getenv('WORDPRESS_DB_HOST'));

/** Database charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The database collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

/**#@+
 * Authentication unique keys and salts.
 *
 * Change these to different unique phrases! You can generate these using
 * the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
 *
 * You can change these at any point in time to invalidate all existing cookies.
 * This will force all users to have to log in again.
 *
 * @since 2.6.0
 */
define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
define( 'NONCE_KEY',        'put your unique phrase here' );
define( 'AUTH_SALT',        'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
define( 'NONCE_SALT',       'put your unique phrase here' );

/**#@-*/

/**
 * WordPress database table prefix.
 *
 * You can have multiple installations in one database if you give each
 * a unique prefix. Only numbers, letters, and underscores please!
 */
$table_prefix = 'wp_';

/**
 * For developers: WordPress debugging mode.
 *
 * Change this to true to enable the display of notices during development.
 * It is strongly recommended that plugin and theme developers use WP_DEBUG
 * in their development environments.
 *
 * For information on other constants that can be used for debugging,
 * visit the documentation.
 *
 * @link https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/
 */
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
@ini_set('display_errors', 1);

/* Add any custom values between this line and the "stop editing" line. */

define('WP_HOME', 'http://stag-blogs.devcentrehouse.eu');
define('WP_SITEURL', 'http://stag-blogs.devcentrehouse.eu');

/* That's all, stop editing! Happy publishing. */

/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
        define( 'ABSPATH', __DIR__ . '/' );
}

/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';

and in my elb rule there is only one HTTP 80 listener attached to forward to target group which is my container

Configuring and managing an ELB and PHP is beyond the scope of what we normally help with.

You can readily test your HTTP flows the same way I did. You can place test files in the acme-challenge folder and try to retrieve them from the public internet. Once you get that working try an actual cert request.

I still think you would do well to investigate using AWS ACM. You are relying heavily on AWS infrastructure anyway.

Don't forget about the option to use a DNS Challenge too. Your DNS provider (Cloudflare) is well-supported by Certbot and other ACME Clients for such a challenge.

3 Likes

okay sure
thank you for the suggestions will check these.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.