Self-signed cert creation

Brief story Link to heading

Recently I had an issue with syncing files and passwords for a small group. We wanted to have easy solution on all devices, and separated from the cloud if possible. So after searching I found a pretty good solution. It is possible to create self-singed certs for a webapp, which would comply with all the standards that Apple and Android and everyone ask for. This is basically the way that any company could generate certs for their intranet infrastructure, which is nice to have even in a small group. There is only a slight down side to do this. You have to add and validate your service domain self-signed Root CA cert, which could be a bit exhausting if you own more than a dozen device and have no remote config solution to do it. Which means you have to add it manually one by one.

So briefly i will use bitwarden as an example below. There is are really good documentations and article how to operate this thing, so this will be a bit short. There is a unofficial rust version of the server which is less resource hungry, which is a perfect candidate for my Raspberry PI 4. It’s called Bitwarden_rs and of course it has a docker version. How lucky we are.

How to make valid self-signed certification. Link to heading

  1. First we create a directories for the bitwarden_data and one for the certs.

  2. cd into the certs directory

  3. First lets create a config file before hand so that we don’t need to fiddle with it later lets call it something.ext and modify the last three line to our need with the actual local domain address. For example if our domain is home and our rig hostname is raspberrypi then DNS.1 = raspberrypi.home

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = <address.domain>
DNS.2 = <other.address.domain>
IP.1 = <static ip here>
  1. We need to create our root CA cer and key first.This command will ask for a secret passphrase needs which will prevent others to create signed certs in our name in the possession of our private key.
openssl genpkey -algorithm RSA -aes128 -out private-ca.key -outform PEM -pkeyopt rsa_keygen_bits:4096 
  1. Lets create our public ca-cert ,which we need to move to other devices later on. You will see this will ask for our private key passphrase.
openssl req -x509 -new -nodes -sha256 -days 750 -key private-ca.key -out self-signed-ca-cert.crt

This will ask us to enter our country code with two letter (expample: US, GB) , our company details and here comes the important part the Common Name: which has to be our DNS.1 , DNS.2 an example Common name: raspberrypi.home, www.raspberrypi.home

  1. Then we generate a key for our service in this case bitwarden. (later on if you have more than one service on this rig you just have to repeat from here for each service. If you would like :D)
openssl genpkey -algorithm RSA -out bitwarden.key -outform PEM -pkeyopt rsa_keygen_bits:4096
  1. Lets create a certificate request file as well some service needs it.once more it will ask for the company details and common name
openssl req -new -key bitwarden.key -out bitwarden.csr
  1. Now we are ready to create our cert for our bitwarden service. So lets do it it will ask for our private key passphrase only.
openssl x509 -req -in bitwarden.csr -CA self-signed-ca-cert.crt -CAkey private-ca.key -CAcreateserial -out bitwarden.crt -days 365 -sha256 -extfile something.ext

As you probably notice above we created our keys to expire private-ca key in 750 days , the bitwarden service in 365. These are really important as Apple require no longer than 825 days expire ,which means anything above will be invalid.

Adding cert to client Link to heading

email or move self-signed-ca-cert.crt file on devices

  • iOS 14: The best article, which i found was this https://www.theictguy.co.uk/adding-trusted-root-certificates-to-ios14/
  • Android: it was proxyman project i found the easiest to explain. https://proxyman.io/blog/2020/09/Install-And-Trust-Self-Signed-Certificate-On-Android-11.html
  • GNU/Linux: on Debian based system to add your cert system wide you have to copy your self-signed-ca-cert.crt into /usr/local/share/ca-certificates and run sudo update-ca-certificates this will add it to your trusted key. On Fedora / Arch they use p11-kit which is slightly different and it seems debian will change to that type as well. for that i found an archwiki article
  • Windows 10: right click on crt file choose Install Certificate ,choose Local Machine and Place all certificate into following store and click browse and choose Trusted Root Certification Authorities press OK, next and Finish
  • MacOS: Open Keychain Access Choose File > Import Items choose the crt file and select System as Destination Keychain after you typed your password in logout to take effect.

Runing bitwarden_rs on our small server Link to heading

  1. Install docker

  2. create docker-compose file lets name it bw.yml :

version: "2.4"
services:
  bitwarden:
    image: bitwardenrs/server:latest
    container_name: bitwarden
    restart: always
    environment:
      - ROCKET_TLS={certs="/ssl/bitwarden.crt",key="/ssl/bitwarden.key"}
      - WEBSOCKET_ENABLED=true  # Enable WebSocket notifications.
    volumes:
      - ./bw-data:/data
      - ./ssl:/ssl
    ports:
      - 443:80
  1. run sudo docker-compose -f bw.yml up -d

  2. Enjoy we finished

Summary Link to heading

After you done all this if you use this private-ca.key to create more keys later next time you have to create bitwarden cert in a year which easy as you don’t need to touch clients, however after the 750 days expires (2 years) you have to do this root_ca.crt dance with the clients. In long shot I think this is a great way to secure even your own small company /home intranet if you have some self-hosted service instead of running everything in plain http. Specially because in a household / office there are plenty IoT or older devices to get compromised, which would then jeopardize our network security and integrity.