本教程适用于以下操作系统版本

  • Debian 12(Bookworm)
  • Debian 11(Bullseye)
  • Debian 10(Buster)

本页内容

  • 先决条件
  • 第 1 步 - 配置防火墙
  • 第 2 步 - 安装 Docker 和 Docker Compose
  • 第 3 步 - 创建 Git 用户
  • 第 4 步 - 配置并安装 Gitea 配置系统时区 创建 Gitea 目录 配置 Gitea Docker Compose 文件 自定义你的 Gitea 安装 安装 Gitea
  • 第 5 步 - 安装 Nginx
  • 第 6 步 - 安装 SSL
  • 第 7 步 - 配置 Nginx
  • 第 8 步 - 访问并配置 Gitea
  • 第 8 步 - 创建第一个仓库
  • 第 9 步 - 配置 SSH
  • 第 10 步 - 使用 SSH 克隆仓库
  • 第 11 步 - 测试首次提交
  • 第 12 步 - 备份和恢复 Gitea
  • 第 13 步 - 升级 Gitea
  • 结论
  • 配置系统时区
  • 创建 Gitea 目录
  • 配置 Gitea Docker Compose 文件
  • 自定义你的 Gitea 安装
  • 安装 Gitea

Gitea 是一个基于 Git 平台的开源代码托管解决方案。它使用 Go 语言编写,可以安装在多种操作系统上,包括 Linux、macOS、Windows,以及 amd64、i386、ARM 等多种架构。它包含仓库文件编辑器、问题跟踪、拉取请求、用户管理、通知、内置 wiki、LFS 支持、Git 钩子等众多功能。

它是一个轻量级应用程序。因此,它可以安装在性能较低的系统上。如果你正在寻找一个占用内存较小的自托管 Git 平台,你应该了解一下 Gitea。

本文将介绍如何在 Debian 12 服务器上安装和配置 Gitea,并设置你的第一个 Git 仓库。Gitea 可以从源代码、二进制文件、Docker 包或软件包进行安装。在本教程中,我们将使用 Docker 进行安装。

先决条件

  • 一台运行 Debian 12 的服务器。
  • 一个具有 sudo 权限的非 root 用户。
  • 一个指向你服务器的完全限定域名(FQDN),例如 gitea.example.com。
  • 如果你的服务器只有 1GB 内存,请确保已启用 swap 交换存储。
  • 确保系统已更新。$ sudo apt update && sudo apt upgrade
  • 在继续之前需要安装一些必要的软件包。其中部分可能已经安装在你的服务器上。$ sudo apt install curl wget nano software-properties-common dirmngr apt-transport-https ca-certificates lsb-release debian-archive-keyring gnupg2 ufw unzip -y

一台运行 Debian 12 的服务器。

一个具有 sudo 权限的非 root 用户。

一个指向你服务器的完全限定域名(FQDN),例如 gitea.example.com。

如果你的服务器只有 1GB 内存,请确保已启用 swap 交换存储。

确保系统已更新。

$ sudo apt update && sudo apt upgrade

在继续之前需要安装一些必要的软件包。其中部分可能已经安装在你的服务器上。

$ sudo apt install curl wget nano software-properties-common dirmngr apt-transport-https ca-certificates lsb-release debian-archive-keyring gnupg2 ufw unzip -y

第 1 步 - 配置防火墙

第一步是配置防火墙。Debian 默认自带 ufw(Uncomplicated Firewall,简易防火墙)。

检查防火墙是否正在运行。

$ sudo ufw status

你将看到如下输出。

Status: inactive

允许 SSH 端口,以免启用防火墙时中断当前连接。

$ sudo ufw allow OpenSSH

同时允许 HTTP 和 HTTPS 端口。

$ sudo ufw allow http
$ sudo ufw allow https

启用防火墙

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

再次检查防火墙的状态。

$ sudo ufw status

你应该会看到类似的输出。

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

第 2 步 - 安装 Docker 和 Docker Compose

Debian 12 自带较旧版本的 Docker。要安装最新版本,首先导入 Docker 的 GPG 密钥。

$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg

