惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Latest news
Latest news
T
Troy Hunt's Blog
V
Vulnerabilities – Threatpost
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
V
V2EX
博客园 - 司徒正美
B
Blog RSS Feed
AWS News Blog
AWS News Blog
MyScale Blog
MyScale Blog
Scott Helme
Scott Helme
Cisco Talos Blog
Cisco Talos Blog
Last Week in AI
Last Week in AI
NISL@THU
NISL@THU
博客园 - Franky
P
Proofpoint News Feed
博客园_首页
C
CERT Recently Published Vulnerability Notes
雷峰网
雷峰网
S
Schneier on Security
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
G
GRAHAM CLULEY
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
WordPress大学
WordPress大学
The Hacker News
The Hacker News
T
Threatpost
阮一峰的网络日志
阮一峰的网络日志
A
Arctic Wolf
Microsoft Azure Blog
Microsoft Azure Blog
T
The Exploit Database - CXSecurity.com
Engineering at Meta
Engineering at Meta
罗磊的独立博客
T
The Blog of Author Tim Ferriss
D
Darknet – Hacking Tools, Hacker News & Cyber Security
I
Intezer
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
SecWiki News
SecWiki News
云风的 BLOG
云风的 BLOG
美团技术团队
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
C
Cyber Attacks, Cyber Crime and Cyber Security
B
Blog
S
Security Affairs

Razeen`s Blog

Let's Encrypt 推出 Gen Y 根证书架构:揭示 Web PKI 的五大未来趋势 通过 Wi-Fi 自动备份你的 iPhone 到 Nas 管理培训感悟:从技术视角看管理之路 UPS 一拖多:保护你的 NAS 和 Linux 服务器 从影音中心到 AI 助手:我的50款 Homelab 服务清单 从SSL证书有效期将缩短到47天聊开去 谈谈特斯拉 Model Y 用车一年的感受和费用分析 弃用 Disqus 评论,使用自建 Waline 使用 Prometheus 和 Grafana 搭建你的证书监控面板 服务器迁移记:一次磁盘换板引发的Linux分区与挂载的学习 改善信息来源, 利用 RSS 高效获取资讯 (RSShub + Reeder5 + WeWe RSS) 多种 Docker 镜像拉取解决方案与实践 App分享 | AppCleaner - Mac上的卸载神器 Azure OpenAI API 申请和使用 如何开通 OneKey 虚拟信用卡,并充值消费 如何拥有一个可长期在国内使用的国外手机号码 分享开通 ChatGPT Plus 过程 如何开通 Depay 虚拟信用卡,并充值消费 如何开通欧易Web3钱包, 交易入账 如何5分钟内1块钱注册 ChatGPT 如何注册美区的 Apple ID (2023年/无需科学上网) NAS折腾记(11): NASTool3.0体验和降级 NAS折腾记(10): Docker版本的NASTool配置 NAS折腾记(9): NASTool与微信交互,微信发送消息远程下载电影【多图】 NAS折腾记(8):群晖安装 NASTool 实现影音半自动化【多图】 内网穿透(2):Tailscale 组网实现内网穿透,操作简单,无成本 内网穿透(1):总结了11中内网穿透的方式,总有一种适合你 NAS折腾记(7):从零开始设置(黑)群晖系统 NAS折腾记(6):黑群晖系统安装好后怎么洗白? NAS折腾记(5):群晖硬盘休眠设置与分析 NAS折腾记(4): 20分钟手把手带你完美安装 DS918+ 黑群晖7.1.1 NAS折腾记(3):NAS 装机 NAS折腾记(2):B360-ITX 双M.2 双2.5G网口 6 SATA主版 开箱 NAS折腾记(1):328元的4盘位Nas机箱开箱 Openwrt + Clash 全局科学上网 Newifi3 刷入 OpenWrt 固件 v21.02 利用 Markdown 画一些流程图、时序图、甘特图等 Homelab(8): 搭建自用 Gitlab 与 Docker 仓库 Nginx Tcp 转发保留客户端真实 IP (PROXY Protocol) Homelab (7):IPSec VPN(基于证书认证)客户端设置 Homelab (6): 基于自签发证书的 IPSec VPN 搭建 Homelab (5): DDNS 动态域名解析 Homelab (4): Linux 服务器基础环境准备 Homelab (3): 整体网络与基础硬件介绍 Go学习笔记(十)老项目迁移 go module 大型灾难记录 Github Actions 初体验之自动化部署 Hexo 博客 记一次 Nginx DNS 缓存导致转发问题 Homelab (2): 电信悦me网关修改桥接模式,路由器拨号 Homelab (1):5分钟上手黑群晖 NAS 终极 Bash 脚本指南 Typora 自动上传图片到七牛云 Ubuntu 20.04 LTS 有线网卡驱动安装 折腾 Ubuntu 20.04 LTS 开发环境 Go学习笔记(九) 计时器的生命周期[译] 利用 git hook 规范你的代码与 commit message 规范 git commit message 与自动化版本控制 超详细 vim 配置 (with MacVim) Golang 中的 RESTful API 最佳实践 折腾服务器(开篇) 我的第一台个人服务器 Newifi3 实现低成本家庭级科学上网 Go学习笔记(八) | 使用 os/exec 执行命令 如何用 Go 调用 Windows API Mac OS 自动根据 WI-FI 名字改变网络位置 关于 Docker 清理 MIME Types 速查表 Go学习笔记(七) | 理解OAuth 2.0并实现一个客户端 我又又又把博客迁移了 Go学习笔记(六) | 使用swaggo自动生成Restful API文档 Go学习笔记(五) | 使用代码片段(snippets)提高编码效率 书单 - 2018 IPFS 初体验,利用 IPFS 托管你的静态网站 记一次 PostgreSQL LIKE 索引优化,联合字段 LIKE 查询优化。 Disqus 添加有趣的 Reactions 的功能 TLS 1.3 详解 (RFC 8446解读) gRPC在Go中的使用(三)gRPC实现TLS加密通信与流模式 gRPC在Go中的使用(二)gRPC实现简单通讯 gRPC在Go中的使用(一)Protocol Buffers语法与相关使用 CentOS 安装 tshark 抓包工具 Go学习笔记(四) | win上使用VSCode搭建Go开发环境 日常 Postgres 数据库点滴记录 简单了解 PKCS 规范 美食篇 | DIY戚风蛋糕(烤箱做蛋糕) Go学习笔记(三) | 怎么写Go基准测试(性能测试) TLS1.3正式更新,为Nginx添加TLS1.3的支持 一次诡异的数据库删除 GitHub Pages自定义域名开启HTTPS 证书透明度是什么?它是怎么工作的? Go学习笔记(二) | 我对 recover 的一点误解 搭建证书透明度(certificate-transparency)日志服务之从入门到放弃 修复远程登陆 Centos 时,出现 UTF-8 Warning HTTPS篇之SSL握手过程详解 Go学习笔记(一) | postgres与golang点点滴滴 AWS 命令行界面(aws-cli)从安装到快速上手 数字证书分类及怎么区分各类数字证书 常用 linux 命令小结(一)文件目录操作 云服务器搭建 hexo 博客,git hooks自动更新 SSH 免密登陆, SSH Config 配置 Golang CGO Mac 交叉编译 Windows 使用 goose 让数据库迁移更加轻松 开始使用Ghost
部署一个自己的 Running Page
2025-04-10 · via Razeen`s Blog

