The easiest way to set this up would be to have a cleartext system partition (on the SD card, I presume) and an encrypted data partition. Use dmcrypt to encrypt the data partition, with a key stored in a key file that's downloaded from the server.
First set up the server infrastructure, then download the key file and create the encrypted volume with
cryptsetup luksFormat /dev/sdb1 /run/data.keyfile or add the key to the existing volume with
cryptsetup luksAddKey /dev/mapper/encrypted /run/data.keyfile. Note that you can arrange for the volume to be unlocked with either a passphrase or a key file, which may be convenient for administration (you can type the passphrase even if the server is not available).
The key file doesn't have to be in any particular format. Just generate some random bytes on the server; 16 bytes is plenty (anything more won't give you better security, but anything less won't give you better performance):
</dev/urandom head -c 16 >pi.keyfile.
Serve the key with HTTPS to avoid it being snooped. If you don't have a certificate that's validated by a CA, create your own and add it to
/etc/ssl/certs, or pass it to the download command (
wget --ca-certificate /etc/local/my.cert or
curl --cacert /etc/local/my.cert).
You need to download the key before activating the encrypting volume. You can do that in one step with one of
wget -nv -O - https://myserver.example.com/pi.keyfile | cryptsetup luksOpen /dev/sdb1 --key-file /dev/stdin
curl https://myserver.example.com/pi.keyfile | cryptsetup luksOpen /dev/sdb1 --key-file /dev/stdin
or you can download the key to a temporary file, then activate the volume, and finally (not necessary, but may slightly improve security) remove the temporary file. The natural place for this temporary file is in
/run, which is in RAM and writable only by root (don't download the key to persistent storage). You should make the file readable only by root (you can set
umask 700 before downloading to arrange that), although it only matters if you don't control all the code that runs at boot time.
If you download the key to a temporary file, you can put the keyfile in
/etc/crypttab, and add a systemd unit to download the keyfile that runs before the one that activates encrypted volume (but after the network is available) and another unit to remove the keyfile afterwards. Putting
wget … | cryptsetup … in
/etc/rc.local looks easier to set up.
You'll probably want to authenticate the client when it downloads the key. The authentication token will have to be stored in cleartext on the Pi. You can use an SSL client certificate:
curl --cert /etc/keyfile.cert https://myserver.example.com/pi.keyfile
wget --certificate /etc/keyfile.cert https://myserver.example.com/pi.keyfile
or a password with HTTP basic authentication, stored in
curl -n --user=pi https://myserver.example.com/pi.keyfile
wget --user=pi /etc/keyfile.cert https://myserver.example.com/pi.keyfile
Configuring basic authentication is perhaps easier to set up on the server side. Use a randomly-generated password with no special characters (e.g.
</dev/urandom | head -c 16 | base64).
Note that whatever you do, someone who steals the Pi will get the password and will be able to download the key if you don't block it first on the sender side. Also, someone who gets physical access to the Pi can quickly pull out the SD card, make a copy, and insert it back; if you don't monitor anything other than uptime, this will look like a power failure. There's no way to completely protect against that. You can put the key in a smartcard, which would prevent the attacker from duplicating it, but not from stealing the smartcard or using it on the spot to download the key file.
Once again, you cannot protect against someone with physical access quickly downloading the key file, then stealing the disk and decrypting it at their leisure. If you want to protect against that, you need to look into tamper-resistant hardware, which is in a different price range.