Skip to content

Instantly share code, notes, and snippets.

@kntjspr
Created October 21, 2025 06:12
Show Gist options
  • Select an option

  • Save kntjspr/582493f145c8d79ac890c09b3ea9b81b to your computer and use it in GitHub Desktop.

Select an option

Save kntjspr/582493f145c8d79ac890c09b3ea9b81b to your computer and use it in GitHub Desktop.
Setup encrypted git remote

⚙️ GOAL

Account Purpose Repo Origin SSH Key GPG Key Encryption
dev Development git@github.com:dev-user/dev-repo.git /root/.ssh/id_dev_ed25519 dev <dev@mail.com> git-remote-gcrypt (Dev GPG)
prod Production git@github.com:prod-user/prod-repo.git /root/.ssh/id_prod_ed25519 prod <other@mail.com> git-remote-gcrypt (Prod GPG)

Everything runs in WSL, keys stored under root, users without root cannot access or push.
The same local repo folder is used for both dev and prod (shared working copy). Dev/prod are not branches but separate configurations (remotes, SSH hosts, GPG keys, and Git identities).
Is this possible? Yes. Git supports multiple remotes in one repo, with per-remote URLs (including gcrypt prefixes) and gcrypt-specific configs. SSH keys are selected via the host in the URL. However, repo-level Git configs (e.g., user.name, user.email, user.signingkey) are shared, so switching between dev/prod requires a simple script or manual commands to update them before committing/pushing. Gcrypt encryption/signing is handled per-remote automatically.


0. Install git-remote-gcrypt

In WSL (assuming Ubuntu/Debian-based distro):

sudo apt update
sudo apt install git-remote-gcrypt

If not available via package manager, clone and install from source:

git clone https://github.com/spwhitton/git-remote-gcrypt.git
cd git-remote-gcrypt
sudo ./install.sh

Ensure GPG is installed: sudo apt install gnupg.


1. Generate SSH keys (as root)

sudo su
mkdir -p /root/.ssh && chmod 700 /root/.ssh
ssh-keygen -t ed25519 -C "dev@github" -f /root/.ssh/id_dev_ed25519
ssh-keygen -t ed25519 -C "prod@github" -f /root/.ssh/id_prod_ed25519
chmod 600 /root/.ssh/id_* 

View public keys and add them to each GitHub account:

cat /root/.ssh/id_dev_ed25519.pub
cat /root/.ssh/id_prod_ed25519.pub

Add those in GitHub → Settings → SSH and GPG keys → New SSH key.


2. Configure SSH for both accounts

Create /root/.ssh/config:

sudo nano /root/.ssh/config

Paste:

# Dev account
Host github-dev
  HostName github.com
  User git
  IdentityFile /root/.ssh/id_dev_ed25519
  IdentitiesOnly yes

# Prod account
Host github-prod
  HostName github.com
  User git
  IdentityFile /root/.ssh/id_prod_ed25519
  IdentitiesOnly yes

3. Test SSH connections

ssh -T github-dev
ssh -T github-prod

You should see:

Hi <user>! You've successfully authenticated, but GitHub does not provide shell access.

4. Import/Create GPG Keys (as root)

Import Dev GPG Key (already in Windows B:)

sudo gpg --import /mnt/b/dev-private-key.asc
sudo gpg --list-secret-keys --keyid-format=long

Find the key ID (like 980F354B5EEF0B51).

Create Prod GPG Key

sudo gpg --quick-generate-key "prod <other@mail.com>" rsa4096 sign,encrypt 2y
sudo gpg --list-secret-keys --keyid-format=long

Note the new key ID (e.g. ABC123DEF456GHI7).

Enable global GPG signing for commits:

git config --global commit.gpgsign true

5. Initialize Shared Local Repo and Add Remotes

Create/init the shared repo folder (e.g., /home/username/shared-repo):

cd /path/to/shared-repo  # Your shared working directory
git init
# Add initial files if needed
git add . && git commit -m "initial shared commit"

Add dev and prod remotes (using gcrypt prefixes for encryption):

# Dev remote (uses github-dev host for SSH key)
git remote add dev gcrypt::github-dev:dev-user/dev-repo.git

# Prod remote (uses github-prod host for SSH key)
git remote add prod gcrypt::github-prod:prod-user/prod-repo.git

Configure per-remote gcrypt settings (encryption/signing keys):

