Skip to main content

SSH Keys

SSH keys provide secure, passwordless authentication for git operations (push, pull, clone) over SSH. When you add an SSH public key to your JJHub account, JJHub’s SSH server matches the key fingerprint on every connection, letting you interact with any repository you have access to without entering a password or token.

Why SSH Keys

  • No passwords: Once your key is registered, git operations authenticate automatically. No credentials to type, paste, or rotate.
  • Strong cryptography: SSH keys use public-key cryptography. Your private key never leaves your machine — only the public key is stored on JJHub.
  • Works everywhere: SSH is supported by every major operating system and git client, including jj’s git backend.
  • Multiple keys: You can register multiple SSH keys on your account — one per machine, one per role, or however you prefer to organize access.

Supported Key Types

JJHub accepts the following SSH key types:
Key TypeAlgorithmMinimum SizeRecommended
Ed25519EdDSAFixed (256-bit)Yes — fastest, most secure, smallest key size
ECDSAECDSA256-bitAcceptable
RSARSA2048-bitAcceptable (4096-bit preferred if using RSA)
Recommendation: Use Ed25519 unless you have a specific reason to use another algorithm. Ed25519 keys are shorter, faster to verify, and resistant to several classes of implementation vulnerabilities that affect RSA and ECDSA.

Generating an SSH Key

If you already have an SSH key you want to use, skip to Adding Your SSH Key to JJHub.

macOS and Linux

Open a terminal and run:
ssh-keygen -t ed25519 -C "[email protected]"
When prompted for a file location, press Enter to accept the default (~/.ssh/id_ed25519). When prompted for a passphrase, enter a strong passphrase (recommended) or press Enter for no passphrase. This creates two files:
  • ~/.ssh/id_ed25519 — your private key (never share this)
  • ~/.ssh/id_ed25519.pub — your public key (this is what you add to JJHub)
Start the SSH agent and add your key:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
On macOS, you can add the key to your Keychain so the agent loads it automatically on login:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
And add the following to your ~/.ssh/config to load keys from Keychain automatically:
Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519

Windows

Using Git Bash or WSL: The same commands from the macOS/Linux section work in Git Bash and WSL:
ssh-keygen -t ed25519 -C "[email protected]"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
Using PowerShell (OpenSSH): Windows 10+ includes OpenSSH. Open PowerShell as administrator and ensure the SSH agent service is running:
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
Then generate your key:
ssh-keygen -t ed25519 -C "[email protected]"
ssh-add $env:USERPROFILE\.ssh\id_ed25519

Using RSA (if Ed25519 is unavailable)

Some older systems do not support Ed25519. In that case, generate an RSA key with at least 4096 bits:
ssh-keygen -t rsa -b 4096 -C "[email protected]"
The resulting files will be ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub.

Adding Your SSH Key to JJHub via CLI

Copy your public key and add it using the jjhub ssh-key add command:
jjhub ssh-key add \
  --title "MacBook Pro" \
  --key "$(cat ~/.ssh/id_ed25519.pub)"
FlagDescription
-t, --title <text>Human-readable title for the key (required)
-k, --key <key>SSH public key string (required)
Use a descriptive title so you can identify the key later — for example, the name of the machine it belongs to.

Adding Your SSH Key via API

You can also register SSH keys through the JJHub API directly:
curl -X POST https://api.jjhub.tech/api/user/keys \
  -H "Authorization: token jjhub_your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "MacBook Pro",
    "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... [email protected]"
  }'
Response (201 Created):
{
  "id": 1,
  "title": "MacBook Pro",
  "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5...",
  "fingerprint": "SHA256:abc123...",
  "created_at": "2026-03-06T12:00:00Z"
}
Error cases:
  • 400 — Missing required fields (title, key)
  • 401 — Not authenticated
  • 409 — Key already exists on your account
  • 422 — Invalid SSH public key format or unsupported key type

Listing Your SSH Keys

Via CLI

jjhub ssh-key list
Example output:
ID    TITLE              FINGERPRINT                   CREATED
1     MacBook Pro        SHA256:abc123...              2026-02-15
2     Work Desktop       SHA256:def456...              2026-03-01

Via API

curl https://api.jjhub.tech/api/user/keys \
  -H "Authorization: token jjhub_your_token"
Response:
[
  {
    "id": 1,
    "title": "MacBook Pro",
    "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5...",
    "fingerprint": "SHA256:abc123...",
    "created_at": "2026-02-15T10:00:00Z"
  }
]

Deleting an SSH Key

Via CLI

jjhub ssh-key delete 1
The positional argument is the key ID, which you can find from jjhub ssh-key list.

Via API

