Jul 15, 2025
10 min read

Managing secrets in CI/CD environments: Advanced techniques for GitHub Actions

Managing secrets in CI/CD environments: Advanced techniques for GitHub Actions

CI/CD pipelines have made shipping code faster, but they’ve also multiplied the number of places secrets live and move. In GitHub Actions alone, secrets are passed through workflows, injected into environments, and reused across deployments. While GitHub offers basic secret storage, most teams use the default settings for static values, manual rotation, and minimal auditing. This creates problems as your organization scales:

  • You forget to revoke secrets after a job finishes.
  • Audit logs don’t show who used which secret and when.
  • You copy the same credentials across staging and prod.
  • Rotation becomes a manual, high-risk chore.

That’s why advanced teams adopt a mindset where secrets aren’t just stored, but created, injected, rotated, and expired automatically as part of each deployment. In this guide, we’ll show you how to implement secrets orchestration inside GitHub Actions using Doppler, focusing on:

  • Injecting secrets without hardcoding them in YAML.
  • Automatically rotating and revoking secrets per deploy.
  • Auditing secret usage with full traceability.

This article is part one of a series on orchestrating CI/CD secrets and focuses specifically on GitHub Actions. (If you use Jenkins or CircleCI, stay tuned for upcoming guides.)

Why static secrets are not enough in GitHub Actions

In GitHub Actions, secrets can live in three different places: (1) repository-level secrets, (2) environment-specific secrets (e.g., dev, staging, prod), and (3) organization-wide secrets. Secrets are injected at runtime, which keeps them out of source control, but managing them still creates hidden risks.

If you’ve ever rotated an API key, you’ve likely had to:

  • Update the secret manually in multiple environments or repositories.
  • Coordinate across teams to avoid overwriting or missing values.
  • Hope no workflows fail silently due to outdated or misconfigured secrets.

This process becomes harder to maintain with every new workflow, teammate, or environment. Secrets drift, and values get out of sync. Moreover, there’s no built-in visibility into how secrets are used or whether they’ve been replaced after exposure.

Static secret storage also makes enforcing short-lived credentials, least-privilege access, or auditability difficult, especially when reusing secrets across projects.

Rather than patching these issues one secret at a time, many teams begin centralizing their secrets strategy. In the next section, we’ll walk through how to connect GitHub Actions to a single control plane using Doppler, starting with how to safely migrate existing secrets.

Using Doppler to centralize secrets across GitHub environments

Doppler has published a tutorial on connecting GitHub Actions. The tutorial includes instructions on how to safely transfer existing GitHub secrets into your Doppler project, ensuring no CI/CD workflow interruptions during the secrets migration.

To begin, we'll follow the GitHub Actions tutorial to connect our GitHub Actions and sync the existing secrets from GitHub to Doppler.

  • Step 1 - Set up a Doppler project: If you do not yet have a Doppler project with dev, staging, and prod configurations, create one now.
  • Step 2 -For each configuration that will sync with GitHub, create a token. This token will be used to sync secrets from GitHub, and will be used just once. To create a token, enter the Doppler project environment, click Access, and add a service token. Choose a short timeframe for the token validity, as this will only be run once.
  • Step 3 - Connect Doppler with a GitHub repository: Click "Syncs" in the left nav. This will prompt you to create an integration (or to select an existing GitHub integration). Follow the steps in the guide to connect your GitHub account/organization to Doppler. (This requires admin rights in the GitHub organization.) Once connected to a repository, we can begin connecting our GitHub Actions secrets into Doppler.
  • Step 4 - Create the GitHub integration: From the Syncs page, click the + Integrations button. Select the organization you wish to connect to at GitHub (in the screenshot below, the dougsillars account), or create a new connection.
Adding a connection to the dougsillars GitHub account
Adding a connection to the dougsillars GitHub account
  • Step 5 - Connect GitHub Actions with Doppler: Choose the GitHub feature (in this case, GitHub Actions), the GitHub repository (or organization), and the repository environment where the workflows are run. Once the repository and Doppler config are connected, the next step is to begin sharing secrets.
  • Step 6 - Importing secrets automatically: Doppler provides a GitHub Action to import existing GitHub secrets into Doppler. This is a secure way to copy the existing values (and names) into Doppler, avoiding accidental typos. The GitHub Action below copies all of the Dev environment variables to the Doppler dev configuration:

When the GitHub Action is run, the user will be prompted for 4 input variables:

  • GitHub Deployment Environment for this job: This is the GitHub environment where secrets are stored
  • Doppler Service Token: The token created in step 2.
  • Doppler Target Project: Your Doppler project name.
  • Doppler Target Config: The Doppler configuration to store the secrets.

As another option, the Doppler token, project, and config can also be run from secrets stored in the GitHub repository. To add secrets in a GitHub Repository, choose Settings > Secrets and Variables > Actions > Repository Secrets. Add the three secrets.

  • Step 7 - Push the Action to GitHub, and run it: Once run, the existing GitHub secrets(both names and values) will be saved on Doppler using the following step of the code:

