1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
Document: WM-089 P. Webb
Category: Self-Host 2026-04-17
Self-hosting my code with cgit (again)
Abstract
cgit is basic but it works well...perfect.
Body
Of all the code forges available, cgit[1] is the most basic but also
the least offensive to me, stylistically (and customizable). Last
weekend I planned to spin up a website for my photography but felt a
sudden urge to get my public repos off Github.
A few hours later, code.webb.page[2] was live. My original plan for
hosting my repos was to wait until EOL[3] was ready but my roadmap
doesn't have that happening anytime soon.
📸[the codex][IMG1]
I setup a repo[4] with all my cgit customizations. Organizing the
CSS[5] alone took a few days, thank goodness nesting exists (inlined
my uchū palette[6] as well).
## Installation
I always start with this handy script[7] for my servers.
```sh
apt install cgit fcgiwrap python3-markdown -y
```
cgit needs `fcgiwrap` and if you want to have READMEs appear in your
repos, you'll need `python3-markdown` (per the `readme=:` lines in
`cgitrc`[8]).
Also, I had to edit `about_formatting.sh`[9] to make relative imagess
appear in my READMEs. Replace this:
```sh
*.markdown|*.mdown|*.md|*.mkd) exec ./md2html; ;;
```
With this:
```sh
*.markdown|*.mdown|*.md|*.mkd) ./md2html | sed 's|src="\./|src="/'"$CGIT_REPO_URL"'/plain/|g'; ;;
```
📸[uchū readme][IMG2]
`fcgiwrap.socket` should be owned by Caddy. Open with:
```sh
systemctl edit fcgiwrap.socket
```
```sh
[Socket]
SocketUser=caddy
SocketGroup=caddy
SocketMode=0660
```
And enable with:
```sh
systemctl enable --now fcgiwrap.socket
```
After updating your `Caddyfile`[10]'s `reverse_proxy`:
```sh
chown caddy:www-data /run/fcgiwrap.socket
```
And reload!
```sh
systemctl reload caddy
```
I like my repos' default branch to be `primary` and I made it so via:
```sh
git config --global init.defaultBranch primary
```
I ran into issues making clone URLs pretty but still useable for me
so I disabled them. You can download the repos via the `/commit` page
in `tar.gz` and `zip` though.
If you do go through the process of changing which users owns the
main repo directory, you'll have to reload `fcgiwrap` to pick up the
group change.
```sh
systemctl restart fcgiwrap
```
Because I like having my repos organized, I have to update `cgitrc`
when adding new ones. Not too bad of a deal-breaker, I'm doing
everything else manually anyway (and it's a one-time thing).
## FIN
I think that's it! I'm gonna keep tinkering with the styling here and
there (the Markdown rendering isn't to my liking) and the structure
(the generated HTML would look nicer if indented when you view source
on the browser).
I still have a number of repos on Github, most of them old and thus
inconsequential. cgit is just a repo viewer so it lacks support for
private repos; so, I'm not fully off Github yet.
EOL can't come soon enough! 🕸️
References
[1] <https://git.zx2c4.com/cgit>
[2] <https://code.webb.page>
[3] </WM-078#:~:text=dap.sh.-,4.%20Code%20Hosting,-Github%20is%20owned>
[4] <https://code.webb.page/cgit.git>
[5] <https://code.webb.page/cgit.git/tree/var/www/cgit/cgit.css>
[6] <https://code.webb.page/nevercease/uchu.git/about>
[7] <https://code.webb.page/script.git/tree/server.sh>
[8] <https://code.webb.page/cgit.git/tree/etc/cgitrc>
[9] <https://code.webb.page/cgit.git/tree/usr/lib/cgit/filters/about-formatting.sh>
[10] <https://code.webb.page/cgit.git/tree/etc/caddy/Caddyfile>
[IMG1] <https://cdn.webb.page/blog/2026/wm-089-a.JPG>
[IMG2] <https://cdn.webb.page/blog/2026/wm-089-b.JPG>
|