创建 Docker 仓库文件。

$ echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

更新系统仓库列表。

$ sudo apt update

安装最新版本的 Docker。

$ sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

验证它是否正在运行。

$ sudo systemctl status docker
? docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; preset: enabled)
     Active: active (running) since Sat 2023-11-18 07:13:39 UTC; 10s ago
TriggeredBy: ? docker.socket
       Docs: https://docs.docker.com
   Main PID: 1891 (dockerd)
      Tasks: 8
     Memory: 27.2M
        CPU: 338ms
     CGroup: /system.slice/docker.service
             ??1891 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

默认情况下,Docker 需要 root 权限。如果你想在每次运行 docker 命令时不必使用 sudo,可以将你的用户名添加到 docker 组。

$ sudo usermod -aG docker $(whoami)

你需要注销服务器并以同一用户重新登录以使更改生效,或者使用以下命令。

$ su - ${USER}

确认你的用户已添加到 Docker 组。

$ groups
navjot sudo users docker

第 3 步 - 创建 Git 用户

为了让用户能够通过 SSH 访问主机,你需要在主机上创建一个单独的 git 用户。运行以下命令来创建 git 用户。

$ sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git

让我们逐一了解上述命令中的所有选项和参数,以便更好地理解。

  • --system - 创建一个系统用户而非普通用户。系统用户用于运行系统服务,不能用于交互式登录。
  • --shell /bin/bash - 将系统用户的登录 shell 设置为 Bash shell。
  • --gecos 'Git Version Control' - 为用户设置描述性字段。该选项是可选的,可以跳过,但如果你的系统用户较多,它会很有用。
  • --group - 创建一个与用户名同名的组。
  • --disabled-password - 禁用该用户的密码登录,有助于提升账户安全性。
  • --home /home/git - 将用户的家目录设置为 /home/git,用于存储用户的文件和配置。
  • git - 指定用户名。这里我们使用 git 作为该账户的用户名。

运行命令后,你将看到如下输出。

