As a full-stack developer, accessing remote servers securely is a critical part of your workflow. SSH keys provide one of the most convenient and secure methods for logging into remote Linux servers.

In this comprehensive 2650+ word guide, we will walk through the step-by-step process for generating SSH keys on Ubuntu, setting up public key authentication, and enhancing the security of your SSH connections from an expert developer perspective.

The Critical Role of SSH in Development

Let‘s first outline why SSH is so crucial for effective and secure development operations:

  • Remote Access: SSH enables running commands, editing files, and managing infrastructure across public or private networks.

  • Automation: Tools like Ansible, Terraform, and custom scripts rely on SSH for remote execution without human interaction.

  • Source Control: Systems like Git use SSH keys for authenticating code pushes and pulls from repositories.

  • CD Pipelines: SSH keys grant CI/CD runtimes access to deploy updates across multiple environments.

With 83% of software engineers working remotely at least some of the time (Forbes), developer productivity hinges on quick, programmatic SSH connections for distributed collaboration.

But breaches also frequently target SSH credentials and keys. Over 20% of reported cyber insurance claims stem from unauthorized SSH access or stolen key data (CoalFire).

Weak or improper SSH implementation can completely undermine infrastructure security – leading to data leaks, service outages, regulatory infractions, and financial damage.

That‘s why properly managing and hardening SSH access through robust key pair usage as outlined in this guide is fundamental for any quality development environment.

Why Use SSH Keys Over Passwords?

By default, SSH utilizes password-based authentication to verify a user‘s identity upon connection. This simply checks a manually entered password against the stored system credentials.

However, raw passwords provide users only 30-40 bits of actual entropy protection in practice regardless of chosen complexity or length. Modern computing can crack through 40-bit encryption almost instantly.

SSH keys on the other hand use asymmetric public-key cryptography which is far more secure:

  • A 4096-bit RSA key has over 150,000,000 times more protection than a standard 8 character complex password (~40 bits).

  • The private key half never gets transmitted or exposed. Only the public key sits on remote servers for authentication.

  • Cryptographic proof through complex mathematical transforms verifies only the holder of the private key is connecting rather than matching plaintext credentials.

On top of drastically stronger security, SSH keys also provide immense convenience benefits:

  • No repeated password typing – Just use your private key file for seamless authentication.

  • Simplified automation – Scripts can leverage keys without buffering for interactive password input.

  • Reduced violations – Limits exposure compared to potentially reusing passwords across systems.

With more entropy, better secrets management, and immense usability advantages, prioritizing SSH keys over passwords is pivotal for watertight security and efficient workflows.

Step 1 – Check for Existing Keys

First, we‘ll verify that you don‘t already have SSH keys configured. This prevents accidentally overwriting them.

Open up a terminal and run:

ls -al ~/.ssh

This lists the .ssh directory contents. Most SSH keys are stored as files starting with id_ like:

  • id_rsa: Default SSH v2 RSA key
  • id_ecdsa: ECDSA elliptic curve key
  • id_ed25519: Ed25519 elliptic curve key

If you see any files like id_rsa.pub or id_ed25519.pub, you likely already have public and private SSH key files configured.

You can reuse these keys if preferred. Identify the key algorithm and bit size to determine if a new key should be generated for improved security.

If no existing keys show up, it‘s safe to generate a new pair.

Step 2 – Generate a New SSH Key Pair

With no prior keys set up, run the following ssh-keygen command in your terminal to create a new one:

ssh-keygen -t rsa -b 4096

This will initiate the interactive key generation process using a 4096 bit RSA key which provides tremendous security while still being compatible with virtually all remote servers.

Select Storage Location

First, you‘ll be prompted to choose a location to save the SSH key pair.

The default ~/.ssh/id_rsa path simply stores the keys in a hidden .ssh folder within your user directory for easy access.

Hit enter to accept this standard file location and name.

For advanced cases with multiple key pairs, enter a custom name like ~/.ssh/my_key_name instead.

Add an Optional Passphrase

Next, you have the option to add a passphrase – an extra password protecting the private key file itself.

With a complex passphrase, even if your private key is somehow obtained, cracking this secondary credential would still take an extreme amount of effort and computing power – keeping the keys securely encrypted.

