From 85a2a330f729d70dfce1b81dc69ec15436a3d44c Mon Sep 17 00:00:00 2001 From: Collin Williams <96917990+bluedragon1221@users.noreply.github.com> Date: Mon, 4 May 2026 09:40:42 -0500 Subject: Initial clean commit --- forgejno.html | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 forgejno.html (limited to 'forgejno.html') diff --git a/forgejno.html b/forgejno.html new file mode 100644 index 0000000..71246e7 --- /dev/null +++ b/forgejno.html @@ -0,0 +1,148 @@ + + + + + + You don't need Forgejo + + + + + + + +
+ +
+ +
+

You Don't Need Forgejo

+

People + ditching + GitHub after recent issues + are looking to self-hosting Forgejo as an alternative.

+

Despite some (poorly disclosed) security issues, I think there's a more fundemental reason why you shouldn't use Forgejo.

+

If you're just a single person trying to publish your independent coding projects, why do you need: CI, Issue Tracking, Pull Requests, Multi-user account management, etc?

+

just use cgit.

+ +

How do git forges (like GitHub) even work?

+

A git forge is basically just a directory of git repositories, served over http or ssh, with a fancy web frontend.

+

On the server, since the repos don't need to store mutable state (local commits, staged files, etc) they're stored in a special format that's basically just the .git + directory of a normal git repository.

+

This is called a bare repository.

+ +

What is cgit?

+

cgit is essentially just a web-based frontend for these bare repos.

+

While full-on software forges (like GitHub or Forgejo) give you many extra features, cgit is just the read-only frontend, with nothing else included.

+

Interested?

+ +

cgit Setup Guide

+

The cgit setup process is fairly involved, but if you were planning on self-hosting Forgejo, then you can handle it.

+

I'll be using Caddy as the webserver for this setup, but I'll link tutorials for NGINX and Apache if prefer xml configuration files and manual https certificates ;)

+ +

To keep everything organized, I'll run cgit under a user called "git". Our git repos will be stored in this directory.

+

$ useradd -r -d /var/lib/cgit -s /usr/bin/git-shell git

+ +

fcgiwrap

+

cgit is served as a cgi application.

+

A long time ago in a galaxy far far away, web servers had builtin support for cgi, but now its often delegated to fcgiwrap.

+

So our first step will be setting up fcgiwrap.

+ +
    +
  1. Install fcgiwrap with a package manager. This will create two systemd files: fcgiwrap.service and fcgiwrap.socket.

  2. +
  3. Open fcgiwrap.service in a text editor ($ systemctl edit fcgiwrap.service) and set the User and Group to be our "git" user.

  4. +
  5. Open fcgiwrap.socket ($ systemctl edit fcgiwrap.socket) and add "SocketUser=caddy" and "SocketGroup=caddy" under the [Socket] section. (replace with the correct Caddy user for your system)

  6. +
+ +

cgit

+

Since cgit is a cgi application, it does not run as its own service. It is simply a script that gets executed by Caddy and piped into fcgiwrap. As such, the setup is pretty simple:

+
    +
  1. Install cgit with a package manager. This will place the cgit files at /var/www/htdocs/cgit

  2. +
  3. +

    Make sure that location is owned by "git", but is readable by all users:

    +

    $ chown -R git /var/www/htdocs/cgit && chmod -R 764 /var/www/htdocs/cgit

    +
  4. +
+ +

Caddy

+

To complete the set up, add this block to the Caddyfile to serve cgit.

+
git.my.tld {
+    @assets path /cgit.css /cgit.js /favicon.svg /robots.txt
+    handle @assets {
+        root * /var/www/htdocs/cgit
+        file_server
+    }
+
+    reverse_proxy unix//run/fcgiwrap-cgit.sock {
+        transport fastcgi {
+            env SCRIPT_FILENAME /var/www/htdocs/cgit/cgit.cgi
+        }
+    }
+}
+ +

Lock down SSH access

+

Using git-shell + blocks normal shell access and allows only git-style SSH commands.

+
    +
  1. Create an SSH directory for the git + user: $ install -d -o git -g git -m 700 /var/lib/cgit/.ssh

  2. +
  3. Add your public key to /var/lib/cgit/.ssh/authorized_keys + with mode 600.

  4. +
+ +

Create some repos

+

Create a bare repository:

+

$ sudo -u git git init --bare /var/lib/cgit/example

+

Push to it from your local machine:

+
$ git remote add origin git@git.my.tld:example
+$ git push -u origin main
+ +

cgitrc

+

A clean default /etc/cgitrc file might look like this:

+
css=/cgit.css
+logo=
+virtual-root=/
+
+enable-index-owner=0
+enable-http-clone=1
+scan-path=/var/lib/cgit
+
+root-title=git.my.tld
+root-desc=Personal git repositories
+snapshots=tar.gz zip
+ +

Tradeoffs

+

You lose integrated issues, pull requests, built-in CI, orgs, and a social graph.

+

In return, you get a tiny stack, fewer moving parts, lower attack surface, lower resource use, and a setup you can understand.

+

For my personal projects, that trade is acceptable.

+
+ + -- cgit v1.3.1