Adding system user `git' (UID 105) ...
Adding new group `git' (GID 111) ...
Adding new user `git' (UID 105) with group `git' ...
Creating home directory `/home/git' ...

记下变量 UID 和 GID 的值,我们下一步会用到。在我们的示例中,UID 为 105,GID 为 111。

第 4 步 - 配置并安装 Gitea

配置系统时区

你可以通过以下命令查看系统当前的时区。

$ timedatectl
               Local time: Sat 2023-11-18 07:15:53 UTC
           Universal time: Sat 2023-11-18 07:15:53 UTC
                 RTC time: Sat 2023-11-18 07:15:53
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

你可以看到系统设置为 GMT 或 UTC 时区。如果你所在的地区使用不同的时区,或者想要更改时区,请使用以下命令进行设置。

$ sudo timedatectl set-timezone Asia/Kolkata

再次检查时区。

$ timedatectl
               Local time: Sat 2023-11-18 12:46:29 IST
           Universal time: Sat 2023-11-18 07:16:29 UTC
                 RTC time: Sat 2023-11-18 07:16:29
                Time zone: Asia/Kolkata (IST, +0530)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

你可以看到时区已更新为 IST,即 GMT+5:30。

创建 Gitea 目录

创建 Gitea 的目录。

$ mkdir ~/gitea-docker

切换到 Gitea 目录。

$ cd ~/gitea-docker

创建用于存储 Gitea 数据和 PostgreSQL 数据库的目录。

$ mkdir {gitea,postgres}

配置 Gitea Docker Compose 文件

创建并打开 Docker Compose 文件进行编辑。

$ nano docker-compose.yml

在其中粘贴以下代码。粘贴之前生成的 UID 和 GID 值。

services:
  server:
    image: gitea/gitea:1.21.0
    container_name: gitea
    environment:
      - USER_UID=105
      - USER_GID=111
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=db:5432
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea
      - GITEA__database__PASSWD=gitea
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea:/data
      - /home/git/.ssh/:/data/git/.ssh
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "2221:22"
    depends_on:
      - db

  db:
    image: postgres:15
    restart: always
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=gitea
      - POSTGRES_DB=gitea
    networks:
      - gitea
    volumes:
      - ./postgres:/var/lib/postgresql/data

networks:
  gitea:
    external: false

按 Ctrl + X 保存文件,并在提示时输入 Y。

我们使用的是上一步创建的用户的 UID(用户标识符)和 GID(组标识符)值。

上述 Docker Compose 文件部署了两个容器——一个用于 Gitea,一个用于 PostgreSQL。我们添加了一些环境变量来配置数据库详情。要将 PostgreSQL 数据库连接到 Gitea 容器,我们在文件中将主机指定为 PostgreSQL 服务的名称。

端口参数 "3000:3000" 和 "2221:22" 指定了端口映射,左侧端口表示主机端口,右侧端口表示容器端口。Gitea 使用 3000 端口提供 Web 服务,这也是我们暴露给服务器的端口。对于 SSH,我们的系统已经使用 22 端口用于登录。因此,我们指定一个自定义端口来执行 SSH 操作。在本示例中,我们使用 2221 端口。该端口也需要通过防火墙开放,这我们已经在本教程的第 1 步中完成。

Gitea 和 PostgreSQL 容器都通过一个名为 gitea 的通用内部 Docker 网络相互连接。当你启动 Docker 安装时,卷挂载会自动在当前文件夹中创建 gitea 和 postgres 目录。compose 文件中指定的用户 ID 就是 Gitea 容器用来创建 gitea 目录的 ID。另一方面,PostgreSQL 容器将由用户 systemd-coredump 管理,这是默认行为。你可以更改该行为,但并非必须。

自定义你的 Gitea 安装

你可以通过将 app.ini 文件添加到 ~/gitea-docker/gitea/gitea/conf 目录来自定义 Gitea 安装。安装完成后,可以从容器内部在 /data/gitea/conf/app.ini 位置编辑该文件。你可以参考 Gitea 的 Github 仓库中的示例 ini 文件。

安装 Gitea

运行以下命令启动 Gitea 容器。

$ docker compose up -d

检查容器的状态,确保它们正常运行。

$ docker ps
CONTAINER ID   IMAGE                COMMAND                  CREATED          STATUS          PORTS                                                                              NAMES
3b5ce50a04fe   gitea/gitea:1.21.0   "/usr/bin/entrypoint…"   43 seconds ago   Up 42 seconds   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp, 0.0.0.0:2221->22/tcp, :::2221->22/tcp   gitea
0908cb9ec3b7   postgres:15          "docker-entrypoint.s…"   43 seconds ago   Up 42 seconds   5432/tcp                                                                           gitea-docker-db-1

你也可以使用以下命令来检查状态。

$ docker compose ps
NAME                IMAGE                COMMAND                                        SERVICE   CREATED              STATUS              PORTS
gitea               gitea/gitea:1.21.0   "/usr/bin/entrypoint /bin/s6-svscan /etc/s6"   server    About a minute ago   Up About a minute   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp, 0.0.0.0:2221->22/tcp, :::2221->22/tcp
gitea-docker-db-1   postgres:15          "docker-entrypoint.sh postgres"                db        About a minute ago   Up About a minute   5432/tcp

第 5 步 - 安装 Nginx

Debian 12 自带较旧版本的 Nginx。要安装最新版本,你需要下载官方的 Nginx 仓库。

导入 Nginx 的签名密钥。

$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

添加 Nginx 稳定版的仓库。

$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/debian `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

更新系统仓库。

$ sudo apt update

安装 Nginx。

$ sudo apt install nginx

验证安装。在 Debian 系统上,以下命令只能配合 sudo 使用。

$ sudo nginx -v
nginx version: nginx/1.24.0

启动 Nginx 服务器。

$ sudo systemctl start nginx

检查服务状态。

$ sudo systemctl status nginx
? nginx.service - nginx - high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Sat 2023-11-18 15:47:20 IST; 1s ago
       Docs: https://nginx.org/en/docs/
    Process: 4225 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
   Main PID: 4226 (nginx)
      Tasks: 2 (limit: 2315)
     Memory: 1.8M
        CPU: 7ms
     CGroup: /system.slice/nginx.service
             ??4226 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
             ??4227 "nginx: worker process"