However, you will have to enter this passphrase with every new SSH session which reduces automation convenience.

Press enter to leave no passphrase for uninterrupted ease of use. But for maximum security, optionally enter a strong memorizable passphrase here and store it separately from the physical keys.

Key Generation

After confirming the details, ssh-keygen leverages cryptographically secure pseudo-random number generation along with complex asymmetric encryption algorithms to produce:

  • A long 4096-bit private key randomly generated and stored at ~/.ssh/id_rsa
  • A corresponding public key utilizing modular mathematical transforms stored at ~/.ssh/id_rsa.pub

These keys authenticate without using vulnerable static passwords – dramatically improving both security and convenience.

The higher 4096-bit size offers immense protection compared to the standard 2048-bit keys. While slightly slower to generate, modern systems can fully support this increased key size.

Step 3 – Copy Public Key to Remote Servers

Now to enable public key authentication on any remote server, the public key needs to be installed in the authorized_keys file of user accounts you want to access.

This allows those user accounts to recognize the private key and verify your identity upon SSH login.

Use ssh-copy-id to effortlessly copy keys:

ssh-copy-id username@remote_host

Running this will securely transfer your public key to the right authorized keys location on the target server.

The first time copying keys to any new remote host, ssh-copy-id may prompt for the account password on that system. This allows initial secure public key installation before disabling passwords entirely.

Manual Key Installation

In certain cases, a remote server may block the system access ssh-copy-id utilizes to install the public key.

If running the command fails, keys can be installed manually through these steps instead:

  1. Copy the Public Key:

    cat ~/.ssh/id_rsa.pub | pbcopy

  2. SSH into Remote Account:

    ssh username@host

  3. Create .ssh Directory:

    mkdir ~/.ssh

  4. Set Folder Permissions:

    chmod 700 ~/.ssh

  5. Open Authorized Keys File:

    nano ~/.ssh/authorized_keys

  6. Paste Public Key Data & Save

While more complex, this allows installing keys to secure public key authentication on practically any remote server environment.

Step 4 – Disable SSH Password Authentication

Now with key-based login functioning, you should outright disable the outdated password authentication mechanism.

This forces all sessions to use SSH keys rather than falling back on crackable static passwords – preventing a major attack vector.

To disable passwords, open the main SSH daemon configuration using:

sudo nano /etc/ssh/sshd_config

Find the PasswordAuthentication directive, and switch it to no:

PasswordAuthentication no

Save the file changes and restart the sshd service:

sudo systemctl restart sshd

Users will now be forced to utilize SSH keys rather than weak passwords when logging into this server over SSH.

Transferring Keys to Other Devices

As a developer, you likely code on multiple computers like a desktop, laptop, and potentially servers that compile code.

To leverage your existing SSH keys from any device, the private key portion needs transferred.

The public key can be freely copied to enable access to new servers.

But the private key should never be openly exposed on a network. It serves as the sole proof of secret ownership that grants you access.

So what‘s the most secure way to transfer SSH private keys between devices?

Option 1: Encrypted USB Drive

The most watertight approach is to store private key files on an encrypted external drive.

For example, a VeraCrypt container holding sensitive SSH keys can provide the raw encrypted data transfer without exposing plaintext credentials even if intercepted.

By physically transporting the VeraCrypt USB drive between systems and mounting to copy keys locally, the private data stays tightly contained.

This "sneakernet" circumvents even having keys touch networked connections. Given the sensitivity, manual encrypted drives are ideal for ultra-high security and air gapped environments.

However, the inconvenience makes it unrealistic for everyday developer workflows.

Option 2: scp CLI Transfer

For typical use, the scp or secure copy command makes transferring private SSH keys over existing SSH connections straightforward:

scp ~/.ssh/id_rsa username@newhost:~/.ssh/id_rsa

This encrypts then copies the key directly into the desired ~/.ssh directory on the target system.

The downside of using scp rather than offline physical transfers is briefly opening the unencrypted key data to the established SSH tunnel.

So ensure you fully trust the source and destination environment when using scp for SSH private keys.

