Mobile app not able to access when using self-signed cert and via Cloudflare DNS

Checklist
I have read intro post: about-the-installation-issues-category/12
I have read the tutorials, help and searched for similar issues
I provide relevant information about my server (component names and versions, etc.)
I provide a copy of my logs and healthcheck
I describe the steps I have taken to trouble shoot the problem
I describe the steps on how to reproduce the issue

I have a DigitalOcean droplet which hosts an API endpoint to a website, and I want to add a password manager alongside it. I followed the installation process for Passbolt as described in passbolt dot com/hosting/install/ce/debian/debian.html. I only got to step 2 and got stuck. Im using Cloudflares origin certificate for my API and wanted to use the same certificated for Passbolt, but got the following error doing sudo nginx -t:

nginx: [emerg] cannot load certificate "/etc/ssl/certs/1680535322-my_key-key.key": PEM_read_bio_X509_AUX() failed (SSL: error:0480006C:PEM routines::no start line:Expecting: TRUSTED CERTIFICATE)
nginx: configuration file /etc/nginx/nginx.conf test failed

From googling I gathered that the cert has to look like:

-----BEGIN TRUSTED CERTIFICATE-----
...
-----END TRUSTED CERTIFICATE-----

, but I cannot find a process by which to add that text, and I am sure adding it manually is not it.
I get the same error even if I try to follow help dot passbolt dot com/configure/https/ce/debian/manual and generate their recommended certificates.

As per this question, I tried using ca-certificates and linking those instead of whatever Passbolts sudo dpkg-reconfigure passbolt-ce-server command does with the key/cert, but Im getting the same issue and am stuck.

Maybe my understanding of certificates is lacking. What am I doing wrong?

Thanks ahead!

Relevant nginx.conf files:

/etc/nginx/sites-available/nginx-passbolt.conf:

server {
  listen 800;
  listen [::]:800;
  # Managed by Passbolt
  # server_name
  client_body_buffer_size     100K;
  client_header_buffer_size   1K;
  client_max_body_size        5M;
  client_body_timeout   10;
  client_header_timeout 10;
  keepalive_timeout     5 5;
  send_timeout          10;
  root /usr/share/php/passbolt/webroot;
  index index.php;
  error_log /var/log/nginx/passbolt-error.log info;
  access_log /var/log/nginx/passbolt-access.log;
  include /etc/passbolt/nginx-ssl.conf;
  location / {
    try_files $uri $uri/ /index.php?$args;
  }
  location ~ \.php$ {
    try_files                $uri =404;
    include                  fastcgi_params;
    fastcgi_pass             unix:/run/php/__PHP_SOCK__;
    fastcgi_index            index.php;
    fastcgi_intercept_errors on;
    fastcgi_split_path_info  ^(.+\.php)(.+)$;
    fastcgi_param            SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param            SERVER_NAME $http_host;
    fastcgi_param PHP_VALUE  "upload_max_filesize=5M \n post_max_size=5M";
  }
}

/etc/passbolt/nginx-ssl.conf:

  listen [::]:4043 ssl http2;
  ssl_certificate /etc/ssl/certs/1680535322-losslessly-api_djkato_net-key.key;
  ssl_certificate_key /etc/ssl/private/1680535322-losslessly-api_djkato_net-crt.crt;
  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;

Hi @Djkato welcome to the forum!

It seems you have the crt and key locations reversed? You have the key file in the certs folder, etc.

Thanks for the tip @garrett! That was definitely my nginx issue and now it passes the nginx -t without issue. After many clean reinstalls and tinkering I finally got a working server and firefox extention. I did not expect there to be so many issues getting this working.
Right now I got stuck on installing the app in my phone.
I installed the certificate on my android and scanned the code, but I cannot get past the QR code scan.

j

QR Scan Android Log
14:31:05 There was an error during transfer update
javax.net.ssl.SSLPeerUnverifiedException: Hostname PROPERIP not verified:
    certificate: sha256/eYwDg2hH3NmlYLMR+Sva0Q/ooIV1aBTmhCyinapoQ4M=
    DN: CN=PROPERIP,O=Djkato,L=CITY,ST=STATE,C=COUNTRY
    subjectAltNames: [PROPERIP]
	at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:389)
	at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
	at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
	at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
	at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
	at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
	at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at com.passbolt.mobile.android.core.networking.interceptor.CookiesInterceptor$AddCookiesInterceptor.intercept(CookiesInterceptor.kt:57)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at com.passbolt.mobile.android.core.networking.interceptor.CookiesInterceptor$ReceivedCookiesInterceptor.intercept(CookiesInterceptor.kt:38)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at com.passbolt.mobile.android.core.networking.interceptor.AuthInterceptor.intercept(AuthInterceptor.kt:22)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at com.passbolt.mobile.android.core.networking.interceptor.ChangeableBaseUrlInterceptor.intercept(ChangeableBaseUrlInterceptor.kt:40)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
	at java.lang.Thread.run(Thread.java:1012)

