Forgejo Basic Setup
Setting up local Git server and Forgejo front-end#
Guide should be transferable to many systems, but here using Ubuntu 24.04 on both hosts.
Create system account “git”#
This will also implicitly create the group “git”:
sudo useradd \
--system \
--shell /bin/bash \
--home /srv/forgejo \
--comment 'Forgejo Git Service' \
git
Create ZFS datasets, tune them, set mountpoints#
Arguably overkill but I will create separate datasets for repos, data, log. Operationally this is useful to rollback forgejo via ZFS snapshot, but leave repos untouched. For light personal use a single dataset is also fine and perhaps preferable - make your call.
If you are not using ZFS, take the intent, apply it to your storage system. :)
Layout:
- tank/services/forgejo (root container)
- tank/services/forgejo/repos (Git data)
- tank/services/forgejo/data (DB and runtime data)
- tank/services/forgejo/log (logs - disposable)
Create datasets#
Here the pool ’tank’ already exists, but ‘services/*’ does not yet; use -p to create missing parents:
sudo zfs create -p tank/services/forgejo/repos
sudo zfs create -p tank/services/forgejo/data
sudo zfs create -p tank/services/forgejo/log
Create mounts#
Serve from ‘/srv’:
sudo zfs set mountpoint=/srv/forgejo tank/services/forgejo
sudo zfs set mountpoint=/srv/forgejo/repos tank/services/forgejo/repos
sudo zfs set mountpoint=/srv/forgejo/data tank/services/forgejo/data
sudo zfs set mountpoint=/srv/forgejo/log tank/services/forgejo/log
Verify mounts#
$ mount | grep forge
tank/services/forgejo on /srv/forgejo type zfs (rw,noatime,xattr,noacl,casesensitive)
tank/services/forgejo/repos on /srv/forgejo/repos type zfs (rw,noatime,xattr,noacl,casesensitive)
tank/services/forgejo/data on /srv/forgejo/data type zfs (rw,noatime,xattr,noacl,casesensitive)
tank/services/forgejo/log on /srv/forgejo/log type zfs (rw,noatime,xattr,noacl,casesensitive)
Tune datasets#
All will have atime=off, and compression=lz4, but we vary recordsize:
repos&dataget the same tune for small files, more efficient IO and storage withrecordsize=16K.logwill use the implicit defaultrecordsize=128K; these files are larger and append-heavy, less metadata overhead this way.
sudo zfs set compression=lz4 tank/services/forgejo/repos
sudo zfs set atime=off tank/services/forgejo/repos
sudo zfs set recordsize=16K tank/services/forgejo/repos
sudo zfs set compression=lz4 tank/services/forgejo/data
sudo zfs set atime=off tank/services/forgejo/data
sudo zfs set recordsize=16K tank/services/forgejo/data
sudo zfs set compression=lz4 tank/services/forgejo/log
sudo zfs set atime=off tank/services/forgejo/log
Align permissions to the ‘git’ user#
sudo chown -R git:git /srv/forgejo
sudo chmod -R 750 /srv/forgejo
verify zfs#
zfs list | grep forgejo zfs get mountpoint | grep forgejo
Install some things#
Dependencies#
You might already have some, command is harmless in that case:
sudo apt update
sudo apt install -y git git-lfs sqlite3 wget curl ca-certificates openssh-server
Forgejo#
Install#
Install forgejo binary - use wget as normal user, move as root, chown/chmod for git user once in place: Check the forgojo download page instructions for updated binary and GPG signature, etc.
cd /tmp
wget https://codeberg.org/forgejo/forgejo/releases/download/v14.0.3/forgejo-14.0.3-linux-amd64
Verify; key verified the binary matches the signed binary, but key is unknown trust; this is “normal”
gpg --keyserver keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710
wget https://codeberg.org/forgejo/forgejo/releases/download/v14.0.3/forgejo-14.0.3-linux-amd64.asc
gpg --verify forgejo-14.0.3-linux-amd64.asc forgejo-14.0.3-linux-amd64
Move it in place, create symlink for upgrade convenience, set correct permissions:
sudo mv forgejo-14.0.3-linux-amd64 /srv/forgejo/forgejo-14.0.3-linux-amd64
sudo ln -s /srv/forgejo/forgejo-14.0.3-linux-amd64 /srv/forgejo/forgejo
sudo chmod +x /srv/forgejo/forgejo-14.0.3-linux-amd64
sudo chown git:git /srv/forgejo/forgejo-14.0.3-linux-amd64
sudo chown -h git:git /srv/forgejo/forgejo
Check it runs#
Check it runs, check version:
sudo -u git /srv/forgejo/forgejo --version
Eg: forgejo version 14.0.3+gitea-1.22.0 (release name 14.0.3) built with GNU Make 4.4.1, go1.25.8 : bindata, timetzdata, sqlite, sqlite_unlock_notify
Initial setup#
Start the web frontend so we can do initial setup:
sudo -u git /srv/forgejo/forgejo web
Go there:
http://<HOST>:3000
Config hints:
database:
- database type: SQLite3 in my case; postgres is overkill, simple file fits my needs better for now
- path: /srv/forgejo/data/forgejo.db repository root path:
- overwrote default to match the ZFS structure; “/srv/forgejo/repos” administrator settings:
- create your administrator username and password
Adjust other settings to your own environment and taste. For now the only defaults I changed here were the title and the slogan.
Install install it#
Click Install button.
Boom! You’re in - you can take a look around if you wish.
We should shut down this process and properly configure in systemd as a service.
ctrl+c out of the running server.
Setup Forgejo as systemd service#
Create the unit file:#
sudo cat <<EOF > /etc/systemd/system/forgejo.service
[Unit]
Description=Forgejo
After=network.target
[Service]
Type=simple
User=git
Group=git
WorkingDirectory=/srv/forgejo
Environment=USER=git
Environment=HOME=/srv/forgejo
Environment=FORGEJO_WORK_DIR=/srv/forgejo
ExecStart=/srv/forgejo/forgejo web --config /srv/forgejo/custom/conf/app.ini
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
ReadWritePaths=/srv/forgejo
CapabilityBoundingSet=
[Install]
WantedBy=multi-user.target
EOF
Optional SQLite performance tweak#
There are pros and cons, check docs and see if it suits your use case. We can do this now before starting the service.
nano /srv/forgejo/custom/conf/app.ini
[database]
SQLITE_JOURNAL_MODE = WAL
Enable and start the forgejo service#
You killed the ephemeral process we started for the install, right? Ok now enable and start properly:
sudo systemctl daemon-reload
sudo systemctl enable --now forgejo
Configure Forgejo admin user/user(s) and SSH key(s)#
Use Forgejo GUI to add your SSH key and follow the verification steps. NOTE: if the server hosting Forgejo has “AllowUsers” set in /etc/ssh/sshd_config, then:
- you will need to add ‘git’ user there
- then
systemctl restart sshd
Configure client SSH#
Update your ~/.ssh/config if needed. In my case I already have a Host entry in my config, but now I have two users (and two separate SSH keys):
- ssh me@tank
- ssh git@tank
So I must add:
Host tank
HostName tank
User git
IdentityFile ~/.ssh/your-custom-key
IdentitiesOnly yes
Git, finally!#
Adjust to suit your purposes. My first repo is hugo.git, for creating this website.
Create first repo in Forgejo GUI#
- Click the ‘+’ icon top right
- “New repository”
- Name: “hugo”
- Ensure “Initialise repository” is unticked
- Click “Create repository”
Nice.
Git basics#
From client workstation we will init and push for first commit.
Git global user and email#
If you haven’t before set global user and email it will complain, so you can do it now:
git config --global user.name "Your Name"
git config --global user.email "you@domain.com"
init and push#
mkdir ~/hugo
cd ~/hugo
echo "My Hugo personal site" > README.md
git init
git switch -c main
git add README.md
git commit -m "first commit"
git remote add origin ssh://git@tank/niall/hugo.git
git push -u origin main
Forgejo#
Forgejo should now reflect this commit and from here it’s a matter of using and tweaking to your liking.
Create something beautiful.