strapi的安装

老实说,strapi的安装真的不是一件容易的事情。 第一步想简单化,于是就用Docker compose来安装,结果并不容易,官方文档不可用,改了半天终于跑起来,然后,嘿嘿,dockerhub上的strapi:latest 早就过期很久了。 于是又琢磨它那个Docker build版本的,问题是,都在宿主机环境build出来了,然后再放到Docker镜像中跑,岂不是脱裤子放屁,多此一举么。 于是回到原点,需要在CLI环境下安装,然后要部署到正式生产环境。 步骤如下: 一、装mysql 8.0 apt install wget lsb-release gnupg -y wget https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb dpkg -i mysql-apt-config_0.8.29-1_all.deb apt update apt install mysql-server 二、装NVM,nodejs和yarn curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.4/install.sh | bash source ~/.nvm/nvm.sh nvm ls-remote nvm install v20.19.5 node -v npm install -g yarn npm list -g 三、初始化strapi mkdir /data cd /data yarn create strapi # 我们要跳过它那个免费30天的grow方案 # 然后数据库是 mysql , 填入mysql的一系列参数 # 使用ts 四、配置strapi # 加入自己的域名 vi /data/strapi/config/server.ts export default ({ env }) => ({ host: env('HOST', '0.0.0.0'), port: env.int('PORT', 1337), url: 'https://blog.rendoumi.com', app: { keys: env.array('APP_KEYS'), }, }); # 建立新文件 vi /data/strapi/src/admin/vite.config.ts import { defineConfig, mergeConfig } from 'vite'; export default (config) => { return mergeConfig(config, defineConfig({ resolve: { alias: { '@': '/src', }, }, server: { allowedHosts: true } })); }; 五、安装nginx,运行程序 apt install nginx # 注释掉无用配置 vi /etc/nginx/nginx.conf # include /etc/nginx/sites-enabled/*; # 新增配置 vi /etc/nginx/conf.d/strapi.conf upstream strapi { server 127.0.0.1:1337; } server { # Listen HTTP listen 80; server_name blog.rendoumi.com; # Redirect HTTP to HTTPS return 301 https://$host$request_uri; } server { # Listen HTTPS listen 443 ssl; server_name webcms.yoov.com; # SSL config ssl_certificate /usr/local/bin/certs/certificates/blog.rendoumi.com.crt; ssl_certificate_key /usr/local/bin/certs/certificates/blog.rendoumi.com.key; # Proxy Config location / { proxy_pass http://strapi; proxy_http_version 1.1; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $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 Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_pass_request_headers on; } } cd /data/strapi yarn develop 然后登录就可以了,诡异的是第四步,如果不gen vite.config.ts,那nginx代理访问local host:1337上会出问题。 ...

2025年10月16日 · 2 分钟 · 233 字 · 八戒

NVM管理的Nodejs如何做成systemd的serivce服务

有很多next、nuxt、yarn的nodejs程序,都是什么npm start或者yarn develop的启动模式,如何搞成systemd的服务呢,这里面麻烦的就是systemd的服务需要使用全路径。 那方法如下: 一、安装nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.4/install.sh | bash 二、安装nodejs和yarn source ~/.nvm/nvm.sh nvm ls-remote nvm install v20.19.5 node -v npm install -g yarn npm list -g 三、弄strapi.service服务 echo $NVM_DIR # 确定 nvm 的安装目录 /root/.nvm which node # 确定 Node.js 的路径 /root/.nvm/versions/node/v20.19.5/bin/node which yarn # 确定 Yarn 的路径 /root/.nvm/versions/node/v20.19.5/bin/yarn cat < EOF > /etc/systemd/system/strapi.service [Unit] Description=Strapi App After=network.target [Service] # 使用用户账户运行服务,替换为实际的用户名 User=root Group=root # 指定工作目录,替换为项目的实际路径 WorkingDirectory=/data/strapi # 加载 nvm 并运行 yarn 或 node Environment="NVM_DIR=/root/.nvm" ExecStart=/bin/bash -c ". $NVM_DIR/nvm.sh && yarn develop" Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now strapi

2025年10月15日 · 1 分钟 · 92 字 · 八戒

OPNsense如何做LoadBalance接入后端的Kubernetes nginx ingress --- Nginx篇