# Dev gcrypt configs (tied to dev remote)
git config remote.dev.gcrypt-signingkey 980F354B5EEF0B51  # Dev GPG key for manifest signing
git config remote.dev.gcrypt-participants 980F354B5EEF0B51  # Dev GPG as recipient (self-trusted)

# Prod gcrypt configs (tied to prod remote)
git config remote.prod.gcrypt-signingkey ABC123DEF456GHI7  # Prod GPG key for manifest signing
git config remote.prod.gcrypt-participants ABC123DEF456GHI7  # Prod GPG as recipient (self-trusted)

Notes:

  • Target repos must exist on GitHub (empty is fine; first push will initialize encrypted content).
  • Gcrypt handles encryption/decryption per-remote: local files stay unencrypted; pushes to dev encrypt with Dev GPG, pulls decrypt with it. Same for prod.
  • Every push to a gcrypt remote uses --force under the hood. Always pull first to sync.

6. Switching Dev/Prod Configs (Shared Repo Challenge)

Repo-level Git configs (user.name, user.email, user.signingkey) apply to the entire shared repo and must be switched manually or via script when changing "mode" (dev vs. prod). Commits/pushes will use the active config + the remote's SSH host (for keys) and gcrypt settings (for encryption).

Option 1: Manual Switch (Simple)

Before working on dev/prod:

Switch to Dev:

cd /path/to/shared-repo
git config user.name "Dev Account"
git config user.email "mail@mail.com"
git config user.signingkey ABC123DEF456GHI6

Switch to Prod:

cd /path/to/shared-repo
git config user.name "Prod Account"
git config user.email "other@mail.com"
git config user.signingkey ABC123DEF456GHI7

Option 2: Bash Script for Easy Switching (Recommended)

Create a switch script (~/switch-git-mode.sh):

#!/bin/bash
cd /path/to/shared-repo || exit 1

case "$1" in
  dev)
    git config user.name "Dev Account"
    git config user.email "mail@mail.com"
    git config user.signingkey 980F354B5EEF0B51
    echo "Switched to DEV mode (SSH: github-dev, GPG: 980F354B5EEF0B51)"
    ;;
  prod)
    git config user.name "Prod Account"
    git config user.email "other@mail.com"
    git config user.signingkey ABC123DEF456GHI7
    echo "Switched to PROD mode (SSH: github-prod, GPG: ABC123DEF456GHI7)"
    ;;
  *)
    echo "Usage: $0 {dev|prod}"
    exit 1
    ;;
esac

Make executable: chmod +x ~/switch-git-mode.sh.
Usage: ~/switch-git-mode.sh dev or ~/switch-git-mode.sh prod.

For even smoother workflow, add aliases to ~/.bashrc:

alias git-dev='~/switch-git-mode.sh dev && cd /path/to/shared-repo'
alias git-prod='~/switch-git-mode.sh prod && cd /path/to/shared-repo'

7. Workflow: Commit and Push

  1. Switch mode (e.g., ~/switch-git-mode.sh dev).
  2. Work/edit files in the shared folder.
  3. Commit (uses active user config + GPG signing key):
    git add . && git commit -m "your message"  
  4. Pull latest from target remote (decrypts with that remote's GPG):
    git pull dev main  # For dev  
    # OR  
    git pull prod main  # For prod  
  5. Push (uses remote's URL/SSH host for auth, gcrypt for encryption):
    git push dev main  # Encrypts with dev GPG, pushes to dev repo  
    # OR  
    git push prod main  # Encrypts with prod GPG, pushes to prod repo  

Notes:

  • Pulls from one remote won't affect the other (separate encrypted histories).
  • If histories diverge, merge/rebase as needed before pushing.
  • For large repos, gcrypt pushes/pulls can be slow over GitHub—consider alternatives like S3 backend for gcrypt if performance is an issue.

8. Summary

Component Location/Setup Owner Purpose
SSH keys /root/.ssh/id_dev_ed25519, /root/.ssh/id_prod_ed25519 root Secure auth (selected via remote host)
GPG keys gpg --list-secret-keys root Commit signing + gcrypt encryption/decryption
SSH Config /root/.ssh/config root Maps hosts to keys (github-dev/prod)
Git Remotes dev & prod (gcrypt:: prefixed URLs) user Separate pushes/pulls to dev/prod repos
Gcrypt Configs remote.<name>.gcrypt-* (per-remote) user Per-remote encryption (Dev/Prod GPG)
Git Identities user.name/email/signingkey (switched via script/manual) user Author/signer per mode (dev/prod)
Shared Repo Folder /home/username/shared-repo user Unencrypted working copy for both modes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment