Users, OIDC and teams
Local, SSO and bot accounts, people who sign in with OIDC, organizations and team membership.
This guide covers accounts (ForgejoUser, short name fjuser), the
organizations they belong to (ForgejoOrganization, fjorg) and the teams
that give them access (ForgejoTeam, fjteam). All three are namespaced:
Kubernetes RBAC decides who may create them in a namespace, and — on a shared
ForgejoInstance — the allow-list which ones. They
are referenced from their own namespace, or from another one when the
operator allows it (references.crossNamespace) and they list that
namespace in spec.sharedWith. A Forgejo object no CR manages is referenced
by name (remoteName); one owned by another CR can't be declared twice
(RemoteObjectClaimed).
Before you begin
- A connected
ForgejoInstancewithREADYset toTrue.
Kinds of accounts
A ForgejoUser is one of three kinds of account, depending on its spec:
| Account | Set in the spec | Password |
|---|---|---|
| External (OIDC, LDAP…) | loginSourceId (and optionally loginName) | None. Forgejo links the account at its first sign-in. |
| Local | no loginSourceId | Generated and written to secretTargets as FORGEJO_USERNAME / FORGEJO_PASSWORD / FORGEJO_URL. Reset if the Secret disappears. |
| Bot | bot: true | Generated and thrown away. The account only works through its tokens and SSH keys. |
Separately, managementPolicy decides whether the operator may change it:
Manage(default): the operator creates the account and keeps it in line with the spec.Observe: the operator never creates, edits or deletes it. It only looks it up, so teams, repositories and tokens can refer to it.
kubectl get fjuser shows the policy in its MODE column.
apiVersion: forgejo.weebo.io/v1alpha1
kind: ForgejoUser
metadata:
name: alice
spec:
username: alice
email: alice@example.com
fullName: Alice Martin
secretTargets: [{ name: alice-credentials, namespace: weebo-forgejo }]Don't lock a bot out of its own tokens
Never set prohibitLogin or mustChangePassword on a bot. Forgejo then
refuses the account's API tokens too. Use prohibitLogin: true only to
disable an account entirely.
People who sign in with OIDC
The authentication source itself (your OIDC provider) is configured in
Forgejo, not by the operator: with the Forgejo Helm chart's gitea.oauth
values, or with forgejo admin auth add-oauth.
There are two ways to manage these people. Pick the first when you know them in advance, the second when they show up on their own.
Create the account ahead of time and link it to the authentication source. Their first sign-in lands on this account.
apiVersion: forgejo.weebo.io/v1alpha1
kind: ForgejoUser
metadata:
name: bob
spec:
username: bob
email: bob@example.com
loginSourceId: 1 # see below
loginName: bob # their username at the provider, if differentloginSourceId is the numeric id of the authentication source: in
Site administration → Authentication sources, click the source. The id is
the number at the end of its URL (for example …/admin/auths/1). Forgejo has no API to look a source up by name.
Organizations and teams
apiVersion: forgejo.weebo.io/v1alpha1
kind: ForgejoOrganization
metadata:
name: weebo
spec:
name: weebo
visibility: private
ownerRef: { name: alice } # the first owner; used at creation only
---
apiVersion: forgejo.weebo.io/v1alpha1
kind: ForgejoTeam
metadata:
name: weebo-devs # the CR's name, used by refs
spec:
organizationRef: { name: weebo }
name: devs # the team's name in Forgejo
permission: write # with unitsMap empty: every unit at this level
memberRefs:
- name: alice
- name: carolRefs (ownerRef, memberRefs…) name CRs, not Forgejo accounts:
alice above is the ForgejoUser from the previous section.
memberRefsis authoritative: anyone else in the team is removed.- Renaming the team (
spec.name) renames it in place. - Moving it to another organization recreates it. That counts as a
disruptive change and needs
the
forgejo.weebo.io/allow-disruptive-update: "true"annotation.
Team access levels
A team's access has three parts. The team says who (memberRefs) and
how much (permission, unitsMap). Where is either every repository
of the organization (includesAllRepositories: true) or the repositories
that list the team in their
teamRefs.
permissionisread,writeoradmin. WithunitsMapempty, every repository unit gets this level.unitsMapsets the level unit by unit (repo.code,repo.issues,repo.pulls,repo.releases,repo.wiki,repo.projects,repo.packages,repo.actions) tonone,read,writeoradmin. Forgejo ignores it whenpermissionisadmin.canCreateOrgRepolets members create repositories in the organization.
| To give… | permission | unitsMap |
|---|---|---|
| Read-only (RO) | read | empty |
| Read-write (RW) | write | empty |
| Full control of the team's repositories (settings, webhooks) | admin | ignored |
| A mix, such as reviewers who read the code and write issues and PRs | read | repo.code: read, repo.issues: write, repo.pulls: write, repo.actions: none |
spec:
organizationRef: { name: weebo }
name: reviewers
permission: read
unitsMap:
repo.code: read
repo.issues: write
repo.pulls: write
repo.actions: none
includesAllRepositories: trueForgejo sets some limits of its own:
- A team belongs to one organization. To grant access to several
organizations, create one
ForgejoTeamper organization. - Owner rights stay with the
Ownersteam.admincovers the team's repositories, not the organization itself, andOwnerscan't be created or managed through aForgejoTeam. - The level is set per team, not per repository.
teamRefsonly grants the repository. To give one repository more access than the others, use a second team.
OIDC groups as team members
Instead of memberRefs, a team can take its members from your identity
provider's groups: Forgejo adds and removes users at each sign-in, and the
operator, with membersPolicy: External, manages the team but never its
members.
spec:
organizationRef: { name: weebo }
name: devs
permission: write
membersPolicy: External # default: ManagedSetting this up, and its limits, are covered in OIDC groups and teams.
SSH keys for a user
ForgejoUserKey (fjukey) adds an SSH key to a user. It's typically used to
give a bot Git access. Without publicKey, the operator generates an ed25519
pair and writes it to the targets:
apiVersion: forgejo.weebo.io/v1alpha1
kind: ForgejoUserKey
metadata:
name: ci-bot-ssh
spec:
userRef: { name: ci-bot }
title: ci
secretTargets: [{ name: ci-bot-ssh, namespace: ci }]It works like a deploy key, including rotation.
Deleting
Users and organizations default to deletionPolicy: Orphan: deleting the CR
never deletes an account or its history. Teams default to Delete. Users are
never purged, even with Delete.