timmc: (Default)
[personal profile] timmc

I have a server I use to host Jabber instant messenger for brainonfire.net. I currently use an SSL cert from StartSSL, but they're known to be sketchy and I don't know how long various IM clients will continue to trust them. I'd like to set up the server to use certs from Let's Encrypt, but it's not clear to me what the least worst way of doing this is, given that the website for that domain is hosted elsewhere.

I host www.brainonfire.net on nearlyfreespeech.net, which has a nice little utility to automatically get and install certs from Let's Encrypt. The cert files end up in a place I can SSH to. The home server I host Jabber on (named kibble) just has Jabber-related ports open, and in particular ports 80 and 443 on that IP go to a different server, named toster. Here are the options I can picture:

  • Manually copy the certs over every 30 days. (I could start with this.)
  • Have kibble automatically SSH into my web host and grab the certs periodically, then install them into Prosody. (I would be *really* leery of doing this -- that SSH environment in my web host has a ton of access, and this would require passwordless SSH keys.)
  • Point the A record for brainonfire.net to toster, which would use haproxy or nginx to forward brainonfire.net requests to kibble, which would just intercept ACME challenges and otherwise send redirects to www.brainonfire.net just like nearlyfreespeech.net would normally do. (This is awful in several ways.)
  • ETA: Have a cron job on the web host copy the keys directly to kibble, into a limited user directory, and then have a cron job on kibble pick up the keys and install them. (This... might work?)

I don't think I can manipulate brainonfire.net's DNS from any of my servers (this is a good thing) and I don't think my web site can see the cert files in order to serve them up to kibble via an authenticated request (this is probably *also* a good thing). I don't want to host my website on kibble, and I can't host Jabber at nearlyfreespeech.net. Are there any other options I've missed?

Edit 2: A coworker suggested what sounds like the right way: Generate the key on kibble, sign a CSR with it, transfer the CSR to the web host. Then periodically use the CSR for cert generation, copying the results back to kibble, as in the last idea above. Much safer!

Edit 3: Success! Here's what I did:

  1. Generate a private key and a CSR on the Jabber server:
    mkdir -p /opt/keys/prosody/brainonfire.net/
    (umask 077; openssl genrsa -out /opt/keys/prosody/brainonfire.net/privkey.pem 4096)
    openssl req -out /opt/keys/prosody/brainonfire.net/csr.pem -key /opt/keys/prosody/brainonfire.net/privkey.pem -new -sha256 -subj "/CN=brainonfire.net"
    cp /opt/keys/prosody/brainonfire.net/privkey.pem /etc/prosody/certs/brainonfire_net.NFSN-LE.key
    
  2. Copy the CSR to the web host.
  3. Set up the dehydrated ACME client config with an appropriate BASEDIR -- certs will go in here, as will registration.
  4. Register with Let's Encrypt: /usr/local/bin/dehydrated --register --accept-terms --config path/to/dehydrated.config
  5. Create a script (create cron job to run once a month) that will ship the certs off to the Jabber server:
    CO=/home/private/sync/cert-oracle
    
    . "$CO/dehydrated.config"
    mkdir -p -- "$BASEDIR"
    
    /usr/local/bin/dehydrated --signcsr "$CO/brainonfire.net-csr.pem" \
                              --config "$CO/dehydrated.config" \
                              --domain brainonfire.net \
                              --full-chain \
                              > "$BASEDIR/latest-chain.pem"
    
    /usr/bin/scp -i /home/private/sync/cert-oracle/ID_certs-to-kibble \
      -P 8443  \
      "$BASEDIR/latest-chain.pem" \
      cert-recv-bof@k.timmc.org:/home/cert-recv-bof/recv/brainonfire.net/
    
  6. On Jabber server, create a script (set to run daily) that will install the cert and restart Prosody if it has changed:
    #!/bin/bash
    
    src_dir=/home/cert-recv-bof/recv/brainonfire.net
    dest_dir=/etc/prosody/certs
    
    function install {
      hash_src=`sha256sum < "$1"`
      hash_dest=`sha256sum < "$2"`
      if [[ "$hash_src" = "$hash_dest" ]]; then
        echo "Not installing file, hasn't changed: $1 -> $2"
        return 2
      fi
      echo "Installing file: $1 -> $2"
    
      touch -- "$2"
      chown prosody:prosody -- "$2"
      chmod o= -- "$2"
      cat < "$1" > "$2"
    
      return 0
    }
    
    if install "$src_dir/latest-chain.pem" "$dest_dir/brainonfire_net.NFSN-LE.chain.pem"; then
      echo "Restarting prosody"
      service prosody stop
      service prosody start
    else
      echo "Nothing to do"
    fi
    

Profile

timmc: (Default)
timmc

June 2017

S M T W T F S
    1 23
45678910
11121314151617
18192021222324
252627282930 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Oct. 17th, 2017 08:13 pm
Powered by Dreamwidth Studios