Let's Encrypt SSL Fails When "SSL Access" is Set to nologin

Hey Hestia team :waving_hand:

I’m facing an issue with Let’s Encrypt SSL generation for domains added by users in HestiaCP. When the user account is created with SSH Access set to “nologin”, the SSL request fails during validation.

Here’s an example error message:

Error: Let's Encrypt validation status 400 (example.com). Details: 403: "The key authorization file from the server did not match this challenge. Expected '-9VMPS7x6XalNcju8MSTAUnFEpUYaBgZ2WfFH-f4M-E.-1UZiii0Rs4OX2HGAGh3n-uNNDP9l649xYlsWGe0xoM' (got '-9VMPS7x6XalNcju8MSTAUnFEpUYaBgZ2WfFH-f4M-E.l5d0jEjDptQwdtd1Egh7y4zQdDUZDeUuuAK2QL1gWpM')"

When I change the user’s SSH Access to bash, the issue disappears and SSL is issued successfully.

As far as I understand, the “nologin” option in the panel maps to /usr/sbin/nologin under the hood, which might be interfering with some parts of the Let’s Encrypt process (e.g., file access or challenge validation).

Questions:

  1. Is this expected behavior when “SSH Access” is set to nologin?
  2. Why does Let’s Encrypt fail in this mode, even though the user shouldn’t need interactive shell access?
  3. Is there a safer or recommended way to allow SSL issuance without giving users full shell access?

Thanks in advance for any guidance :folded_hands:

Best regards,

Hey, just wanted to add a quick note:

As far as we remember, this wasn’t an issue in the past. We used to issue Let’s Encrypt certificates without any problems even when SSL Access was set to nologin. Both web and mail domains worked fine — no need to switch to bash.

Now it seems like something changed recently, either in HestiaCP or maybe in how Let’s Encrypt / acme.sh handles the validation. Of course, it’s also possible that we broke something on our end without realizing :sweat_smile:

Just wanted to check if anyone else has seen this behavior, or if there’s something we might be missing.

Thanks again for your time and support!

Do you mean the setting for SSH Access, perhaps? It should have no effect on obtaining Let’s Encrypt certificates.

For practical reasons I use different automations for my certificates, so you might wait to see if anyone else has seen what you are describing.

What have you found in the relevant system logs?

Hi again,

You’re absolutely right — I meant SSH, not SSL. Thanks for catching that! :folded_hands:

Also, as you know, Let’s Encrypt limits certificate issuance to 5 per domain per week, so I ran out of attempts while trying to debug the issue. That limited my ability to test further.


Here’s what I found in the logs:

/var/log/hestia/error.log

v-update-letsencrypt-ssl kazakhukuk.com Error: Let's Encrypt validation status 400 (mail.kazakhukuk.com).
Details: 403:"185.72.9.232: Invalid response from https://webmail.kazakhukuk.com/.well-known/acme-challenge/...: 404"

– Several domains failed due to validation issues. DNS records were properly set up, and propagation was confirmed externally.
– The ACME challenge path seems inaccessible during validation.

I’m now suspecting a permission or web root ownership issue, potentially related to nologin users.
Even when the web root exists, it seems the ACME challenge files are either not being created or not served properly.

If there are any known limitations or requirements when using Let’s Encrypt with nologin-type users in Hestia, I’d really appreciate any guidance :folded_hands:

Thanks again!

I can’t imagine how it could be related to SSH Access.

Could you please show the output of these commads (replace YourUser with the actual user)?

cat /home/YourUser/conf/mail/kazakhukuk.com/nginx.conf
cat /home/YourUser/conf/mail/kazakhukuk.com/nginx.conf_letsencrypt
ls -ld /home/YourUser/
namei -l /home/YourUser/conf/mail/kazakhukuk.com/nginx.conf
1 Like

root@admin:~# cat /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.conf

