更新日志
更新Forgejo Actions
2026-02-01- 撰写Forgejo Runner安装部署流程
- 修正部分描述
创建文章
2025-11-22- 撰写Forgejo Server安装部署流程
Forgejo是一个自托管的轻量级Git服务托管平台。伴随着Gitea逐渐露出商业模式的苗头,Forgejo从中分叉出来,秉持着最初的纯粹的社区精神。本文将简单介绍Forgejo的自部署流程以及注意事项,希望若是有有缘人看到能够少踩坑。
事前准备
这里仅介绍使用Docker Compose安装的流程,所以在开始之前,请确保你已经安装了Docker和Docker Compose。
前排提醒,博主使用的是Linux发行版是Ubuntu 24.04,因发行版原因命令有所不同请自行调整!
安装部署
Forgejo Server
首先创建一个git用户。
sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' \ --group --disabled-password --home /home/git git把用户git添加到docker用户组中:
sudo usermod -aG docker git查看用户id号,待会儿在docker-compose.yml文件中需要使用。
id -u git比如我这是111。
接下来创建容器目录,我这边使用的是 /var/www/docker/forgejo_server 目录。
在容器目录创建文件夹data,并给用户git授权。
sudo chown git:git data/在容器目录下创建docker-compose.yml文件,键入以下内容:
networks: forgejo: external: false
services: server: image: codeberg.org/forgejo/forgejo:13 container_name: forgejo environment: - USER_UID=111 - USER_GID=111 - FORGEJO__database__DB_TYPE=postgres - FORGEJO__database__HOST=db:5432 - FORGEJO__database__NAME=forgejo - FORGEJO__database__USER=forgejo - FORGEJO__database__PASSWD=forgejo restart: always networks: - forgejo volumes: - ./data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro ports: - "3000:3000" - "2222:22" depends_on: - db
db: image: postgres:14 restart: always environment: - POSTGRES_USER=forgejo - POSTGRES_PASSWORD=forgejo - POSTGRES_DB=forgejo networks: - forgejo volumes: - ./postgres:/var/lib/postgresql/data- "3000:3000"映射的是Web端口,- "2222:22"映射的是SSH端口。
这边根据实际情况自行修改,比如USER_UID、USER_GID修改为用户git的实际uid和gid,数据库信息可适当修改,如POSTGRES_PASSWORD可设置更复杂的密码。
接下来便可以启动容器了。
docker-compose up -d然后你应该可以看见容器成功启动了。
但是目前并未完全安装完毕,如果现在直接使用SSH的话将会发生如下情况:
❯ ssh -T git@git.peean.netgit@git.peean.net's password:Permission denied, please try again.git@git.peean.net's password:Permission denied, please try again.git@git.peean.net's password:git@git.peean.net: Permission denied (publickey,password).这里便是踩坑点了,这是由于SSH运行在容器内部,如果需要SSH支持,则必须将SSH连接从主机传递到容器。
创建shell脚本:
sudo vim /usr/local/bin/forgejo-shell键入以下内容:
#!/bin/sh/usr/bin/docker exec -i -u git --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" forgejo sh "$@"然后赋予执行权限:
sudo chmod +x /usr/local/bin/forgejo-shell把用户git的登录shell改成 /usr/local/bin/forgejo-shell:
sudo usermod -s /usr/local/bin/forgejo-shell git更改SSH配置文件:
sudo vim /etc/ssh/sshd_config在文件最末尾添加以下内容:
Match User git AuthorizedKeysCommandUser git AuthorizedKeysCommand /usr/bin/docker exec -i -u git forgejo /usr/local/bin/forgejo keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k重启sshd服务
sudo systemctl restart sshd接下来就算大功告成了,现在添加完SSH后使用SSH测试应返回如下形式的结果:
❯ ssh -T git@git.peean.netHi there, Peean! You've successfully authenticated...开始愉快的使用独属于你的私人Git服务吧!
Forgejo Runner
重新找个地方建个文件夹作为 runner 运行的容器目录,这边采用的是 /var/www/docker/forgejo_runner。
使用以下脚本以 root 用户身份创建一个权限为非 root 的 data 目录:
#!/usr/bin/env bash
set -e
mkdir -p data/.cache
chown -R 1001:1001 datachmod 775 data/.cachechmod g+s data/.cache运行 bash setup.sh 后,定义以下 docker-compose.yml 文件:
services: docker-in-docker: image: docker:dind container_name: 'docker_dind' privileged: 'true' command: ['dockerd', '-H', 'tcp://0.0.0.0:2375', '--tls=false'] restart: 'unless-stopped'
runner: image: 'data.forgejo.org/forgejo/runner:11' links: - docker-in-docker depends_on: docker-in-docker: condition: service_started container_name: 'runner' environment: DOCKER_HOST: tcp://docker-in-docker:2375 # User without root privileges, but with access to `./data`. user: 1001:1001 volumes: - ./data:/data restart: 'unless-stopped'
command: '/bin/sh -c "while : ; do sleep 1 ; done ;"'接下来需要配置和注册 runner,先启动容器:
docker-compose up -d然后通过以下方式进入:
docker exec -it runner /bin/sh在此 shell 中,运行如下命令以创建包含默认设置的配置文件。然后你可以根据需要编辑配置文件 config.yml。
forgejo-runner generate-config > config.ymlCAUTION官方文档写成
forgejo-runner config > config.yml了,这是错误的!(又获取是老版本是这样的写的?我并没有用过,所以无法确认)
在同一 shell 中,运行如下命令来注册 runner:
forgejo-runner register接下来会交互式地引导你完成注册 runner 的过程,类似如下:
~ $ forgejo-runner registerINFO Registering runner, arch=amd64, os=linux, version=v11.3.1.WARN Runner in user-mode.INFO Enter the Forgejo instance URL (for example, https://next.forgejo.org/):https://git.peean.netINFO Enter the runner token:6om01axzegBu98YCpsFtda4Go2DuJe7BEepzz2F3HYINFO Enter the runner name (if set empty, use hostname: 37dc42b87b32):forgejo-runnerINFO Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-20.04:docker://node:20-bookworm,ubuntu-18.04:docker://node:20-bookworm):ubuntu-22.04:docker://ghcr.io/catthehacker/ubuntu:act-22.04INFO Registering runner, name=forgejo-runner, instance=https://git.peean.net, labels=[ubuntu-22.04:docker://ghcr.io/catthehacker/ubuntu:act-22.04].DEBU Successfully pinged the Forgejo instance serverINFO Runner registered successfully.第一个问题 Enter the Forgejo instance URL:填写 Forgejo 实例的URL,例如 https://git.peean.net。
第二个问题 Enter the runner token:填写 Forgejo 实例的 Registration Token,获取位置前往 https://<YOUR_FORGEJO_URL>/admin/actions/runners 页面,点击 Create new runner(创建新运行器) 获取,例如 6om01axzegBu98YCpsFtda4Go2DuJe7BEepzz2F3HY。

第三个问题 Enter the runner name:填写 runner 的名称,例如 forgejo-runner。
第四个问题 Enter the runner labels:填写 runner 的标签,例如 ubuntu-22.04:docker://ghcr.io/catthehacker/ubuntu:act-22.04。
标签这块的填写格外重要,可参考 nektos/act 以及 Forgejo Actions administrator guide/Choosing labels。
这将在当前目录下创建一个 .runner 文件,内容如下:
{ "WARNING": "This file is automatically generated by act-runner. Do not edit it manually unless you know what you are doing. Removing this file will cause act runner to re-register as a new runner.", "id": 1, "uuid": "d2ax6368-9c20-4dy0-9a5a-e09c53854zb5", "name": "forgejo-runner", "token": "864e6019009e1635d98adf3935b305d32494d42a", "address": "https://git.peean.net", "labels": [ "ubuntu-22.04:docker://ghcr.io/catthehacker/ubuntu:act-22.04" ]}现在应该已经可以看见 runner 了,但是目前的状态是 Offline(离线) 的。

现在使用 exit 命令退出 shell 进入宿主机,然后使用 docker compose down 命令关闭容器,并将 docker-compose.yml 文件中的 command 行修改为如下内容:
command: '/bin/sh -c "sleep 5; forgejo-runner daemon --config config.yml"'在这里,sleep 语句为 docker-in-docker 服务提供了一些额外的启动时间,允许 docker-in-docker 服务在 forgejo-runner daemon 启动之前启动。
做完这些就可以运行 docker compose up -d 重启容器了。
现在再次查看 runner 的状态,应该已经变成了 Idle(空闲) 的状态。