新托管了一个机房服务器,基本全用开源软件来构建: 那Firewall就用的OPNsense,后端自建Kubernetes,那OPNsense需要当作一个LoadBalance来使用 结构图如下,证书是放在了Nginx ingres上: 那方法有很多,各有利弊,说下第三个,Nginx的做法 relayd和caddy都说完了,那还有Nginx,Nginx的话,如果证书挂在OPNsense,那就可以用WAF的功能 如果证书放在后端Kubernetes的Nginx ingress上,那就无法用WAF了,算是data stream 那提前说一句,Nginx的配置是有Bug的,如果无法清除干净,需要ssh登录opnsense,然后 把 /conf/下xml配置文件中的 nginx 部分删除掉,然后重启服务器,才可以 os-nginx的配置方法如下: 第一步:首先去Upstream的Upstream Server子标签,建立两组服务器 第二步:再去Upstream的Upstream子标签,建立两组服务 建立的时候advanced mode要打开,PROXY Protocol要选中,Server选中各自的4个服务器,其它保持缺省即可。 第三步:去Data Streams的子标签Stream Servers,建两组服务 编辑一下,监听端口只选指定IP的80和443,PROXY Protocol不要选中,然后Route就选Upstream,Upstream Servers选中对应的,其它缺省即可。 那对应的,后端Kubernetes的Nginx ingress也要做相应配置 Nginx ingress的configmap,需要加上Proxy Protocol的部分 我们用的是官网的 ingress-nginx,配置文件是 ingress-nginx 的namespace中 configmap ingress-nginx-controller,内容如下,对应data那两行: apiVersion: v1 data: use-proxy-protocol: "true" kind: ConfigMap metadata: annotations: meta.helm.sh/release-name: ingress-nginx meta.helm.sh/release-namespace: ingress-nginx nginx.ingress.kubernetes.io/configuration-snippet: "true" nginx.ingress.kubernetes.io/location-snippet: "true" nginx.ingress.kubernetes.io/server-snippet: "true" creationTimestamp: "2025-08-27T07:38:49Z" labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.1 helm.sh/chart: ingress-nginx-4.13.1 name: ingress-nginx-controller namespace: ingress-nginx resourceVersion: "22298827" uid: d6eeef3c-7e44-4667-854a-c7693006b221 编辑后,nginx ingress会自动reload ...

2025年10月14日 · 1 分钟 · 91 字 · 八戒

OPNsense如何做LoadBalance接入后端的Kubernetes nginx ingress --- caddy篇

新托管了一个机房服务器,基本全用开源软件来构建: 那Firewall就用的OPNsense,后端自建Kubernetes,那OPNsense需要当作一个LoadBalance来使用 结构图如下,证书是放在了Nginx ingres上: 那方法有很多,各有利弊,说下第二个,Caddy的做法 Caddy真的是王道,什么泛域名,一个端口跑3个协议,都可以 用到Caddy,就要解决后端Nginx ingress无法获得客户真实IP的问题 Caddy配置如下: General Settings: Enable Layer4 Proxy 要勾选上 Auto HTTPS 要选中Off 其它保持默认,然后去到Layer4 Proxy进行配置,同样要配2个,一个HTTP,一个TLS 编辑HTTP的代理,注意 Domain 的地方需要把用到的所有域名列进去 编译TLS的代理 注意上面,Proxy Protocol都要选中v2,这样客户端真实IP才可以透传给后端的Nginx ingress 那同样后端的Nginx ingress的configmap,也需要加上Proxy Protocol的部分 我们用的是官网的 ingress-nginx,配置文件是 ingress-nginx 的namespace中 configmap ingress-nginx-controller,内容如下 apiVersion: v1 data: use-proxy-protocol: "true" kind: ConfigMap metadata: annotations: meta.helm.sh/release-name: ingress-nginx meta.helm.sh/release-namespace: ingress-nginx nginx.ingress.kubernetes.io/configuration-snippet: "true" nginx.ingress.kubernetes.io/location-snippet: "true" nginx.ingress.kubernetes.io/server-snippet: "true" creationTimestamp: "2025-08-27T07:38:49Z" labels: app.kubernetes.io/component: controller app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx app.kubernetes.io/version: 1.13.1 helm.sh/chart: ingress-nginx-4.13.1 name: ingress-nginx-controller namespace: ingress-nginx resourceVersion: "22298827" uid: d6eeef3c-7e44-4667-854a-c7693006b221 编辑后,nginx ingress会自动reload ...

2025年10月14日 · 1 分钟 · 88 字 · 八戒

