GitHub Actions secrets: deploy without publishing passwords or keys

Published on 2026-10-26 by frfrand

Configure CI secrets and minimum permissions in GitHub Actions

GitHub Actions secrets: deploy without publishing passwords or keys

Automating a deployment loses its meaning if, to use it, you end up pasting the server password into a public YAML. GitHub Actions allows managing secrets and tokens, but you must also limit which workflows can use them.

The idea is to solve a data or deployment problem that appears in real applications. We will see the concept straight to the point, an implementation example, and what to check before taking it to production.

What GitHub Actions secrets do

Actions secrets and variables are configured per repository, environment, or organization according to permissions. Secrets must not be printed or sent to artifacts. For cloud services, OIDC-based ephemeral credentials can be more secure than permanent keys when the provider supports it.

It is not enough to repeat a recipe if you do not understand who reads the data, from what process, and with what permissions. In an application with reservations, invoices, or users, a race condition or a poorly designed access policy can be more serious than a slow API.

A concrete example

# Extracto ilustrativo de workflow
name: test
on: [push]
jobs:
  checks:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - run: echo 'Ejecutar pruebas antes del deploy'
# Secrets: se referencian desde secrets.*, nunca se escriben en YAML

The names, tables, and keys in this example are illustrative. Try it first on a test or staging database and adapt permissions, indexes, and versions. When there are write operations, do not run sample queries on customer data without reviewing what they modify.

Step by step

  1. Separate publishing tests: not every push should automatically reach production.
  2. Grant minimal permissions to the GITHUB_TOKEN of the workflow.
  3. Store credentials in Secrets and use protected environments with approval when appropriate.
  4. Review permissions of external PRs, forks, and third-party dependencies.
  5. Check logs and artifacts to ensure they do not contain sensitive values.

At the end, do not settle for "the SQL did not give an error." Verify the actual effect from the API and with concurrency or permission tests as appropriate. In databases, there are errors that only appear when two users do something at the same time.

Example work project

An agency has two client repositories and deploys a Django API to each VPS. One deployment credential per client prevents a compromised workflow from accessing all projects.

That scenario helps distinguish performance from consistency. Speeding up a query is useless if it allows creating two reservations for a single seat, nor does a huge database fix the backend allowing querying data from another client.

The typical error

Although GitHub masks certain patterns, printing transformed secrets or passing them to third-party processes can leak them. Do not use pull_request_target with untrusted code without analyzing risks.

It's also a good idea to have a recovery plan. Before touching schema, users, or policies, save a verifiable copy or reversible migration and check that the application can keep working during the change.

How would I solve this with ArduMaker?

With ArduMaker you can connect Git repositories and organize deployments by Company. If you keep CI in GitHub Actions, separate test permissions and the minimum credentials needed to publish each project.

ArduMaker allows you to deploy services from Git and work with databases and processes within the VPS. The panel does not replace your application logic: transactions, permissions, and validations must be correctly designed in the code and the database.

Three checks before publishing

Integrity: if a request is repeated or fails halfway through, do the data end up in a valid state?

Security: can an authenticated user access only their own information, and does the API use a base identity with minimum permissions?

Recovery: do you know how to restore the data and revert the compatible code version if an update goes wrong?

If you can answer those three questions with tests, your backend is much better prepared than when you only checked if the endpoint returned 200.

Resources to learn more

To conclude: choose the simplest solution that allows you to maintain correct, secure, and recoverable data. Performance comes after measuring.

  • GitHub Actions
  • Tutorial
  • ArduMaker

Keep reading

All articles · VPS plans