Codeberg/Community
54
325
Fork
You've already forked Community
12

No private key found for "/dev/fd/63" when using generated SSH key verification command. #2066

Closed
opened 2025年08月06日 00:40:04 +02:00 by wsulla · 25 comments

Comment

I decided to add a new SSH key to my Codeberg account today, it has been a while, and I have a new computer I would like to use for git. I am using OpenSuSE Tumbleweed, and have git and forgejo installed. And I have restarted with fresh keys, getting the same result.

About a year ago, it went off without a hitch, I was able to create an SSH key using ssh-keygen -t ed25519 -f ~/.ssh/SERVER_id_ed25519 -C "NEW COMPUTER access to codeberg" and pretty sure I needed to point the verification command at the local public key file when I did it before.

I can add the public key to codeberg, and when I try to connect to verify with ssh -T git@codeberg.org after setting up my ssh_config to point to my public key.

When try to verify by providing a signature for my SSH key, I am told to generate a signature using bash -c "echo -n '{{TOKEN}}' | ssh-keygen -Y sign -n gitea -f <(echo '{{PUBLIC KEY}}')"

I get No private key found for "/dev/fd/63" in return, instead of a signature.

It works if I actually point it at the public key file though.

### Comment I decided to add a new SSH key to my Codeberg account today, it has been a while, and I have a new computer I would like to use for git. I am using OpenSuSE Tumbleweed, and have git and forgejo installed. And I have restarted with fresh keys, getting the same result. About a year ago, it went off without a hitch, I was able to create an SSH key using `ssh-keygen -t ed25519 -f ~/.ssh/SERVER_id_ed25519 -C "NEW COMPUTER access to codeberg"` and pretty sure I needed to point the verification command at the local public key file when I did it before. I can add the public key to codeberg, and when I try to connect to verify with `ssh -T git@codeberg.org` after setting up my ssh_config to point to my public key. When try to verify by providing a signature for my SSH key, I am told to generate a signature using `bash -c "echo -n '{{TOKEN}}' | ssh-keygen -Y sign -n gitea -f <(echo '{{PUBLIC KEY}}')"` I get `No private key found for "/dev/fd/63"` in return, instead of a signature. It works if I actually point it at the public key file though.

Hi, what shell do you use? And what was the value of {{PUBLIC KEY}}?

Hi, what shell do you use? And what was the value of `{{PUBLIC KEY}}`?
Author
Copy link

Bash, and it was the public key of my SSH key for Codeberg.

Bash, and it was the public key of my SSH key for Codeberg.

Feels like a regression of forgejo/forgejo#7516, CC @senekor do you have a clue?

Feels like a regression of https://codeberg.org/forgejo/forgejo/pulls/7516, CC @senekor do you have a clue?

Yeah, that seems related, but I don't have an idea what could be the problem right now.

Yeah, that seems related, but I don't have an idea what could be the problem right now.

I actually I can reproduce this 🤔 I guess that's good, but I'm sure I tested that command on regular files when I came up with this approach. Will investigate further.

I actually I can reproduce this 🤔 I guess that's good, but I'm sure I tested that command on regular files when I came up with this approach. Will investigate further.
Author
Copy link

Sorry if I should have raised this on the forgejo repo!

Sorry if I should have raised this on the forgejo repo!

This is very strange. It doesn't even work for my use case (anymore?) (password manager as ssh agent without a public key file on disk).

This is very strange. It doesn't even work for _my_ use case (anymore?) (password manager as ssh agent without a public key file on disk).

Weirdly enough, it does work when I execute the command on a server I'm ssh'ed into and I've forwarded my ssh agent. 😅

Weirdly enough, it _does_ work when I execute the command on a server I'm ssh'ed into and I've forwarded my ssh agent. 😅

This means the shell in which the line is copied does not have access to the private key. See forgejo/forgejo#8628 where you can comment if needed.

This means the shell in which the line is copied does not have access to the private key. See https://codeberg.org/forgejo/forgejo/issues/8628 where you can comment if needed.

@earl-warren wrote in #2066 (comment):

This means the shell in which the line is copied does not have access to the private key. See forgejo/forgejo#8628 where you can comment if needed.

This contradicts what is being said here

@wsulla wrote in #2066 (comment):

When try to verify by providing a signature for my SSH key, I am told to generate a signature using bash -c "echo -n '{{TOKEN}}' | ssh-keygen -Y sign -n gitea -f <(echo '{{PUBLIC KEY}}')"

I get No private key found for "/dev/fd/63" in return, instead of a signature.

It works if I actually point it at the public key file though.

@earl-warren wrote in https://codeberg.org/Codeberg/Community/issues/2066#issuecomment-6153127: > This means the shell in which the line is copied does not have access to the private key. See forgejo/forgejo#8628 where you can comment if needed. This contradicts what is being said here @wsulla wrote in https://codeberg.org/Codeberg/Community/issues/2066#issue-2004460: > When try to verify by providing a signature for my SSH key, I am told to generate a signature using `bash -c "echo -n '{{TOKEN}}' | ssh-keygen -Y sign -n gitea -f <(echo '{{PUBLIC KEY}}')"` > > I get `No private key found for "/dev/fd/63"` in return, instead of a signature. > > It works if I actually point it at the public key file though.
Author
Copy link

I am not sure why it wouldn't have permission to access the private key. I made the keys with the same user I was running the command with.

I created a test key to poke around with a bit, because I had a theory.

I wondered if it might be something like running it in Konsole was doing something, but if I try to run it using a TTY (switching using control alt + F4), and that also didn't work, still No private key found for "/dev/fd/63".

If I try running with sudo substituted into the commands, I still have the issue.

So, if I run "sudo echo -n '{{TOKEN}}' | sudo ssh-keygen -Y sign -n gitea -f <(echo 'ssh-ed{{SSH PUBLIC KEY}}')", I still get No private key found for "/dev/fd/63"

I am not sure why it wouldn't have permission to access the private key. I made the keys with the same user I was running the command with. I created a test key to poke around with a bit, because I had a theory. I wondered if it might be something like running it in Konsole was doing something, but if I try to run it using a TTY (switching using control alt + F4), and that also didn't work, still `No private key found for "/dev/fd/63"`. If I try running with sudo substituted into the commands, I still have the issue. So, if I run `"sudo echo -n '{{TOKEN}}' | sudo ssh-keygen -Y sign -n gitea -f <(echo 'ssh-ed{{SSH PUBLIC KEY}}')"`, I still get `No private key found for "/dev/fd/63"`

I've gathered a little more information. ssh-keygen can be run with -vvv for some debug output, but it's not a lot for the sign command. In my case, I got:

debug1: Couldn't get agent socket: agent not present

So it couldn't connect to my ssh agent. I'm using 1Password, and my config looks something like this:

IdentityAgent "~/.1password/agent.sock"

Apparantly, ssh-keygen doesn't respect that? I was able to fix it with:

SSH_AUTH_SOCK=~/.1password/agent.sock bash -c "echo -n ...

I'm not sure what changed about my environment from when I implemented this...

So then I tried figuring out what went wrong in OP's case, with a normal key file. I disabled my ssh agent and generated a key file. The signing command with -vvv also says "agent not present". So I tried running an agent and loading the generated key in it:

eval "$(ssh-agent -s)"
ssh-add
bash -c "echo -n ...

This worked for me! @wsulla can you confirm that works for you as well?

I'm still not sure what the best solution is, but at least we'll know a little more about what's going on...

I've gathered a little more information. `ssh-keygen` can be run with `-vvv` for some debug output, but it's not a lot for the sign command. In my case, I got: > debug1: Couldn't get agent socket: agent not present So it couldn't connect to my ssh agent. I'm using 1Password, and my config looks something like this: ``` IdentityAgent "~/.1password/agent.sock" ``` Apparantly, ssh-keygen doesn't respect that? I was able to fix it with: ```sh SSH_AUTH_SOCK=~/.1password/agent.sock bash -c "echo -n ... ``` I'm not sure what changed about my environment from when I implemented this... So then I tried figuring out what went wrong in OP's case, with a normal key file. I disabled my ssh agent and generated a key file. The signing command with `-vvv` also says "agent not present". So I tried running an agent and loading the generated key in it: ```sh eval "$(ssh-agent -s)" ssh-add bash -c "echo -n ... ``` This worked for me! @wsulla can you confirm that works for you as well? I'm still not sure what the best solution is, but at least we'll know a little more about what's going on...

Ok, here's a one-liner that should work for normal keys in files:

bash -c 'if test -z "$SSH_AUTH_SOCK"; then eval "$(ssh-agent -s)"; ssh-add; fi; echo -n "{{token}}" | ssh-keygen -Y sign -n gitea -f <(echo "{{public_key}}")'

For people like me, we could add a note below telling them that they need to set their ssh agent via the SSH_AUTH_SOCK environment variable, doing it in ~/.ssh/config won't work.

