Fixing Go Module Authentication Errors with Private GitHub Repositories

Struggling with "Authentication failed" errors when running `go mod tidy` on private GitHub repositories, even though your SSH keys are perfectly configured? You're not alone. The issue stems from Go modules defaulting to HTTPS while your SSH configuration only applies to SSH connections.

Fixing Go Module Authentication Errors with Private GitHub Repositories

The Problem: When SSH Config Isn't Enough

If you're working with Go modules and private GitHub repositories, you might encounter this frustrating error:

go: downloading github.com/YourOrg/private-repo v0.0.0-20250924075251-8178d5227f9d
go: github.com/YourOrg/private-repo@v0.0.0-20250924075251-8178d5227f9d: invalid version: git ls-remote -q origin: exit status 128:
remote: Invalid username or token. Password authentication is not supported for Git operations.
fatal: Authentication failed for 'https://github.com/YourOrg/private-repo/'

This happens even when you have SSH keys properly configured in your ~/.ssh/config:

Host company.github.com
  HostName github.com
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/company_id_rsa
  IdentitiesOnly yes

Why This Happens

The root cause is simple but not obvious: Go modules default to using HTTPS for GitHub repositories, while your SSH configuration only applies to SSH connections. When go mod tidy tries to fetch dependencies, it uses URLs like https://github.com/YourOrg/private-repo, completely bypassing your SSH setup.

Solution Options

Option 1: Personal Access Token (Traditional Approach)

Step 1: Create a GitHub Personal Access Token

  1. Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
  2. Click "Generate new token (classic)"
  3. Name it something like "Go Modules Access"
  4. Set appropriate expiration (90+ days recommended)
  5. Critical: Select the repo scope for full control of private repositories
  6. Copy and securely save the token

Step 2: Configure Git Credentials

# Enable credential storage
git config --global credential.helper store

# Set your GitHub username
git config --global user.name "YourGitHubUsername"

Step 3: Configure Go for Private Modules

# Tell Go these are private repositories
go env -w GOPRIVATE=github.com/YourOrg/*

# Skip checksum verification for private repos
go env -w GONOSUMDB=github.com/YourOrg/*

When running go mod tidy, you'll be prompted for:

  • Username: Your GitHub username
  • Password: The Personal Access Token (NOT your GitHub password)

This is the elegant solution if you already have SSH keys configured. Instead of switching to HTTPS authentication, make Go use your existing SSH setup.

The Magic Command:

git config --global url."git@company.github.com:YourOrg/".insteadOf "https://github.com/YourOrg/"

This command tells Git: "Whenever you see https://github.com/YourOrg/, replace it with git@company.github.com:YourOrg/"

Complete Setup:

# 1. Configure URL rewriting for your organization
git config --global url."git@company.github.com:YourOrg/".insteadOf "https://github.com/YourOrg/"

# 2. Tell Go these repositories are private
go env -w GOPRIVATE=github.com/YourOrg/*

# 3. Test the setup
go mod tidy

Why the SSH Approach Is Better

  1. Leverages Existing Infrastructure: Uses your already-configured SSH keys and custom host aliases
  2. No Token Management: No need to create, rotate, or secure Personal Access Tokens
  3. Organization-Specific: Only affects your organization's repositories, leaving public repos unchanged
  4. Seamless Integration: Works transparently with all Git operations

Understanding the URL Rewriting

When you run the URL rewriting command, here's what happens:

Before:

go mod tidy tries to access: https://github.com/YourOrg/private-repo

After:

Git automatically translates to: git@company.github.com:YourOrg/private-repo
Uses your SSH config and company_id_rsa key

Troubleshooting Tips

Verify Your Configuration

# Check if URL rewriting is configured
git config --global --get-regexp url

# Check Go private module settings
go env GOPRIVATE
go env GONOSUMDB

Test SSH Connection

# Test your SSH setup
ssh -T git@company.github.com

You should see: Hi YourUsername! You've successfully authenticated...

Common Issues

  1. Wrong SSH Host: Make sure your URL rewriting uses the exact host from your SSH config (company.github.com)

  2. Missing GOPRIVATE: Without this, Go tries to use the public proxy, which won't work for private repos

  3. SSH Key Issues: Verify your SSH key is loaded and has repository access:

    ssh-add -l
    

Alternative: Global GitHub SSH Rewriting

If you want ALL GitHub repositories to use SSH:

git config --global url."git@github.com:".insteadOf "https://github.com/"

But the organization-specific approach is more controlled and safer.

Conclusion

The SSH URL rewriting approach is the cleanest solution for developers already using SSH keys with GitHub. It requires minimal configuration changes and integrates seamlessly with existing workflows.

Key Takeaways:

  • Go modules use HTTPS by default, ignoring SSH configurations
  • URL rewriting bridges this gap elegantly
  • Organization-specific rewriting provides precise control
  • Always set GOPRIVATE for your private repositories

With these steps, your go mod tidy operations will work smoothly with your private repositories, using your existing SSH key infrastructure.