Skip to main content
Private preview. fremforge is in private preview — invited customers only. Content is still subject to change. Request access →

Secrets and environment variables

Secrets are encrypted values injected into workflow jobs as environment variables. They are write-only after creation. The value is never readable back through the UI or API. This page covers scopes, creation, workflow usage, rotation, and limits.

Secrets are encrypted at rest with T Cloud DEW KMS and decrypted only at job execution time on the runner.

Org-level secrets ship as a first-class fremforge admin tab at frem.sh/<org>/_admin/secrets (created 2026-05-10). Repo-level and environment-level secrets remain in Forgejo native UI under each repo’s Settings → Secrets and Settings → Environments → <env> → Secrets, that’s where Forgejo’s per-repo and per-environment scopes live, and the precedence model (environment → repo → org) is enforced by Forgejo at job execution time.

Scopes

ScopeWhere setAvailable to
Org secretOrg admin → SecretsAll repos in the org
Repo secretRepo Settings → SecretsThat repo only
Environment secretRepo Settings → Environments → <env> → SecretsJobs that declare environment: <env>

Precedence: environment secret overrides repo secret overrides org secret. When the same name exists at multiple scopes, the most specific scope wins.

Creating secrets

Via the UI: navigate to the appropriate scope → New secret → enter name (UPPER_SNAKE_CASE convention) and value → Save.

Via the API:

# Org secret
curl -X PUT \
  -H "Authorization: Bearer <PAT>" \
  -H "Content-Type: application/json" \
  -d '{"name":"MY_SECRET","data":"the-value"}' \
  https://frem.sh/api/v1/orgs/<org>/actions/secrets/MY_SECRET

# Repo secret
curl -X PUT \
  -H "Authorization: Bearer <PAT>" \
  -H "Content-Type: application/json" \
  -d '{"name":"MY_SECRET","data":"the-value"}' \
  https://frem.sh/api/v1/repos/<org>/<repo>/actions/secrets/MY_SECRET

Secrets are write-only after creation. You cannot read back a secret value through the API or UI. You can only overwrite or delete.

Using secrets in workflows

Reference secrets with ${{ secrets.NAME }}. Secrets are available as environment variables.

env:
  DATABASE_URL: ${{ secrets.DATABASE_URL }}

steps:
  - name: Deploy
    env:
      API_KEY: ${{ secrets.DEPLOY_API_KEY }}
    run: ./deploy.sh

Secrets are masked in logs: any log output that exactly matches a secret value is replaced with ***. Masking applies to exact matches only; base64-encoded, URL-encoded, or otherwise transformed variants of the secret value are not automatically masked.

Environment secrets and deployment gates

Jobs that declare environment: only receive secrets scoped to that environment (plus repo and org secrets). This is intentional: environment secrets gate production credentials behind the environment’s approval flow.

jobs:
  deploy-prod:
    runs-on: fremforge
    environment: production   # triggers approval gate if reviewers are configured
    steps:
      - name: Deploy
        env:
          DB_URL: ${{ secrets.PROD_DB_URL }}   # environment secret on 'production'
        run: ./deploy.sh

Configure required reviewers under Repo Settings → Environments → <env>. The job pauses for approval before the step runs; the secret is not injected until the job is approved and executing.

Secret rotation

  1. Create the new credential in the external system first.
  2. Overwrite the secret in fremforge with the new value. Do not delete and recreate.
  3. Trigger a new workflow run to verify the new credential works end-to-end.
  4. Revoke the old credential in the external system.

Overwriting preserves the audit trail and avoids a window where the secret is missing from jobs running between delete and recreate.

Limits

ItemLimit
Max secret value size64 KB
Org secrets1,000
Repo secrets100 per repo
Environment secrets100 per environment
Secret name patternAlphanumeric and underscore; must start with a letter; cannot start with FORGEJO_ or GITHUB_

OIDC as a secret alternative

For deploying to cloud providers (T Cloud, AWS, Azure, GCP), consider OIDC token federation instead of long-lived credentials stored as secrets. OIDC issues short-lived tokens per job, scoped to the specific workflow run. Nothing to rotate, nothing to leak.

OIDC is the recommended pattern for any job that deploys to cloud infrastructure.

Cross-references