commit 6968343da20f621831668d68c9f7575dc6a3f1b0 Author: ka1i Date: Sat Jul 12 17:19:14 2025 +0800 init: alpine base git server diff --git a/README.md b/README.md new file mode 100644 index 0000000..6ad3feb --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Alpine 自托管 Git 服务器-Gitea 版 + +使用 Docker 容器技术,快速搭建 Git 服务器,该教程主要使用 Gitea 搭建 Git 服务器。并使用 Nginx 进行代理,支持 HTTPS 加密; diff --git a/nginx/conf.d/default.conf b/nginx/conf.d/default.conf new file mode 100644 index 0000000..1c8a892 --- /dev/null +++ b/nginx/conf.d/default.conf @@ -0,0 +1,6 @@ +server { + listen 80 default; + server_name _; + + return 404; +} diff --git a/nginx/conf.d/server/gitea.conf b/nginx/conf.d/server/gitea.conf new file mode 100644 index 0000000..b2d6281 --- /dev/null +++ b/nginx/conf.d/server/gitea.conf @@ -0,0 +1,25 @@ +server { + listen 443 ssl; + server_name git.guzal.cc; + + http2 on; + + ssl_certificate /etc/nginx/certs/ca.cer; + ssl_certificate_key /etc/nginx/certs/ca.key; + + client_max_body_size 4096m; + + proxy_connect_timeout 3600; + proxy_send_timeout 3600; + proxy_read_timeout 3600; + + location ~ .*\.(gif|jpg|png|css|js)(.*) { + proxy_pass http://gitea:3000; + expires 3d; + } + + location / { + proxy_pass http://gitea:3000$request_uri; + proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP + } +} \ No newline at end of file diff --git a/nginx/conf.d/server/registry.conf b/nginx/conf.d/server/registry.conf new file mode 100644 index 0000000..06e91bc --- /dev/null +++ b/nginx/conf.d/server/registry.conf @@ -0,0 +1,51 @@ +## Set a variable to help us decide if we need to add the +## 'Docker-Distribution-Api-Version' header. +## The registry always sets this header. +## In the case of nginx performing auth, the header is unset +## since nginx is auth-ing before proxying. +map $upstream_http_docker_distribution_api_version $docker_distribution_api_version { + '' 'registry/2.0'; +} + +server { + listen 443 ssl; + server_name registry.guzal.cc; + + http2 on; + + ssl_certificate /etc/nginx/certs/ca.cer; + ssl_certificate_key /etc/nginx/certs/ca.key; + + ssl_protocols TLSv1.3 TLSv1.2; + ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + + # disable any limits to avoid HTTP 413 for large image uploads + client_max_body_size 0; + + # required to avoid HTTP 411: see Issue #1486 (https://github.com/moby/moby/issues/1486) + chunked_transfer_encoding on; + + location /v2/ { + # Do not allow connections from docker 1.5 and earlier + # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents + if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) { + return 404; + } + # To add basic authentication to v2 use auth_basic setting. + # auth_basic "Registry realm"; + # auth_basic_user_file /etc/nginx/registry.htpasswd; + + ## If $docker_distribution_api_version is empty, the header is not added. + ## See the map directive above where this variable is defined. + add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always; + + proxy_pass http://registry:5000; + proxy_set_header Host $http_host; # required for docker client's sake + proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 900; + } +} diff --git a/nginx/conf.d/vhost/guzal.cc-443.conf b/nginx/conf.d/vhost/guzal.cc-443.conf new file mode 100644 index 0000000..5a9ee41 --- /dev/null +++ b/nginx/conf.d/vhost/guzal.cc-443.conf @@ -0,0 +1,15 @@ +server { + listen 443 ssl; + server_name guzal.cc; + + http2 on; + + ssl_certificate /etc/nginx/certs/ca.cer; + ssl_certificate_key /etc/nginx/certs/ca.key; + ssl_session_timeout 5m; + ssl_protocols TLSv1.3 TLSv1.2; + ssl_prefer_server_ciphers on; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + + return 301 https://www.$http_host$request_uri; +} diff --git a/nginx/conf.d/vhost/guzal.cc-80.conf b/nginx/conf.d/vhost/guzal.cc-80.conf new file mode 100644 index 0000000..be476a2 --- /dev/null +++ b/nginx/conf.d/vhost/guzal.cc-80.conf @@ -0,0 +1,6 @@ +server { + listen 80; + server_name guzal.cc *.guzal.cc; + + return 301 https://$http_host$request_uri; +} diff --git a/nginx/conf.d/vhost/www.guzal.cc-443.conf b/nginx/conf.d/vhost/www.guzal.cc-443.conf new file mode 100644 index 0000000..388d91a --- /dev/null +++ b/nginx/conf.d/vhost/www.guzal.cc-443.conf @@ -0,0 +1,30 @@ +server { + listen 443 ssl; + server_name www.guzal.cc; + + http2 on; + + ssl_certificate /etc/nginx/certs/ca.cer; + ssl_certificate_key /etc/nginx/certs/ca.key; + ssl_session_timeout 5m; + ssl_protocols TLSv1.3 TLSv1.2; + ssl_prefer_server_ciphers on; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + + if ($request_method !~ ^(GET|HEAD|POST)$ ) { + return 444; + } + + if ($http_user_agent ~* LWP::Simple|BBBike) { + return 403; + } + + location / { + root /usr/share/nginx/web_root/www.ixayda.com/home; + } + + error_page 400 403 404 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} \ No newline at end of file diff --git a/nginx/html/50x.html b/nginx/html/50x.html new file mode 100644 index 0000000..ef0b355 --- /dev/null +++ b/nginx/html/50x.html @@ -0,0 +1,28 @@ + + + + + Error + + + + +

An error occurred.

+

Sorry, the page you are looking for is currently unavailable.
+ Please try again later.

+

If you are the system administrator of this resource then you should check + the error log for details.

+

Faithfully yours, nginx.

+ + + \ No newline at end of file diff --git a/nginx/www_root/index.html b/nginx/www_root/index.html new file mode 100644 index 0000000..3b8ca0b --- /dev/null +++ b/nginx/www_root/index.html @@ -0,0 +1,33 @@ + + + + + Welcome to nginx! + + + + +

Welcome to nginx!

+

If you see this page, the nginx web server is successfully installed and + working. Further configuration is required.

+ +

For online documentation and support please refer to + nginx.org.
+ Commercial support is available at + nginx.com. +

+ +

Thank you for using nginx.

+ + + \ No newline at end of file diff --git a/swarm/docker-compose.yml b/swarm/docker-compose.yml new file mode 100644 index 0000000..87fd6fe --- /dev/null +++ b/swarm/docker-compose.yml @@ -0,0 +1,87 @@ +version: "3.9" + +services: + nginx: + image: nginx:alpine + ports: + - target: 80 + published: 80 + mode: host + - target: 443 + published: 443 + mode: host + configs: + - source: nginx + target: /etc/nginx/nginx.conf + secrets: + - source: cakey + target: /etc/nginx/certs/ca.key + mode: 0440 + - source: cacer + target: /etc/nginx/certs/ca.cer + mode: 0440 + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + - /data/nginx/conf.d:/etc/nginx/conf.d + - /data/nginx/html:/usr/share/nginx/html:ro + - /data/nginx/www_root:/usr/share/nginx/www_root:ro + networks: + - inline + depends_on: + - gitea + - registry + + gitea: + image: gitea/gitea:1.23.7 + ports: + - target: 22 + published: 22 + mode: host + environment: + - USER_UID=1000 + - USER_GID=1000 + - APP_NAME=Where the world builds software + - RUN_MODE=prod + - RUN_USER=git + - DB_TYPE=sqlite3 + - DISABLE_SSH=false + - LFS_START_SERVER=true + - REQUIRE_SIGNIN_VIEW=false + - DISABLE_REGISTRATION=true + - DEFAULT_ACTIONS_URL=self + - DOMAIN=git.guzal.cc + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + - /data/gitea:/data + networks: + - inline + + registry: + image: registry:latest + environment: + - REGISTRY_HTTP_SECRET=HnpapIhqHs6V4fv/lT4iIg== + volumes: + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + - /data/registry:/var/lib/registry + networks: + - inline + +networks: + host: + external: true + name: "host" + inline: + external: false + +configs: + nginx: + file: ./nginx.conf + +secrets: + cakey: + file: /root/.acme.sh/guzal.cc_ecc/guzal.cc.key + cacer: + file: /root/.acme.sh/guzal.cc_ecc/fullchain.cer diff --git a/swarm/nginx.conf b/swarm/nginx.conf new file mode 100644 index 0000000..4e40fc1 --- /dev/null +++ b/swarm/nginx.conf @@ -0,0 +1,70 @@ +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format json_analytics '{' + '"msec": "$msec", ' # request unixtime in seconds with a milliseconds resolution + '"connection": "$connection", ' # connection serial number + '"connection_requests": "$connection_requests", ' # number of requests made in connection + '"pid": "$pid", ' # process pid + '"request_id": "$request_id", ' # the unique request id + '"request_length": "$request_length", ' # request length (including headers and body) + '"remote_addr": "$remote_addr", ' # client IP + '"remote_user": "$remote_user", ' # client HTTP username + '"remote_port": "$remote_port", ' # client port + '"time_local": "$time_local", ' + '"time_iso8601": "$time_iso8601", ' # local time in the ISO 8601 standard format + '"request": "$request", ' # full path no arguments if the request + '"request_uri": "$request_uri", ' # full path and arguments if the request + '"args": "$args", ' # args + '"status": "$status", ' # response status code + '"body_bytes_sent": "$body_bytes_sent", ' # the number of body bytes exclude headers sent to a client + '"bytes_sent": "$bytes_sent", ' # the number of bytes sent to a client + '"http_referer": "$http_referer", ' # HTTP referer + '"http_user_agent": "$http_user_agent", ' # user agent + '"http_x_forwarded_for": "$http_x_forwarded_for", ' # http_x_forwarded_for + '"http_host": "$http_host", ' # the request Host: header + '"server_name": "$server_name", ' # the name of the vhost serving the request + '"request_time": "$request_time", ' # request processing time in seconds with msec resolution + '"upstream": "$upstream_addr", ' # upstream backend server for proxied requests + '"upstream_connect_time": "$upstream_connect_time", ' # upstream handshake time incl. TLS + '"upstream_header_time": "$upstream_header_time", ' # time spent receiving upstream headers + '"upstream_response_time": "$upstream_response_time", ' # time spend receiving upstream body + '"upstream_response_length": "$upstream_response_length", ' # upstream response length + '"upstream_cache_status": "$upstream_cache_status", ' # cache HIT/MISS where applicable + '"ssl_protocol": "$ssl_protocol", ' # TLS protocol + '"ssl_cipher": "$ssl_cipher", ' # TLS cipher + '"scheme": "$scheme", ' # http or https + '"request_method": "$request_method", ' # request method + '"server_protocol": "$server_protocol", ' # request protocol, like HTTP/1.1 or HTTP/2.0 + '"pipe": "$pipe", ' # "p" if request was pipelined, "." otherwise + '"gzip_ratio": "$gzip_ratio", ' + '"http_cf_ray": "$http_cf_ray"' + '}'; + + access_log /var/log/nginx/access.log json_analytics; + + sendfile on; + tcp_nopush on; + + keepalive_timeout 65; + + gzip off; + + server_tokens off; + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/conf.d/vhost/*.conf; + include /etc/nginx/conf.d/server/*.conf; +} +