OPNsense如何做LoadBalance接入后端的Kubernetes nginx ingress --- relayd篇

新托管了一个机房服务器,基本全用开源软件来构建: 那Firewall就用的OPNsense,后端自建Kubernetes,那OPNsense需要当作一个LoadBalance来使用 结构图如下,证书是放在了Nginx ingres上: 那方法有很多,各有利弊,先说第一个,relayd的做法 relayd是最早的OPNsense的插件,用来做负载均衡,安装这个plugin插件 配置如下: General Settings: 由于虚机的cpu是4个,所以进程设置成4 Backend Hosts: 后端节点有4个,只写IP即可 Table Checks: 端口检查,因为是直通,所以就设置成TCP检查即可 Tables: Hosts选中4个节点 Virtual Server: 80和443各有一个 每个呢,设置好前面的监听地址和端口,后端的Table 服务器和Table check的协议,就ok了 最后去 General Settings 选中 Enable Relayd,然后save,就可以了 这么多贴图,是因为如果从CLI配置,其实就一个很简单的relayd.conf文本文件 但是从GUI,就一大堆,而且生成的东西简直不知所云 这样做relayd就相当于一个直通的LoadBalance,把流量送入后端的Nginx ingress所开的NodePort。 这样就可用了。 这样有个弊端,Nginx的ingress拿不到客户端的真实IP,X-forwarded-for无法传过来真的客户端IP,网上查文档是可以的,但是从GUI配了半天,也不知道怎么配,服了也是。

2025年10月14日 · 1 分钟 · 36 字 · 八戒

seaweedfs的s3进阶试用方法

SeaweedFS 已经用docker compose的方式部署在生产环境内中了,对外只开放了一个S3的端口127.0.0.1:8333,然后前面套上Caddy的https代理,这样很安全了。 那进阶的要求又来了: 一、S3的pre signed的URL 由于程序之前是在AWS跑的,所以用了S3的最佳实践,pre sign url来进行上传和下载,那seaweedfs也是完全支持的,基本是无缝修改 给出验证程序: import boto3 from botocore.client import Config # Configure the S3 client to point to your SeaweedFS S3 gateway s3_client = boto3.client( 's3', endpoint_url='https://s3.rendoumi.com', # Replace with your SeaweedFS S3 gateway address aws_access_key_id='aaaaaaaa', aws_secret_access_key='bbbbbbb', config=Config(signature_version='s3v4') ) bucket_name = 'myfiles' object_key = 'your-object-key' expiration_seconds = 3600 # URL valid for 1 hour # Generate a pre-signed URL for uploading (PUT) try: upload_url = s3_client.generate_presigned_url( 'put_object', Params={'Bucket': bucket_name, 'Key': object_key, 'ContentType': 'application/octet-stream'}, ExpiresIn=expiration_seconds ) print(f"Pre-signed URL for upload: {upload_url}") except Exception as e: print(f"Error generating upload URL: {e}") # Generate a pre-signed URL for downloading (GET) try: download_url = s3_client.generate_presigned_url( 'get_object', Params={'Bucket': bucket_name, 'Key': object_key}, ExpiresIn=expiration_seconds ) print(f"Pre-signed URL for download: {download_url}") except Exception as e: print(f"Error generating download URL: {e}") 能看到临时生成的upload的URL和download的URL,是完美支持的 ...

2025年09月17日 · 2 分钟 · 222 字 · 八戒

Postgres pgbackrest备份以及指定时间点恢复