在你的 Web 浏览器中打开服务器的 IP 地址。你应该会看到如下页面,这表示你的服务器已正常运行。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

第 6 步 - 安装 SSL

我们需要安装 Certbot 来生成 SSL 证书。你可以使用 Debian 的仓库安装 Certbot,或者使用 Snapd 工具获取最新版本。我们将使用 Snapd 版本。

Debian 12 默认未安装 Snapd。请安装 Snapd 软件包。

$ sudo apt install snapd

运行以下命令,确保你的 Snapd 版本是最新的。

$ sudo snap install core && sudo snap refresh core

安装 Certbot。

$ sudo snap install --classic certbot

使用以下命令,通过创建指向 /usr/bin 目录的符号链接,确保 Certbot 命令可以运行。

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

验证 Certbot 是否正常工作。

$ certbot --version
certbot 2.7.4

生成 SSL 证书。

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d gitea.example.com

上述命令会将证书下载到服务器上的 /etc/letsencrypt/live/gitea.example.com 目录。

生成 Diffie-Hellman 组证书。

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

检查 Certbot 续期调度服务。

$ sudo systemctl list-timers

你会发现 snap.certbot.renew.service 是已计划运行的服务之一。

NEXT                        LEFT           LAST                        PASSED      UNIT                      ACTIVATES     
---------------------------------------------------------------------------------------------------------------------------               
Sat 2023-11-18 18:41:45 IST 2h 49min left Sat 2023-11-18 12:22:34 IST 3h 29min ago apt-daily.timer           apt-daily.service
Sat 2023-11-18 20:40:00 IST 4h 47min left -                           -            snap.certbot.renew.timer  snap.certbot.renew.service
Sun 2023-11-19 00:00:00 IST 8h left       -                           -            dpkg-db-backup.timer      dpkg-db-backup.service

对流程进行一次空运行,以检查 SSL 续期是否正常工作。

$ sudo certbot renew --dry-run

如果你没有看到任何错误,说明一切就绪。你的证书将自动续期。

第 7 步 - 配置 Nginx

运行以下命令,为你的站点添加配置文件。

$ sudo nano /etc/nginx/conf.d/gitea.conf

在编辑器中粘贴以下代码。

# Connection header for WebSocket reverse proxy
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}

map $remote_addr $proxy_forwarded_elem {

    # IPv4 addresses can be sent as-is
    ~^[0-9.]+$ "for=$remote_addr";

    # IPv6 addresses need to be bracketed and quoted
    ~^[0-9A-Fa-f:.]+$ "for=\"[$remote_addr]\"";

    # Unix domain socket names cannot be represented in RFC 7239 syntax
    default "for=unknown";
}

map $http_forwarded $proxy_add_forwarded {

   # If the incoming Forwarded header is syntactically valid, append to it
    "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";

    # Otherwise, replace it
    default "$proxy_forwarded_elem";
}

