Set Up an Agent to Push Directly to a GitHub Repo

Set Up an Agent to Push Directly to a GitHub Repo

Goal

This guide walks through a gentle, practical way to let an agent such as Hermes commit and push directly to a GitHub repository without placing your main personal GitHub SSH key on the server.

The target architecture is:

Local developer machine -> GitHub repository
Hermes agent on server  -> commit and push directly to master

The server uses a dedicated GitHub machine user and a dedicated SSH key:

Hermes agent -> dedicated machine user -> server-only SSH key -> minimal repo access

When to use this setup

This approach tends to fit well when:

  • The agent needs to create commits.
  • The agent needs to push changes back to GitHub.
  • The server needs write access to the repository.
  • You want commit history to clearly show which commits were made by the agent.
  • You do not want your main personal GitHub key stored on the server.

If the server only needs to pull code, a read-only deploy key is usually enough. If the agent needs to push, a machine user is often cleaner than sharing a personal account key.

Required GitHub permissions

The machine user only needs:

Repository permission: Write

Write access allows the machine user to:

  • Clone the repository.
  • Pull updates.
  • Create commits.
  • Push branches.
  • Push directly to master if branch rules allow it.

Try to avoid Admin unless the agent genuinely needs repository administration rights.

Step 1: Create a dedicated GitHub machine user

Create a separate GitHub account for the agent.

Example:

skywirex-hermes

Recommended account setup:

  • Enable 2FA.
  • Use a separate email address.
  • Give the profile a clear automation identity.
  • Prefer not to reuse your main GitHub account.

Example display name:

Hermes Agent

GitHub allows manually created machine users for automation. In most cases, it is best to avoid auto-created accounts or multiple accounts for the same workflow.

Step 2: Add the machine user to the repository

Open the target repository on GitHub.

For a personal repository:

Repository -> Settings -> Collaborators

For an organization repository:

Repository -> Settings -> Collaborators and teams

Add the machine user:

skywirex-hermes

Give it:

Write

Then log in as the machine user and accept the invitation.

Step 3: Generate a dedicated SSH key on the server

SSH into the server using the same Linux user that runs the agent:

ssh your-user@your-server

Generate a dedicated SSH key:

ssh-keygen -t ed25519 -C "hermes@your-server"

When prompted for the key path, use a clear filename:

~/.ssh/id_ed25519_hermes_github

For unattended automation, leaving the passphrase empty is usually simpler, though it does make server security more important. If you prefer a passphrase, just make sure the agent runtime has a proper SSH agent setup.

Print the public key:

cat ~/.ssh/id_ed25519_hermes_github.pub

Copy the full public key line.

Step 4: Add the SSH key to the machine user

Log in to GitHub as the machine user.

Go to:

Settings -> SSH and GPG keys -> New SSH key

Use:

Title: production-server-hermes
Key type: Authentication Key
Key: paste the public key from the server

Save the key.

Add this key to the machine user account rather than your main personal GitHub account.

Step 5: Configure an SSH alias on the server

Edit SSH config on the server:

nano ~/.ssh/config

Add:

Host github-hermes
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_hermes_github
  IdentitiesOnly yes

Set permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519_hermes_github
chmod 600 ~/.ssh/config

Test authentication:

ssh -T github-hermes

Expected result:

Hi skywirex-hermes! You've successfully authenticated...

Step 6: Configure the repository remote

Enter the repository directory on the server:

cd /path/to/your/repo

Check the current remote:

git remote -v

Set the remote to use the SSH alias:

git remote set-url origin git@github-hermes:OWNER/REPO.git

Example:

git remote set-url origin git@github-hermes:skywirex/brain.git

Verify:

git remote -v

Expected shape:

origin  git@github-hermes:skywirex/brain.git (fetch)
origin  git@github-hermes:skywirex/brain.git (push)

Step 7: Configure Git commit identity

Inside the repository on the server:

git config user.name "Hermes Agent"
git config user.email "[email protected]"

If the machine user’s GitHub noreply email has a different format, get it from:

GitHub -> Settings -> Emails

Verify:

git config user.name
git config user.email

Expected result:

Hermes Agent
[email protected]

Step 8: Allow direct pushes to master

If the repository has no branch protection or ruleset blocking master, Write access is enough for direct pushes.

If branch protection is in place, open:

Repository -> Settings -> Branches

Check the rule for:

master

To let the agent push directly to master, make sure these settings are not blocking it:

Require a pull request before merging: off
Require status checks before merging: off
Restrict who can push to matching branches: off

If you want to keep protection rules, add the machine user as an allowed bypass or allowed pusher if your GitHub plan and repository settings support it.

The simplest direct-push configuration usually looks like this:

Machine user: Write access
master: no required pull request
master: no required status checks
master: no push restriction

It is usually best to avoid force-push permission unless you have a very specific recovery workflow in mind.

Step 9: Test pull and push

On the server:

cd /path/to/your/repo
git checkout master
git pull --rebase origin master

Create an empty test commit:

git commit --allow-empty -m "Test Hermes push"

Push directly to master:

git push origin master

If this succeeds, the setup is in good shape.

Check GitHub. The commit should appear under the machine user or the configured commit identity:

Hermes Agent

Step 10: Let Hermes use the repository

It helps if Hermes runs as the same Linux user that owns the SSH key and repository checkout.

The runtime user should be able to access:

~/.ssh/id_ed25519_hermes_github
~/.ssh/config
/path/to/your/repo

A typical sync sequence for Hermes is:

git pull --rebase origin master
git add .
git commit -m "Update from Hermes"
git push origin master

Using git pull --rebase before committing or pushing can reduce conflicts when your local machine and the server both push to the same branch.

Daily workflow

From your local machine:

git pull origin master
# edit files
git add .
git commit -m "Update from local"
git push origin master

From the server or Hermes:

git pull --rebase origin master
# agent edits files
git add .
git commit -m "Update from Hermes"
git push origin master

Both sides can push to the same master branch while still using separate identities and separate SSH keys.

Security risks

Direct agent pushes to master are convenient, though they do carry real risk:

  • The agent can push broken commits.
  • The server and local machine can create Git conflicts.
  • If the server is compromised, an attacker can push to the repository.
  • If the agent writes incorrect files, master history can become noisy.

Risk reduction checklist:

Keep Admin permission off the machine user.
Keep your main personal SSH key off the server.
Avoid force push unless it is truly necessary.
Enable 2FA for the machine user.
Use clear commit messages.
Back up the repository and server.
Review commit history regularly.

Revoking access

If the server is compromised or the agent should no longer have access, revoke access right away.

Option 1: remove the SSH key from the machine user:

GitHub machine user -> Settings -> SSH and GPG keys

Delete:

production-server-hermes

Option 2: remove the machine user from the repository:

Repository -> Settings -> Collaborators

Remove:

skywirex-hermes

Option 3: remove the local key from the server:

rm ~/.ssh/id_ed25519_hermes_github
rm ~/.ssh/id_ed25519_hermes_github.pub

Final setup

Recommended final state:

Machine user: skywirex-hermes
Repository permission: Write
Server SSH key: dedicated Hermes key
Remote URL: git@github-hermes:OWNER/REPO.git
Branch: master
Branch protection: does not block direct push

This setup is a practical balance between:

Simple deployment
No personal key on the server
Minimal required repository permission
Clear commit attribution
Easy access revocation