Which would be fine, if there was a proper documentation on the manual import process, which I also cannot get past unfortunately. What is User ID*, Account URL* and Private Key*? User ID googled to be gettable from the browser url, but what url and what private key? Only url pointing to my website:port? Private key as in PGP I made during installation? With those assumptions it did not work either, log:

Manual transfer Android Log
14:43:08 There was an error during unlockKey
go.Universe$proxyerror: gopenpgp: key is not locked
	at com.proton.Gopenpgp.crypto.Key.unlock(Native Method)
	at com.passbolt.mobile.android.gopenpgp.OpenPgp$unlockKey$2.invokeSuspend(OpenPgp.kt:98)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)

go.Universe$proxyerror: gopenpgp: key is not locked
	at com.proton.Gopenpgp.crypto.Key.unlock(Native Method)
	at com.passbolt.mobile.android.gopenpgp.OpenPgp$unlockKey$2.invokeSuspend(OpenPgp.kt:98)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
14:43:08 gopenpgp: key is not locked

Appreciate the help, cheers <3

For manually importing your certificate into your device see here Passbolt Help | How to import SSL certificate on mobile application

For troubleshooting (if needed) any issues with the cert see here Passbolt Help | Troubleshoot SSL the first sections have links speaking to chain of trust issues (hopefully you will not have those, but just in case).

Sorry, not understanding this part. Can you clarify what you are referring to?

I did follow that guide when installing my certificate on phone.

Troubleshooting SSL:

As for the user id ,account url etc I mean this part of the app:

I have never personally seen that screen before. What are you clicking to get there?

Normally we start with the browser extension access, go to our user’s profile settings, and click on Mobile setup in the left menu.

From there, we are shown a QR code to start the process…

Yes, But when I attempt the QR code method it fails due to logs attached above.
I got to the manual account import screen like this:


ok sorry about that!

3 fields are:

  • email address for user
  • host url
  • private key for your user saved as the recovery kit

No worries, thanks for trying to help!
The first field I know is not the email address but the user UUID, which I got thanks to this forum post.
The second and third seem to match now!
Unfortunately I am now again getting the same issue as when trying to use the QR code despite having added the certificate that is served with my website, Logs:

Manual account import Android Log
javax.net.ssl.SSLPeerUnverifiedException: Hostname 164.90.xxx.xxx not verified:
    certificate: sha256/eYwDg2hH3NmlYLMR+Sva0Q/ooIV1aBTmhCyinapoQ4M=
    DN: CN=164.90.xxx.xxx,O=Djkato,L=XXX,ST=XXX,C=XX
    subjectAltNames: [164.90.XXX.XXX]
	at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:389)
	at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
	at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
	at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
	at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
	at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
	at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at com.passbolt.mobile.android.core.networking.interceptor.CookiesInterceptor$AddCookiesInterceptor.intercept(CookiesInterceptor.kt:57)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at com.passbolt.mobile.android.core.networking.interceptor.CookiesInterceptor$ReceivedCookiesInterceptor.intercept(CookiesInterceptor.kt:38)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at com.passbolt.mobile.android.core.networking.interceptor.AuthInterceptor.intercept(AuthInterceptor.kt:22)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at com.passbolt.mobile.android.core.networking.interceptor.ChangeableBaseUrlInterceptor.intercept(ChangeableBaseUrlInterceptor.kt:40)
	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
	at java.lang.Thread.run(Thread.java:1012)
15:41:01 Generic error occurred
15:41:51 App went background
15:41:51 Passphrase cache cleared

I think the short answer here is your cert is the problem. Passbolt’s requirements are very tight, and not all certs made by other vendors will work.

The SSL cert troubleshooter page will help confirm if the cert you are using has all the needed parts (sections). The screenshot you posted above from the SSL Checked is showing it’s not going to work as-is.

To create a cert of your own see Passbolt Help | Manual HTTPS configuration on Debian and Ubuntu with user provided certificates

I followed these steps exactly to generate my SSL keys though. Are the requirements so tight that not even following the guide will help?

openssl req -x509 \
-newkey rsa:4096 \
-days 640 \
-subj "/C=XX/ST=XX/L=XX/O=Djkato/CN=164.90.XXX.XXX/" \
-nodes \
-addext "subjectAltName = DNS:164.90.XXX.XXX" \
-keyout key.pem \
-out cert.pem

I used this command to generate it, then used dpkg-reconfigure passbolt-ce-server and pointed to the same IP and certificate/key, checked all the files if they are using the correct ports. I had to add the key to my PC firefox and Android phone. Both can access it through browser, just this app seems to have an issue.

What gives you the hint from the screenshot that it is not going to work? Maybe that will give me a lead.
Frustrating when I do not even know where to look for the issue anymore after 3 days of trying to make it work.

I cannot assign my IP to a DNS as it already is assigned to Cloudflare, which via DNS only proxies default 443 and 80 HTTP/HTTPS ports. Passbolt is another service for the same server. Without a domain Lets encrypt will not issue me a trusted certificate, so my only option is to use a self signed certificate.
If it is impossible to use self signed certificates, then why include an article on how to do it? The only issue both https://whatsmychaincert.com and https://www.sslshopper.com have is that it is self-signed.

I can understand you are frustrated and I’m certainly not wanting to be the cause of it. I’m assuming most of your questions are rhetorical, but I get it. The good news is that the setup works for almost everyone right away, and the majority of those who do have problems along the way are able to sort it out eventually.

At first you were saying you were using a Cloudflare signed certificate. This was why I was saying to create your own. I don’t think you ever mentioned you already did?

My thought is that you should first attempt to get passbolt going without Cloudflare in the mix. Then add Cloudflare. Is this possible to try?

Also, the more specific you are about what you were referring to, the better for understanding. For example you are saying I cannot assign my IP to a DNS as it already is assigned to Cloudflare and I am assuming you mean your public IP address? Are you not able to access your IP address directly?

I should also mention there is another user recently posting in the forum about not being able to access their passbolt via the app when they are relying on VPN. So maybe your issue is related in that you are routing through another provider first and not directly accessing your passbolt install.

1 Like

This reply was being written for multiple days. Final update and solution on the bottom.

My intention is not to dump my frustrations on you, just more so thinking aloud. Apologies if it came across that way.

Yes at the start I tried using a Cloudflare signed Origin certificate. That is because my API is using it to proxy through Cloudflares DNS via Origin Certificates. This certificate is still basically self signed, and Cloudflare does say that it only is valid between the Origin server and Cloudflare, not to the outside. So somewhere later I changed to a self signed one, forgot to mention that. Though right now I am trying again with the Cloudflare signed one, as it’s the easiest way to get a trusted certificate, since I am already routed through them.

Cloudflare Proxy allows many ports I just found out outside the standard 443 HTTPS and 80 HTTP, so it migth be possible to have two services on different ports. Though if I disable this proxy I loose my SSL certificate for my website which makes use of the API point.

I am, that is my work around to my whole DNS situation. The IP address leads directly to my server. Lets encrypt nor anyone provides certificates for IP addresses and I cannot use another domain with this IP, so Cloudflare self signed is the only way if I don’t want to install my own one on all devices(Which I wouldn’t even mind if it worked).

Somewhere during writing this reply I got stuck on ruining my DNS and or web server all together and now bopth my API and passbolt servers are down. I cannot access it neither through IP or DNS. I probably screwed up something drastic in my NGINX setup and I cannot find it for now.

I kept on uninstalling and installing passbolt-ce-server and all its dependencies until even that broke. I can’t get through the installation script without it failing on connecting to the DB during the installation process.

Though a restart and a day later it somehow works again?

SOLUTION:
I Installed the passbolt-ca-server as usual, then pointed the installation helper to the cloudflare origin certificates and set up my db as usual. I made a default file / nginx server, which redirects all http to https, and then in my /etc/nginx/sites-enabled/nginx-passbolt.conf I did the following changes:

server {

  # I moved the /etc/passbolt/ssl-nginx.conf here for convenience
  listen [::]:443 ssl http2;

  server_name passbolt-vault.mydomain.tld;

  #THESE POINT TO THE KEYS GENERATED IN FILE /etc/passbolt/ssl-nginx.conf
  ssl_certificate ###;
  ssl_certificate_key ###;


  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-ECDS>
  ssl_prefer_server_ciphers off;

  client_body_buffer_size     100K;
  client_header_buffer_size   1K;
  client_max_body_size        5M;

  client_body_timeout   10;
  client_header_timeout 10;
  keepalive_timeout     5 5;
  send_timeout          10;

  root /usr/share/php/passbolt/webroot;
  index index.php;
  error_log /var/log/nginx/passbolt-error.log info;
  access_log /var/log/nginx/passbolt-access.log;


  location / {
    try_files $uri $uri/ /index.php?$args;
  }

In my Clouflare dash, I removed the A record pointing to my subdomain and added only an AAAA record (make sure your server has IPV6 IP enabled and set up)
And then you can have another server in another file listening elsewhere, for example:
saleor.conf

server {
  listen 443 http2 ssl;
  listen [::]:443 http2 ssl;

  server_name saleor-api.mydomain.tld;
  #  ssl cert n key
  location /hook/ {
  proxy_pass http://saleor;
  }
}

upstream saleor {
  server 127.0.0.1:5467;
}

Hopefully this will help someone attempting to do the same :).

UPDATE:
Welp, now the app works. So I guess it took me a week to set up. I hope the app will continue to work with me and not against me from now on :slight_smile:

Thank you very much for your help, hopefully won’t have to see you soon (Cause it will not have any errors, not because of you x) ) <3

1 Like