最近狠折腾了一通postgres的备份,跟MySQL的阿里RDB恢复一样,如何不停止数据库服务,恢复某个表的数据到某个时间点,然后放到另一个表中呢? 其实用之前的wal恢复一样的,就是要把当天实例的全备份和wal都复制到另外一台上,然后恢复,再把数据给dump下来,再建一个新表,把数据导回去。 Postgres的wal和PITR时间点恢复 用pgbackrest感觉会好一些,其实都差不多,步骤如下: 一、安装并配置pgbackrest apt install pgbackrest # 建立备份的大本营 mkdir -p /var/lib/pgbackrest chmod 750 /var/lib/pgbackrest chown postgres:postgres /var/lib/pgbackrest # 编辑 /etc/pgbackrest.conf [global] repo1-path=/var/lib/pgbackrest repo1-retention-full=26 repo1-retention-archive=180 log-level-file=info log-level-console=info [global:archive-push] compress-level=3 [main] pg1-path=/var/lib/postgresql/13/main pg1-port=5432 讲解一下参数 global里面是全局配置 repo1-path=/var/lib/pgbackrest # pgBackRest 存储库路径 repo1-retention-full=26 # 保留最近的 26 个全量备份,大概6个月,180天 repo1-retention-archive=180 # 保留最近 180 天的 WAL 日志 log-level-file=info # 文件日志级别 log-level-console=info # 控制台日志级别 global:archive-push 设置的是wal归档的保存方式是压缩保存 main部分设置的是要备份的postgres源的路径和端口,【main】是stanza的名字 上面的备份其实有三种备份,full和incr和wal备份,那如果full和增量都没了,只要wal还在,那么依然能恢复到180天之内的某个时间点。wal很占空间,full也很占空间,一定要算准了。 那其实pgbackrest是用postgres身份去执行命令的,所以不用认证身份。 二、配置postgres vi /etc/postgresql/13/main/postgresql.conf # wal归档方法: #archive_mode = on #archive_command = 'cp %p /data/backup/%f' # pgbackrest归档方法: archive_mode = on archive_command = 'pgbackrest --stanza=main archive-push %p' wal_level = replica #备份级别是副本 max_wal_senders = 3 #最多wal日志发到3个客户端去 # 需要重启postgres systemctl restart postgresql 三、测试pgbackrest的备份功能 # 建立一个stanza sudo -u postgres pgbackrest --stanza=main --log-level-console=info stanza-create # 检查 sudo -u postgres pgbackrest --stanza=main --log-level-console=info check # 查看信息 sudo -u postgres pgbackrest info ...

2025年09月15日 · 3 分钟 · 443 字 · 八戒

seaweed S3服务单机版正式环境的部署

公司要做系统迁移,从AWS迁移到自建机房,那迁移的项目就一大堆,S3也在其中之列。 找来找去,第一首选的替代软件是minio,可是万恶的minio团队在这个时间点,已经后台移除了 admin 相关的操作权限 要想用呢,只能用个老版本的:quay.io/minio/minio:RELEASE.2025-04-22T22-12-26Z 那只能再找了,于是找到了SeaweedFS,这个软件其实是个彻头彻尾的单文件,但是分布式全集群架构 简单的说,就是一个软件,包含了10几种功能。 而我们呢,其实就要它的一个功能s3,而且要用于生产。网上一大堆的教程都是各种分布式的部署,如果机器足够,大家可以参考网上教程。 我们单台机器,硬盘底层是raid10,然后上层就只提供s3,而且要配置简单,没有什么安全问题,这台机器是直接暴露公网IP的。 那最简单的方法就是Docker compose,而且只放开s3的指定端口: services: seaweedfs-s3: image: chrislusf/seaweedfs container_name: seaweedfs-s3 volumes: - ./data:/data - ./config/config.json:/seaweedfs/config.json ports: - "127.0.0.1:8333:8333" # - "9333:9333" entrypoint: /bin/sh -c command: | "echo 'Starting SeaweedFS S3 server' && \ weed server -dir=/data -volume.max=120 -s3 -s3.config /seaweedfs/config.json" restart: unless-stopped 仔细解释上面的参数: ports 只开了 127.0.0.1:8333 的S3端口,其它都不开,如果需要查看服务状态,可以临时打开9333端口查看,看完再关 -volume.max=120,这个务必要注意,seaweed是分卷的,一个卷最多30G,缺省是8个卷。那缺省就是只有240G的容量,我们的硬盘是4T的,剩余3.7TB,那算下来,30*120=3600G=3.6T。这样就对准了,这个参数一定要根据生产的实际情况进行调整. 另外还把config.json的配置文件给mount入docker卷中了,配置文件里放的就是S3的IAM访问权限控制 详细看一下config.json { "identities": [ { "name": "admin", "credentials": [ { "accessKey": "aaa", "secretKey": "bbb" } ], "actions": [ "Admin", "Read", "List", "Tagging", "Write" ] }, { "name": "goods", "credentials": [ { "accessKey": "ccc", "secretKey": "ddd" } ], "actions": [ "Read:goods", "Write:goods", "List:goods", "Tagging:goods", "Admin:goods" ] } ] } 解释一下,上面定义了一个admin用户,可以对所有s3进行读写和管理。 ...

2025年09月15日 · 1 分钟 · 141 字 · 八戒

