Secrets are managed by Drone by injecting them as environment variables into your build container.

Here’s how Drone handles secrets, and how you can leverage it for secure CI/CD.

The Problem: Hardcoding Secrets

The most basic way to use a secret in a CI pipeline is to hardcode it directly into your .drone.yml file.

kind: pipeline
type: docker
name: default

steps:
- name: deploy
  image: plugins/drone-cli
  settings:
    token:
      from_secret: github_token

This example uses a secret named github_token. When Drone runs this pipeline, it will look for a secret named github_token in your repository’s settings and inject its value into the github_token environment variable within the deploy step’s container.

Where Secrets Live

Drone stores secrets in a few places:

  • Repository-level secrets: These are specific to a single repository. You can manage these through the Drone UI under your repository’s settings.
  • User-level secrets: These are available to all repositories owned by a specific user. You manage these in your user settings in the Drone UI.
  • Organization-level secrets: These are available to all repositories within a specific organization. You manage these in the organization’s settings in the Drone UI.

The order of precedence for secrets is: Repository > User > Organization. If a secret with the same name exists at multiple levels, the repository-level secret will take precedence.

Injecting Secrets: The from_secret Keyword

The from_secret keyword is the primary mechanism for injecting secrets.

steps:
- name: build
  image: golang:1.20
  commands:
    - go build
    - echo $CI_GITHUB_TOKEN # This will be empty by default
- name: push
  image: plugins/docker
  settings:
    username:
      from_env: DOCKER_USERNAME # Example of using an environment variable
    password:
      from_secret: docker_password

In this example:

  • The build step has access to environment variables that Drone automatically injects, like CI_GITHUB_TOKEN (if configured).
  • The push step needs a docker_password. It retrieves this from a secret named docker_password.
  • It also shows username being sourced from an environment variable DOCKER_USERNAME. This is useful if you have a DOCKER_USERNAME secret and want to use its value in a different environment variable name for your plugin.

Sensitive Data and Environment Variables

Drone automatically injects a set of predefined environment variables prefixed with CI_. Some of these are sensitive.

  • CI_COMMIT_SHA: The commit SHA.
  • CI_COMMIT_REF: The branch or tag name.
  • CI_COMMIT_AUTHOR: The author of the commit.
  • CI_PIPELINE_STATUS: The status of the pipeline (success or failure).
  • CI_BUILD_NUMBER: The build number.
  • CI_BUILD_URL: The URL to the build.

Important: While Drone attempts to mask secrets in logs, it’s not foolproof. Never rely solely on log masking for truly sensitive data.

Using Secrets with Plugins

Many Drone plugins are designed to consume secrets directly.

kind: pipeline
type: docker
name: publish-docker-image

steps:
- name: build
  image: plugins/docker
  settings:
    repo: octocat/hello-world
    username:
      from_secret: docker_username
    password:
      from_secret: docker_password

Here, the plugins/docker image expects username and password settings. We provide these by referencing secrets named docker_username and docker_password. Drone will automatically make these secrets available as environment variables within the build step’s container, and the plugin will read them.

Managing Secrets in the UI

  1. Repository Secrets: Navigate to your repository in the Drone UI, click "Settings," and then "Secrets." You can add, edit, and delete secrets here.
  2. User Secrets: Navigate to your user settings in the Drone UI (usually by clicking your avatar), then "Secrets."
  3. Organization Secrets: Navigate to your organization settings in the Drone UI, then "Secrets."

How from_secret Works Under the Hood

When Drone encounters from_secret: my_secret_name, it does the following:

  1. Lookup: It searches for a secret named my_secret_name in the following order: repository secrets, user secrets, organization secrets.
  2. Injection: Once found, Drone injects the secret’s value into the build container as an environment variable. The name of this environment variable is derived from the secret name, typically by converting it to uppercase and prefixing it with CI_ if it’s a repository or organization secret, or just uppercase if it’s a user secret. For example, a repository secret named docker_password might become the CI_DOCKER_PASSWORD environment variable.
  3. Plugin Consumption: If you’re using a plugin that expects a specific setting (like password), and that setting is configured with from_secret: docker_password, the plugin will access the injected environment variable (e.g., CI_DOCKER_PASSWORD).

Best Practices

  • Least Privilege: Grant secrets only to the repositories or organizations that absolutely need them.
  • Avoid Overriding: Be mindful of secret naming collisions between repository, user, and organization levels. Use distinct names to prevent unexpected behavior.
  • Use Environment Variables for Non-Sensitive Data: For configuration values that aren’t strictly sensitive (like build arguments or image tags), use from_env or directly set them in your .drone.yml.
  • Regularly Rotate Secrets: Treat CI/CD secrets like any other sensitive credential and rotate them periodically.
  • Consider Vault Integration: For more advanced secret management, Drone integrates with HashiCorp Vault and other external secret stores. This allows you to manage secrets centrally outside of Drone itself.

The next step in mastering Drone secrets is understanding how to integrate with external secret management systems like HashiCorp Vault.

Want structured learning?

Take the full Drone course →