Introduction
To automate a process securely, you can create a GitHub App owned by an enterprise account, then install the app in the enterprise or organization where the automation will take place.
GitHub Apps provide tokens that you can use to authenticate API calls to GitHub in scripts and workflows. These tokens are suitable for enterprises with specific security and auditing requirements, because they are:
- Temporary
- Scoped to specific accounts and permissions
- Associated with the app's identity rather than a user account
A common need for large enterprises is to keep an automation consistent and up-to-date across many organizations. You can accomplish this by installing an app programmatically. For example, if you need to configure all organizations with certain policies and settings, you could install a GitHub App for this task in every organization.
This guide will demonstrate the steps required to programmatically install an enterprise-owned GitHub App in an organization. Once the app is installed, you'll use it to create a new repository.
Overview of the process
In this guide, you'll use the GitHub CLI to make the API calls required to request access tokens and install an app in an organization. In reality, this process would be part of a custom script tailored to your company's needs.
You will:
- Create two apps owned by your enterprise account.
- One will have permission to install apps in organizations.
- The other will have permission to automate a process in an organization (in this case, creating a repository).
- Authenticate the first app to obtain an enterprise-scoped access token.
- Use the enterprise-scoped token to call an API that installs the automation app in an organization.
- Authenticate the organization-installed app to obtain an organization-scoped access token.
- Use the organization-scoped token to call an API that creates a repository in the organization.
At each stage, you will use a token that only has permission to perform specific actions in a specific account. From a security and auditing perspective, this approach is superior to relying on a single token with permission to perform actions across your enterprise and organizations.
Prerequisites
To follow this guide on your own device, you must:
- Be an enterprise owner.
- Be an owner of an enterprise-owned organization where you will perform the automation.
- Have the GitHub CLI installed for making API calls. See Installation in the GitHub CLI repository.
- Have
openssl
installed in order to generate a JSON web token (JWT). Many devices have OpenSSL installed by default. You can check by runningopenssl -v
, which returns a version number if installed. - Use a Unix shell such as Bash, ZSH, or Git Bash.
1. Prepare to generate a JWT
To request an access token from an app, you need a JSON web token (JWT) generated from the app's client ID and private key. Many programming languages have built-in methods for generating a JWT. In this tutorial, you will use a Bash script to generate a JWT from the command line using openssl
.
-
Copy the contents of the Bash script for generating a JWT from GitHub アプリの JSON Web トークン (JWT) の生成.
-
Save the contents in a new file in your home directory, called
gen-jwt.sh
. -
Make the script executable.
Shell chmod +x ~/gen-jwt.sh
chmod +x ~/gen-jwt.sh
2. Create two enterprise apps
GitHub Apps can only generate tokens with the fine-grained permissions and account scopes you allow. In this step, you will create two enterprise-owned apps: one with enterprise-level permission to install apps, and another with organization-level permission to create a repository.
a. Create the installer app
The "installer app" will be installed on the enterprise account, and will have permission to install the other app in an organization.
-
Create a new app under your enterprise account.
- Go to your enterprise account settings.
- In the left sidebar, click GitHub Apps.
- Click New GitHub App.
-
You can leave most of the values as defaults, except:
- Call the app
YOUR-HANDLE-installer-app
, replacingYOUR-HANDLE
with your GitHub username. - Set the "Homepage URL" to
https://github.com
. - Deselect Expire user authorization tokens and, under "Webhook", deselect Active.
- Under "Enterprise permissions", give the app read and write permissions for Enterprise organization installations.
- Call the app
-
After creating the app, copy the Client ID and save it as a variable called
INSTALLER_APP_CLIENT_ID
. For example, on the command line:Shell export INSTALLER_APP_CLIENT_ID='abcde12345'
export INSTALLER_APP_CLIENT_ID='abcde12345'
-
On the app page, scroll down and click Generate a private key. The private key file will be downloaded.
-
Make a note of the file path, which will look something like
~/YOUR-HANDLE-installer-app.DOWNLOAD-DATE.private-key.pem
. -
In the left sidebar of the app page, click Install app, then install the new app on the enterprise account. Installing an app gives the app permission to perform actions in the account.
-
Look at the URL in your browser to find the app's installation ID. This is a string of numbers at the end of the
/enterprises/ENTERPRISE/settings/installations/ID
URL. Save this as theINSTALLER_APP_INSTALL_ID
variable.Shell export INSTALLER_APP_INSTALL_ID='12345678'
export INSTALLER_APP_INSTALL_ID='12345678'
-
Save the name of the enterprise where the app is installed as a variable.
Shell export ENTERPRISE='octo-enterprise'
export ENTERPRISE='octo-enterprise'
b. Create the automation app
The "automation app" will be installed in an organization, and will have permission to create repositories in that organization. In reality, you would give this app whatever permissions are required to automate a process in your organizations.
-
Create a new app under your enterprise account.
- Call the app
YOUR-HANDLE-automation-app
, replacingYOUR-HANDLE
with your GitHub username. - Set the "Homepage URL" to
https://github.com
. - Deselect Expire user authorization tokens and, under "Webhook", deselect Active.
- Under "Repository permissions", give the app read and write permissions for Administration.
- Call the app
-
After creating the app, copy the Client ID and save it as the
AUTOMATION_APP_CLIENT_ID
variable.Shell export AUTOMATION_APP_CLIENT_ID='abcde12345'
export AUTOMATION_APP_CLIENT_ID='abcde12345'
-
Scroll down and click Generate a private key. The private key file will be downloaded.
-
Make a note of the file path, which will look something like
~/YOUR-HANDLE-automation-app.DOWNLOAD-DATE.private-key.pem
. -
Save the name of the organization where the app will be installed as a variable.
Shell export ORG='octo-org'
export ORG='octo-org'
3. Authenticate the installer app
Authenticating an app allows you to obtain a token with the scope and permissions you defined when you registered the app. In this case, you will obtain a token for the installer app, which will give you permission to install the automation app in an organization.
-
Generate a JWT using the Bash script you saved. For example:
Shell ~/gen-jwt.sh $INSTALLER_APP_CLIENT_ID ~/YOUR-HANDLE-installer-app.DOWNLOAD-DATE.private-key.pem
~/gen-jwt.sh $INSTALLER_APP_CLIENT_ID ~/YOUR-HANDLE-installer-app.DOWNLOAD-DATE.private-key.pem
-
Copy the JWT (the long string after
JWT=
) and save it as a variable.Shell export INSTALL_JWT='abcde12345'
export INSTALL_JWT='abcde12345'
-
Use the JWT to authenticate a request for an installation access token. This step uses the Create an installation access token for an app API endpoint and requires the app's installation ID.
Shell gh api --method POST "/app/installations/$INSTALLER_APP_INSTALL_ID/access_tokens" --header "Authorization: Bearer $INSTALL_JWT"
gh api --method POST "/app/installations/$INSTALLER_APP_INSTALL_ID/access_tokens" --header "Authorization: Bearer $INSTALL_JWT"
-
You should see a JSON object containing a
token
property. Copy the access token (the value of thetoken
property, without quotes) and save it as theINSTALLER_APP_INSTALL_TOKEN
variable.Shell export INSTALLER_APP_INSTALL_TOKEN='abcde12345'
export INSTALLER_APP_INSTALL_TOKEN='abcde12345'
4. Install the automation app
The installation access token you just received gives you permission to call the API for installing apps in an organization. Here, we will use the token to install the automation app (the second app you created) in a specific organization. In reality, you could call this API multiple times to install an app in multiple organizations.
-
Run the following command. We're using the Install a GitHub App on an enterprise-owned organization API endpoint, authenticating with the installation token you just requested, and passing the client ID of the automation app that we want to install.
Shell gh api --method POST \ "/enterprises/$ENTERPRISE/apps/organizations/$ORG/installations" \ --header "Authorization: Bearer $INSTALLER_APP_INSTALL_TOKEN" \ --header "Accept: application/vnd.github+json" \ --header "X-GitHub-Api-Version: 2022-11-28" \ --field "client_id=$AUTOMATION_APP_CLIENT_ID" \ --field "repository_selection=all"
gh api --method POST \ "/enterprises/$ENTERPRISE/apps/organizations/$ORG/installations" \ --header "Authorization: Bearer $INSTALLER_APP_INSTALL_TOKEN" \ --header "Accept: application/vnd.github+json" \ --header "X-GitHub-Api-Version: 2022-11-28" \ --field "client_id=$AUTOMATION_APP_CLIENT_ID" \ --field "repository_selection=all"
-
If successful, you should see a large number of properties returned, starting with the app's installation ID.
To check the app was successfully installed, go to
https://github.com/organizations/ORG/settings/installations
, replacing ORG with the organization name. You should see the newly installed app on the page. -
Find the installation ID of the new installation, and save it as
AUTOMATION_APP_INSTALL_ID
. To find the ID, you can either copy the first ID property returned by the API, or click Configure next to the app installation in the UI and copy the ID from the URL.Shell export AUTOMATION_APP_INSTALL_ID='12345678'
export AUTOMATION_APP_INSTALL_ID='12345678'
5. Authenticate the automation app
Just as you authenticated the installer app to obtain an enterprise-scoped token, you now need to perform the same process for the automation app. This will give you an organization-scoped token with permission to create repositories.
-
Generate a JWT with the automation app's client ID and private key. For example:
Shell ~/gen-jwt.sh $AUTOMATION_APP_CLIENT_ID ~/octocat-automation-app.2025-10-08.private-key.pem
~/gen-jwt.sh $AUTOMATION_APP_CLIENT_ID ~/octocat-automation-app.2025-10-08.private-key.pem
-
Copy the JWT (the long string after
JWT=
) and save it as a variable.Shell export AUTO_JWT='abcde12345'
export AUTO_JWT='abcde12345'
-
Use the JWT to authenticate a request for an installation access token, this time passing the installation ID and JWT for the newly installed automation app.
Shell gh api --method POST "/app/installations/$AUTOMATION_APP_INSTALL_ID/access_tokens" --header "Authorization: Bearer $AUTO_JWT"
gh api --method POST "/app/installations/$AUTOMATION_APP_INSTALL_ID/access_tokens" --header "Authorization: Bearer $AUTO_JWT"
-
Copy the new installation access token and save it as the
AUTOMATION_APP_INSTALL_TOKEN
variable.Shell export AUTOMATION_APP_INSTALL_TOKEN='abcde12345'
export AUTOMATION_APP_INSTALL_TOKEN='abcde12345'
6. Automate a process
The installation token you just received gives you permission to create a repository in the organization where the app is installed.
-
Run the following command. Notice we're authenticating with the installation token we just obtained.
Shell gh api --method POST \ "/orgs/$ORG/repos" \ --header "Authorization: Bearer $AUTOMATION_APP_INSTALL_TOKEN" \ --header "Accept: application/vnd.github+json" \ --header "X-GitHub-Api-Version: 2022-11-28" \ --field "name=automatic-repo" \ --field "description=Repository created automatically using GitHub App automation" \ --field "private=false" \ --field "auto_init=true"
gh api --method POST \ "/orgs/$ORG/repos" \ --header "Authorization: Bearer $AUTOMATION_APP_INSTALL_TOKEN" \ --header "Accept: application/vnd.github+json" \ --header "X-GitHub-Api-Version: 2022-11-28" \ --field "name=automatic-repo" \ --field "description=Repository created automatically using GitHub App automation" \ --field "private=false" \ --field "auto_init=true"
-
To check the repository was created successfully, go to
https://github.com/orgs/ORG/repositories
, replacing ORG with the name of your organization.
7. Uninstall the apps
For security, uninstall the apps from the enterprise and organization. This will revoke all tokens associated with the apps. For instructions, see インストールした GitHub App の確認と変更.
Next steps
You have seen how to install an app programmatically in organizations and run an automation. Now, you should be ready to automate a real process across multiple organizations. For more information about what apps can do, see GitHub App の作成について.
ヒント
In the real world, you would likely perform the installation as a one-time process. The organization-level automation would be defined in a separate script, triggered by webhooks or cron jobs. However, security-conscious enterprises may prefer to install and uninstall an app every time the automation runs, in order to limit impact if the app's private key is exposed.