Ok, here's a one-liner that should work for normal keys in files: ```sh bash -c 'if test -z "$SSH_AUTH_SOCK"; then eval "$(ssh-agent -s)"; ssh-add; fi; echo -n "{{token}}" | ssh-keygen -Y sign -n gitea -f <(echo "{{public_key}}")' ``` For people like me, we could add a note below telling them that they need to set their ssh agent via the `SSH_AUTH_SOCK` environment variable, doing it in `~/.ssh/config` won't work.
Author
Copy link

That works for me!

If I ssh-add ~/.ssh/my_codeberg_public_key and pre-authenticate using the passphrase I have on my keyfile, I get the expected signature. So I guess having a password on my keyfile breaks the command. I get no prompt for the password for my keyfile when I run the pre-generated command.

When I try to do it by manually pointing at the keyfile, I am prompted for my password. Which I guess explains why it works.

Thank you @senekor for looking into it , and I think trying to do this without asking people to point at their keyfile is an awesome idea. Happy to try other things.

That works for me! If I `ssh-add ~/.ssh/my_codeberg_public_key` and pre-authenticate using the passphrase I have on my keyfile, I get the expected signature. So I guess having a password on my keyfile breaks the command. I get no prompt for the password for my keyfile when I run the pre-generated command. When I try to do it by manually pointing at the keyfile, I am prompted for my password. Which I guess explains why it works. Thank you @senekor for looking into it , and I think trying to do this without asking people to point at their keyfile is an awesome idea. Happy to try other things.
Author
Copy link

Sorry, I missed your last comment. I had to specifically add my public key in SSH add.

Sorry, I missed your last comment. I had to specifically add my public key in SSH add.

In my testing, using a key in a file without a passphrase also didn't work at first, so that wasn't the issue I think. I also tried the oneliner above with a key in a file with a passphrase this time and it also worked (prompting me for the passphrase). I didn't need to tell ssh-add specifically with key to load, it discovered that automatically.

