Set this on any server the internet can reach. LFSX_ALLOWED=acme/* names the repositories this
server is for, and everything else is answered 404 before the forge is asked.
Without it the server mirrors the forge for every repository on it. That is the whole permission
model, and it has one consequence worth stating plainly: anybody with an account can create a
repository, is its admin, and can therefore push objects for it here. On github.com that is
everyone. The forge is right, it is their repository; the disk is yours.
LFSX_ALLOWED=acme/*,partner/shared-assets
An entry is org/repo, org/prefix-* for a run of repositories, or org/* for all of an
organisation's, the same syntax as restricted namespaces. Matching
ignores case. An entry that is not org/repo is dropped and logged rather than widened, and a list
where nothing parsed serves nothing rather than everything.
Being listed only lets a repository in. The caller still gets exactly what the forge grants, so a
token with pull on acme/assets still cannot push to it.
A repository outside the list is a 404 for everybody, its admin included and a caller with no
credentials too: there is nothing to authenticate for, and the forge is never asked, so a stranger
walking repository names spends none of the lookup budget.
The server logs a warning at boot when it talks to a forge and no list is set.
The dashboard can change the list without a restart. What it saves takes precedence
over LFSX_ALLOWED until it is reset.
Doing it in the reverse proxy instead
It works, and it is the right place if the proxy already filters by path. The server answers on
/health, /ready, /metrics, under /-/ for the dashboard and any other forge, and under
/{org}/{repo}/ and nowhere else, so allowing the first three, /-/ and the prefixes you want, and refusing the rest, is the whole rule. Match the organisation
without regard to case, since the forge does. LFSX_ALLOWED does the same thing without needing
the proxy to know the URL layout, and keeps working if a route is ever added.