Gitea + Nginx

本篇可知道:

  • 如何用 Docker 架設 Gitea server
  • 利用 Nginx docker 設定 reverse proxy(for https, http)

架設 Gitea server

  1. 建立一個目錄儲存 Git 資料

     `mkdir gitea_store`
    
  2. 寫在 docker-compose.yml

version: "3"
services:
  gitea:
    image: gitea/gitea:latest
    ports:
      - "10022:22"
      - "10080:3000"
    volumes:
      - ./gitea_storage:/data
    container_name: gitea
  1. up service

docker-compose up 將 Gitea container 啟用後,瀏覽器開啟 http://hostname:10080, 開始初始及設定 GITEA

主要看使用者習慣來選擇 DB,及 domain name 等,如果往後需要變更設定也可以修改此檔案 gitea_store/gitea/conf/app.ini

  • 22 port for ssh
  • 3000 port for http

可惜的是 gitea 只能 http/https 選擇其一

所以我們在前面多加一層 nginx 做 https/http, 在 proxy 至 gitea

  1. down

docker-compose down

Nginx

  1. 新增一資料夾 nginx,主要放置 nginx 設定檔 及 snippets
mkdir nginx
mkdir nginx/conf.d      // site setting
mkdir nginx/snippets
  1. 設定 nginx 幫我們handle http, 再 proxy 至 gitea

新增 gitea.confnginx/conf.d,這邊要注意到 gitea:3000,主要藉由 docker compose 啟動時,會先將 container service 綁定到同一個 bridge networking 上。倘若 service 名稱有修改,對應名稱也必須修正。

upstream gitea.server {
    server gitea:3000;
}


server {
    listen      80;
    listen [::]:80;
    server_name  http.gitea.server;

    location / {
        proxy_pass http://gitea.server;
        include snippets/proxy_params;
    }
}

由於 nginx:stable-alpine 預設沒有 proxy_params 設定 proxy header,新增至 nginx/snippets/proxy_params

proxy_set_header Host $http_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;

修改 docker-compose.yml 加入 Nginx 部份,並刪除 gitea 對外的 10800 port。

version: "3"
services:
  gitea:
    image: gitea/gitea:latest
    ports:
      - "10022:22"
    volumes:
      - /var/lib/gitea:/data
    container_name: gitea

  nginx:
  image: nginx:stable-alpine
  ports:
    - "10080:80"
  volumes:
    - ./nginx/conf.d/:/etc/nginx/conf.d/
    - ./nginx/snippets:/etc/nginx/snippets

重啟 service

docker-compose up

接著開啟瀏覽器 http://localhost:10080 ,測試 10080 port 是否能正常開啟 Gitea 網頁,代表確實有透過 Nginx reverse proxy 連接 Docker 內部的 Gitea server。

至此階段我們已經打通 nginx 與 gitea 的串街

TLS, self sign

  1. 新增一資料夾 nginx/cert,主要放置 self sign cert
mkdir nginx/cert/
  1. 產生 key

self sign CA, 此次架設 gitea server, 為內部使用 使用 self sign

我們使用 minica 產生 self sign CA

cert.pem
key.pem
  1. nginx 新增 listen port for https

接著修改 docker-compose.yml 增加 mapping cert 跟 port mapping(10443 for https)

version: "3"
services:
  gitea:
    image: gitea/gitea:latest
    ports:
      - "10022:22"
    volumes:
      - ./GITEA_STORAGE:/data
    container_name: gitea
  nginx:
    image: nginx:stable-alpine
    ports:
      - "10080:80"
      - "10443:443"
    volumes:
      - ./nginx/conf.d/:/etc/nginx/conf.d/
      - ./nginx/snippets:/etc/nginx/snippets
      - ./nginx/cert:/etc/cert

修改 nginx/conf.d/gitea.conf

我們新增

upstream gitea.server {
    server gitea:3000;
}


server {
    listen      80;
    listen [::]:80;
    server_name  http.gitea.server;

    location / {
        proxy_pass http://gitea.server;
        include snippets/proxy_params;
    }
}


server {
        listen      443 ssl http2;
        listen [::]:443 ssl http2;
        server_name https.gitea.server;
        server_name_in_redirect off;

        location / {
                proxy_pass http://gitea.server;
                include snippets/proxy_params;
        }

        # SSL Setting
        ssl_certificate /etc/cert/cert.pem;
        ssl_certificate_key /etc/cert/key.pem;
}

重啟 service

接著開啟瀏覽器 https://localhost:10443 ,測試 10443 port 是否能正常開啟 Gitea 網頁,代表確實有透過 Nginx reverse proxy 連接 Docker 內部的 Gitea server。

Let’s Encrypt Setting(optional)

安裝 Certbot

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot

申請 SSL 憑證

sudo certbot certonly --standalone -d YOUR.DOMAIN

撰寫 Ngnix SSL 憑證 header 設定 nginx/snippets/ssl-params.conf,方便未來 SSL 憑證都可以使用。

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# disable HSTS header for now
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

修改 nginx/conf.d/gitea.conf,預期 http(80)的都會移轉至 https(443)

upstream YOUR.DOMAIN {
	server gitea:3000;
}

server {
	listen      80;
	listen [::]:80;
	server_name  YOUR.DOMAIN;
	return 301 https://$host$request_uri;
}

server {
	listen      443 ssl http2;
	listen [::]:443 ssl http2;
	server_name YOUR.DOMAIN;
	server_name_in_redirect off;

	location / {
		proxy_pass http://YOUR.DOMAIN;
		include snippets//proxy_params;
	}

  # SSL Setting
	ssl_certificate /etc/letsencrypt/live/YOUR.DOMAIN/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/YOUR.DOMAIN/privkey.pem;
	include snippets/ssl-params.conf;
}

記得將本機的 /etc/letsencrypt 相關設定掛載到 Nginx container,才能讀取到本機上的憑證,並開啟 443 port 對外開放。

version: "3"
services:
  gitea:
    image: gitea/gitea:latest
    ports:
      - "10022:22"
    volumes:
      - /var/lib/gitea:/data
    container_name: gitea

  nginx:
    image: nginx:stable-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d/:/etc/nginx/conf.d/
      - ./nginx/snippets/:/etc/nginx/snippets/
      - /etc/letsencrypt:/etc/letsencrypt

Issues

  1. 單檔 size 過大, 不能 push 至 gitea
error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 Request Entity Too Large
fatal: The remote end hung up unexpectedly

If you get error 413, then the issue doesn't lie with git but with your web server. It's your web server that is blocking big upload files.

問題出在 nginx 的 body size limit

The default value for client_max_body_size directive is 1 MiB.

It can be set in http, server and location context — as in the most cases, this directive in a nested block takes precedence over the same directive in the ancestors blocks.

改變 client_max_body_size to 1G

Refer