There are a number of methods you can use to verify the host keys on a Droplet. Each has some pros and cons.
The first way is to launch the web console while it is in the process of booting and view the output. This includes the key’s fingerprint. It looks like:
Generating public/private ecdsa key pair.
Your identification has been saved in /etc/ssh/ssh_host_ecdsa_key.
Your public key has been saved in /etc/ssh/ssh_host_ecdsa_key.pub.
The key fingerprint is:
SHA256:Xsq8YwExqeayL+OFLq1hRL4o6I0SK7gzL9+in2bjPlc root@ubuntu-s-1vcpu-1gb-nyc3-01
The key's randomart image is:
+---[ECDSA 256]---+
| . |
| + |
| . . o |
|o o . |
| o o .S . |
|= o.. E+.o |
|**.o.. =. |
|&o&+. o. |
|*^XXo ... |
+----[SHA256]-----+
Unfortunately, that can be very hard to catch as it scrolls by.
The second option would be to log into the Droplet via the web console. This requires that you have a user with password authentication enabled. While you can disable this latter, I still consider this a major drawback. Once on the Droplet, you can check the fingerprint by running:
- ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
DigitalOcean has support for cloud-init
which enables another set of options for verify the host keys.
The first option utilizing cloud-init
is generating a key locally and providing it via user data. One draw back to this approach is that the user-data is also served via the DigitalOcean metadata service. So any user on that specific Droplet could retrieve the key by running curl http://169.254.169.254/metadata/v1/user-data
Here’s an example:
#cloud-config
ssh_keys:
rsa_private: |
-----BEGIN RSA PRIVATE KEY-----
K95I4FVq5Y6lbHGxjN8v7owd2CwjIoHbmgzciJUshtLQXGXiPOLo2v1PI14IfIQf
GUrHNw6DHIsjYMdSdfwh7LPF5yJP2xEflWljy/D4WC2CZ/XbvnBw3/T731PLbnXM
al1O7zeNRmTUlnZjdlgQKt6bl1NbXhhNDXjETR6D03tHTwDmWhSIHBoDM1kzIyq2
2ZqIxQECgYEA7yiKedA2ZI4iThqGH8ozvoxyTHPqpFHg5kCFEHUE9XlBnkGMMoq4
Aq7yY8tDAem0n/lRK/sQEIVUV4c/4CDnR2ZLZtfVq4lDKTHmYJxJAYM0qTkFy/oQ
dQv6n34PQp///g8b8k81uguA7IsaLNhADQn+/ByDyA2xGFJH9yTfJCiMJ579tldp
FnGYFGwk5HZ9ksNPqoqb3H93SVzH0gjZqvqGqNaNAZupjHx8UNW4PX1io0agtaWW
47Iw92J29glG5frLTGaQyzJpQwiKyxTAMgNF8ioWe3GRZrdXvhQNPDkqZqVwiSmX
JBEH2jrDRE+rurtNQLd7GGESO2/GFRDUDcPAz0W1D9+M38VU8c4=
-----END RSA PRIVATE KEY-----
Next, you can use the “phone home” module provided by cloud-init
. This is probably the cleanest solution, but it requires that you have a service listening for callbacks. It allows you to provide a URL which will receive a POST containing the Droplet’s public keys. You can limit it to only the ones you want, like so:
#cloud-config
phone_home:
url: http://example.com/
post:
- pub_key_ecdsa
- instance_id
Another draw back to the above approach is that you can not modify the format of the content. So if the service requires a specific format (e.g. Slack’s incoming webhooks), you’ll need a different approach. This is what I’ve used to post the fingerprint to Slack:
#cloud-config
runcmd:
- DROPLET=`curl http://169.254.169.254/metadata/v1/id`
- SSH_PUB_KEY=`ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub`
- |
curl -X POST --data-urlencode "payload={\"text\": \"SSH Public key for Droplet $DROPLET\n$SSH_PUB_KEY\"}" https://hooks.slack.com/services/MYUNIQUE/URL
This fetches both the fingerprint and the Droplet’s ID and POSTs them to a Slack URL in the required JSON format.
I found ways to validate host keys with Azure and with EC2 but still haven’t found the equivalent for DigitalOcean Droplets.