关注 Running Page 项目很久了,今天终于把它部署在我博客上了。Running Page 是一个将运动数据可视化的开源项目,它支持汇总运动记录、生成热力图,并与MapBox结合展示路线。 本文将分享如何通过GitLab CI/CD自动化构建静态页面,并集成苹果快捷指令一键触发部署。

搭建准备

官方支持了 Vercel(推荐)和 GitHub Pages 自动部署,但个人还是比较喜欢跑在自己的服务器上,正好自己搭建了Gitlab, 于是就小折腾了一番。

准备的环境有:

  • Gitlab CE 仓库:之前在家搭建了一个私有的,用来托管日常自己写的代码和自动部署博客;

  • Gitlab Runner: 安装一个 Gitlab Runn 来跑工作流;

  • 服务器:Racknerd上买了个小机来跑我的博客;

  • 跑步数据: 官方支持了很多平台的跑步数据导入,我主力用的是 keep, 准备好账号/密码就好了。

image-20250412092600972

构建页面

导入仓库

Gitlab 有个很好用的功能,可以直接导入Github的项目,利用这个功能,就能将 Running Page 的仓库导入到私有的仓库了。

我在导入的时候出现了两次导入失败的情况,可能是网络的问题,重试后就成功导入了

image-20250412165736786

自定义修改

Running Page 是支持自定义站点标题等信息的,官方文档写的很细致的,这里不展开了。

不过修改的内容,建议切换到一个自己的分支,进行修改,方便后面的维护与更新。

最近 ChatGPT 生图的功能非常👍,我按照原来的风格我重新做了个 Logo 😄 logo

