forgejo/discussions
49
43

Allow-list who may create repos/orgs, decoupled from registration #477

Closed
opened 2026年06月12日 16:42:19 +02:00 by lsmith · 2 comments

Subsystem: registration / permissions.
Status: ready now; no upstream redesign dependency.

Problem

Everyone should be able to register, file issues, fork, and open PRs — but only approved users should be able to create new repositories/organisations. Forgejo currently couples these.

Why current options don't cover it

  • EMAIL_DOMAIN_ALLOWLIST gates registration itself — we want the opposite: everyone registers, the domain (or claim) governs repository creation.
  • MAX_CREATION_LIMIT caps repos per user; an admin can override it per-user, but only manually and not by domain/claim — so it can't express "domain A may create, domain B may not" at scale under open registration.

Ask

Gate the "new repository / new organisation" action by email domain (and ideally group / OIDC claim), decoupled from registration. Everyone can still register, file issues, fork, and open PRs; only creation is gated. For external-IdP setups, allow the gate to read a group/claim so the policy lives at the IdP.

Umbrella context

Who's asking: This request comes from Zentrum SDS, the Swiss public-sector digital-sovereignty initiative (anchored at the Bern University of Applied Sciences), which is planning the Forgejo-based opencode.ch code platform. "We" throughout refers to this group.

Open instances need open registration so people can file issues and contribute (fork → PR). But open registration also lets anyone create new repositories, which raises two problems:

  • Resource use — new repositories accumulate and consume shared Actions runner resources.
  • Content moderation — arbitrary repositories (spam, abuse, off-topic or unlawful content) on a public-sector-branded platform.

Both force operators to police and delete repositories by hand (a known pain on code.forgejo.org itself). The shape we want: anyone participates, only approved users create repositories.

