Restore Laravel Forge Access to Bitbucket

Baseline

Laravel Forge uses custom ssh configuration to authenticate against the repository. Config is located in ~/.ssh/forge-config-ID file.

It uses separate private key when authenticating to bitbucket.org host.

Host bitbucket.org
IdentityFile /home/forge/.ssh/forge_ID
Host bitbucket.org
IdentityFile /home/forge/.ssh/forge_ID

Laravel Forge private key isn't added to ssh-agent, actually ssh-agent is not running at all, neither it is configured to be loaded by default. That can be verified by running ssh -Tvvv [email protected].

...
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files
debug1: /etc/ssh/ssh_config line 21: Applying options for *
debug2: resolving "bitbucket.org" port 22
debug2: ssh_connect_direct
debug1: Connecting to bitbucket.org [18.205.93.2] port 22.
debug1: Connection established.
debug1: identity file /home/forge/.ssh/id_rsa type 0
debug1: identity file /home/forge/.ssh/id_rsa-cert type -1
debug1: identity file /home/forge/.ssh/id_dsa type -1
debug1: identity file /home/forge/.ssh/id_dsa-cert type -1
debug1: identity file /home/forge/.ssh/id_ecdsa type -1
debug1: identity file /home/forge/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/forge/.ssh/id_ecdsa_sk type -1
debug1: identity file /home/forge/.ssh/id_ecdsa_sk-cert type -1
debug1: identity file /home/forge/.ssh/id_ed25519 type -1
debug1: identity file /home/forge/.ssh/id_ed25519-cert type -1
debug1: identity file /home/forge/.ssh/id_ed25519_sk type -1
debug1: identity file /home/forge/.ssh/id_ed25519_sk-cert type -1
debug1: identity file /home/forge/.ssh/id_xmss type -1
debug1: identity file /home/forge/.ssh/id_xmss-cert type -1
...
...
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: include /etc/ssh/ssh_config.d/*.conf matched no files
debug1: /etc/ssh/ssh_config line 21: Applying options for *
debug2: resolving "bitbucket.org" port 22
debug2: ssh_connect_direct
debug1: Connecting to bitbucket.org [18.205.93.2] port 22.
debug1: Connection established.
debug1: identity file /home/forge/.ssh/id_rsa type 0
debug1: identity file /home/forge/.ssh/id_rsa-cert type -1
debug1: identity file /home/forge/.ssh/id_dsa type -1
debug1: identity file /home/forge/.ssh/id_dsa-cert type -1
debug1: identity file /home/forge/.ssh/id_ecdsa type -1
debug1: identity file /home/forge/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/forge/.ssh/id_ecdsa_sk type -1
debug1: identity file /home/forge/.ssh/id_ecdsa_sk-cert type -1
debug1: identity file /home/forge/.ssh/id_ed25519 type -1
debug1: identity file /home/forge/.ssh/id_ed25519-cert type -1
debug1: identity file /home/forge/.ssh/id_ed25519_sk type -1
debug1: identity file /home/forge/.ssh/id_ed25519_sk-cert type -1
debug1: identity file /home/forge/.ssh/id_xmss type -1
debug1: identity file /home/forge/.ssh/id_xmss-cert type -1
...

Laravel Forge Worker adds its SSH private key to the local git repository config ~/example.org/.git/config to use it as preflight for every git command involving remotes as core.sshCommand value.

[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
sshCommand = ssh -F /home/forge/.ssh/forge-config-ID
[remote "origin"]
url = [email protected]:org/repo
fetch = +refs/heads/main:refs/remotes/origin/main
[branch "main"]
remote = origin
merge = refs/heads/main
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
sshCommand = ssh -F /home/forge/.ssh/forge-config-ID
[remote "origin"]
url = [email protected]:org/repo
fetch = +refs/heads/main:refs/remotes/origin/main
[branch "main"]
remote = origin
merge = refs/heads/main

Premise

At some point access key for Laravel Forge Worker can be removed from the bitbucket.org repository. Or under some circumstances core.sshCommand value can also be removed from the local repo config.

We can restore original functionality set up by Forge or completely change SSH keys used for deployments.

Get public key back

By default there's no public key stored for the Laravel Forge Worker, and in case it was removed, we can generate it again from private key by using ssh-keygen command.

ssh-keygen -y -f /home/forge/.ssh/forge_ID
ssh-keygen -y -f /home/forge/.ssh/forge_ID

Then add it to the Access keys in the bitbucket.org repository settings.

Fix git config

Update ~/example.org/.git/config by specifying ssh configuration to use.

[core]
...
sshCommand = ssh -F /home/forge/.ssh/forge-config-ID
[core]
...
sshCommand = ssh -F /home/forge/.ssh/forge-config-ID

Generating new key pairs

Keys recently removed from the repository can't be re-added for the next 30 days. In this case generate a new key pair:

ssh-keygen -t ed25519 -C "[email protected]"
ssh-keygen -t ed25519 -C "[email protected]"

If you are using a legacy system that doesn't support the Ed25519 algorithm, use:

ssh-keygen -t rsa -b 4096 -C "[email protected]"
ssh-keygen -t rsa -b 4096 -C "[email protected]"

Epilogue

Employing techniques described we can:

  • Fix broken Laravel Forge deployments;
  • Replace old SSH keys with new ones;
  • Set up different SSH access keys for each repo, and use more extensive custom setups.