另外注意一点,如果想放在站点的子目录(如 /running/),需要设置一下环境变量PATH_PREFIX, 或直接修改vite.config.tsbase base: process.env.PATH_PREFIX || '/running/'

构建与部署

接下来就是使用 CI/CD 自动构建了。直接使用官方仓库的 Dockerfile 就可以完成静态页面的构建,那这部分步骤就很清晰了。

graph LR
    B[使用Docker构建] --> C[从Docker中复制静态页面]
    C --> D[静态页面保存构建产物]
    D --> E[rsync推送页面到服务器]

为了安全,我们先将我们的密码/服务器私钥设置到项目下的 Setting > CI/CD > Variables中,我这里加了三个

  • keep 登陆手机号KEEP_LOGIN_PHONE
  • keep 登陆密码 KEEP_LOGIN_PASSWORD
  • 博客服务器的私钥 BLOG_SSH_PRIVATE_KEY (可以生成一个专用的私钥用来部署, 注意提前在服务器配置好公钥)

在添加变量的时候可以将 Masked钩上,Protect variable 不要随便勾选,除非你讲你自己的分支设置成保护分支,不然构建的时候获取不到值。

到这里就写好这个简易的.gitlab-ci.yml了。

image: docker:latest

stages:
  - build
  - deploy