How existing public-sector platforms handle it:

  • opencode.de (GitLab-based) — anyone can register to comment and file tickets; creating new repositories is gated by an email-domain allow-list. The planned Swiss opencode.ch (Forgejo-based) needs the same. (How an outside contributor is granted the ability to fork is exactly the gap Issue B addresses.)
  • code.overheid.nl (Forgejo-based) — avoids the problem by closing registration to government organisations only. Valid, but it hinders adoption of and contribution to the code hosted there (outside contributors, civil society, vendors can't easily fork and send PRs), undercutting the "public money, public code" goal.

This request is for operators who want registration to stay open — so the code on the platform gets real external engagement — while still controlling who creates repositories and how forks work.

Shared notes (apply to both issues):

  • Forward-looking: relation to federation. Long term, federation (ForgeFed/ActivityPub, NLnet-funded) addresses the cross-instance version of "participate without us maintaining external accounts": an external contributor keeps their home-forge identity and forks/PRs across instances, so the host never provisions accounts for them — and the "fork yes / create-repository no" split falls out naturally. These local controls and federation are complementary, not competing: federation is still experimental (federated stars/follows today; federated forks/PRs and, explicitly, access control & moderation not yet built), so the controls here are what work now; and even once federation lands, the creation allow-list (Issue A) still applies for local open registration. If anyone on the federation/moderation side has related work underway, please flag it so the access-control model doesn't diverge.
  • We'd rather upstream this than carry a soft fork, and are interested in co-designing and helping fund the work. Happy to write an RFC and prototype.
  • External-IdP deployments: where Forgejo consumes OIDC from an external identity provider (Keycloak/Zitadel/Authelia), the allow-list in Issue A is most naturally expressed as a group/claim rule at the IdP, consumed by Forgejo's existing group→team mapping. The email-domain gate is then just one way to populate that group.
**Subsystem:** registration / permissions. **Status:** ready now; no upstream redesign dependency. ### Problem Everyone should be able to register, file issues, fork, and open PRs — but only **approved users** should be able to create **new repositories/organisations**. Forgejo currently couples these. ### Why current options don't cover it - `EMAIL_DOMAIN_ALLOWLIST` gates **registration itself** — we want the opposite: everyone registers, the domain (or claim) governs **repository creation**. - `MAX_CREATION_LIMIT` caps repos per user; an admin can override it per-user, but only **manually** and **not by domain/claim** — so it can't express "domain A may create, domain B may not" at scale under open registration. ### Ask Gate the **"new repository / new organisation" action** by **email domain (and ideally group / OIDC claim)**, decoupled from registration. Everyone can still register, file issues, fork, and open PRs; only creation is gated. For external-IdP setups, allow the gate to read a group/claim so the policy lives at the IdP. ## Umbrella context **Who's asking:** This request comes from [Zentrum SDS](https://zentrumsds.ch/), the Swiss public-sector digital-sovereignty initiative (anchored at the Bern University of Applied Sciences), which is planning the Forgejo-based **opencode.ch** code platform. "We" throughout refers to this group. Open instances need **open registration** so people can file issues and contribute (fork → PR). But open registration also lets anyone **create new repositories**, which raises two problems: - **Resource use** — new repositories accumulate and consume shared Actions runner resources. - **Content moderation** — arbitrary repositories (spam, abuse, off-topic or unlawful content) on a public-sector-branded platform. Both force operators to police and delete repositories by hand (a known pain on `code.forgejo.org` itself). **The shape we want: anyone participates, only approved users create repositories.** How existing public-sector platforms handle it: - **`opencode.de`** (GitLab-based) — anyone can register to comment and file tickets; creating new repositories is gated by an email-domain allow-list. The planned Swiss **`opencode.ch`** (Forgejo-based) needs the same. (How an outside contributor is granted the ability to *fork* is exactly the gap Issue B addresses.) - **`code.overheid.nl`** (Forgejo-based) — avoids the problem by **closing registration** to government organisations only. Valid, but it **hinders adoption of and contribution to the code hosted there** (outside contributors, civil society, vendors can't easily fork and send PRs), undercutting the "public money, public code" goal. This request is for operators who want registration to stay **open** — so the code on the platform gets real external engagement — while still controlling who creates repositories and how forks work. **Shared notes (apply to both issues):** - **Forward-looking: relation to federation.** Long term, [federation](https://nlnet.nl/project/Federated-Forgejo/) (ForgeFed/ActivityPub, NLnet-funded) addresses the *cross-instance* version of "participate without us maintaining external accounts": an external contributor keeps their home-forge identity and forks/PRs across instances, so the host never provisions accounts for them — and the "fork yes / create-repository no" split falls out naturally. These local controls and federation are **complementary, not competing**: federation is still experimental (federated stars/follows today; federated forks/PRs and, explicitly, access control & moderation not yet built), so the controls here are what work *now*; and even once federation lands, the creation allow-list (Issue A) still applies for *local* open registration. **If anyone on the federation/moderation side has related work underway, please flag it** so the access-control model doesn't diverge. - We'd rather **upstream this than carry a soft fork**, and are interested in **co-designing and helping fund** the work. Happy to write an RFC and prototype. - **External-IdP deployments:** where Forgejo consumes OIDC from an external identity provider (Keycloak/Zitadel/Authelia), the allow-list in Issue A is most naturally expressed as a **group/claim rule at the IdP**, consumed by Forgejo's existing group→team mapping. The email-domain gate is then just one way to populate that group.
mahlzahn changed title from (削除) open registration with controlled project/fork creation (削除ここまで) to open registration with controlled repository/fork creation 2026年06月12日 16:52:05 +02:00
lsmith changed title from (削除) open registration with controlled repository/fork creation (削除ここまで) to open registration with controlled repository creation 2026年06月14日 21:46:34 +02:00
lsmith changed title from (削除) open registration with controlled repository creation (削除ここまで) to Allow-list who may create repos/orgs, decoupled from registration 2026年06月14日 21:52:05 +02:00
Author
Copy link

FTR I split off the fork related aspects into #478

FTR I split off the fork related aspects into https://codeberg.org/forgejo/discussions/issues/478
Author
Copy link

Closing: the core ask is met with existing Forgejo features (v15).

Hat tip to @crystal , whose Mastodon thread surfaced the config recipe that makes this work.

The goal, open registration, but only approved users create repos/orgs, is achievable today without an upstream change:

  1. Lock self-service creation globally. MAX_CREATION_LIMIT = 0 blocks personal-namespace repo creation for everyone; DISABLE_REGULAR_ORG_CREATION = true blocks org creation by regular users. Forking and AGit forkless PRs stay open (ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT defaults to true), so registration, issues, and contribution are unaffected.

  2. Grant creation back to approved users, in an org namespace. Add them to an organization team with "Create repositories" enabled. Org creation is governed by CanCreateOrgRepo, a pure team-membership check that does not consult MAX_CREATION_LIMIT, so team members can create in the org despite the global 0. (Personal-namespace creation uses the separate CanCreateRepo, which honours the global limit and stays blocked.)

  3. Drive that membership from the allow-list automatically. With an external IdP, Forgejo's existing OIDC group→team mapping re-syncs membership from a group claim on every login, so an email-domain / claim allow-list expressed at the IdP grants and revokes creation rights with no manual step, at scale. Without an IdP, a small admin-API job can reconcile the same team membership.

Net: everyone registers / files issues / forks / opens PRs; only approved users (by domain or claim) create — automatically, decoupled from registration. That is exactly the ask.

(Aside: the original "resource use" rationale is better addressed at the runner layer — repos and forks are cheap; untrusted CI is the scarce resource — so creation gating is really about moderation/provenance.)

One residual, much narrower than this umbrella: the recipe grants creation in an org namespace. There is still no out of the box way to gate personal-namespace creation by domain/claim (it is globally on or off). Operators who specifically want open personal-namespace creation gated by domain would still need that, filing a focused follow-up for just that piece. However in my use case we do nit need personal-namespaces at all.

Closing as resolved by existing features; happy to contribute documentation that makes the recipe discoverable.

**Closing: the core ask is met with existing Forgejo features (v15).** Hat tip to **@crystal**, whose [Mastodon thread](https://hachyderm.io/@crystal/116764839623332956) surfaced the config recipe that makes this work. The goal, open registration, but only approved users create repos/orgs, is achievable today without an upstream change: 1. **Lock self-service creation globally.** `MAX_CREATION_LIMIT = 0` blocks personal-namespace repo creation for everyone; `DISABLE_REGULAR_ORG_CREATION = true` blocks org creation by regular users. Forking and AGit forkless PRs stay open (`ALLOW_FORK_WITHOUT_MAXIMUM_LIMIT` defaults to `true`), so registration, issues, and contribution are unaffected. 2. **Grant creation back to approved users, in an org namespace.** Add them to an **organization team with "Create repositories" enabled**. Org creation is governed by `CanCreateOrgRepo`, a pure team-membership check that does **not** consult `MAX_CREATION_LIMIT`, so team members can create in the org despite the global `0`. (Personal-namespace creation uses the separate `CanCreateRepo`, which honours the global limit and stays blocked.) 3. **Drive that membership from the allow-list automatically.** With an external IdP, Forgejo's existing **OIDC group→team mapping** re-syncs membership from a group claim on every login, so an email-domain / claim allow-list expressed at the IdP grants and revokes creation rights with no manual step, at scale. Without an IdP, a small admin-API job can reconcile the same team membership. Net: everyone registers / files issues / forks / opens PRs; only approved users (by domain or claim) create — automatically, decoupled from registration. That is exactly the ask. *(Aside: the original "resource use" rationale is better addressed at the runner layer — repos and forks are cheap; untrusted CI is the scarce resource — so creation gating is really about moderation/provenance.)* **One residual, much narrower than this umbrella:** the recipe grants creation in an **org** namespace. There is still no out of the box way to gate **personal-namespace** creation by domain/claim (it is globally on or off). Operators who specifically want open *personal-namespace* creation gated by domain would still need that, filing a focused follow-up for just that piece. However in my use case we do nit need personal-namespaces at all. Closing as **resolved by existing features**; happy to contribute documentation that makes the recipe discoverable.
Sign in to join this conversation.
No Branch/Tag specified
No results found.
No results found.
Labels
Clear labels
User research - Accessibility
Requires input about accessibility features, likely involves user testing.
User research - Blocked
Do not pick as-is! We are happy if you can help, but please coordinate with ongoing redesign in this area.
User research - Community
Community features, such as discovering other people's work or otherwise feeling welcome on a Forgejo instance.
User research - Config (instance)
Instance-wide configuration, authentication and other admin-only needs.
User research - Errors
How to deal with errors in the application and write helpful error messages.
User research - Filters
How filter and search is being worked with.
User research - Future backlog
The issue might be inspiring for future design work.
User research - Git workflow
AGit, fork-based and new Git workflow, PR creation etc
User research - Labels
Active research about Labels
User research - Moderation
Moderation Featuers for Admins are undergoing active User Research
User research - Needs input
Use this label to let the User Research team know their input is requested.
User research - Notifications/Dashboard
Research on how users should know what to do next.
User research - Rendering
Text rendering, markup languages etc
User research - Repo creation
Active research about the New Repo dialog.
User research - Repo units
The repo sections, disabling them and the "Add more" button.
User research - Security
User research - Settings (in-app)
How to structure in-app settings in the future?
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
forgejo/discussions#477
Reference in a new issue
forgejo/discussions
No description provided.
Delete branch "%!s()"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?