weebo-forgejo

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 ForgejoInstance with READY set to True.

Kinds of accounts

A ForgejoUser is one of three kinds of account, depending on its spec:

AccountSet in the specPassword
External (OIDC, LDAP…)loginSourceId (and optionally loginName)None. Forgejo links the account at its first sign-in.
Localno loginSourceIdGenerated and written to secretTargets as FORGEJO_USERNAME / FORGEJO_PASSWORD / FORGEJO_URL. Reset if the Secret disappears.
Botbot: trueGenerated 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 different

loginSourceId 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: carol

Refs (ownerRef, memberRefs…) name CRs, not Forgejo accounts: alice above is the ForgejoUser from the previous section.

  • memberRefs is 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.

How a ForgejoTeam grants accessUsers listed in memberRefs belong to a team of one organization. The team's permission and unitsMap set the access level per repository unit. The team reaches repositories either through includesAllRepositories or through each repository's teamRefs.WHOHOW MUCHWHEREForgejoUseraliceForgejoUsercarolspec.memberRefs(authoritative)ForgejoOrganization weeboForgejoTeamdevspermissionreadread · write · adminunitsMaprepo.codereadrepo.issueswriterepo.pullswriterepo.actionsnonenone · read · write · adminempty: every unit at permissionignored when permission is adminappteamRefs: [weebo-devs]docsteamRefs: [weebo-devs]infranot listed: no accessincludesAll-Repositories: trueevery repo, even future
The team sets the level, the repository decides whether the team gets in.
  • permission is read, write or admin. With unitsMap empty, every repository unit gets this level.
  • unitsMap sets the level unit by unit (repo.code, repo.issues, repo.pulls, repo.releases, repo.wiki, repo.projects, repo.packages, repo.actions) to none, read, write or admin. Forgejo ignores it when permission is admin.
  • canCreateOrgRepo lets members create repositories in the organization.
To give…permissionunitsMap
Read-only (RO)readempty
Read-write (RW)writeempty
Full control of the team's repositories (settings, webhooks)adminignored
A mix, such as reviewers who read the code and write issues and PRsreadrepo.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: true

Forgejo sets some limits of its own:

  • A team belongs to one organization. To grant access to several organizations, create one ForgejoTeam per organization.
  • Owner rights stay with the Owners team. admin covers the team's repositories, not the organization itself, and Owners can't be created or managed through a ForgejoTeam.
  • The level is set per team, not per repository. teamRefs only 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: Managed

Setting 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.

Next

Repositories.

On this page