The workflow uses the Doppler CLI doppler secrets upload command to upload the secrets from GitHub into the Doppler project/config chosen. It also automatically deletes the three Doppler secrets as they will not be used again.

Secrets successfully migrated to Doppler
Secrets successfully migrated to Doppler

Once this process is repeated for all GitHub/Doppler environments, all of the CI/CD secrets are now securely stored on Doppler, and the Secrets store at GitHub no longer requires manual maintenance. When a new GitHub Action secret is required, it can be created in the Doppler dashboard(or via the CLI or API), and it will be automatically pushed to GitHub for use. Here, a new secret DOPPLER_SIDE_SECRET was created in the Doppler dashboardand immediately synced to GitHub:

New secret added in Doppler
New secret added in Doppler
…that immediately appears in GitHub.
…that immediately appears in GitHub.

Advanced techniques for managing CI/CD secrets

Now that Doppler is securely managing secrets for our GitHub Actions, let's dig into some advanced techniques for secrets management in our CI/CD workflows.

Updating secrets via the CLI

You can easily rotate or update a secret with the Doppler UI, but it can also be updated via the API or CLI. The CLI command doppler secrets set uses parameters to update secrets:

While this manual updating is nice, let’s jump into automating the updating, rotating, and deletion of secrets for CI/CD workflows.

Updating secrets on each deployment

Regular rotation of secrets is a common security best practice. An even better approach is using automated secrets rotation on every deployment. Short-lived secrets limit the window of opportunity for hackers to access secure systems: they are not valid long enough for extensive damage to be done. One drawback to automatically rotating secrets can make logging and auditing a challenge in legacy systems.

Creating automated secrets rotation is possible on every deployment workflow by leveraging the Doppler CLI. The following workflow (see it on GitHub) uses just-in-time secret creation to create a secret that is used once before being deleted.

Let's walk through what is happening. On each push to main, several steps are taken:

Step 1: Generate random string

  • Generates a random 16 hex character string. Note that the echo step is commented out—we do not want to expose the new secret in the GitHub logs. The random string is saved as steps.generate.outputs.random_string.
  • In reality, this step might be a call to a third party tool to generate a new token.

Step 2: Install the Doppler CLI.

Step 3: Change API_KEY Secret. Breaking down this command:

  • doppler secrets set API_KEY
    • This command asks to set the API_KEY variable.
  • --project "$DOPPLER_TARGET_PROJECT"
    • The in the chosen project
  • config "$DOPPLER_TARGET_CONFIG"
    • Which environment in the project
  • --silent
    • No output for the logs. We can't write our new secret into the GitHub logs.
  • --no-interactive
    • This is to be automatic, no user interaction
  • --raw "$RANDOM_STRING"
    • Use the random string just created as the password

Step 4: Echo text.

  • Here is where actual CI/CD actions can take place with the new GitHub secret.

Step 5: Delete the Variable.

  • Now that all the actions have completed, delete the API_KEY from Doppler and from GitHub. Even if compromised, the secret can no longer be used.

Now, on every push, the API_KEY secret in the dev environment created, used just once, and then deleted. Using this GitHub Action code as a framework, teams can include steps to perform installations and deployments of code, leveraging Doppler to implement a one-time secret for the deployment.

Compliance readiness audit trails

"When was the secret last rotated?" "Who last made changes to the configuration?" Enterprise security frameworks (i.e., SOC-2, ISO 27001, and HIPAA) require audit logs to demonstrate compliance with the framework’s requirements. With secrets saved on GitHub, there is no audit log to help teams understand when and how changes are made to your secrets. With Doppler, there is a built-in audit trail that shows who made each change and when.

A Screenshot of an audit log. All logs can be clicked to see both the old and new secrets that were stored. Hidden here for security.
A Screenshot of an audit log. All logs can be clicked to see both the old and new secrets that were stored. Hidden here for security.

Doppler also supports exporting security event logs to external logging services like Datadog and Splunk, keeping all log activities in a centralized location.

CLI Logging

The Doppler CLI makes auditing password changes easy. The log can be found by running doppler activity. The last two entries are Modified Secret and a Deleted Secret: both actions performed by the GitHub Action described above.

Automating CI/CD security with Doppler

Automation has made deploying applications faster, but the way many teams handle secrets hasn’t kept up. Secrets often remain scattered across environments, rotated manually, and audited inconsistently. This creates risk, increases maintenance, and slows down delivery.

Centralizing secrets in a single control plane is a smarter approach. With Doppler, teams can manage the entire lifecycle: from injection to rotation and expiration, all within their GitHub Actions workflows. Secrets stay in sync, remain short-lived, and are fully auditable.

In this guide, you saw how to migrate secrets into Doppler, automate secret creation and deletion during deployments, and track changes using CLI logs and audit trails. This is the first in a series: upcoming guides will cover bringing the same orchestration model to Jenkins and CircleCI.

Enjoying this content? Stay up to date and get our latest blogs, guides, and tutorials.

Related Content

Explore More