# Redirect all non-encrypted to encrypted
server {
    listen 80;
    listen [::]:80;
    server_name gitea.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name gitea.example.com;

    ssl_certificate     /etc/letsencrypt/live/gitea.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/gitea.example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/gitea.example.com/chain.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] valid=60s;
    resolver_timeout 2s;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    access_log /var/log/nginx/gitea.access.log main;
    error_log  /var/log/nginx/gitea.error.log;

    tcp_nopush on;

    # security headers
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
    add_header Permissions-Policy "interest-cohort=()" always;

    # . files
    location ~ /\.(?!well-known) {
        deny all;
    }

    location / {
        client_max_body_size 100M;
        proxy_pass  http://localhost:3000;
        proxy_http_version 1.1;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header Forwarded $proxy_add_forwarded;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

完成后,按 Ctrl + X 关闭编辑器,并在提示时按 Y 保存文件。

打开 /etc/nginx/nginx.conf 文件进行编辑。

$ sudo nano /etc/nginx/nginx.conf

在 include /etc/nginx/conf.d/*.conf; 这一行之前添加以下内容。

server_names_hash_bucket_size 64;

按 Ctrl + X 保存文件,并在提示时输入 Y。然后测试 Nginx 配置。

$ sudo nginx -t

你应该会看到类似如下的输出,表明你的配置正确。

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重新加载 Nginx 服务。

$ sudo systemctl reload nginx

第 8 步 - 访问并配置 Gitea

在浏览器中访问 URL https://gitea.example.com,将出现如下安装界面。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

大多数字段会根据 Docker compose 文件中的值预先填充。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

输入 gitea.example.com 作为服务器域名,输入 https://gitea.example.com 作为 Gitea 基础 URL。将 SSH 服务器端口的值从 22 改为 2221。其余设置保持原样。

如果你想使用邮件功能,可以添加你的 SMTP 服务器详情。展开页面的邮件设置(Email Settings)部分,并按截图所示填写数值。请确保像图中那样将 SMTP 端口与主机名一起填写。在本教程中,我们使用的是 Amazon SES 服务。你可以使用任何你喜欢的 SMTP 服务。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

在安装之前,还有一些设置你需要查看。要更改它们,请展开页面的服务器和第三方服务设置(Server and Third-Party Service Settings)部分。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

根据你的需求更改设置。我们启用了“默认隐藏电子邮件地址”(Hide Email Addresses by Default)选项以确保更好的隐私,并启用了“需要登录才能查看页面”(Require Sign-in to View Pages)以保持我们的 Git 站点私有。如果你不希望人们注册账户,请启用“禁用自助注册”(Disable Self-Registration)选项。

最后但同样重要的是,设置你的管理员账户。展开页面的管理员账户设置(Administrator Account Settings)部分,并填写所需的值。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

完成后点击“安装 Gitea”(Install Gitea)按钮以完成安装。你将被重定向到 Gitea 仪表板。如果由于某种原因出现了 502 错误,请刷新页面。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

第 8 步 - 创建第一个仓库

让我们创建第一个仓库。为此,点击仪表板上的 + 号。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

填写仓库详情。从下拉菜单中选择默认问题(Issue)标签。为你的仓库选择合适的许可证。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

为你的仓库选择默认分支。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

确认无误后,点击“创建仓库”(Create repository)按钮,在你的 Gitea 安装上创建第一个仓库。你将被重定向到你的仓库主页。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

第 9 步 - 配置 SSH

让我们配置 SSH,以便与新建的仓库一起使用。

在本教程中,我们将使用一台预装 Ubuntu 的本地电脑。不过,这些命令在任何操作系统的终端上应该都能基本不变地运行。

在本地电脑上创建一个用于 Gitea 的新 SSH 密钥。

$ ssh-keygen -f ~/.ssh/gitea-demo -t rsa -b 4096 -C "HowtoForge Gitea Demo" -q -N "yourpassphrase"

在上面的命令中,用强密码短语替换占位符。这将在 ~/.ssh/gitea-demo 位置创建一个 SSH 密钥。

接下来,打开你的 Gitea 个人资料设置:点击你的头像下拉菜单,然后选择“设置”(Settings)选项。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

接下来,切换到页面上的 SSH/GPG 密钥(SSH/GPG Keys)标签页。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

为你的 SSH 密钥添加一个名称。回到本地电脑的终端,运行以下命令以输出用于 Gitea 的公钥。

$ cat ~/.ssh/gitea-demo.pub

复制生成的输出,并将其粘贴回 Gitea 的 SSH 密钥页面的内容(Content)框中。

点击“添加密钥”(Add Key)按钮,完成密钥添加。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

回到本地电脑,将 SSH 代理设置为保持活动状态 1 小时。

$ eval $(ssh-agent -t 3600)

将新创建的 SSH 密钥添加到 SSH 代理。

$ ssh-add ~/.ssh/gitea-demo
Enter passphrase for /home/navjot/.ssh/gitea-demo:
Identity added: /home/navjot/.ssh/gitea-demo (HowtoForge Gitea Demo)

系统将提示你输入密码短语。

第 10 步 - 使用 SSH 克隆仓库

让我们使用 SSH 克隆新建的仓库。再次访问仓库页面,选择 SSH 选项后复制 SSH URL。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

它应该类似如下。

ssh://
[email protected]
:2221/navjot/howtoforge.git

在本地电脑上运行以下命令,使用 SSH 克隆仓库。

$ git clone ssh://
[email protected]
:2221/navjot/howtoforge.git
Cloning into 'howtoforge'...
The authenticity of host '[gitea.example.com]:2221 ([128.199.48.13]:2221)' can't be established.
ED25519 key fingerprint is SHA256:H7t5hNmEpZkYC9u3sXbA1mnGXCnoqaUZGL+gpAG9uNs.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[gitea.example.com]:2221' (ED25519) to the list of known hosts.
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.

系统将提示你添加主机凭据。输入 yes 以继续克隆仓库。

你将在你的系统上看到已克隆的仓库。

$ ls
howtoforge

切换到该目录。

$ cd howtoforge

检查新克隆仓库的 Git 状态。为此,你的本地电脑上需要安装 Git。

$ git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

由此可以确认 SSH 工作正常。

第 11 步 - 测试首次提交

既然我们已经设置了第一个仓库,现在该进行一些更改并将其提交了。

让我们更新 README.md 文件。在你的本地电脑上,打开 readme 文件进行编辑。

$ nano README.md

编辑文件,完成后按 Ctrl + X 并在提示时输入 Y 以保存。

再次检查 Git 状态。

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

这表明 Readme 文件已编辑但尚未提交。将文件添加到暂存区,为提交做准备。

$ git add README.md

提交文件。

$ git commit -m "Update the Readme file for Gitea tutorial."
[main bb2956f] Update the Readme file for Gitea tutorial.
 1 file changed, 3 insertions(+), 1 deletion(-)

将文件推送到你的 Gitea 服务器。

$ git push origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 378 bytes | 378.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To ssh://gitea.example.com:2221/navjot/howtoforge.git
   bd1248f..bb2956f  main -> main

要确认,请回到 Gitea 仓库页面。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

你会注意到 Readme 文件已更新,并且显示了最新的提交信息。要查看更改,请点击提交信息,即可查看包含差异的如下页面。

在 Debian 12 上用 Docker 安装 Gitea DevOps 代码托管平台

这完成了我们仓库的首次提交。你可以开始在你的 Gitea 安装上开展你的项目了。

第 12 步 - 备份和恢复 Gitea

Gitea 自带一个命令行工具,可以通过一条命令执行备份。要在 Docker 容器内运行命令行工具来执行备份,请运行以下命令。

$ docker exec -u git -it -w /app/gitea gitea bash -c '/usr/local/bin/gitea dump -c /data/gitea/conf/app.ini'

我们使用与第 3 步创建并在安装过程中配置相同的用户来运行该命令,即在上述命令中使用 -u git 参数。参数 -w /app/gitea 定义了 Docker 容器内存储备份文件的文件夹。备份文件夹必须选择 git 用户有写入权限的目录。在 Docker 容器内,只有两个这样的文件夹。一个是 /data 文件夹,另一个是 /app/gitea 文件夹。我们不能使用 /data 文件夹,因为命令行工具会备份整个数据文件夹,如果将其用作目标目录,会导致无限循环,从而占满你的服务器空间。因此,我们只能将备份存储在 /app/gitea 文件夹中。

命令中的下一项是容器名称 gitea。之后,我们指定用于在容器内执行命令的 Linux shell 类型。参数 -c 指定你需要在容器内运行的命令。要运行的命令是 /usr/local/bin/gitea dump -c /data/gitea/conf/app.ini,它会运行命令行工具,并指定其配套配置文件的路径。

命令运行后,你将看到如下输出。

2023/11/20 06:21:41 ...les/setting/cache.go:75:loadCacheFrom() [I] Cache Service Enabled
2023/11/20 06:21:41 ...les/setting/cache.go:90:loadCacheFrom() [I] Last Commit Cache Service Enabled
2023/11/20 06:21:41 ...s/setting/session.go:74:loadSessionFrom() [I] Session Service Enabled
2023/11/20 06:21:41 ...es/setting/mailer.go:237:loadMailerFrom() [I] Mail Service Enabled
2023/11/20 06:21:41 ...es/setting/mailer.go:259:loadNotifyMailFrom() [I] Notify Mail Service Enabled
2023/11/20 06:21:41 ...s/storage/storage.go:176:initAttachments() [I] Initialising Attachment storage with type: local
2023/11/20 06:21:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /data/gitea/attachments
2023/11/20 06:21:41 ...s/storage/storage.go:166:initAvatars() [I] Initialising Avatar storage with type: local
2023/11/20 06:21:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /data/gitea/avatars
2023/11/20 06:21:41 ...s/storage/storage.go:192:initRepoAvatars() [I] Initialising Repository Avatar storage with type: local
2023/11/20 06:21:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /data/gitea/repo-avatars
2023/11/20 06:21:41 ...s/storage/storage.go:186:initLFS() [I] Initialising LFS storage with type: local
2023/11/20 06:21:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /data/git/lfs
2023/11/20 06:21:41 ...s/storage/storage.go:198:initRepoArchives() [I] Initialising Repository Archive storage with type: local
2023/11/20 06:21:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /data/gitea/repo-archive
2023/11/20 06:21:41 ...s/storage/storage.go:208:initPackages() [I] Initialising Packages storage with type: local
2023/11/20 06:21:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /data/gitea/packages
2023/11/20 06:21:41 ...s/storage/storage.go:219:initActions() [I] Initialising Actions storage with type: local
2023/11/20 06:21:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /data/gitea/actions_log
2023/11/20 06:21:41 ...s/storage/storage.go:223:initActions() [I] Initialising ActionsArtifacts storage with type: local
2023/11/20 06:21:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /data/gitea/actions_artifacts
2023/11/20 06:21:41 cmd/dump.go:265:runDump() [I] Dumping local repositories... /data/git/repositories
2023/11/20 06:21:41 cmd/dump.go:306:runDump() [I] Dumping database...
2023/11/20 06:21:41 cmd/dump.go:318:runDump() [I] Adding custom configuration file from /data/gitea/conf/app.ini
2023/11/20 06:21:41 cmd/dump.go:334:runDump() [I] Custom dir /data/gitea is inside data dir /data/gitea, skipped
2023/11/20 06:21:41 cmd/dump.go:346:runDump() [I] Packing data directory.../data/gitea
2023/11/20 06:21:41 cmd/dump.go:430:runDump() [I] Finish dumping in file gitea-dump-1700441501.zip

现在,让我们了解一下恢复过程。你应该已经运行了一个全新的 Gitea Docker 安装。但不要执行安装过程。

登录到 Docker shell。

$ docker exec --user git -it gitea bash

切换到 app/gitea 目录。

$ cd app/gitea

解压备份文件。

$ unzip gitea-dump-1700441501.zip

切换到解压后的目录。

$ cd gitea-dump-1700441501

恢复 /data/gitea 文件夹。

$ mv data/* /data/gitea

恢复仓库。

$ mv repos/* /data/git/gitea-repositories/

修正文件权限。

$ chown -R git:git /data

重新生成 Git 钩子。

$ /usr/local/bin/gitea -c '/data/gitea/conf/app.ini' admin regenerate hooks

退出 Docker shell。

$ exit

第 13 步 - 升级 Gitea

升级 Gitea 是一个简单的过程。

关闭并移除现有容器。由于数据保存在主机上容器之外的位置,因此数据会被保留。

$ cd ~/gitea-docker
$ docker compose down --remove-orphans

打开 docker-compose.yml 文件,更改 Gitea 容器的版本。然后,拉取新的 Gitea 镜像。

$ docker pull

启动新的容器。

$ docker compose up -d

检查状态。

$ docker ps

结论

至此,我们完成了本教程:在 Debian 12 服务器上使用 Docker 安装 Gitea 代码托管服务。我们还安装了 Nginx 服务器作为代理,并通过 SSL 使用公开 URL 暴露 Gitea。如果你有任何问题,请在下方评论中留言。