server {
        listen      185.72.9.232:80;
        server_name webmail.kazakhukuk.com mail.kazakhukuk.com;
        root        /var/lib/roundcube;
        index       index.php index.html index.htm;
        access_log  /var/log/nginx/domains/webmail.kazakhukuk.com.log combined;
        error_log   /var/log/nginx/domains/webmail.kazakhukuk.com.error.log error;

        include /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.forcessl.conf*;

        location ~ /\.(?!well-known\/) {
                deny all;
                return 404;
        }

        location ~ ^/(README.md|config|temp|logs|bin|SQL|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ {
                deny all;
                return 404;
        }

        location / {
                alias /var/lib/roundcube/;

                try_files $uri $uri/ =404;

                proxy_pass http://185.72.9.232:8080;

                location ~* ^.+\.(ogg|ogv|svg|svgz|swf|eot|otf|woff|woff2|mov|mp3|mp4|webm|flv|ttf|rss|atom|jpg|jpeg|gif|png|webp|ico|bmp|mid|midi|wav|rtf|css|js|jar)$ {
                        expires 7d;
                        fastcgi_hide_header "Set-Cookie";
                }
        }

        location @fallback {
                proxy_pass http://185.72.9.232:8080;
        }

        location /error/ {
                alias /var/www/document_errors/;
        }

        include /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.conf_*;
}

root@admin:~# cat /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.conf_letsencrypt

location ~ "^/\.well-known/acme-challenge/([-_A-Za-z0-9]+)$" {
    default_type text/plain;
    return 200 "$1.l5d0jEjDptQwdtd1Egh7y4zQdDUZDeUuuAK2QL1gWpM";
}

root@admin:~# ls -ld /home/hadsizefendi/
drwxr-x--x+ 16 root root 4096 Apr 7 17:51 /home/hadsizefendi/

root@admin:~# namei -l /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.conf

f: /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.conf
drwxr-xr-x root        root         /
drwxr-xr-x root        root         home
drwxr-x--x root        root         hadsizefendi
drwxr-xr-x root        root         conf
drwxr-x--x root        root         mail
drwxrwx--x Debian-exim mail         kazakhukuk.com
-rw-r----- root        hadsizefendi nginx.conf

All looks fine, check nginx conf:

nginx -t

If no errors:

systemctl reload nginx 
systemctl status nginx --no-pager -l

Once done, I’ll try to check the acme-challenge if that doesn’t work, we’ll restart the service but first I want to check whether a reload works.

1 Like

The user hadsizefendi has SSH Access set to bash, as you requested above.

However, the information I shared earlier was for the burak user, whose SSH Access is set to nologin.

root@admin:~# cat /home/burak/conf/mail/theuigame.com/nginx.conf


server {
        listen      185.72.9.232:80;
        server_name webmail.theuigame.com mail.theuigame.com;
        root        /var/lib/roundcube;
        index       index.php index.html index.htm;
        access_log  /var/log/nginx/domains/webmail.theuigame.com.log combined;
        error_log   /var/log/nginx/domains/webmail.theuigame.com.error.log error;

        include /home/burak/conf/mail/theuigame.com/nginx.forcessl.conf*;

        location ~ /\.(?!well-known\/) {
                deny all;
                return 404;
        }

        location ~ ^/(README.md|config|temp|logs|bin|SQL|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ {
                deny all;
                return 404;
        }

        location / {
                alias /var/lib/roundcube/;

                try_files $uri $uri/ =404;

                proxy_pass http://185.72.9.232:8080;

                location ~* ^.+\.(ogg|ogv|svg|svgz|swf|eot|otf|woff|woff2|mov|mp3|mp4|webm|flv|ttf|rss|atom|jpg|jpeg|gif|png|webp|ico|bmp|mid|midi|wav|rtf|css|js|jar)$ {
                        expires 7d;
                        fastcgi_hide_header "Set-Cookie";
                }
        }

        location @fallback {
                proxy_pass http://185.72.9.232:8080;
        }

        location /error/ {
                alias /var/www/document_errors/;
        }

        include /home/burak/conf/mail/theuigame.com/nginx.conf_*;
}

root@admin:~# cat /home/burak/conf/mail/theuigame.com/nginx.conf_letsencrypt


location ~ "^/\.well-known/acme-challenge/([-_A-Za-z0-9]+)$" {
    default_type text/plain;
    return 200 "$1.SOEv7pUZvPT82XAN9McHHSPlZawT_DHtRi1KHhGRkzU";
}

root@admin:~# ls -ld /home/burak/

drwxr-x--x+ 15 root root 4096 Apr 7 17:33 /home/burak/

root@admin:~# namei -l /home/burak/conf/mail/theuigame.com/nginx.conf

f: /home/burak/conf/mail/theuigame.com/nginx.conf
drwxr-xr-x root        root  /
drwxr-xr-x root        root  home
drwxr-x--x root        root  burak
drwxr-xr-x root        root  conf
drwxr-x--x root        root  mail
drwxrwx--x Debian-exim mail  theuigame.com
-rw-r----- root        burak nginx.conf

root@admin:~# nginx -t

nginx: [warn] conflicting server name "abcbul.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.abcbul.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "ai.emanet.in" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "ai.upcreate.art" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "baski360.net" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.baski360.net" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "baystonglobal.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.baystonglobal.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "bomontidijital.com.tr" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.bomontidijital.com.tr" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "carvente.be" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.carvente.be" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "emcandle.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.emcandle.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "koc-de.emanet.in" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "metamente.net" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.metamente.net" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "plan.emanet.in" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "qr.emanet.in" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "quattrovisual.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.quattrovisual.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "rnconstruction.bzh" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.rnconstruction.bzh" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "shop.emanet.in" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "stock.bomontidijital.com.tr" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.stock.bomontidijital.com.tr" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "stock.emanet.in" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "temizmir.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.temizmir.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "upcreate.art" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.upcreate.art" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "upweb.emanet.in" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "mail.hadsizefendi.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "mail.upcreate.art" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "webstree.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "www.webstree.com" on 185.72.9.232:80, ignored
nginx: [warn] conflicting server name "mail.hadsizefendi.com" on 185.72.9.232:443, ignored
nginx: [warn] conflicting server name "mail.upcreate.art" on 185.72.9.232:443, ignored
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

root@admin:~# systemctl reload nginx

root@admin:~# systemctl status nginx --no-pager -l

● nginx.service - nginx - high performance web server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Tue 2025-05-27 16:30:14 +03; 2 days ago
       Docs: https://nginx.org/en/docs/
    Process: 1140078 ExecReload=/bin/sh -c /bin/kill -s HUP $(/bin/cat /run/nginx.pid) (code=exited, status=0/SUCCESS)
   Main PID: 898543 (nginx)
      Tasks: 8 (limit: 9435)
     Memory: 221.2M (peak: 402.1M swap: 24.3M swap peak: 38.0M)
        CPU: 7min 29.008s
     CGroup: /system.slice/nginx.service
             ├─898543 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
             ├─898544 "nginx: worker process"
             ├─898545 "nginx: worker process"
             ├─898546 "nginx: worker process"
             ├─898547 "nginx: worker process"
             ├─898548 "nginx: worker process"
             ├─898549 "nginx: worker process"
             └─898550 "nginx: cache manager process"

May 30 01:14:34 admin.upcreate.art systemd[1]: Reloading nginx.service - nginx - high performance web server...
May 30 01:14:34 admin.upcreate.art systemd[1]: Reloaded nginx.service - nginx - high performance web server.
May 30 01:14:36 admin.upcreate.art systemd[1]: Reloading nginx.service - nginx - high performance web server...
May 30 01:14:36 admin.upcreate.art systemd[1]: Reloaded nginx.service - nginx - high performance web server.
May 30 01:22:29 admin.upcreate.art systemd[1]: Reloading nginx.service - nginx - high performance web server...
May 30 01:22:29 admin.upcreate.art systemd[1]: Reloaded nginx.service - nginx - high performance web server.
May 30 01:22:31 admin.upcreate.art systemd[1]: Reloading nginx.service - nginx - high performance web server...
May 30 01:22:31 admin.upcreate.art systemd[1]: Reloaded nginx.service - nginx - high performance web server.
May 30 01:22:46 admin.upcreate.art systemd[1]: Reloading nginx.service - nginx - high performance web server...
May 30 01:22:46 admin.upcreate.art systemd[1]: Reloaded nginx.service - nginx - high performance web server.

:warning: However, most of the domains listed in the nginx -t output are Node.js projects, not traditional mail or PHP sites.

None of them work. Please, show the output of the nginx commands I posted above.

Also, show the output of these commands too:

cat /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.ssl.conf
cat /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.ssl.conf_letsencrypt

root@admin:~# cat /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.ssl.conf

server {
        listen      185.72.9.232:443 ssl;
        server_name webmail.kazakhukuk.com mail.kazakhukuk.com;
        root        /var/lib/roundcube;
        index       index.php index.html index.htm;
        access_log  /var/log/nginx/domains/webmail.kazakhukuk.com.log combined;
        error_log   /var/log/nginx/domains/webmail.kazakhukuk.com.error.log error;

        ssl_certificate     /home/hadsizefendi/conf/mail/kazakhukuk.com/ssl/kazakhukuk.com.pem;
        ssl_certificate_key /home/hadsizefendi/conf/mail/kazakhukuk.com/ssl/kazakhukuk.com.key;
        #Commented out ssl_stapling directives due to Lets Encrypt ending OCSP support in 2025
        #ssl_stapling        on;
        #ssl_stapling_verify on;

        # TLS 1.3 0-RTT anti-replay
        if ($anti_replay = 307) { return 307 https://$host$request_uri; }
        if ($anti_replay = 425) { return 425; }

        location ~ /\.(?!well-known\/) {
                deny all;
                return 404;
        }

        location ~ ^/(README.md|config|temp|logs|bin|SQL|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ {
                deny all;
                return 404;
        }

        location / {
                alias /var/lib/roundcube/;

                try_files $uri $uri/ =404;

                proxy_pass https://185.72.9.232:8443;

                location ~* ^.+\.(ogg|ogv|svg|svgz|swf|eot|otf|woff|woff2|mov|mp3|mp4|webm|flv|ttf|rss|atom|jpg|jpeg|gif|png|webp|ico|bmp|mid|midi|wav|rtf|css|js|jar)$ {
                        expires 7d;
                        fastcgi_hide_header "Set-Cookie";
                }
        }

        location @fallback {
                proxy_pass https://185.72.9.232:8443;
        }

        location /error/ {
                alias /var/www/document_errors/;
        }

        proxy_hide_header Upgrade;

        include /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.ssl.conf_*;
}

root@admin:~# cat /home/hadsizefendi/conf/mail/kazakhukuk.com/nginx.ssl.conf_letsencrypt


location ~ "^/\.well-known/acme-challenge/([-_A-Za-z0-9]+)$" {
    default_type text/plain;
    return 200 "$1.l5d0jEjDptQwdtd1Egh7y4zQdDUZDeUuuAK2QL1gWpM";
}

You have duplicated server names in your conf and nginx is ignoring the duplicated ones, so seems it is taking precedence another conf.
Anyway, in that output I can’t see warnings about mail.kazakhukuk.com

Please, restart nginx:

systemctl restart nginx
systemctl status nginx --no-pager -l

root@admin:~# systemctl restart nginx
root@admin:~# systemctl status nginx --no-pager -l


● nginx.service - nginx - high performance web server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Fri 2025-05-30 01:37:55 +03; 4s ago
       Docs: https://nginx.org/en/docs/
    Process: 1150868 ExecStart=/usr/sbin/nginx -c ${CONFFILE} (code=exited, status=0/SUCCESS)
   Main PID: 1150870 (nginx)
      Tasks: 9 (limit: 9435)
     Memory: 46.1M (peak: 46.6M)
        CPU: 272ms
     CGroup: /system.slice/nginx.service
             ├─1150870 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
             ├─1150871 "nginx: worker process"
             ├─1150872 "nginx: worker process"
             ├─1150873 "nginx: worker process"
             ├─1150875 "nginx: worker process"
             ├─1150876 "nginx: worker process"
             ├─1150877 "nginx: worker process"
             ├─1150878 "nginx: cache manager process"
             └─1150879 "nginx: cache loader process"

May 30 01:37:55 admin.upcreate.art nginx[1150868]: nginx: [warn] conflicting server name "upcreate.art" on 185.72.9.232:80, ignored
May 30 01:37:55 admin.upcreate.art nginx[1150868]: nginx: [warn] conflicting server name "www.upcreate.art" on 185.72.9.232:80, ignored
May 30 01:37:55 admin.upcreate.art nginx[1150868]: nginx: [warn] conflicting server name "upweb.emanet.in" on 185.72.9.232:80, ignored
May 30 01:37:55 admin.upcreate.art nginx[1150868]: nginx: [warn] conflicting server name "mail.hadsizefendi.com" on 185.72.9.232:80, ignored
May 30 01:37:55 admin.upcreate.art nginx[1150868]: nginx: [warn] conflicting server name "mail.upcreate.art" on 185.72.9.232:80, ignored
May 30 01:37:55 admin.upcreate.art nginx[1150868]: nginx: [warn] conflicting server name "webstree.com" on 185.72.9.232:80, ignored
May 30 01:37:55 admin.upcreate.art nginx[1150868]: nginx: [warn] conflicting server name "www.webstree.com" on 185.72.9.232:80, ignored
May 30 01:37:55 admin.upcreate.art nginx[1150868]: nginx: [warn] conflicting server name "mail.hadsizefendi.com" on 185.72.9.232:443, ignored
May 30 01:37:55 admin.upcreate.art nginx[1150868]: nginx: [warn] conflicting server name "mail.upcreate.art" on 185.72.9.232:443, ignored
May 30 01:37:55 admin.upcreate.art systemd[1]: Started nginx.service - nginx - high performance web server.

Ok, now it works, so the problem is nginx is not reloading correctly and needs a restart.

Run this script to check the number of open files, looks like you will need to raise the limits for nginx. Anyway, if you run the script now, it couldn’t have the same issue because you just restarted nginx.

curl -fsSLm15 https://7j.gg/chknof | sudo bash -s --

root@admin:~# curl -fsSLm15 https://7j.gg/chknof | sudo bash -s –
color yellow

Checking services nginx apache2
The open files limit threshold has been set at 80%

Process 1154664 :: /usr/sbin/apache2 -k start
Current open files:   711
Limit for open files: 8192

Process 1154706 :: /usr/sbin/apache2 -k start
Current open files:   709
Limit for open files: 8192

Process 1154724 :: /usr/sbin/apache2 -k start
Current open files:   718
Limit for open files: 8192

Process 1154725 :: /usr/sbin/apache2 -k start
Current open files:   718
Limit for open files: 8192

Process 1154798 :: nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
Current open files:   533
Limit for open files: 1024

Process 1154799 :: nginx: worker process
Current open files:   535
Limit for open files: 65535

Process 1154800 :: nginx: worker process
Current open files:   533
Limit for open files: 65535

Process 1154801 :: nginx: worker process
Current open files:   533
Limit for open files: 65535

Process 1154802 :: nginx: worker process
Current open files:   533
Limit for open files: 65535

Process 1154803 :: nginx: worker process
Current open files:   533
Limit for open files: 65535

Process 1154804 :: nginx: worker process
Current open files:   533
Limit for open files: 65535

Process 1154805 :: nginx: cache manager process
Current open files:   530
Limit for open files: 65535

Now it’s fine but could reach the limit easily, raise the open files limits for nginx, 1024 is too low.

mkdir -p /etc/systemd/system/nginx.service.d/
echo -e "[Service]\nLimitNOFILE=65535" > /etc/systemd/system/nginx.service.d/override.conf
systemctl daemon-reload
systemctl restart nginx
1 Like

Thanks a lot, sahsanu!

I’ve applied the override with LimitNOFILE=65535 as you suggested, and it’s now properly set for the master process too. Appreciate your help and the script you provided earlier!

By the way, just out of curiosity — do you know why the default open file limit for nginx master process is still set so low (1024) on most distros, even though modern web servers often need much higher limits?

1 Like

You’re welcome :wink:

I’m not sure, but nowadays, 1024 is too low.

1 Like