Certbot Failed Redirect Loop Detected on Frappe Press

I face some issues when use Frappe Press,
The function custom domain. For example i have a site rtg.mbwcloud.com, and i want to set a custom domain to these site. after add a CName records to rtg.mbwcloud.com and verify DNS

I check the system ran this command: certbot certonly --webroot --webroot-path /mbwcloud/presscmc/.certbot/webroot/ --logs-dir /mbwcloud/presscmc/.certbot/logs --work-dir /mbwcloud/presscmc/.certbot --config-dir /mbwcloud/presscmc/.certbot --force-renewal --agree-tos --eff-email --email nghienbt@mbw.vn --staple-ocsp --key-type rsa --rsa-key-size 2048 --cert-name rtg.mbw.vn --domains rtg.mbw.vn

It produced this output:

i try erprtg.mbwcloud.com same domain as primary site rtg.mbwcloud.com with this function and its success. but can't try with others domain.

My web server is (include version): nginx

The operating system my web server runs on is (include version): ubuntu

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

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.8.0
This is my proxy.conf

map $host $subdomain_map {
    ~^(?<subdomain>[^.]*).*$ $subdomain.mbwcloud.com;
}


upstream 537dd53c4d63cc0b {
	server 192.168.0.7:80;
	keepalive 100;
}


upstream site_not_found {
	server 127.0.0.1:10090;
	keepalive 100;
}

upstream deactivated {
	server 127.0.0.1:10091;
	keepalive 100;
}

upstream suspended {
	server 127.0.0.1:10092;
	keepalive 100;
}

upstream suspended_saas {
	server 127.0.0.1:10093;
	keepalive 100;
}