build:
  stage: build
  tags:
    - linux01
  script:
    # 构建 Docker 镜像
    - docker build --build-arg app=Keep --build-arg keep_phone_number=$KEEP_LOGIN_PHONE --build-arg keep_password=$KEEP_LOGIN_PASSWORD --build-arg YOUR_NAME="Razeen" -t running-page:$CI_COMMIT_SHA .
    
    # 创建临时容器来获取构建产物
    - docker create --name temp_container running-page:$CI_COMMIT_SHA
    - docker cp temp_container:/usr/share/nginx/html ./dist
    - docker rm temp_container
    
    # 保存构建产物
    - mkdir -p artifacts
    - cp -r dist/* artifacts/
  artifacts:
    paths:
      - artifacts/
    expire_in: 1 week
  allow_failure: false

deploy:
  stage: deploy
  tags:
    - homelab01
  script:
    - mkdir -p ~/.ssh
    - echo "$BLOG_SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - ls -la ~/.ssh
    - echo -e "Host *\n\tStrictHostKeyChecking no\n" > ~/.ssh/config
    - chmod 600 ~/.ssh/config
    
    # 使用 rsync 同步文件
    # 'ssh -p 2222' 如果SSH是非常规端口
    - rsync -avz -e 'ssh -p 2222' --delete artifacts/ root@118.93.29.15:/www/running/
  dependencies:
    - build
  allow_failure: false

同时,服务器配置好的nginx路径。

    location /running {
        root                        /www/;
        index                       index.html index.htm;
    }

快捷方式触发

上面的 CI/CD 配置写好了,但没加触发条件。为了方便记录,我这里使用了苹果的快捷方式来触发。

在项目下 Settings > C1/CD > Pipeline trigger tokens 中,可以添加一个工作流触发的 Token, 然后可以通过 POST 对应的URL触发了,如

# https://git.isw.app/ => gitlab 地址 
# 25 => 项目ID
# REF_NAME => 分支 或 tag (我这里触发的分支)
# glptt-xxxxx => 工作流触发 token 
https://git.razeen.app/api/v4/projects/25/ref/REF_NAME/trigger/pipeline?token=glptt-xxxxx

接着,我们使用 获取URL内容 的组件来触发工作流,注意请求方式使用POST。再加个弹窗展示返回内容。给快捷方式选个LOGO,保存,设置快捷方式到桌面。这样一键触发就制作好了。

image-20250412165609885

再在 CI/CD配置中加上对应的触发条件。这里加上了页面触发和触发器触发。

# 简化触发器配置
workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "trigger"
      when: always
    - if: $CI_PIPELINE_SOURCE == "web"
      when: always

自动同步代码

之前的步骤已经完成自动构建和部署了,但我还希望我本地的代码能和 GitHub 的保持持续的同步,需要时和自己的分支合并就可更新自己的Page了。

Gitlab 自带 Mirroring repositories 功能,能自动将本地代码与指定远程保持一致,但 CE 版本只能同步推送,这里就需要用CI实现一下。

sync-upstream:
  stage: sync
  tags:
    - m1max
  script:
    # 配置 Git
    - git config --global user.name "GitLab CI"
    - git config --global user.email "gitlab-ci@isw.app"
    
    # 克隆仓库
    # REPO_TOKEN 在项目下的 Setting > Access Tokens 中添加一个Token, 并设置到CI/CD的环境变量中去
    # 需要 read_repository, write_repository 的权限
    # CI 开头的环境变量是CI自带的,不用设置
    - git clone https://oauth2:${REPO_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git repo
    - cd repo
    
    # 确保在 master 分支
    - git checkout master
    
    # 添加上游仓库
    - git remote add upstream https://github.com/yihong0618/running_page.git
    
    # 获取上游更新
    - git fetch upstream
    
    # 合并上游更新到本地 master 分支
    - git merge upstream/master -m "Merge upstream changes"
    
    # 推送到 GitLab 仓库
    - git push https://oauth2:${REPO_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git master

此外,为了持续更新,在后台再加个订单调度。为了不和build/deploy 冲突,添加两个条件来区分构建和同步的场景。

  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule" && $SYNC_ONLY == "true"
      when: always
    - if: $CI_PIPELINE_SOURCE == "web" && $CI_JOB_NAME == "sync-upstream"
      when: always

image-20250412165248283

总结

至此,基本全部实现了。以后每次跑完步就可以触发一下更新上去了。为了身体健康,为了热力图效果,运动起来!!

详细配置

老习惯,最后贴一下全部的配置。.gitlab-ci.yml。防止多个构建和并发同时执行,加了一个resource_group

image: docker:latest

stages:
  - sync
  - build
  - deploy

variables:
  GIT_STRATEGY: clone

# 简化触发器配置
workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "trigger"
      when: always
    - if: $CI_PIPELINE_SOURCE == "web"
      when: always
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: always

.build_template: &build_template
  resource_group: running-page-pipeline
  interruptible: false

deploy:
  <<: *build_template
  stage: deploy
  tags:
    - homelab01
  script:
    - mkdir -p ~/.ssh
    - echo "$BLOG_SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - ls -la ~/.ssh
    - echo -e "Host *\n\tStrictHostKeyChecking no\n" > ~/.ssh/config
    - chmod 600 ~/.ssh/config
    - rsync -avz -e 'ssh -p 2222' --delete artifacts/ root@118.93.29.15:/www/running/
  dependencies:
    - build
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule" && $SYNC_ONLY == "true"
      when: never
    - if: $CI_PIPELINE_SOURCE == "web" && $CI_JOB_NAME == "sync-upstream"
      when: never
    - when: always
  allow_failure: false

build:
  <<: *build_template
  stage: build
  tags:
    - linux01
  script:
    - docker build --build-arg app=Keep --build-arg keep_phone_number=$KEEP_LOGIN_PHONE --build-arg keep_password=$KEEP_LOGIN_PASSWORD --build-arg YOUR_NAME="Razeen" -t running-page:$CI_COMMIT_SHA .
    - docker create --name temp_container running-page:$CI_COMMIT_SHA
    - docker cp temp_container:/usr/share/nginx/html ./dist
    - docker rm temp_container
    - mkdir -p artifacts
    - cp -r dist/* artifacts/
  artifacts:
    paths:
      - artifacts/
    expire_in: 1 week
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - activities/
      - assets/
      - GPX_OUT/
      - TCX_OUT/
      - FIT_OUT/
      - Workouts/
      - run_page/data.db
      - src/static/activities.json
      - imported.json
    policy: pull-push
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule" && $SYNC_ONLY == "true"
      when: never
    - if: $CI_PIPELINE_SOURCE == "web" && $CI_JOB_NAME == "sync-upstream"
      when: never
    - when: always
  allow_failure: false
  
sync-upstream:
  stage: sync
  resource_group: repo-sync
  tags:
    - m1max
  script:
    - git config --global user.name "GitLab CI"
    - git config --global user.email "gitlab-ci@isw.app"
    - git clone https://oauth2:${REPO_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git repo
    - cd repo
    - git checkout master
    - git remote add upstream https://github.com/yihong0618/running_page.git
    - git fetch upstream
    - git merge upstream/master -m "Merge upstream changes"
    - git push https://oauth2:${REPO_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git master
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule" && $SYNC_ONLY == "true"
      when: always
    - if: $CI_PIPELINE_SOURCE == "web" && $CI_JOB_NAME == "sync-upstream"
      when: always
  allow_failure: true

配置中用了三个runner的 tag, homelab01linux01 跑在家里服务器上,m1max 跑在本地电脑上,需要按照好对应的 git 等命令。