Self-hosted Subversion server
Set it in the browser.
Enforce it on every client.
SvnBd manages repositories, accounts and path permissions from a web console, then compiles them into the authz and htpasswd files Apache reads on every request. One set of rules, honoured by the browser and by svn alike.
Console writes data/conf/authz
[docs:/trunk]
mahi = rw
$ svn commit -m "fix the install steps"
Sending trunk/README.md
Transmitting file data .done
Committed revision 42.
No second place to keep permissions in sync. The console is the only writer; Apache is the only enforcer.
A control plane and a data plane, kept apart on purpose
The console never speaks the Subversion wire protocol. It owns everything around the repositories — creating them, hashing credentials, compiling access rules — and leaves the serving to Apache and mod_dav_svn, exactly as VisualSVN does on Windows.
Because both sides read the same generated files, a permission you set in the console is the permission a checkout gets. There is no sync step to forget, and nothing to reconcile after a change.
Everything you would otherwise do over SSH
Each row is a real mechanism, not a wrapper around a config file you still have to edit. The right column is what actually runs.
| In the console | Underneath |
|---|---|
| RepositoriesCreate, delete, standard trunk/branches/tags | svnadmin create |
| Repository browserTree, files, history, changesets, diffs — at any revision | svn --xml, peg revisions |
| AccountsSVN users, self-service password portal | htpasswd -bnB (bcrypt) |
| GroupsGrant to a team instead of a person | [groups] in authz |
| PermissionsPer repository, per path: read, read-write, none | authz, default deny |
| HooksNine standard hooks, edited in the browser | repos/<name>/hooks/ |
| BackupsHot copy a live repository, then verify it | svnadmin hotcopy · verify |
| ActivityWho did what, from where, and whether it worked | append-only audit log |
The parts worth being strict about
Console sign-ins use PBKDF2-SHA256 at 210,000 iterations. Subversion accounts are bcrypt-hashed straight into the htpasswd file. Neither is recoverable, including by the server.
Every external tool is invoked with an argv array, so a repository named with a semicolon is just an invalid name — not a command. Names containing .. or a path separator are rejected before that.
The generated authz file opens with [/] * =. Nobody reaches a repository until a rule says so, and a rule can only be added by someone signed in to the console.
Browsing a repository replays your credentials against Apache first. If a checkout would be refused, so is the page — the browser is never a second, looser door.
Five failed sign-ins lock the account for fifteen minutes. Failures are logged with the address they came from, whether or not the username exists.
Creating, deleting, resetting and signing in all land in an append-only audit log with the actor, the address and the result. The console cannot edit it.
Running in about five minutes
One Debian or Ubuntu host. Subversion and Apache from the distribution, the console published next to them.
# 1 — the Subversion side
sudo apt-get install subversion libapache2-mod-svn
sudo a2enmod dav dav_svn authz_svn
# 2 — the console
dotnet publish -c Release -o published
ASPNETCORE_URLS=http://0.0.0.0:3122 dotnet published/SvnBd.dll
# 3 — point Apache at the files the console generates
# Settings → Download svnbd-apache.conf, then a2ensite
Sign in, add a repository, grant yourself access. Then anyone on the team checks out the same way they always have:
svn checkout https://svn.void.bd/svn/<repo>