map $actual_host $upstream_server_hash {
rtg.mbwcloud.com http://537dd53c4d63cc0b;
map $host $actual_host {

	
	erprtg.mbwcloud.com rtg.mbwcloud.com;
	
	
	
	default $host;
	
	
}

map $upstream_http_access_control_allow_origin $access_control_allow_origin {
	default $upstream_http_access_control_allow_origin;
	"" "https://$host";
}

map $upstream_http_access_control_allow_headers $access_control_allow_headers {
	default $upstream_http_access_control_allow_headers;
	"" "'Origin, Content-Type, Accept";
}

map $upstream_http_access_control_allow_credentials $access_control_allow_credentials {
	default $upstream_http_access_control_allow_credentials;
	"" "true";
}

map $upstream_http_access_control_allow_methods $access_control_allow_methods {
	default $upstream_http_access_control_allow_methods;
	"" "'GET, POST, OPTIONS";
}

proxy_cache_path /tmp/cache keys_zone=proxy_cache_zone:10m loader_threshold=300 loader_files=200 max_size=200m;





server {
	listen 443 http2 ssl;
	server_name erprtg.mbwcloud.com;
			
	ssl_certificate /home/frappe/agent/nginx/hosts/*.mbwcloud.com/fullchain.pem;
	ssl_certificate_key /home/frappe/agent/nginx/hosts/*.mbwcloud.com/privkey.pem;
	ssl_trusted_certificate /home/frappe/agent/nginx/hosts/*.mbwcloud.com/chain.pem;

	ssl_session_timeout 1d;
	ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
	ssl_session_tickets off;

	ssl_protocols TLSv1.2 TLSv1.3;
	ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
	ssl_prefer_server_ciphers off;

	ssl_stapling on;
	ssl_stapling_verify on;

	resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
	resolver_timeout 2s;

	client_max_body_size 250M;
	client_body_buffer_size 16K;
	client_header_buffer_size 1k;

	more_set_headers "X-Frame-Options: SAMEORIGIN";
	more_set_headers "X-XSS-Protection: 1; mode=block";
	more_set_headers "X-Content-Type-Options: nosniff";
	more_set_headers "Referrer-Policy: no-referrer-when-downgrade";
	more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains; preload";

	
	location /assets/ {
		proxy_http_version 1.1;

		proxy_cache proxy_cache_zone;
		proxy_cache_key $scheme$host$request_uri;
		proxy_cache_valid 200 302 2m;
		proxy_cache_valid 404 1m;
		proxy_cache_bypass $http_secret_cache_purge;

		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header Connection "";

		more_set_headers "X-Proxy-Upstream: $upstream_server_hash";
		more_set_headers "X-Proxy-Cache: $upstream_cache_status";

		proxy_pass $upstream_server_hash;
	}

	location /socket.io {
		proxy_http_version 1.1;

		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header Connection "upgrade";

		more_set_headers "X-Proxy-Upstream: $upstream_server_hash";

		proxy_pass $upstream_server_hash;
	}

	location / {
		proxy_http_version 1.1;

		proxy_read_timeout 600;
		proxy_buffering off;
		proxy_buffer_size 128k;
		proxy_buffers 100 128k;

		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header X-Forwarded-Proto $scheme;
		
		proxy_set_header Connection "";
		

		more_set_headers "X-Proxy-Upstream: $upstream_server_hash";

		more_set_headers "Access-Control-Allow-Origin: $access_control_allow_origin";
		more_set_headers "Access-Control-Allow-Headers: $access_control_allow_headers";
		more_set_headers "Access-Control-Allow-Credentials: $access_control_allow_credentials";
		more_set_headers "Access-Control-Allow-Methods: $access_control_allow_methods";

		proxy_pass $upstream_server_hash;
	}

	proxy_intercept_errors on;
	error_page 429 /exceeded.html;
	location /exceeded.html {
		root /home/frappe/agent/repo/agent/pages;
		internal;
	}
	
}


server {
	listen 443 http2 ssl default_server;
##them ipv6
	listen [::]:443 http2 ssl default_server;
	server_name *.mbwcloud.com;
			
	ssl_certificate /home/frappe/agent/nginx/hosts/*.mbwcloud.com/fullchain.pem;
	ssl_certificate_key /home/frappe/agent/nginx/hosts/*.mbwcloud.com/privkey.pem;
	ssl_trusted_certificate /home/frappe/agent/nginx/hosts/*.mbwcloud.com/chain.pem;

	ssl_session_timeout 1d;
	ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
	ssl_session_tickets off;

	ssl_protocols TLSv1.2 TLSv1.3;
	ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
	ssl_prefer_server_ciphers off;

	ssl_stapling on;
	ssl_stapling_verify on;

	resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
	resolver_timeout 2s;

	client_max_body_size 250M;
	client_body_buffer_size 16K;
	client_header_buffer_size 1k;

	more_set_headers "X-Frame-Options: SAMEORIGIN";
	more_set_headers "X-XSS-Protection: 1; mode=block";
	more_set_headers "X-Content-Type-Options: nosniff";
	more_set_headers "Referrer-Policy: no-referrer-when-downgrade";
	more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains; preload";

	
	location /assets/ {
		proxy_http_version 1.1;

		proxy_cache proxy_cache_zone;
		proxy_cache_key $scheme$host$request_uri;
		proxy_cache_valid 200 302 2m;
		proxy_cache_valid 404 1m;
		proxy_cache_bypass $http_secret_cache_purge;

		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header Connection "";

		more_set_headers "X-Proxy-Upstream: $upstream_server_hash";
		more_set_headers "X-Proxy-Cache: $upstream_cache_status";

		proxy_pass $upstream_server_hash;
	}

	location /socket.io {
		proxy_http_version 1.1;

		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header Connection "upgrade";

		more_set_headers "X-Proxy-Upstream: $upstream_server_hash";

		proxy_pass $upstream_server_hash;
	}

	location / {
		proxy_http_version 1.1;

		proxy_read_timeout 600;
		proxy_buffering off;
		proxy_buffer_size 128k;
		proxy_buffers 100 128k;

		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header X-Forwarded-Proto $scheme;
		
		proxy_set_header Connection "";
		

		more_set_headers "X-Proxy-Upstream: $upstream_server_hash";

		more_set_headers "Access-Control-Allow-Origin: $access_control_allow_origin";
		more_set_headers "Access-Control-Allow-Headers: $access_control_allow_headers";
		more_set_headers "Access-Control-Allow-Credentials: $access_control_allow_credentials";
		more_set_headers "Access-Control-Allow-Methods: $access_control_allow_methods";

		proxy_pass $upstream_server_hash;
	}

	proxy_intercept_errors on;
	error_page 429 /exceeded.html;
	location /exceeded.html {
		root /home/frappe/agent/repo/agent/pages;
		internal;
	}
	
}



server {
	listen 80;
	listen [::]:80;
	server_name _;

	location ^~ /.well-known/acme-challenge/ {
		return 301 http://ssl.mbwcloud.com$request_uri;
	}
	location / {
		return 301 https://$host$request_uri;
	}
}


server {
	listen 127.0.0.1:10090;
	location / {
		return 307 https://admin.mbwcloud.com/dashboard/#/sites/new?domain=$host;
	}
}

server {
	listen 127.0.0.1:10091;

	root /home/frappe/agent/repo/agent/pages;
	error_page 503 /deactivated.html;

	location / {
		return 503;
	}

	location = /deactivated.html {
		internal;
	}
}


server {
	listen 127.0.0.1:10092;

	root /home/frappe/agent/repo/agent/pages;
	error_page 402 /suspended.html;

	location / {
		return 402;
	}

	location = /suspended.html {
		internal;
	}
}


server {
	listen 127.0.0.1:10093;

	root /home/frappe/agent/repo/agent/pages;
	error_page 402 /suspended_saas.html;

	location / {
		return 402;
	}

	location = /suspended_saas.html {
		internal;
	}

}

Hi @aedudon, and welcome to the LE community forum :slight_smile:

The cert request is for "rtg.mbw.vn", but the HTTP vhost sends all the HTTP requests to "ssl.mbwcloud.com":

Is that expected?

2 Likes

thanks for your reply, this is opensource from Frappe, show after i setup the system, and check code. Them specify the code like this, i don't know how to config this correct.
image

1 Like

Edited to help clean up the topic.

Using the online tool Let's Debug to debug can be helpful.

Best Practice - Keep Port 80 Open

The HTTP-01 challenge of the Challenge Types - Let's Encrypt requires Port 80 accessible.
"The HTTP-01 challenge can only be done on port 80."

1 Like

I would add another HTTP vhost specifically just to handle the ACME challenge requests.

AFTER ensuring that HTTP [TCP port 80] is allowed in from the Internet.

2 Likes

image
i allow port 80 and run nmap again. how about next step?

And now https://letsdebug.net/rtg.mbw.vn/1896438 reports OK. :slight_smile:

1 Like

yeah, but now it's show.

Show i think problem is config file. Can u show me how to fix it's correctly

And

$ curl -Ii http://rtg.mbw.vn/.well-known/acme-challenge/sometestfile
HTTP/1.1 301 Moved Permanently
Date: Tue, 23 Apr 2024 02:47:51 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: http://ssl.mobiwork.vn/.well-known/acme-challenge/sometestfile
Server: Frappe Cloud

Redirecting http://rtg.mbw.vn/.well-known/acme-challenge/sometestfile to http://ssl.mobiwork.vn/.well-known/acme-challenge/sometestfile

$ curl -Ii http://ssl.mobiwork.vn/.well-known/acme-challenge/sometestfile
HTTP/1.1 200 OK
Date: Tue, 23 Apr 2024 02:48:04 GMT
Connection: keep-alive

I would not have expect HTTP/1.1 200 OK, unless you really have a file called sometestfile there.

Edited, FYI @aedudon

Error : No host match ssl.mobiwork.vn


curl -i http://ssl.mobiwork.vn/.well-known/acme-challenge/sometestfile
HTTP/1.1 200 OK
Date: Tue, 23 Apr 2024 03:10:08 GMT
Connection: keep-alive
Transfer-Encoding: chunked

Error : No host  match ssl.mobiwork.vn

Thanks to @MikeMcQ assistance and keen eyes. :slight_smile:

1 Like

i check but its show no host match at LetsEncryptStaging

@aedudon correct
See the last line here
image

Your server doesn't know about the domain name ssl.mobiwork.vn, it returns
Error : No host match ssl.mobiwork.vn
as show here:

$ curl -i http://ssl.mobiwork.vn/.well-known/acme-challenge/sometestfile
HTTP/1.1 200 OK
Date: Tue, 23 Apr 2024 19:45:35 GMT
Connection: keep-alive
Transfer-Encoding: chunked

Error : No host  match ssl.mobiwork.vn
1 Like

Since you stated

For general nginx information you might find nginx documentation and https://forum.nginx.org/ helpful.

However I do not know if

is or is not Nginx.

1 Like