curl -X DELETE https://api.jjhub.tech/api/user/keys/1 \
  -H "Authorization: token jjhub_your_token"
Returns 204 No Content on success.

Testing Your SSH Connection

After adding your key, verify that JJHub recognizes it:
ssh -T ssh.jjhub.tech
If your key is configured correctly, you will see a message like:
Hi alice! You've successfully authenticated with JJHub.
If you get a Permission denied error, see Troubleshooting below.

Using SSH with jj

Once your SSH key is registered, you can clone, push, and pull repositories over SSH.

Cloning a repository

# Using the jjhub CLI (auto-detects SSH or HTTPS based on your config)
jjhub repo clone owner/repo

# Using jj directly with an SSH URL
jj git clone ssh://ssh.jjhub.tech/owner/repo

Pushing changes

jj git push
jj uses the remote URL stored in the repository configuration. If you cloned over SSH, pushes automatically use SSH.

Setting SSH as your default protocol

If you want the CLI to always generate SSH clone URLs:
jjhub config set git_protocol ssh
This is the default. To switch to HTTPS instead:
jjhub config set git_protocol https

Multiple SSH Keys

If you use multiple JJHub accounts (for example, a personal account and a work account), or if you want to use different keys for different hosts, configure SSH to select the right key automatically.

SSH Config for Multiple Accounts

Edit ~/.ssh/config to define host aliases:
# Personal JJHub account
Host jjhub-personal
  HostName ssh.jjhub.tech
  User git
  IdentityFile ~/.ssh/id_ed25519_personal
  IdentitiesOnly yes

# Work JJHub account
Host jjhub-work
  HostName ssh.jjhub.tech
  User git
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes
Then clone using the alias:
jj git clone ssh://jjhub-personal/owner/repo
jj git clone ssh://jjhub-work/org/repo
The IdentitiesOnly yes directive ensures SSH only offers the specified key, preventing the agent from trying other keys and hitting authentication failures.

Testing a specific key

ssh -T -i ~/.ssh/id_ed25519_work ssh.jjhub.tech

Troubleshooting

Permission denied (publickey)

This means JJHub’s SSH server did not accept any of the keys your SSH client offered. Check that your key is added to JJHub:
jjhub ssh-key list
If your key is not listed, add it:
jjhub ssh-key add --title "My Key" --key "$(cat ~/.ssh/id_ed25519.pub)"
Check that the SSH agent has your key loaded:
ssh-add -l
If your key is not listed, add it:
ssh-add ~/.ssh/id_ed25519
Check that you are connecting to the right host:
ssh -vT ssh.jjhub.tech
The verbose output (-v) shows which keys SSH is offering and whether the server accepts them. Look for lines like Offering public key and Server accepts key.

Wrong key being used

If you have multiple keys and SSH is offering the wrong one, use an SSH config file to specify which key to use for JJHub:
Host ssh.jjhub.tech
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes
The IdentitiesOnly yes directive prevents the SSH agent from offering other keys.

SSH agent not running

If ssh-add -l returns Could not open a connection to your authentication agent, the SSH agent is not running. macOS/Linux:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
Windows (PowerShell):
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

Key format not supported

JJHub accepts Ed25519, ECDSA, and RSA (2048+ bits) keys. If you receive a 422 error when adding a key, check:
  • The key is a public key (not the private key). Public key files end in .pub.
  • The key format is supported. DSA keys and RSA keys smaller than 2048 bits are rejected.
  • The key string is complete and has not been truncated. Public keys are a single line — make sure no line breaks were introduced when copying.

Connection timeout

If ssh -T ssh.jjhub.tech hangs without responding:
  • Check that your firewall or corporate network allows outbound SSH connections (port 22).
  • Try connecting on an alternate network to rule out network-level blocking.
  • Verify DNS resolution: nslookup ssh.jjhub.tech should return an IP address.

SSH Keys vs Other Authentication Methods

MethodScopeProtocolBest For
Personal SSH keysAll repos the user can accessSSH (git push/pull)Developer workstations
Deploy keysSingle repositorySSH (git push/pull)CI/CD, deployment scripts
API tokensScoped by token permissionsHTTPS (API calls)Programmatic API access, scripts
JJHUB_TOKENScoped by token permissionsHTTPS (CLI API calls)CI environments without SSH
Personal SSH keys are the right choice for day-to-day development on your own machine. For automated systems that need access to a single repository, use deploy keys instead.

API Reference

MethodEndpointDescription
GET/api/user/keysList SSH keys on your account
POST/api/user/keysAdd an SSH key
GET/api/user/keys/:idGet an SSH key
DELETE/api/user/keys/:idDelete an SSH key