feat: base git/gnupg install + auto SSH/GPG key setup for external git
Provision Coder Templates / provision (push) Successful in 2m11s
Provision Coder Templates / provision (push) Successful in 2m11s
- Every template's coder_agent startup script now unconditionally
installs git and gnupg as base packages (guarded on `command -v`, so
it's a fast no-op where already present, e.g. templates/web's baked
image). Not every base image ships gnupg by default.
- cli-setup-wizard.sh (all 6 templates) now tracks whether the user
actually ended up authenticated against GitHub and/or Gitea via the
existing gh/tea install-and-login prompts. If at least one succeeded,
it asks once more whether to auto-generate an SSH key (ed25519) and a
GPG signing key (ed25519, quick-gen) and register them with whichever
host(s) are in play - stays completely silent for "local git only"
(neither gh nor tea set up).
- GitHub: `gh ssh-key add` / `gh gpg-key add` (official gh CLI
subcommands).
- Gitea: direct calls against `/api/v1/user/keys` and
`/api/v1/user/gpg_keys`, reusing the token `tea login add` already
stored in tea's config.yml (parsed with a small awk extractor).
- Either upload failing (already added, API shape mismatch, etc.)
just prints the manual command/URL and moves on - never blocks the
rest of the wizard, consistent with every other step's style.
- git is configured to sign commits with the new key
(user.signingkey + commit.gpgsign) once a GPG key exists, whether
freshly generated or already present from a prior run.
README updated to document both additions.
This commit is contained in:
@@ -19,6 +19,12 @@ WIZARD_DONE_FILE="${HOME}/.cache/coder-cli-wizard/done"
|
||||
FORCE=0
|
||||
[ "${1:-}" = "--force" ] && FORCE=1
|
||||
|
||||
# Tracks whether the user actually ended up authenticated against GitHub
|
||||
# and/or Gitea below, so the SSH/GPG key step can ask about exactly the
|
||||
# host(s) in play (and stay silent - "local git only" - if neither).
|
||||
DID_GITHUB=0
|
||||
DID_GITEA=0
|
||||
|
||||
export BUN_INSTALL="${HOME}/.bun"
|
||||
export PATH="${BUN_INSTALL}/bin:${HOME}/.local/bin:${PATH}"
|
||||
|
||||
@@ -112,6 +118,7 @@ else
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1 && DID_GITHUB=1
|
||||
|
||||
# --- Gitea CLI (tea) ---
|
||||
if command -v tea >/dev/null 2>&1; then
|
||||
@@ -136,6 +143,101 @@ else
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
TEA_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/tea/config.yml"
|
||||
if command -v tea >/dev/null 2>&1 && [ -f "$TEA_CONFIG" ]; then
|
||||
TEA_URL="$(awk '/^logins:/{f=1} f && /^ url:/{print $2; exit}' "$TEA_CONFIG")"
|
||||
TEA_TOKEN="$(awk '/^logins:/{f=1} f && /^ token:/{print $2; exit}' "$TEA_CONFIG")"
|
||||
[ -n "$TEA_URL" ] && [ -n "$TEA_TOKEN" ] && DID_GITEA=1
|
||||
fi
|
||||
|
||||
# --- SSH + GPG keys for the external git host(s) selected above ---
|
||||
# Only asks if the user actually set up GitHub and/or Gitea just now -
|
||||
# stays silent for "local git only" (neither was set up).
|
||||
if [ "$DID_GITHUB" -eq 1 ] || [ "$DID_GITEA" -eq 1 ]; then
|
||||
if [ "$DID_GITHUB" -eq 1 ] && [ "$DID_GITEA" -eq 1 ]; then
|
||||
KEY_HOSTS_DESC="GitHub and Gitea"
|
||||
elif [ "$DID_GITHUB" -eq 1 ]; then
|
||||
KEY_HOSTS_DESC="GitHub"
|
||||
else
|
||||
KEY_HOSTS_DESC="Gitea"
|
||||
fi
|
||||
|
||||
if ask_yes_no "Auto-generate an SSH key and a GPG signing key, and register them with $KEY_HOSTS_DESC?"; then
|
||||
KEY_NAME="${GIT_AUTHOR_NAME:-$(whoami)}"
|
||||
KEY_EMAIL="${GIT_AUTHOR_EMAIL:-$(whoami)@$(hostname)}"
|
||||
|
||||
# SSH key: ed25519, no passphrase (disposable dev workspace convenience;
|
||||
# add one manually afterwards with `ssh-keygen -p` if you want one).
|
||||
SSH_KEY="$HOME/.ssh/id_ed25519"
|
||||
if [ ! -f "$SSH_KEY" ]; then
|
||||
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
|
||||
ssh-keygen -t ed25519 -N "" -C "$KEY_EMAIL" -f "$SSH_KEY" -q
|
||||
echo "Generated SSH key: ${SSH_KEY}.pub"
|
||||
else
|
||||
echo "SSH key already exists at ${SSH_KEY}.pub, reusing it."
|
||||
fi
|
||||
|
||||
if [ "$DID_GITHUB" -eq 1 ]; then
|
||||
if gh ssh-key add "${SSH_KEY}.pub" --title "coder-$(hostname)" 2>/dev/null; then
|
||||
echo "SSH key added to GitHub."
|
||||
else
|
||||
echo "Couldn't add the SSH key to GitHub automatically (may already be added). Add manually: gh ssh-key add ${SSH_KEY}.pub"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DID_GITEA" -eq 1 ]; then
|
||||
SSH_PUB_JSON="$(sed 's/\\/\\\\/g; s/"/\\"/g' "${SSH_KEY}.pub")"
|
||||
if curl -fsS -X POST "${TEA_URL%/}/api/v1/user/keys" \
|
||||
-H "Authorization: token ${TEA_TOKEN}" -H "Content-Type: application/json" \
|
||||
-d "{\"title\":\"coder-$(hostname)\",\"key\":\"${SSH_PUB_JSON}\"}" >/dev/null 2>&1; then
|
||||
echo "SSH key added to Gitea."
|
||||
else
|
||||
echo "Couldn't add the SSH key to Gitea automatically (may already be added). Add manually at: ${TEA_URL%/}/user/settings/keys"
|
||||
fi
|
||||
fi
|
||||
|
||||
# GPG key: ed25519 signing key, no passphrase, no expiry.
|
||||
if gpg --list-secret-keys --with-colons "$KEY_EMAIL" 2>/dev/null | grep -q '^sec'; then
|
||||
echo "GPG key for $KEY_EMAIL already exists, reusing it."
|
||||
else
|
||||
mkdir -p "$HOME/.gnupg" && chmod 700 "$HOME/.gnupg"
|
||||
grep -qF "allow-loopback-pinentry" "$HOME/.gnupg/gpg-agent.conf" 2>/dev/null \
|
||||
|| echo "allow-loopback-pinentry" >> "$HOME/.gnupg/gpg-agent.conf"
|
||||
gpgconf --kill gpg-agent 2>/dev/null
|
||||
if gpg --batch --pinentry-mode loopback --passphrase '' --quick-gen-key "$KEY_NAME <$KEY_EMAIL>" ed25519 sign 0 2>/dev/null; then
|
||||
echo "Generated GPG signing key for $KEY_EMAIL."
|
||||
else
|
||||
echo "GPG key generation failed. Generate manually with: gpg --quick-gen-key \"$KEY_NAME <$KEY_EMAIL>\" ed25519 sign 0"
|
||||
fi
|
||||
fi
|
||||
GPG_KEY_ID="$(gpg --list-secret-keys --with-colons "$KEY_EMAIL" 2>/dev/null | awk -F: '/^sec/{print $5; exit}')"
|
||||
|
||||
if [ -n "$GPG_KEY_ID" ]; then
|
||||
git config --global user.signingkey "$GPG_KEY_ID"
|
||||
git config --global commit.gpgsign true
|
||||
echo "Configured git to sign commits with this key."
|
||||
|
||||
if [ "$DID_GITHUB" -eq 1 ]; then
|
||||
if gpg --armor --export "$GPG_KEY_ID" | gh gpg-key add - 2>/dev/null; then
|
||||
echo "GPG key added to GitHub."
|
||||
else
|
||||
echo "Couldn't add the GPG key to GitHub automatically (may already be added). Add manually: gpg --armor --export $GPG_KEY_ID | gh gpg-key add -"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DID_GITEA" -eq 1 ]; then
|
||||
GPG_ARMORED_JSON="$(gpg --armor --export "$GPG_KEY_ID" | awk '{printf "%s\\n", $0}')"
|
||||
if curl -fsS -X POST "${TEA_URL%/}/api/v1/user/gpg_keys" \
|
||||
-H "Authorization: token ${TEA_TOKEN}" -H "Content-Type: application/json" \
|
||||
-d "{\"armored_public_key\":\"${GPG_ARMORED_JSON}\"}" >/dev/null 2>&1; then
|
||||
echo "GPG key added to Gitea."
|
||||
else
|
||||
echo "Couldn't add the GPG key to Gitea automatically (may already be added). Add manually at: ${TEA_URL%/}/user/settings/keys"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if ask_yes_no "Mark setup wizard as complete so it stops asking on new terminals?"; then
|
||||
|
||||
Reference in New Issue
Block a user