From 997d078b6498870d40275940297557ba69690489 Mon Sep 17 00:00:00 2001 From: ChenKaiLiuG Date: Sat, 28 Feb 2026 04:38:23 +0800 Subject: [PATCH] Add FRP --- config/non-used-dashboard-conf.yml | 33 ---- karylab-entrance/bitnami-harbor.yml | 153 +++++++++++++++ karylab-entrance/config/frpc.toml | 42 ++++ .../config/gitea-runner-config.yml | 7 +- karylab-entrance/exchange.md | 122 ++++++++++++ karylab-entrance/gitea.yml | 51 +++-- karylab-entrance/others/docker-harbor.yml | 103 ++++++++++ .../docker-registry-master.yml} | 4 +- karylab-entrance/others/rundeck-registry.yml | 180 ++++++++++++++++++ {sh => karylab-entrance/sh}/ollama-monitor.sh | 0 {sh => karylab-entrance/sh}/vllm-monitor.sh | 0 karylab-entrance/vpstunnel+npm.yml | 43 +++++ karylab-vps/config/frps.toml | 23 +++ karylab-vps/vps-tunnel.yml | 17 ++ 14 files changed, 722 insertions(+), 56 deletions(-) delete mode 100644 config/non-used-dashboard-conf.yml create mode 100644 karylab-entrance/bitnami-harbor.yml create mode 100644 karylab-entrance/config/frpc.toml create mode 100644 karylab-entrance/exchange.md create mode 100644 karylab-entrance/others/docker-harbor.yml rename karylab-entrance/{docker-registry.yml => others/docker-registry-master.yml} (96%) create mode 100644 karylab-entrance/others/rundeck-registry.yml rename {sh => karylab-entrance/sh}/ollama-monitor.sh (100%) rename {sh => karylab-entrance/sh}/vllm-monitor.sh (100%) create mode 100644 karylab-entrance/vpstunnel+npm.yml create mode 100644 karylab-vps/config/frps.toml create mode 100644 karylab-vps/vps-tunnel.yml diff --git a/config/non-used-dashboard-conf.yml b/config/non-used-dashboard-conf.yml deleted file mode 100644 index 37c5ab0..0000000 --- a/config/non-used-dashboard-conf.yml +++ /dev/null @@ -1,33 +0,0 @@ ---- -# 頁面設定 -pageInfo: - title: My Dashboard - description: Welcome to your new dashboard! - navLinks: - - title: GitHub - path: https://github.com/Lissy93/dashy - - title: Documentation - path: https://dashy.to/docs - -# 應用程式區塊 -sections: - - name: Getting Started - icon: fas fa-rocket - items: - - title: Dashy Documentation - description: Everything you need to know - icon: fas fa-book - url: https://dashy.to/docs - - title: Source Code - description: View on GitHub - icon: fab fa-github - url: https://github.com/Lissy93/dashy - -# 主題與樣式設定 -appConfig: - theme: colorful - layout: auto - iconSize: medium - language: en - editingPassword: "your_secure_password" - diff --git a/karylab-entrance/bitnami-harbor.yml b/karylab-entrance/bitnami-harbor.yml new file mode 100644 index 0000000..cc49d5d --- /dev/null +++ b/karylab-entrance/bitnami-harbor.yml @@ -0,0 +1,153 @@ +version: '3' + +services: +# 1. Harbor Core Service + harbor-core: + image: docker.io/bitnami/harbor-core:latest + container_name: harbor-core + restart: always + environment: + - BITNAMI_DEBUG=false + - HARBOR_ADMIN_PASSWORD=${HARBOR_ADMIN_PASSWORD} # <--- 請修改管理員密碼 + # Harbor 核心服務的資料庫連線設定 + - HARBOR_DATABASE_HOST=harbor-db + - HARBOR_DATABASE_PORT_NUMBER=5432 + - HARBOR_DATABASE_USER=bn_harbor + - HARBOR_DATABASE_PASSWORD=${HARBOR_GENERAL_PASSWORD} + - HARBOR_DATABASE_NAME=bitnami_harbor + # Redis 連線設定 + - HARBOR_REDIS_HOST=harbor-redis + - HARBOR_REDIS_PORT_NUMBER=6379 + - HARBOR_REDIS_PASSWORD=${HARBOR_GENERAL_PASSWORD} + # 重要:如果有域名,請改成 https://你的域名 (NPM有處理,不加埠號);只是內網用,改成 http://你的IP:port + - HARBOR_EXTERNAL_URL=http://192.168.10.100:7700 + - HARBOR_REGISTRY_URL=http://harbor-registry:5000 + # Notary 服務設定(如果不使用 Notary,可以忽略這些設定) + - HARBOR_NOTARY_SERVER_HOSTNAME=harbor-notary-server + - HARBOR_NOTARY_SIGNER_HOSTNAME=harbor-notary-signer + depends_on: + - harbor-db + - harbor-redis + - harbor-registry + volumes: + - /mnt/data/External/harbor/core:/data + networks: + - harbor-network + + # 2. Harbor Portal Service + harbor-portal: + image: docker.io/bitnami/harbor-portal:latest + container_name: harbor-portal + restart: always + ports: + - "7700:8080" # HTTP 入口 (NPM 反代請指到這裡) + - "7750:8443" # HTTPS 入口 + environment: + - BITNAMI_DEBUG=false + - HARBOR_PORTAL_API_URL=http://harbor-core:8080/api + - NGINX_HTTP_PORT_NUMBER=8080 + - NGINX_HTTPS_PORT_NUMBER=8443 + networks: + - harbor-network + depends_on: + - harbor-core + + # 3. Harbor Job Service + harbor-jobservice: + image: docker.io/bitnami/harbor-jobservice:latest + container_name: harbor-jobservice + restart: always + environment: + - BITNAMI_DEBUG=false + - HARBOR_JOBSERVICE_DATABASE_HOST=harbor-db + - HARBOR_JOBSERVICE_DATABASE_USER=bn_harbor + - HARBOR_JOBSERVICE_DATABASE_PASSWORD=${HARBOR_GENERAL_PASSWORD} + - HARBOR_JOBSERVICE_DATABASE_NAME=bitnami_harbor + - HARBOR_JOBSERVICE_REDIS_HOST=harbor-redis + - HARBOR_JOBSERVICE_REDIS_PORT_NUMBER=6379 + - HARBOR_JOBSERVICE_REDIS_PASSWORD=${HARBOR_GENERAL_PASSWORD} + - HARBOR_JOBSERVICE_CORE_URL=http://harbor-core:8080 + depends_on: + - harbor-core + - harbor-redis + volumes: + - harbor-jobservice:/var/log/jobs + networks: + - harbor-network + + # 4. Harbor Registry Service (映像檔儲存) + harbor-registry: + image: docker.io/bitnami/harbor-registry:latest + container_name: harbor-registry + restart: always + environment: + - BITNAMI_DEBUG=false + - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/storage + - REGISTRY_HTTP_ADDR=:5000 + - REGISTRY_REDIS_HOST=harbor-redis + - REGISTRY_REDIS_PORT=6379 + - REGISTRY_REDIS_PASSWORD=${HARBOR_GENERAL_PASSWORD} + - REGISTRY_AUTH_TOKEN_REALM=http://harbor-core:8080/service/token + # 為了方便,這裡關閉了部分複雜的安全驗證,依賴 Harbor Core 控制 + volumes: + - /mnt/data/External/harbor/registry:/storage + networks: + - harbor-network + depends_on: + - harbor-redis + + # 5. Harbor Registry Controller + harbor-registryctl: + image: docker.io/bitnami/harbor-registryctl:latest + container_name: harbor-registryctl + restart: always + environment: + - BITNAMI_DEBUG=false + - REGISTRYCTL_REGISTRY_HOST=harbor-registry + - REGISTRYCTL_REGISTRY_PORT=5000 + - REGISTRYCTL_REDIS_HOST=harbor-redis + - REGISTRYCTL_REDIS_PORT=6379 + - REGISTRYCTL_REDIS_PASSWORD=${HARBOR_GENERAL_PASSWORD} + - REGISTRYCTL_CHECK_INTERVAL=30m + depends_on: + - harbor-registry + - harbor-redis + volumes: + - /mnt/data/External/harbor/registry:/storage + networks: + - harbor-network + + # 6. Harbor Database (PostgreSQL資料庫) + harbor-db: + image: docker.io/bitnami/postgresql:latest + container_name: harbor-db + restart: always + environment: + - POSTGRESQL_USERNAME=bn_harbor + - POSTGRESQL_PASSWORD=${HARBOR_GENERAL_PASSWORD} + - POSTGRESQL_DATABASE=bitnami_harbor + volumes: + - harbor-db:/bitnami/postgresql + networks: + - harbor-network + +# 7. Redis Cache (快取) + harbor-redis: + image: docker.io/bitnami/redis:latest + container_name: harbor-redis + restart: always + environment: + - REDIS_PASSWORD=${HARBOR_GENERAL_PASSWORD} + volumes: + - harbor-redis:/bitnami/redis/data + networks: + - harbor-network + +volumes: + harbor-db: + harbor-redis: + harbor-jobservice: + +networks: + harbor-network: + driver: bridge \ No newline at end of file diff --git a/karylab-entrance/config/frpc.toml b/karylab-entrance/config/frpc.toml new file mode 100644 index 0000000..fb8206f --- /dev/null +++ b/karylab-entrance/config/frpc.toml @@ -0,0 +1,42 @@ +# ===================================================== +# FRP Client (frpc) 設定 +# 部署位置:UCG 內網機器(與 npm container 同網段) +# 對接目標:PVE VM 上的 frps(具備固定 IP) +# ===================================================== + +serverAddr = "45.64.97.4" # PVE VM 固定 IP +serverPort = 7000 # 與 frps 的 bindPort 對應 + +# TLS 加密控制通道(與 frps 的 transport.tls.force = true 對應) +[transport] +tls.enable = true + +# 連線驗證(需與 frps 的 auth token 相同) +[auth] +method = "token" +token = "your_strong_secret_token" # TODO: 改為強密碼,frps 端要一致 + +# ------------------------------------------------------- +# HTTP (Port 80) → NPM +# ------------------------------------------------------- +[[proxies]] +name = "npm-http" +type = "tcp" +localIP = "npm" # 同 frp_network 內直接用 container name +localPort = 80 +remotePort = 80 + +# ------------------------------------------------------- +# HTTPS (Port 443) → NPM +# ------------------------------------------------------- +[[proxies]] +name = "npm-https" +type = "tcp" +localIP = "npm" +localPort = 443 +remotePort = 443 + +# ------------------------------------------------------- +# NPM 管理後台 (Port 81) 僅供內網存取,不對外 tunnel +# 請直接在內網透過 http://內網機器IP:81 登入 +# ------------------------------------------------------- \ No newline at end of file diff --git a/karylab-entrance/config/gitea-runner-config.yml b/karylab-entrance/config/gitea-runner-config.yml index aaa6608..3a83024 100644 --- a/karylab-entrance/config/gitea-runner-config.yml +++ b/karylab-entrance/config/gitea-runner-config.yml @@ -36,9 +36,10 @@ container: docker_host: "tcp://docker:2375" privileged: true # DinD 需要 privileged 模式 - # 讓 job 容器能解析 "docker" hostname,指向 DinD daemon 所在的宿主機 - # host-gateway 會自動解析為容器的宿主機 IP(對 job 容器來說就是 DinD) - options: "--add-host=docker:host-gateway" + # 让 job 容器能解析 hostname + # docker: DinD daemon (使用 gitea-net 中的固定 IP 172.24.0.11) + # server: Gitea 服务器 (使用固定 IP 172.24.0.10) + options: "--add-host=docker:172.24.0.11 --add-host=server:172.24.0.10" workdir_parent: /workspace # 允許掛載的路徑,設為無限制以免綁手綁腳 valid_volumes: diff --git a/karylab-entrance/exchange.md b/karylab-entrance/exchange.md new file mode 100644 index 0000000..8664857 --- /dev/null +++ b/karylab-entrance/exchange.md @@ -0,0 +1,122 @@ +# 工程師交接 + +## 1. cloudflared -> vps tunnel(已完成) + +### 實作結果:採用方案一(FRP) + +#### 檔案清單 + +| 檔案 | 位置 | 說明 | +|---|---|---| +| `vpstunnel+npm.yml` | `karylab-entrance/` | 內網 compose stack(frpc + npm + filebrowser) | +| `frpc.toml` | `karylab-entrance/config/` | frpc 設定,掛載至 frpc container | +| `vps-tunnel.yml` | `karylab-vps/` | VPS compose stack(frps) | +| `frps.toml` | `karylab-vps/config/` | frps 設定,掛載至 frps container | + +#### 架構說明 + +``` +[外部訪客] + │ TCP 80/443 + ▼ +[PVE VM(固定 IP)] + └─ frps container + │ TLS 加密隧道(Port 7000) + ▼ +[UCG 內網] + └─ frpc container ─→ npm container(Port 80/443) + │ + ▼ + NAS / 其他內網服務 +``` + +#### 安全設計 + +- **控制通道 TLS**:frps 強制 `transport.tls.force = true`,frpc 開啟 `tls.enable = true`,控制通道全程加密 +- **Token 驗證**:frpc 與 frps 使用 HMAC-SHA256 簽名的 token 驗證身份 +- **NPM 管理後台(Port 81)不對外 tunnel**:只能從內網直接存取 `http://內網機器IP:81` +- **建議**:在 VPS 防火牆(UFW / iptables)限制 Port 7000 只允許內網出口 IP 連入 + +#### 部署注意事項 + +1. **VPS 防火牆**必須開放 inbound TCP Port **80、443、7000**,否則 frpc 會出現 `i/o timeout` +2. `frpc.toml` 的 `serverAddr` 填入 VPS 固定 IP 或可解析的網域皆可 +3. `frpc.toml` 與 `frps.toml` 的 `token` 必須設定為**同一組強密碼** +4. 設定檔路徑: + - VPS:`/opt/frp/frps.toml` + - 內網:`/opt/cloudflare/frp/frpc.toml` + +--- + + + +### 目標: + +原來是cloudflare tunnel對接npm 再讓npm去找相關的設備 +直接把tunnel換成其他容器 然後對接vps(pve上的vm) + +### 方案說明: + +部署在 PVE 上的那台「固定 IP VM」當作私有的 Cloudflare 節點(也就是您的自建 VPS),然後用特定的「隧道容器」來取代 cloudflared+npm.yml 中的 cloudflared,打通兩個隔離的網段。新的版本更新到 vpstunnel+npm.yml。 + +要達成這個目的,有兩種主流的開源工具/容器可以完美取代 Cloudflare Tunnel,以下為您分析兩種作法: + +**方案一:使用 FRP (Fast Reverse Proxy) —— 最直接的 1:1 替換** +FRP 的運作邏輯與 Cloudflare Tunnel 幾乎一模一樣,只是伺服器從 Cloudflare 變成了您的 PVE VM。 + +架構配置: +``` +前端 (您的 PVE VM - 具備固定 IP):安裝並運行 frps (FRP Server) 容器。它負責監聽來自網際網路的請求(如 Port 80, 443, 25565)。 + +後端 (您的 UCG 網段內):部署一個 frpc (FRP Client) 容器。這個容器會主動向 frps 發起連線,建立一條加密隧道。 + +路由分發:frpc 收到流量後,將 HTTP/HTTPS 流量轉交給同在 UCG 網段內的 NPM (Nginx Proxy Manager),再由 NPM 去找 UCG 底下的 NAS 或其他設備。 +``` +優點:架構與 Cloudflare Tunnel 概念完全一致,完全不用開 Port,因為是 frpc 由內向外主動連線的。 + +缺點:設定檔是基於 ini/yaml,需要稍微學習一下語法。 + +參考資源:FRP 官方 GitHub 專案庫與文件 + +**方案二:使用 WireGuard 或 Tailscale —— 網路層的虛擬區網 (推薦)** +與其只代理特定 Port,不如在 PVE VM 和 UCG 網段之間建立一個專屬的「虛擬私有區域網路 (VPN)」。 + +架構配置: +``` +前端 (您的 PVE VM):安裝 NPM 以及 Tailscale (或 WireGuard) 容器。將 Zyxel 的 80/443 Port Forwarding 到這個 VM。 + +後端 (您的 UCG 網段內):只需要在負責提供服務的機器(或 NPM)上安裝 Tailscale,讓它們加入同一個虛擬網路。 + +路由分發:當外部訪客連線到您的固定 IP (PVE VM) 時,VM 上的 NPM 會解析網域,並透過 Tailscale 給的虛擬 IP(例如 100.x.x.x)將流量安全地轉發到 UCG 底下的設備。 +``` +優點: + +極致的隔離:Tailscale / WireGuard 使用點對點加密,流量穿梭在 Zyxel 網段與 UCG 網段之間時是完全加密的。 + +管理方便:所有伺服器都在同一個虛擬網段內,互相溝通就像在同一個 Switch 下一樣簡單。 + +參考資源:Tailscale 官方網站、WireGuard 官方網站 + +**流量動線解析 (以方案二為例)** +假設訪客要訪問您在 UCG 網段下的 Nextcloud: + +外部訪客輸入 cloud.example.com。 + +DNS (Cloudflare 灰雲) 將網域解析到您的 中華電信固定 IP。 + +流量抵達 vps 側路由器,透過 Port Forwarding 送入 PVE VM (自建 VPS) 的 Port 443。 + +PVE VM 上的 NPM 接收到請求,查看設定規則,發現要把流量送給 Nextcloud。 + +流量進入 隧道容器 (WireGuard/Tailscale),被加密打包。 + +加密封包穿越實體網路,抵達 UCG 網段下的目標機器。 + +目標機器解密封包,交由 Nextcloud 容器 處理。 + +這樣做的好處? +擺脫限制:完全沒有 Cloudflare 的 100MB 檔案大小限制,也沒有任何協議的限制(您可以傳輸 TCP, UDP, 甚至跑自訂協議)。 + +完美隔離:您的 UCG 路由器不需要開放任何對外 Port (Inbound 規則維持全擋),所有的外部威脅第一時間都是由 Zyxel 底下的 PVE VM 承受。就算 VM 被攻破,攻擊者也無法直接看見 UCG 底下的設備(除非他們破解了加密隧道)。 + +掌控權:資料不再經過第三方的邊緣節點解密(Cloudflare 橘雲會解密 HTTPS 流量),真正的端到端都在您自己的掌控之下。 \ No newline at end of file diff --git a/karylab-entrance/gitea.yml b/karylab-entrance/gitea.yml index 85f54da..e182217 100644 --- a/karylab-entrance/gitea.yml +++ b/karylab-entrance/gitea.yml @@ -11,7 +11,8 @@ services: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_DB=gitea networks: - - gitea-net + gitea-net: + ipv4_address: 172.24.0.3 volumes: - postgres_db:/var/lib/postgresql/data @@ -31,11 +32,14 @@ services: - GITEA__database__PASSWD=${POSTGRES_PASSWORD} # 啟用 Actions (關鍵設定) - GITEA__actions__ENABLED=true + # 開啟內建 Registry 功能 + - GITEA__packages__ENABLED=true # 允許發送 webhook 到內部 IP - GITEA__webhook__ALLOWED_HOST_LIST=* networks: - - gitea-net - - webproxy + gitea-net: + ipv4_address: 172.24.0.10 + webproxy: {} depends_on: - db ports: @@ -54,8 +58,19 @@ services: privileged: true # DinD 必須開啟此權限才能運作 environment: - DOCKER_TLS_CERTDIR= # 設為空字串以關閉 TLS,簡化內部連線 + # 允許連回 Gitea 的 Registry (因為是 HTTP) + # 設置 DNS 讓內部容器能解析 gitea-net 的 service name + command: + - "dockerd" + - "--host=unix:///var/run/docker.sock" + - "--host=tcp://0.0.0.0:2375" + - "--insecure-registry=172.24.0.10:3000" + - "--insecure-registry=server:3000" + - "--dns=172.24.0.1" + - "--dns=8.8.8.8" networks: - - gitea-net + gitea-net: + ipv4_address: 172.24.0.11 volumes: - gitea_docker_certs:/certs/client - gitea_docker_data:/var/lib/docker # 持久化,避免重啟後又要重新 pull image @@ -65,22 +80,21 @@ services: image: gitea/act_runner:latest container_name: gitea_runner restart: always + networks: + gitea-net: + ipv4_address: 172.24.0.5 + volumes: + - /mnt/data/External/gitea/runner_data:/data + environment: + - CONFIG_FILE=/data/config.yaml + # 注意:Runner 需要註冊 Token,我們在啟動後手動輸入一次即可 + - GITEA_INSTANCE_URL=http://server:3000 + # 關鍵修改:告訴 Runner 不要找 Socket,而是用 TCP 連線到 docker 容器 + - DOCKER_HOST=tcp://docker:2375 + - GITEA_RUNNER_REGISTRATION_TOKEN=${REGISTRATION_TOKEN} depends_on: - server - docker - networks: - - gitea-net - volumes: - - /mnt/data/External/gitea/runner_data:/data - - environment: - - CONFIG_FILE=/data/config.yaml - - # 注意:Runner 需要註冊 Token,我們在啟動後手動輸入一次即可 - - GITEA_INSTANCE_URL=http://server:3000 - - # 關鍵修改:告訴 Runner 不要找 Socket,而是用 TCP 連線到 docker 容器 - - DOCKER_HOST=tcp://docker:2375 volumes: postgres_db: @@ -90,6 +104,9 @@ volumes: networks: gitea-net: driver: bridge + ipam: + config: + - subnet: 172.24.0.0/16 # npm bridge webproxy: external: true \ No newline at end of file diff --git a/karylab-entrance/others/docker-harbor.yml b/karylab-entrance/others/docker-harbor.yml new file mode 100644 index 0000000..41e51a0 --- /dev/null +++ b/karylab-entrance/others/docker-harbor.yml @@ -0,0 +1,103 @@ +version: '3.8' + +services: + # 1. Harbor 映像服務器 - 提供容器映像管理功能 + harbor: + image: goharbor/harbor-core:v2.9.3 + container_name: harbor-core + restart: always + ports: + - "5700:8080" + environment: + CORE_URL: http://harbor:8080 + DATABASE_TYPE: postgresql + POSTGRES_HOST: harbor-db + POSTGRES_PORT: 5432 + POSTGRES_USERNAME: ${POSTGRES_USERNAME} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: registry + REGISTRY_URL: http://harbor-registry:5000 + REGISTRY_CONTROLLER_URL: http://harbor-registry:5000 + LOG_LEVEL: info + PERMITTED_REGISTRY_TYPES: docker-registry + QUOTA_PER_PROJECT_ENABLED: "true" + READ_ONLY: "false" + volumes: + - harbor_core_data:/data + networks: + - harbor-network + - webproxy + depends_on: + - harbor-db + - harbor-registry + + # 2. Harbor 資料庫 - 儲存 Harbor 的元數據 + harbor-db: + image: postgres:14 + container_name: harbor-db + restart: always + environment: + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: registry + volumes: + - harbor_db_data:/var/lib/postgresql/data + networks: + - harbor-network + + # 3. Harbor Registry - 儲存容器映像的註冊表 + harbor-registry: + image: registry:2 + container_name: harbor-registry + restart: always + ports: + - "5600:5000" + environment: + REGISTRY_HTTP_ADDR: 0.0.0.0:5000 + REGISTRY_HTTP_RELATIVEURLS: 'true' + REGISTRY_STORAGE_DELETE_ENABLED: 'true' + volumes: + - /mnt/data/External/harbor/registry:/var/lib/registry + networks: + - harbor-network + + # 4. BuildKit 編譯服務 - 用於高效構建容器映像 + buildkitd: + image: moby/buildkit:latest + container_name: buildkitd + restart: always + privileged: true + ports: + - "5500:1234" + environment: + BUILDKIT_HOST: tcp://0.0.0.0:1234 + volumes: + - buildkit_data:/var/lib/buildkit + networks: + - harbor-network + + # 5. BuildKit Web UI - 提供 BuildKit 的 Web 界面 + buildkit-ui: + image: tonistiiii/buildkit-ui:latest + container_name: buildkit-ui + restart: always + ports: + - "5400:8080" + environment: + BUILDKIT_HOST: tcp://buildkitd:1234 + networks: + - harbor-network + - webproxy + depends_on: + - buildkitd + +volumes: + harbor_core_data: + harbor_db_data: + buildkit_data: + buildkit_cache: + +networks: + harbor-network: + driver: bridge + webproxy: + external: true diff --git a/karylab-entrance/docker-registry.yml b/karylab-entrance/others/docker-registry-master.yml similarity index 96% rename from karylab-entrance/docker-registry.yml rename to karylab-entrance/others/docker-registry-master.yml index 63c7ffa..f096606 100644 --- a/karylab-entrance/docker-registry.yml +++ b/karylab-entrance/others/docker-registry-master.yml @@ -112,10 +112,8 @@ services: DRONE_SERVER_HOST: dronedocker.karylab.com DRONE_SERVER_PROTO: https DRONE_RPC_SECRET: ${DRONE_RANDOM_SECRET} - # Webhook 密鑰設定(必須和 Gitea Webhook 設定一致) - DRONE_WEBHOOK_SECRET: a1212416fb0515155c2c88f00a7879ad # Gitea 配置 - 連接到本機 Gitea 服務 - DRONE_GITEA_SERVER: http://git.karylab.com + DRONE_GITEA_SERVER: https://git.karylab.com DRONE_GITEA_CLIENT_ID: ${GITEA_DRONE_CLIENT_ID:-drone_client} DRONE_GITEA_CLIENT_SECRET: ${GITEA_DRONE_SECRET:-drone_secret} volumes: diff --git a/karylab-entrance/others/rundeck-registry.yml b/karylab-entrance/others/rundeck-registry.yml new file mode 100644 index 0000000..b833608 --- /dev/null +++ b/karylab-entrance/others/rundeck-registry.yml @@ -0,0 +1,180 @@ +version: '3.8' + +services: + # 1. Docker 編譯伺服器 - Docker-in-Docker,隔離編譯環境 + build-server: + image: docker:dind + container_name: docker-build-server + restart: always + privileged: true # DinD 必要權限 + command: + - dockerd + - --host=unix:///var/run/docker.sock + - --host=tcp://0.0.0.0:2375 + - --storage-driver=overlay2 + # 允許來自內部的 HTTP 推送 (關鍵) + - --insecure-registry=registry:5000 + environment: + DOCKER_TLS_CERTDIR: "" # 關閉 TLS 方便內部通訊 + volumes: + - build-cache:/var/lib/docker + networks: + - rundeck-network + healthcheck: + test: ["CMD", "test", "-f", "/shared-bin/docker"] + interval: 5s + timeout: 2s + retries: 3 + start_period: 15s + + # 2. Docker Registry - 儲存編譯好的 Image + registry: + image: registry:2 + container_name: local-registry + restart: always + ports: + - "5700:5000" # 外部 Portainer 拉取用 192.168.1.XX:5700 + environment: + REGISTRY_HTTP_ADDR: 0.0.0.0:5000 + REGISTRY_STORAGE_DELETE_ENABLED: 'true' + volumes: + - /mnt/data/External/rundeck/registry_data:/var/lib/registry + networks: + - rundeck-network + depends_on: + build-server: + condition: service_healthy + + # 3. Registry Web UI - 可視化管理鏡像 + registry-ui: + image: joxit/docker-registry-ui:latest + container_name: docker-registry-ui + restart: always + ports: + - "5600:80" + environment: + REGISTRY_TITLE: "Docker Registry" + SINGLE_REGISTRY: 'true' + REGISTRY_SECURED: 'false' + DELETE_IMAGES: 'true' + SHOW_CATALOG_NB_TAGS: 'true' + NGINX_PROXY_PASS_URL: 'http://registry:5000' + networks: + - rundeck-network + depends_on: + - registry + + # 4. Rundeck - 編譯任務編排(通過網路連接到 DinD,不掛載宿主 socket) + rundeck: + image: rundeck/rundeck:5.18.0 + container_name: rundeck-builder + restart: always + ports: + - "5500:4440" + volumes: + - rundeck-data:/home/rundeck/server/data + - docker-bin:/usr/local/bin/docker-share + environment: + # 請修改為你的外部 IP (讓瀏覽器能正確轉址) + - RUNDECK_GRAILS_URL=http://192.168.10.100:5500 + - RUNDECK_SERVER_FORWARDED=true + # DinD 連接參數 告訴 Rundeck 裡的 docker 指令去連線 build-server + - DOCKER_HOST=tcp://build-server:2375 + - DOCKER_TLS_VERIFY= + # 將掛載進來的 docker 資料夾加入 PATH,這樣就能直接打 docker 指令了 + - PATH=/usr/local/bin/docker-share:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + # 資料庫設定 + - RUNDECK_DATABASE_URL=jdbc:mysql://rundeck-db/rundeck?autoReconnect=true&useSSL=false + - RUNDECK_DATABASE_USERNAME=rundeck + - RUNDECK_DATABASE_PASSWORD=${ROOT_PASSWORD} + - RUNDECK_DATABASE_DRIVER=org.mariadb.jdbc.Driver + networks: + - rundeck-network + - webproxy + depends_on: + - build-server + - rundeck-db + + # 5. Rundeck 資料庫 - 儲存 Rundeck 的任務和設定 + rundeck-db: + image: mariadb:10 + container_name: rundeck-db + restart: always + environment: + MYSQL_ROOT_PASSWORD: ${ROOT_PASSWORD} + MYSQL_DATABASE: rundeck + MYSQL_USER: rundeck + MYSQL_PASSWORD: ${ROOT_PASSWORD} + volumes: + - rundeck-db-data:/var/lib/mysql + networks: + - rundeck-network + + # 6. 編譯伺服器垃圾回收 - 通過 TCP 清理編譯緩存和未使用的層 + build-server-gc: + image: docker:cli + container_name: docker-build-gc + restart: always + environment: + DOCKER_HOST: tcp://build-server:2375 + networks: + - rundeck-network + entrypoint: | + sh -c 'while true; do + echo "[$(date)] 清理構建緩存..." >> /proc/1/fd/1 + docker builder prune -af || true + echo "[$(date)] 清理懸空鏡像..." >> /proc/1/fd/1 + docker image prune -af || true + echo "[$(date)] 清理完成,24小時後再執行..." >> /proc/1/fd/1 + sleep 86400 + done' + depends_on: + build-server: + condition: service_healthy + + # 7. Registry 垃圾回收 - 定期清理未被引用的 blobs + registry-gc: + image: registry:2 + container_name: docker-registry-gc + restart: always + environment: + REGISTRY_HTTP_ADDR: 0.0.0.0:5000 + REGISTRY_STORAGE_DELETE_ENABLED: 'true' + volumes: + - /mnt/data/External/rundeck/registry_data:/var/lib/registry + - registry_gc_logs:/tmp + networks: + - rundeck-network + entrypoint: | + sh -c 'while true; do + echo "[$(date)] 執行 Registry 垃圾回收..." >> /tmp/gc.log + registry garbage-collect /etc/docker/registry/config.yml >> /tmp/gc.log 2>&1 + echo "[$(date)] Registry 垃圾回收完成,24小時後再執行..." >> /tmp/gc.log + sleep 86400 + done' + depends_on: + - registry + + # 7. Docker CLI Loader (Portainer 專用技巧) + # 因為不能用 Dockerfile,開一個容器把 docker 執行檔複製出來 + docker-cli-loader: + image: docker:cli + container_name: tool-docker-loader + # 執行完複製就自動退出,不需要 restart + restart: "no" + command: sh -c "cp /usr/local/bin/docker /shared-bin/docker && chmod +x /shared-bin/docker" + volumes: + - docker-bin:/shared-bin + +volumes: + build-cache: + docker-bin: + rundeck-data: + rundeck-db-data: + registry_gc_logs: + +networks: + rundeck-network: + driver: bridge + webproxy: + external: true \ No newline at end of file diff --git a/sh/ollama-monitor.sh b/karylab-entrance/sh/ollama-monitor.sh similarity index 100% rename from sh/ollama-monitor.sh rename to karylab-entrance/sh/ollama-monitor.sh diff --git a/sh/vllm-monitor.sh b/karylab-entrance/sh/vllm-monitor.sh similarity index 100% rename from sh/vllm-monitor.sh rename to karylab-entrance/sh/vllm-monitor.sh diff --git a/karylab-entrance/vpstunnel+npm.yml b/karylab-entrance/vpstunnel+npm.yml new file mode 100644 index 0000000..1cf1b79 --- /dev/null +++ b/karylab-entrance/vpstunnel+npm.yml @@ -0,0 +1,43 @@ +version: "3.9" + +services: + frpc: + image: snowdreamtech/frpc:latest + container_name: frpc + restart: unless-stopped + networks: + - frp_network + volumes: + - /opt/cloudflare/frp/frpc.toml:/etc/frp/frpc.toml:ro + + npm: + image: jc21/nginx-proxy-manager:latest + container_name: npm + restart: unless-stopped + ports: + - "80:80" + - "81:81" + - "443:443" + networks: + - frp_network + - webproxy + volumes: + - /opt/cloudflare/npm/data:/data + - /opt/cloudflare/npm/letsencrypt:/etc/letsencrypt + + filebrowser: + image: filebrowser/filebrowser:latest + container_name: filebrowser + restart: unless-stopped + ports: + - "18080:80" + networks: + - frp_network + volumes: + - /opt/cloudflare/files:/srv + +networks: + frp_network: + driver: bridge + webproxy: + external: true \ No newline at end of file diff --git a/karylab-vps/config/frps.toml b/karylab-vps/config/frps.toml new file mode 100644 index 0000000..7463195 --- /dev/null +++ b/karylab-vps/config/frps.toml @@ -0,0 +1,23 @@ +# ===================================================== +# FRP Server (frps) 設定 +# 部署位置:PVE VM(具備固定 IP) +# ===================================================== + +bindPort = 7000 # 與 frpc 的 serverPort 對應 + +# TLS 加密控制通道(強制要求 frpc 必須使用 TLS 連線) +[transport.tls] +force = true # 拒絕所有非 TLS 的 frpc 連線 + +# 連線驗證(需與 frpc 的 token 相同) +[auth] +method = "token" +token = "your_strong_secret_token" # TODO: 改為強密碼,需與 frpc.toml 一致 + +# Dashboard(可選) +# 若要啟用 frps web 管理介面,取消下方註解 +# [webServer] +# addr = "0.0.0.0" +# port = 7500 +# user = "admin" +# password = "your_dashboard_password" diff --git a/karylab-vps/vps-tunnel.yml b/karylab-vps/vps-tunnel.yml new file mode 100644 index 0000000..4df66b0 --- /dev/null +++ b/karylab-vps/vps-tunnel.yml @@ -0,0 +1,17 @@ +version: "3.9" + +services: + frps: + image: snowdreamtech/frps:latest + container_name: frps + restart: unless-stopped + ports: + - "80:80" # HTTP → 轉給內網 NPM + - "443:443" # HTTPS → 轉給內網 NPM + - "7000:7000" # frpc 控制通道(建議用防火牆限制來源 IP) + volumes: + - /opt/frp/frps.toml:/etc/frp/frps.toml:ro + +networks: + default: + driver: bridge