In my testing, using a key in a file without a passphrase also didn't work at first, so that wasn't the issue I think. I also tried the [oneliner above](https://codeberg.org/Codeberg/Community/issues/2066#issuecomment-6166414) with a key in a file **with a passphrase** this time and it also worked (prompting me for the passphrase). I didn't need to tell `ssh-add` specifically with key to load, it discovered that automatically.
Author
Copy link

OK, interesting, I am still seeing the same issue with your one-liner. I am not very experienced with SSH, but looking at the man page, if you run ssh-add without modification, it only adds keys with standard names. I create one key per service, so my private keyfile for this test key is named codeberg2_id_ed25519 and the public key is codeberg2_id_ed25519.pub. So, I think your one liner only works without specifying if your keyfile is named one of ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519_sk.

For your one liner to work for me, I need to make it bash -c 'if test -z "$SSH_AUTH_SOCK"; then eval "$(ssh-agent -s)"; ssh-add {{LOCATION OF PRIVATE KEY}}; fi; echo -n "{{TOKEN}}" | ssh-keygen -Y sign -n gitea -f <(echo "{{SSH PUBLIC KEY}}")'

OK, interesting, I am still seeing the same issue with your one-liner. I am not very experienced with SSH, but looking at the man page, if you run ssh-add without modification, it only adds keys with standard names. I create one key per service, so my private keyfile for this test key is named `codeberg2_id_ed25519` and the public key is `codeberg2_id_ed25519.pub`. So, I think your one liner only works without specifying if your keyfile is named one of `~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519_sk.` For your one liner to work for me, I need to make it `bash -c 'if test -z "$SSH_AUTH_SOCK"; then eval "$(ssh-agent -s)"; ssh-add {{LOCATION OF PRIVATE KEY}}; fi; echo -n "{{TOKEN}}" | ssh-keygen -Y sign -n gitea -f <(echo "{{SSH PUBLIC KEY}}")'`

I see. We could try to be sneaky and enumerate the key files with custom names in the ~/.ssh directory:

ssh-add $(find ~/.ssh/ -name "*.pub" | sed "s/.pub//")

Surely there are more exotic setups this doesn't cover, but I think we have to draw the line somewhere.

I see. We could try to be sneaky and enumerate the key files with custom names in the `~/.ssh` directory: ```sh ssh-add $(find ~/.ssh/ -name "*.pub" | sed "s/.pub//") ``` Surely there are more exotic setups this doesn't cover, but I think we have to draw the line somewhere.

Does the old way of specifying the public key works? We could resurrect the old way and offer it as fallback if the one via <(...) doesn't work.

Does the old way of specifying the public key works? We could resurrect the old way and offer it as fallback if the one via `<(...)` doesn't work.
Author
Copy link

I was assuming that I was just on the wrong side of the line that has to be drawn somewhere, maybe enough to have an FAQ entry, or be offered an alternative, but not enough to be handled by the auto-generated command.

I like the idea of a fallback to the old way in case your very svelte and tidy way of doing it doesn't work.

I was assuming that I was just on the wrong side of the line that has to be drawn somewhere, maybe enough to have an FAQ entry, or be offered an alternative, but not enough to be handled by the auto-generated command. I like the idea of a fallback to the old way in case your very svelte and tidy way of doing it doesn't work.

Actually I'm curious, why do you have multiple ssh keys on one machine? I can't think of a security benefit to that.

Actually I'm curious, why do you have multiple ssh keys on one machine? I can't think of a security benefit to that.
Author
Copy link

I don't entirely remember, but when I sat down and taught myself how SSH keys work a few years ago, that is what I decided to do. Since I use a config file, it isn't something I think about much outside of adding new places I want to SSH into. I can't remember if I found a strong argument for it being more secure, but I kind of liked the idea of a separation of concerns.

I don't entirely remember, but when I sat down and taught myself how SSH keys work a few years ago, that is what I decided to do. Since I use a config file, it isn't something I think about much outside of adding new places I want to SSH into. I can't remember if I found a strong argument for it being more secure, but I kind of liked the idea of a separation of concerns.

btw, this worked for me:

echo -n "{{TOKEN}}" > /tmp/token

sudo ssh-keygen -Y sign -f "{{SSH PUBLIC KEY}}" -n gitea /tmp/token

cat /tmp/token.sig

btw, this worked for me: `echo -n "{{TOKEN}}" > /tmp/token` `sudo ssh-keygen -Y sign -f "{{SSH PUBLIC KEY}}" -n gitea /tmp/token` `cat /tmp/token.sig`

The related PR was merged, I think this issue can be closed now.

The [related PR](https://codeberg.org/forgejo/forgejo/pulls/8821) was merged, I think this issue can be closed now.
Author
Copy link

Agreed, thank you so much for looking into this.

Agreed, thank you so much for looking into this.
jasewolf referenced this issue from a commit 2025年09月07日 10:49:16 +02:00
Sign in to join this conversation.
No Branch/Tag specified
main
No results found.
Labels
Clear labels
accessibility

Reduces accessibility and is thus a "bug" for certain user groups on Codeberg.
bug

Something is not working the way it should. Does not concern outages.
bug
infrastructure

Errors evidently caused by infrastructure malfunctions or outages
Codeberg

This issue involves Codeberg's downstream modifications and settings and/or Codeberg's structures.
contributions welcome

Please join the discussion and consider contributing a PR!
docs

No bug, but an improvement to the docs or UI description will help
duplicate

This issue or pull request already exists
enhancement

New feature
infrastructure

Involves changes to the server setups, use `bug/infrastructure` for infrastructure-related user errors.
legal

An issue directly involving legal compliance
licence / ToS

involving questions about the ToS, especially licencing compliance
please chill
we are volunteers

Please consider editing your posts and remember that there is a human on the other side. We get that you are frustrated, but it's harder for us to help you this way.
public relations

Things related to Codeberg's external communication
question

More information is needed
question
user support

This issue contains a clearly stated problem. However, it is not clear whether we have to fix anything on Codeberg's end, but we're helping them fix it and/or find the cause.
s/Forgejo

Related to Forgejo. Please also check Forgejo's issue tracker.
s/Forgejo/migration

Migration related issues in Forgejo
s/Pages

Issues related to the Codeberg Pages feature
s/Weblate

Issue is related to the Weblate instance at https://translate.codeberg.org
s/Woodpecker

Woodpecker CI related issue
security

involves improvements to the sites security
service

Add a new service to the Codeberg ecosystem (instead of implementing into Gitea)
upstream

An open issue or pull request to an upstream repository to fix this issue (partially or completely) exists (i.e. Gitea, Forgejo, etc.)
wontfix

Codeberg's current set of contributors are not planning to spend time on delegating this issue.
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
5 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Codeberg/Community#2066
Reference in a new issue
Codeberg/Community
No description provided.
Delete branch "%!s()"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?