6.7 KiB
Git Provider Setup
This document covers manual setup for GitHub OAuth, Puter Git (Gitea), webhooks, and Convex environment variables.
Never place admin or user tokens in checked-in
.envfiles or browser variables. All secrets must be Convex environment variables set vianpx convex env set.
GitHub OAuth Application
- Go to GitHub Settings → Developer settings → OAuth Apps and open the app whose client ID will be stored in Convex.
- Set the application name and homepage URL. The homepage URL should be the current
SITE_URL. - Set the single Authorization callback URL to exactly:
GitHub OAuth Apps support one callback URL. Scheme, host, port, and path must match the
<SITE_URL>/api/auth/callback/githubredirect_urisent by Better Auth exactly. - Generate a client secret.
- Set the credentials on the Convex deployment—not only in the local
.envfile:cd packages/backend npx convex env set GITHUB_CLIENT_ID <your-client-id> npx convex env set GITHUB_CLIENT_SECRET <your-client-secret> npx convex env list
The configured SITE_URL, GitHub callback URL, and browser URL are one unit. For a shared Convex deployment, switch all three before testing a different public origin. See Auth Proxy for the deployment boundary.
Requested scopes
Zopu requests GitHub identity and private-repository access: read:user, user:email, repo, and read:org. repo grants access to private repositories; read:org permits organization repository discovery.
GitHub Webhook (manual setup for OAuth-based version)
- Go to the GitHub repository Settings > Webhooks > Add webhook.
- Payload URL:
<CONVEX_SITE_URL>/api/git/webhooks/github - Content type:
application/json - Secret: generate a strong random string and set it as:
npx convex env set GITHUB_WEBHOOK_SECRET <your-webhook-secret> - Select individual events:
- Push
- Repository (created, deleted, transferred, renamed, visibility)
- Delete
- Create
- Public
- Fork
- Do not select "Send me everything."
Puter Git (Gitea) Admin Token
- As a Gitea admin, go to Settings > Applications > Generate New Token.
- Select scopes:
write:admin,write:organization,write:repository. - Set the token:
npx convex env set PUTER_GIT_ADMIN_TOKEN <your-admin-token>
This token is used only for platform administration (user creation, organization creation, repository creation, migration). It is never used for end-user operations.
Puter Git Webhook
After a repository is created or migrated, Zopu ensures a webhook is configured automatically. If manual setup is needed:
- Go to the Gitea repository Settings > Webhooks > Add Webhook > Gitea.
- Target URL:
<CONVEX_SITE_URL>/api/git/webhooks/puter - HTTP method: POST
- Content-Type:
application/json - Secret: generate a strong random string and set it as:
npx convex env set GITEA_WEBHOOK_SECRET <your-webhook-secret> - Trigger on: Push events, Repository events.
Credential Encryption Key
Generate a 32-byte encryption key for AES-GCM credential encryption:
openssl rand -base64 32 | base64 | tr -d '\n' | pbcopy
Set it as:
npx convex env set GIT_CREDENTIAL_ENCRYPTION_KEY <base64url-encoded-32-bytes>
The key must be exactly 32 bytes when base64url-decoded.
Same-Origin Proxy for Better Auth Callbacks
Better Auth requires the callback URL to be on the same origin as SITE_URL. If your Convex deployment uses a different origin:
- Configure a reverse proxy (e.g., Caddy) to forward
/api/auth/*to the Convex deployment. - Set
SITE_URLto the proxy origin. - Set
CONVEX_SITE_URLto the Convex deployment URL.
Validation Procedures
Verify a Puter PAT connection
- Connect a Puter PAT through the UI.
- Verify the connection state shows
active. - List private repositories to confirm token validity.
Verify GitHub OAuth
- Click "Connect GitHub" in the UI.
- Complete the GitHub OAuth flow.
- Verify the connection state shows
active.
OAuth diagnostics
| Symptom | Cause | Fix |
|---|---|---|
Provider not found from /api/auth/link-social |
GITHUB_CLIENT_ID or GITHUB_CLIENT_SECRET is absent from the Convex deployment env store. A local .env does not configure cloud functions. |
Set both variables with npx convex env set and verify with npx convex env list. |
GitHub Invalid Redirect URI |
GitHub's saved callback does not exactly equal the app's redirect_uri. |
Set the OAuth App's single callback to <SITE_URL>/api/auth/callback/github. |
state_mismatch at a convex.site page |
Better Auth started on the public origin but GitHub returned to the direct Convex host, so the public-origin state cookie is unavailable. | Set Better Auth baseURL to SITE_URL; proxy /api/auth/* through the public origin. |
email_doesn't_match after selecting GitHub |
A deployment predates the explicit-link policy or has not received the current auth configuration. | Deploy the current backend. Explicit linkSocial allows a different GitHub email without changing the Zopu account email. |
externalEmail is null during connectGithub |
The GitHub account hides its public email; GitHub returns null from /user. |
Deploy the current backend, which normalizes nullable provider emails before Convex persistence. |
GitHub connections are explicit authenticated account links. The linked GitHub email may differ from the existing Zopu account email; Zopu retains the existing account email and only stores the GitHub identity and OAuth credential needed for repository access.
Reconnection
If a token is expired or revoked:
- The connection state shows
reauth-required. - Reconnect the provider through the UI.
- The old connection state is updated to
active. - Projects, repositories, Work, and artifacts are not deleted.
Environment Variables Summary
| Variable | Required | Description |
|---|---|---|
SITE_URL |
Yes | Public-facing URL |
CONVEX_SITE_URL |
Yes | Convex deployment URL (may differ from SITE_URL with proxy) |
GIT_CREDENTIAL_ENCRYPTION_KEY |
Yes | Base64url-encoded 32-byte AES-GCM key |
PUTER_GIT_ADMIN_TOKEN |
Yes | Gitea admin token for provisioning |
GITHUB_CLIENT_ID |
For GitHub | OAuth app client ID |
GITHUB_CLIENT_SECRET |
For GitHub | OAuth app client secret |
GITHUB_WEBHOOK_SECRET |
For GitHub webhooks | HMAC verification secret |
GITEA_WEBHOOK_SECRET |
For Puter webhooks | HMAC verification secret |
FLUE_DB_TOKEN |
Yes | Private agent backend token |
FLUE_URL |
Optional | Private agent backend URL |
NATIVE_APP_URL |
Optional | Native app deep-link scheme |