How to Configure SSH for Git and Bitbucket on a Remote Server

Cloning a repository over HTTPS requires entering your username and password (or a personal access token) on every push. SSH authentication uses a key pair instead — set it up once and you never enter credentials again. Here’s the complete workflow for a fresh Linux server.

Problem: After setting up a remote server, git clone or git pull with a Bitbucket repository fails because no SSH key has been generated or registered on the server.

Solution: Generate an SSH key pair on the server with ssh-keygen -t ed25519, copy the public key, add it to Bitbucket under Personal Settings → SSH Keys, then verify the connection with ssh -T git@bitbucket.org before running any Git commands.

# Step 1 — connect to the server
ssh username@server-ip-or-hostname

# Step 2 — check for an existing key pair
ls ~/.ssh/id_*.pub 2>/dev/null || echo "No key found"

# Step 3 — generate a new Ed25519 key pair (recommended over RSA)
ssh-keygen -t ed25519 -C "deploy@example.com"
# Press Enter to accept the default path (~/.ssh/id_ed25519)
# Optionally set a passphrase for additional security

# Step 4 — view and copy the public key
cat ~/.ssh/id_ed25519.pub

Add the public key to Bitbucket: go to Account Settings → SSH Keys → Add key, paste the key, and save. For GitHub it's Settings → SSH and GPG keys → New SSH key.

# Step 5 — test the connection
ssh -T git@bitbucket.org
# Expected: "logged in as username"

# Step 6 — create the project directory and initialise Git
mkdir -p /var/www/my-project && cd /var/www/my-project
git init

# Step 7 — add the remote (copy the SSH URL from Bitbucket/GitHub)
git remote add origin git@bitbucket.org:username/my-repo.git

# Step 8 — fetch and check out the main branch
git fetch origin
git checkout -t origin/main   # or 'master' for older repos

Verify your working tree after checkout:

ls -la          # list files
pwd             # confirm current directory
git status      # should say "nothing to commit, working tree clean"

NOTE: If Git clones the repository into a nested subfolder (project/project/files instead of project/files), the remote URL was pointing to a repository with a directory at its root. Move all files up one level with mv project/* . && rmdir project, then verify with ls -la.