Overall, scp enables efficient developer shifting between systems while maintaining moderately high security.

Option 3: SSH Config Trick

SSH even includes a built-in method to transparently use the same key pair across many devices:

  1. On your main development system, choose the key you want to standardize on.

  2. Create/modify ~/.ssh/config with:

    Host *
      IdentityFile ~/.ssh/id_rsa
  3. Transfer the public key to all servers you need access to from any system.

  4. Now copy just the private key file to additional devices.

This special * host rule will auto-select the defined private key identity for all SSH connections.

Therefore, on any computer with the actual ~/.ssh/id_rsa file present, your single key pair works for transparent authentication without manual swapping or transfers back and forth.

The drawback is potential key discovery or theft brings down all devices rather than just one. Adjust security practices accordingly.

Strengthening SSH Keys

Up to this point, we‘ve covered theSSH key basics – generation, installation, and hardening server access.

But beyond that foundation, there are further steps advanced developers can take to bolster security:

Add Optional Passphrases

Earlier I noted that leaving SSH keys without a passphrase simplifies workflows but reduces security.

You can add a passphrase to an existing private key at any time without regeneration:

ssh-keygen -p

After entering and confirming the new passphrase, ssh-keygen will encrypt the private key using thousands of KDF derivation rounds.

Now even if your private key file leaks or is stolen, actually utilizing it requires cracking both the RSA encryption and the secondary passphrase making attacks exponentially more difficult.

Just keep in mind passphrases introduce friction requiring entering them each SSH session. Store complex phrases separately from physical key files as a best practice.

Utilize Hardware Keys

For ultimate security, consider using a hardware security key instead of typical private key files. Popular options include:

  • YubiKey: Supports FIDO U2F, OTP, and now CCID Smartcard protocols for complex MFA and challenge response authentication not vulnerable to simple key file theft.

  • SoloKeys: Open source FIDO security key platform built ground up with exceptional opsec and cryptography.

  • OnlyKey: Crypto key support including SSH, GPG, and storages encrypted by device password and tamper proofing.

These utilize your SSH keys internally but introduce advanced features:

  • Hardware tamper proofing makes extracting keys nearly impossible.
  • Two factor and touch-to-activate stops unattended malicious access.
  • Seed backups allow restoring destroyed units while maintaining high security

By combining leading hardware protections and encryption with SSH‘s foundation, hardware keys prevent many attack vectors on private credentials.

Automate Keys for Pipelines

Rather than manually handling SSH keys, best practice is tightly integrating and provisioning key usage in automated tools:

  • CI/CD Systems: Credential manager plugins help incorporate keys securely in build/deploy stages.

  • Configuration Management: Tools like Ansible, Chef, and Saltstack codify distribution of public keys to servers needed for infra management.

  • Secret Managers: Vault products securely inject keys only at runtime such as during dynamic Docker build tasks.

Full lifecycle SSH key automation maintains security by limiting manual transfers while still enabling critical remote execution.

Integrating SSH functionality into all relevant systems cards keys to each technology‘s specific security model for defense in depth.

Conclusion & Best Practices

Properly implemented SSH keyed-based authentication underpins secure remote access for modern development operations:

  • 26x times faster deployments reported after implementing automated SSH key CI/CD workflows according to Sonatype surveys

  • 81% lower SSH attack success rates with properly hardened key-only server policies per Enterprise Management Associates

  • 92% of breaches involve exposure of access credentials like passwords cracked versus decoded SSH keys (Verizon DBIR)

Hopefully this guide served as a comprehensive reference for expertly generating and hardening SSH key pairs while preventing critical attacks.

Here are some final best practices to follow in your infrastructure:

  • Utilize keys over password authentication whenever possible
  • Generate new domain-specific keys per app, environment, or at minimum per-server
  • Restrict keys only to necessary user accounts under principle of least privilege
  • Transfer private keys only through secure temporary encrypted channels
  • Expire keys that may have underwent potential exposure after 30-90 days
  • Monitor key generation and deployment through central SIEM logging

Implementing these SSH key management fundamentals will greatly enhance infrastructure security and auditability.

Please leave any other questions on advanced SSH key usage below!

Similar Posts