生产环境Elasticsearch 8单节点Docker-compose的安装方法

要在生产环境建一套Elasticsearch 8.0,单节点搭配Kibana,确实是困难重重,新版本需要TLS验证了 现在这个时间节点,2025年9月2日,Elasticsearch最新版本是9.0,后撤2个版本是8.18.6 那就用这个版本了,然后根据官方的文档会把人搞糊涂的。 正确的方法如下: 一、建立自签的证书 其实可以用ACME的证书,但是没有人会三个月就去重启一下ES的容器,更新证书吧! 那只能选择自建CA,自签一个证书了! 因为有2个pod,es和kibana,所以要签两张证书,签证书随便用ES的一个版本就可以: wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.4.1-linux-x86_64.tar.gz tar -zxf elasticsearch-8.4.1-linux-x86_64.tar.gz cd elasticsearch-8.4.1/ ./bin/elasticsearch-certutil ca --pem # 得到CA证书,放在当前目录ca目录下 unzip elastic-stack-ca.zip # 生成签发配置文件 cat << EOF >instances.yml instances: - name: es01 dns: - es01 - localhost ip: - 127.0.0.1 - name: kibana dns: - kibana - localhost ip: - 127.0.0.1 EOF # 签发2个pod的证书 ./bin/elasticsearch-certutil cert --ca-cert ca/ca.crt --ca-key ca/ca.key --pem --in instances.yml # 得到2张证书和key unzip certificate-bundle.zip # 生成两个目录,es01和kibana # 准备好证书目录 mkdir -p /data/elasticsearch/certs mv ca es01 kibana /data/elasticsearch/certs # 准备好持久化卷 mkdir -p /data/elasticsearch/kibanadata mkdir -p /data/elasticsearch/esdata01 二、配置docker-compose.yaml 8.18.6版本的docker-compose.yaml文件,位于:/data/elasticsearch/docker-compose.yaml ...

2025年09月02日 · 4 分钟 · 679 字 · 八戒

AWS托管的Valkey数据转移到社区Redis.io去

这还真是个大活,耗费了整整一天的时间。 究其原因根本就是无论AWS托管的Valkey还是社区的Redis.io,都是被魔改过的阉割版,真是无语他妈给无语开门,无语到家了! 说一下详细的过程: 接到这个任务,首先想到的是同步软件redis-Gunyu https://github.com/mgtv-tech/redis-GunYu 结果是失败,原因很奇葩,因为aws valkey是必须带tls连接的,Gunyu不支持,放弃。 然后找到了redis-shake https://tair-opensource.github.io/RedisShake 结果还是失败,理由是不支持PSync,用了scan_reader也失败 然后就又想到了万能的ChatGPT和Google的Gemini,分别给了2个python程序,也是失败 原因是不支持Migrate命令,而且valkey是基于redis 7.2改的,而Redis.io是8.0,命令不兼容 走投无路之下想到了rdb-tools,先把valkey做个备份,放到S3桶里 valeky-20250819-0001.rdb valeky-20250819-0002.rdb valeky-20250819-0003.rdb valeky-20250819-0004.rdb valeky-20250819-0005.rdb valeky-20250819-config.json cat valeky-20250819-config.json { "valeky-20250819/valeky-20250819-0002.rdb" : { "Slots" : "0-5496", "rdbSize" : "5234516" }, "valeky-20250819/valeky-20250819-0004.rdb" : { "Slots" : "5497-8375", "rdbSize" : "4340658" }, "valeky-20250819/valeky-20250819-0003.rdb" : { "Slots" : "10082-16383", "rdbSize" : "5962581" }, "valeky-20250819/valeky-20250819-0001.rdb" : { "Slots" : "8376", "rdbSize" : "2218" }, "valeky-20250819/valeky-20250819-0005.rdb" : { "Slots" : "8377-10081", "rdbSize" : "1540505" } } 看起来是5个rdb备份,每个文件对应redis不同的slots 用rdb来解析备份文件,结果失败,因为不认识valkey rdb的版本。 没办法了,又找到了这个软件 https://github.com/HDT3213/rdb 下载后,首先想处理成json文件,然后灌入到redis.io ./rdb-linux-amd64 -c json -o 0001.json valeky-20250819-0001.rdb 失败,因为json文件灌入的时候redis.io又被阉割了,命令不支持 ...

2025年08月20日 · 1 分钟 · 123 字 · 八戒