From 0d5cddb7f5e87843f87ba14499fe82ee7f9b7d91 Mon Sep 17 00:00:00 2001 From: Meng Sen Date: Mon, 14 Oct 2024 12:44:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83=E5=BA=94=E7=94=A8=20Certimat?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Meng Sen --- .github/README.md | 1 + README.md | 1 + apps/certimate/0.2.0/data.yml | 17 +++++++ apps/certimate/0.2.0/docker-compose.yml | 20 ++++++++ apps/certimate/0.2.0/scripts/init.sh | 15 ++++++ apps/certimate/0.2.0/scripts/uninstall.sh | 10 ++++ apps/certimate/0.2.0/scripts/upgrade.sh | 15 ++++++ apps/certimate/README.md | 58 ++++++++++++++++++++++ apps/certimate/data.yml | 16 ++++++ apps/certimate/logo.png | Bin 0 -> 17936 bytes 10 files changed, 153 insertions(+) create mode 100644 apps/certimate/0.2.0/data.yml create mode 100644 apps/certimate/0.2.0/docker-compose.yml create mode 100644 apps/certimate/0.2.0/scripts/init.sh create mode 100644 apps/certimate/0.2.0/scripts/uninstall.sh create mode 100644 apps/certimate/0.2.0/scripts/upgrade.sh create mode 100644 apps/certimate/README.md create mode 100644 apps/certimate/data.yml create mode 100644 apps/certimate/logo.png diff --git a/.github/README.md b/.github/README.md index 39ae73de3..b8b7596d3 100644 --- a/.github/README.md +++ b/.github/README.md @@ -87,6 +87,7 @@ | 🟢 | | Artalk | https://artalk.js.org/ | 一个自托管的评论系统 | | | 🟢 | | Bark | https://bark.day.app/ | 一款注重隐私、安全可控的自定义通知推送工具 | | | 🟢 | | Casdoor | https://casdoor.org/ | 身份和访问管理(IAM)/单点登录(SSO)平台 | | +| 🟢 | | Certimate | https://docs.certimate.me/ | SSL证书管理工具 | | | 🟢 | | Cookie Cloud | https://github.com/easychen/CookieCloud/ | CookieCloud是一个和自架服务器同步浏览器Cookie和LocalStorage的小工具 | | | 🟢 | | DeepLX | https://deeplx.owo.network/ | DeepL免费API(无需TOKEN) | | | 🟢 | | Dockge | https://dockge.kuma.pet/ | 面向堆栈的管理器 | | diff --git a/README.md b/README.md index 7765df399..bd63c97f6 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ | 🟢 | | Artalk | https://artalk.js.org/ | 一个自托管的评论系统 | | | 🟢 | | Bark | https://bark.day.app/ | 一款注重隐私、安全可控的自定义通知推送工具 | | | 🟢 | | Casdoor | https://casdoor.org/ | 身份和访问管理(IAM)/单点登录(SSO)平台 | | +| 🟢 | | Certimate | https://docs.certimate.me/ | SSL证书管理工具 | | | 🟢 | | Cookie Cloud | https://github.com/easychen/CookieCloud/ | CookieCloud是一个和自架服务器同步浏览器Cookie和LocalStorage的小工具 | | | 🟢 | | DeepLX | https://deeplx.owo.network/ | DeepL免费API(无需TOKEN) | | | 🟢 | | Dockge | https://dockge.kuma.pet/ | 面向堆栈的管理器 | | diff --git a/apps/certimate/0.2.0/data.yml b/apps/certimate/0.2.0/data.yml new file mode 100644 index 000000000..c01683633 --- /dev/null +++ b/apps/certimate/0.2.0/data.yml @@ -0,0 +1,17 @@ +additionalProperties: + formFields: + - default: "/home/certimate" + edit: true + envKey: CERTIMATE_ROOT_PATH + labelZh: 数据持久化路径 + labelEn: Data persistence path + required: true + type: text + - default: 8090 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelZh: Web UI 端口 + labelEn: Web UI port + required: true + rule: paramPort + type: number diff --git a/apps/certimate/0.2.0/docker-compose.yml b/apps/certimate/0.2.0/docker-compose.yml new file mode 100644 index 000000000..cd6888012 --- /dev/null +++ b/apps/certimate/0.2.0/docker-compose.yml @@ -0,0 +1,20 @@ +networks: + 1panel-network: + external: true + +services: + certimate: + image: usual2970/certimate:v0.2.0 + container_name: ${CONTAINER_NAME} + labels: + createdBy: "Apps" + restart: always + networks: + - 1panel-network + ports: + - ${PANEL_APP_PORT_HTTP}:8090 + env_file: + - /etc/1panel/envs/global.env + - ${ENV_FILE:-/etc/1panel/envs/default.env} + volumes: + - ${CERTIMATE_ROOT_PATH}/data:/app/pb_data diff --git a/apps/certimate/0.2.0/scripts/init.sh b/apps/certimate/0.2.0/scripts/init.sh new file mode 100644 index 000000000..77b849120 --- /dev/null +++ b/apps/certimate/0.2.0/scripts/init.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +if [ -f .env ]; then + source .env + + # setup-1 add default values + CURRENT_DIR=$(pwd) + sed -i '/^ENV_FILE=/d' .env + echo "ENV_FILE=${CURRENT_DIR}/.env" >> .env + + echo "Check Finish." + +else + echo "Error: .env file not found." +fi diff --git a/apps/certimate/0.2.0/scripts/uninstall.sh b/apps/certimate/0.2.0/scripts/uninstall.sh new file mode 100644 index 000000000..c86c4fbca --- /dev/null +++ b/apps/certimate/0.2.0/scripts/uninstall.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ -f .env ]; then + source .env + + echo "Check Finish." + +else + echo "Error: .env file not found." +fi diff --git a/apps/certimate/0.2.0/scripts/upgrade.sh b/apps/certimate/0.2.0/scripts/upgrade.sh new file mode 100644 index 000000000..77b849120 --- /dev/null +++ b/apps/certimate/0.2.0/scripts/upgrade.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +if [ -f .env ]; then + source .env + + # setup-1 add default values + CURRENT_DIR=$(pwd) + sed -i '/^ENV_FILE=/d' .env + echo "ENV_FILE=${CURRENT_DIR}/.env" >> .env + + echo "Check Finish." + +else + echo "Error: .env file not found." +fi diff --git a/apps/certimate/README.md b/apps/certimate/README.md new file mode 100644 index 000000000..23b05c6c0 --- /dev/null +++ b/apps/certimate/README.md @@ -0,0 +1,58 @@ +# Certimate + +SSL证书管理工具 + +![Certimate](https://file.lifebus.top/imgs/certimate_cover.png) + +开源的SSL证书管理工具,可以帮助你自动申请、部署SSL证书,并在证书即将过期时自动续期。 + +An open-source SSL certificate management tool that helps you automatically apply for and deploy SSL certificates, as +well as automatically renew them when they are about to expire. + +![](https://img.shields.io/badge/%E6%96%B0%E7%96%86%E8%90%8C%E6%A3%AE%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91%E5%B7%A5%E4%BD%9C%E5%AE%A4-%E6%8F%90%E4%BE%9B%E6%8A%80%E6%9C%AF%E6%94%AF%E6%8C%81-blue) + +## 简介 + +做个人产品或在小企业负责运维的同学,需要管理多个域名,要给域名申请证书。但手动申请证书有以下缺点: + +😱麻烦:申请、部署证书虽不困难,但也挺麻烦的,尤其是维护多个域名的时候。 + +😭易忘:当前免费证书有效期仅90天,这就要求定期操作,增加工作量的同时,也很容易忘掉,导致网站无法访问。 + +Certimate 就是为了解决上述问题而产生的,它具有以下特点: + ++ 操作简单:自动申请、部署、续期 SSL 证书,全程无需人工干预。 ++ 支持私有部署:部署方法简单,只需下载二进制文件执行即可。二进制文件、docker 镜像全部用 github actions 生成,过程透明,可自行审计。 ++ 数据安全:由于是私有部署,所有数据均存储在本地,不会保存在服务商的服务器,确保数据的安全性。 + +## 概念 + +Certimate 的工作流程如下: + ++ 用户通过 Certimate 管理页面填写申请证书的信息,包括域名、dns 服务商的授权信息、以及要部署到的服务商的授权信息。 ++ Certimate 向证书场商的 API 发起申请请求,获取 SSL 证书。 ++ Certimate 存储证书信息,包括证书内容、私钥、证书有效期等,并在证书即将过期时自动续期。 ++ Certimate 向服务商的 API 发起部署请求,将证书部署到服务商的服务器上。 + +这就涉及域名、dns 服务商的授权信息、部署服务商的授权信息等。 + +## 支持的服务商列表 + +| 服务商 | 是否域名服务商 | 是否部署服务 | 备注 | +|------------|---------|--------|------------------------------------------| +| 阿里云 | 是 | 是 | 支持阿里云注册的域名,支持部署到阿里云 CDN,OSS | +| 腾讯云 | 是 | 是 | 支持腾讯云注册的域名,支持部署到腾讯云 CDN | +| 七牛云 | 否 | 是 | 七牛云没有注册域名服务,支持部署到七牛云 CDN | +| CloudFlare | 是 | 否 | 支持 CloudFlare 注册的域名,CloudFlare 服务自带SSL证书 | +| SSH | 否 | 是 | 支持部署到 SSH 服务器 | +| WEBHOOK | 否 | 是 | 支持回调到 WEBHOOK | + +## 安装说明 + +> 用户名 `admin@certimate.fun` +> +> 密码:`1234567890` + +--- + +![Ms Studio](https://file.lifebus.top/imgs/ms_blank_001.png) diff --git a/apps/certimate/data.yml b/apps/certimate/data.yml new file mode 100644 index 000000000..9284f5490 --- /dev/null +++ b/apps/certimate/data.yml @@ -0,0 +1,16 @@ +additionalProperties: + key: certimate + name: Certimate + tags: + - WebSite + - Tool + - Middleware + - Local + shortDescZh: SSL证书管理工具 + shortDescEn: SSL Certificate Management Tool + type: website + crossVersionUpdate: true + limit: 0 + website: https://docs.certimate.me/ + github: https://github.com/usual2970/certimate/ + document: https://docs.certimate.me/docs/intro/ diff --git a/apps/certimate/logo.png b/apps/certimate/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e95ace5ca795543a199e2b9607c7ec5d68e96fb2 GIT binary patch literal 17936 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,BO5VlzKO`iv8dP!{HG`+f^X>^9z%3b_^+ zY01LGq!t2cH`{!!eidms{~m$}_48t+*jsr&Xn702Qq4-h8h)*T*k+ga!5nIu>kmuH z4x|pyzT-&f!$+wgLoWp-(4C3Jv=9Kdx9~?ttPr$u<$F2IAi4V@;8|FtKL@YzNtGIoLui+Y?5qf#3J88?Dr}mP-&&SC8o**}~t|gt87_<1Re^S5_gL&dW z!1a>c_J*9vBD{F07Q{;9je#`YL>zg2!5;`g3WhJW z^}bnsGjXOradnK8_byE4i6mb2Qce)98MZJ3(zodJ?)~Sb=egc5I`*+@-vGWtu8J4D z91^`TdRdl0NLq#((%?fPB!oCrct0Fylhw-W{pmLohIEeiAZdL?Q|ppp($PKRGQH4d zyz{NK{457_^X%EQr_(%NX+ZzG z$Hh7wa_>E0KLjoXJ$p4AzGl=WEd@bQL@#BE9$OMdOr-mb(8!U_D2*`c-v!9pvInkL zpc=22SV^3~)AC7xWA=64a)PS=H$wX)I^No2cw+FnE(EG%)VF1z$0W$0NZUZ5DcO&n zZ!S~dg~S5?y_+oF?%x{avk?Yy;6fJk)MpxZz5 zvi<2Wt!N~WCtho{;}?=^dlRpn*?=^IGKq|MYZ3|B+T=f5IPaT$j_6J30ZkfKogc{d zBS~1m%<<@QmiJ`fDJD}q;{p_4Dm}NqskuH5@^X4|1MJ6aAL`hbD91vofc^RY*!Mnb zIRKIYBS#%Fs(0t-_EUVs>Qiu8VPsMZC>X!o5&_hI?u*|ZQT6y9ppMM^pI}#xqA7On zc&>Wh(2Mt-K*M(4ER-v(PA~1SG`ySb5R6Vacrtd6s)!=jxW|J${;e=!c6ILC@ zqjG>I#pv}Mg&Zm9@eQyWUtT!;{cxF&)DMDQ?SwPrOvVk$XZrxW34AyfPn+2otJx5+ zb#WOrK!!Y412|0>nDwqRsrUO;)H;RARQax;=a%CqEfu|}>Un>`-g6|DuI5s69=Jv7*bAXQrBa+y1k=L40Hw&xIG_(XO8d7aZRWmV zbwTk$nzhL`Nvan6zQU@_NIbc|wzknA_%UCVJj2!zF`7au?rQa$_kt8aorXZBj<=Mg zTt!(yP77LtQ9u{Gb|`vPjZGbHK>*kcyvB@@vq4RuiUh#(sc#Bt!F(ky`Ya|zNZCLd zhNSU5?fYS+nU@d9n8d-gn)GA;^3`isq|vu{fk$$N^~Z~wXA^nK{~?xvVHl7-h6$*7 z*$4v_NBmd>Hsn{Hr2%n(had?6(jPWubrdH^TuRti1)DR*x(mDnNpA>qm&Gpe0yCfM zS0!*`X9Z=kES3~v@tc&H#t<}l{(EzO!X;R>Bgsy}OZm>+N)42!5v<|AHUc>D+qbNB zZ&nYM`0uR8uN*jQHC}mf?>=R5D;!F*QP*3zYYX)GYtO){X0QVE@}2{k*qN5j6D=r|C4M_JjJt?LcBhvf-MlR_J$o zuR*j1s1~q)|E^$>IwX~TTr!H7&0(c?vG`ra#tnddZ-Vy(TKR1?5&Wq!gP>@GX(xfQ z;h^K$2g>~5r%W^$VdkCh0c<}CVe6zC1zcecG;w?2%5g7R!=M;)=O6F!P0GDZN^)Uq zGU1h%O(xt+@ln#2u!a9hGB*BWz5SWgq$spG=IJ-nop1RRl;1E2EhiQ{Z)YGGd7Q`W z686Cieoz#t;?7GkK>7bw3E(j<4>B_rk;@z*LE=zNQO4cQ%aA>YKg~0}S%pu>r;r$4 ztH)xsIZ>Pqa5b!zCTo0hp3|2Gv_^(GY~iiDW=kdEhywGCREmQ264>1Fd@z$gsDcE$ zQhsMAt{ptB4ZR|P(gn`bwO587wpQf@qr}(<{-DAERB(B~ILuN)h#~@a7=16|e!8cD zI)+ww6xp!oUG@D4B`E#h#L-4sLH#j!%}7wn;4T5lze>69lD+oT6#7?DqWA8ee5P>A zQes*;{TT;{S7fE0|*{f zP;ewbUI){$AZ>ZJ4_+f;GT{qQq84p%#;Dzq&bQnxW6(2_nj&*v*S05|!-s1d{;QIK z-hYTVD_pz94oU!lh=hFeSx=5(DUGXr#4RLNK`o8xNRXtt6cHdtVE@Nh%{P6STbDfFGlr4DDLF9?9f5i^BzrFdtiXu8~7{^V3pQmisWTY(vVvj0%g7Z}v z?{R;DkIJ@yNxw-zKjz&@se<`-l32!v;w82Z|EolMi#-Ddzv#C2IycqE0L_|{@bw2- z4CgM_N(l$}NI>S&b{k>Ml$ye1`_#~d4o2L?JH#Vt+@LG+p`?j9_cKovP~5Az_~FC(3z{~^P*`P(Mb>`K=VjMquqWm!H} z)!VQmE$a6^%=8@jU$;#LVNkhc{N?jBZT1neo{H3_ScVL80V1@B?9}d${e7j%UOsWh+r0aZR6#n$Nf++v9p+MXj(A4-G_dCUp1QuLqyJ!d(!rB3G9NFtZ{mvE(!L11euG&9NZ{RZSnn@|VS6$@8(=;&b#PSv z^IpT^o(!i8W~743fAuZEjVDomhNXIzXu^{;e61UeL;xwyeW)Sv>MV2pm2A8FHr&rvK;{$T z0~oJs%~fZ^+(_IXzqUYg{`J6>8k>KGp*?JObj6jVY6pTNInRp;m>6KFAP5mc`nv#| zB{P<;_V;G`0g(5a0c2~$((?Uf{!vNT2?Q#VU5MG;<19aTn<>jj8@7(huCPH%qbjhO zXz)D4*%FqXngp<}yOwbn{8@rISjaYpjwL|Ai@U(EtPj)>Q-E1&I+~t+usj#1x+CMP zMriN5i7C`>mXRfefS?xA+#Hr(n{>_IcI1XJMf45mnNb^mSX5-Xx2iyDLQ`nkA*jhe zbn2_HI$!(yg;)i1)EKDBWi38W9F29>EtTKU4FI*ntG7|IHGXqv2=~b3hCp2~Fq@dA z>3q$)HqFFhdexRd1YuJ^;nTFvMBLfQ({c}G{yT#%Tx}B*Hc!AGUHEa=i6O3kYh8=yo*rC~|P$5x>Vjc;)B! zQR6ZE!zca|^vnjaWxw~6QVyye-4gc}r!FycAMv~)yRpI(UEDtT)y%%Dwzr(+LEhZi zekiJ>voPt2okjKJI@f=GpvT2@Lh+cHrFTeweLfn{I$gD2Tz)Yo_(PivQ&8CDmC!g@s4Z99TJ#t6YJOPM9iE@i`a9C_)Q|s3 zesT@2%_}ZgspZwtRQ>5v1XplE2g9W^P@yo@agw zdXXY@hhnw$=Z$rbK9*%A3%@m;6}}vYv(O#fGtok(rr&yuknm` zIikn775Rm^$U=yqjMC~d|!YGa%J>JDuiJ#!^99dyRX#3AYaH}JfNMp?-3C(-32)`0vA<=r{CR66^ipv! zw%{2BLGL-cuq>-?f;#t`U`ev`ty-^gUFj{^8$7J~TC{frcycHJU4HlOKc4+Cs@M>t zu3-@2=CdMnCMH5*rC}(+!G8R`s`tAQTS()FxO-Wbi@2hF5o+E)o&QOU-n*@Oefp}6 zKAYk2W91flW>H}}C`U47ONPBW%`mn?s>R@$o3M9O(Y@CMr;D{3H$PW7_6?97zLxrg zCBr=aHS(s_*RQ0f$mhFXaT7Bir^2nyOmbhFF4>4b-JWA6il3xD-6q4#y4o3?-J<*4 ze!YZaFNA}JaHF_%HkX!wH|KKq4Pc`$ni>ch!U?>-4!Yh%ON!EJC0VuxP1g2II+|UG ziby#hfFq}`>U~YFu+Z>D#>oEw_Fxiw@|uFsZkzwvJ;Qv&;i0+GknhVU&#MTc#r=<) zy(ZO*1S5EFGSUACS>aEq7M4Mug#>=K_k68f%!zv3mOxWB^X&$J} zoM~sIhnV2cT_UW`r=W97chpXl>7Zy=nbIkI|F4(Q3f4+rQ-+1Ea_$+{OFXvVGVYb1 zl=GA|C~qi!Wmqnpv$|2Zx4Xnvt8rip5u3L=zjcK8)_xC9pjK-7K2raXLuqV^A~;!< zUc(|Q;*Ru!$AavF+lr89UmU{M;vRTgTXrk7dqr!7|9y;oJ zFFX3cc`u_`Vy%m>HEN2?@#