引子
一段时间没处理腾讯云服务器的事情,有两台,以为那台在用的有效期更长,结果忽视了腾讯的提醒,再到最后,过期几个月了。导致站点数据完全丢失,包括N多的图片,有的是技术文章的图片,更要命的还有很多生活图片、视频、旅行图片,仅有的可能是旅行原图还有可能找得到,但是站点里的图都是经过了挑选、截取后的,再去补充图,非常难搞。
多年的心血,很受伤。
建站5.0
已另买了一台阿里服务器,五年七百多块,比较便宜了,因为几乎是最低配的,开了按流量计费。
先把思路搞清楚:
- 文章一般本地电脑有复本,没有问题;
- 图片一定是双备,打算发布一个简易程序,它来处理:一方面上传到百度网盘作为备份,二方面上传到其它minio文件服务器,这样既不占个人云服务器磁盘空间,又不产生阿里云网络流量;
- 用docker建所有运行环境,包括:nginx、hugo、定制程序等,后续更方便迁移和发布,Hugo的主题选用loveit,作者的博客在这里,使用了很多组件,感觉还可以。
但是该主题有点问题:
- 生成的目录貌似不稳定,一会有,一会没有;
- 有的功能鸡肋还不准确,比如字数不知道怎么统计来的,但基本错的,还有预计阅读时间什么的;
- 页面内容稍显复杂.
还是原来的那款minimal更符合我的喜好,但是官方居然下架了,找到另一个国人的,比较清爽,该主题的github地址在这里
首页右侧有标签样的东西,其解释的是categories,另外tag解释在每篇文章的最后。
1 安装java/hugo/nginx/git
这个比较简单,其中hugo是下载的安装包,链接在这里
安装了阿里云的免费SSL,在配置的时候要注意,域名解析是否先配置到位了,疏漏将浪费很多时间。
另外,还有一个很奇葩的情况:xshell以及mobaxterm用私钥怎么都连不上远程服务器,包括重新生成,并且公钥也已经导入到服务器的.ssh目录下,但是filezilla却可以。这个情况原因不明。
hugo启动时,关闭ssh连接就自动中断了,用下面这个命令行:nohup hugo server -D » log.log 2>&1 &
自hugo 0.6起,就不支持在md中夹杂着raw html,那么以前的就不作用了,比如:
<p align="center">
<video id="video" controls="" preload="none" poster="https://yidu.seaeverit.com/cslib_image/roadl/2f67acf37e5e324eb10a2d12baa3df9f.png" width="540" height="960">
<source id="mp4" src="https://yidu.seaeverit.com/cslib_image/roadl/37187b5fb4af2b30770790cfc00591b4.mp4" type="video/mp4">
<!--<source id="webm" src="http://media.w3.org/2010/05/sintel/trailer.webm" type="video/webm">
<source id="ogv" src="http://media.w3.org/2010/05/sintel/trailer.ogv" type="video/ogg">
<p>Your user agent does not support the HTML5 Video element.</p>-->
</video>
</p>
新增shortcodes文件:/layouts/shortcodes/youtube.html,其内容为:
<div class="embed video-player">
<iframe class="youtube-player" type="text/html" width="640" height="385" src="https://www.youtube.com/embed/{{ index .Params 0 }}" allowfullscreen frameborder="0">
</iframe>
</div>
在md中只要这样写就好了:
[{{]< youtube 09jf3ow9jfw >[}}] # 去掉中括号,这是为了防止内容脚本化
则会生成:
<div class="embed video-player">
<iframe class="youtube-player" type="text/html"
width="640" height="385"
src="https://www.youtube.com/embed/09jf3ow9jfw"
allowfullscreen frameborder="0">
</iframe>
</div>
如法刨制,比如新增mp4.html:
<p align="center">
<video controls="" preload="none" poster="{{ index .Params 0 }}" width="640" height="352">
<source src="{{ index .Params 1 }}" type="video/mp4">
</video>
</p>
在md中这样写就可以了:
[{{]< mp4 "https://yidu.seaeverit.com/cslib_image/roadl/728ee0c0b9a28b0f0cef20bd6ab5d61b.png" "https://yidu.seaeverit.com/cslib_image/roadl/eba4a465eb5bb302aa215a0335452ab3.mp4" "640" "352" >[}}]
完美解决心病,注意param中如果有特殊字符,比如:,用引号引起参数即可。
2 搭建代码托管环境
2.1 配置git仓库
自己建一个远程git仓库,本来打算搞个gitlab,但服务器配置太低,CPU超限。
参考自这里
$ groupadd git # 添加用户组
$ adduser --system --home /home/git --shell /usr/bin/git-shell --group git # 添加用户
$ ssh-keygen -t rsa -b 2048 -f privatealiyun230205.pem # 将阿里云生成的访问文件,转成rsa对privatealiyun230205.pem/privatealiyun230205.pem.pub
Generating public/private rsa key pair.
privatealiyun230205.pem already exists.
Overwrite (y/n)? yes
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in privatealiyun230205.pem.
Your public key has been saved in privatealiyun230205.pem.pub.
The key fingerprint is:
SHA256:qk+EUMX/79LaV5Z5PmEwVgndj+RQHHRuzQ4uIMqpkmQ daniel@daniel.local
The key's randomart image is:
+---[RSA 2048]----+
| .o. =*.+|
| . . . oBo|
| . .. . +o.*|
| . o o.. . =o+.|
| E . = S. o + +|
| o . o . . . =+|
| o . o o .+o|
| . o ..o ...|
| ... .+o. .|
+----[SHA256]-----+
$ cd /home/git && mkdir .ssh
$ touch .ssh/authorized_keys # 授权文件,将公钥内容导入
$ chmod -R 0700 .ssh # 授权
$ chown -R git:git .ssh
创建空仓库:
:/ git init --bare projects.git # 加Bare,表示创建裸仓库,一般用于远程仓库,在工作目录下,只有.git目录,没有可以浏览和删除的本地仓库
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /home/git/projects.git/
2.2 安装轻量代码托管gitea
下载页面在这里,居然用的是Caddy服务器,下载的版本是这样的
与gitlab/github等对比说明链接在[这里](https://docs.gitea.io/zh-tw/comparison/
赋权:chmod +x gitea-1.19-linux-amd64
运行:./gitea-1.19-linux-amd64 web
报错:Gitea is not supposed to be run as root. Sorry. If you need to use privileged TCP ports please instead use setcap and the
cap_net_bind_service permission
原因是gitea不支持root用户,使用git用户
chown -R git:git ./gitea-1.19-linux-amd64
su git # 切换为git用户,但是上文已经将git用户禁用了shell
改回git用户的配置:
vim /etc/passwd
git:x:116:126::/home/git:/bin/bash
再运行还是一堆错误:
./gitea-1.19-linux-amd64 web
2023/02/25 16:29:38 cmd/web.go:105:runWeb() [I] Starting Gitea on PID: 17004
2023/02/25 16:29:38 ...s/setting/setting.go:253:newFileProviderFromConf() [E] Unable to check if /root/program/custom/conf/app.ini is a file. Error: stat /root/program/custom/conf/app.ini: permission denied
2023/02/25 16:29:38 ...es/setting/server.go:356:loadServerFrom() [E] Unable to check if /root/program/custom/robots.txt is a file. Error: stat /root/program/custom/robots.txt: permission denied
2023/02/25 16:29:38 .../setting/packages.go:66:loadPackagesFrom() [E] Unable to create chunked upload directory: /root/program/data/tmp/package-upload (mkdir /root/program: permission denied)
2023/02/25 16:29:38 ...s/install/setting.go:21:PreloadSettings() [I] AppPath: /root/program/gitea-1.19-linux-amd64
2023/02/25 16:29:38 ...s/install/setting.go:22:PreloadSettings() [I] AppWorkPath: /root/program
2023/02/25 16:29:38 ...s/install/setting.go:23:PreloadSettings() [I] Custom path: /root/program/custom
2023/02/25 16:29:38 ...s/install/setting.go:24:PreloadSettings() [I] Log path: /root/program/log
2023/02/25 16:29:38 ...s/install/setting.go:25:PreloadSettings() [I] Configuration file: /root/program/custom/conf/app.ini
2023/02/25 16:29:38 ...s/install/setting.go:26:PreloadSettings() [I] Prepare to run install page
2023/02/25 16:29:38 ...ation/translation.go:59:func1() [F] Failed to list locale files: unable to check if custom directory "/root/program/custom/options/locale" is a directory. stat /root/program/custom/options/locale: permission denied
从错误信息看,因为程序是放在/root/program下,这个root目录归root用户的,可能就权限问题。在它下面创建不了custom/log/data等目录。
可能需要先进行一些配置,目前看就是创建一些目录,参考这里,如下:
mkdir -p /var/lib/gitea/{custom,data,log}
chown -R git:git /var/lib/gitea/
chmod -R 750 /var/lib/gitea/
# 下面这三行可能跟解决问题无关,是gitea程序目录所在,当然,下述启动命令有指定到这个目录下写app.ini文件,但并没有生成该文件,目录仍为空
mkdir /etc/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea
再次运行,错误依旧,这样看来文件夹虽然创建了,但是gitea程序并不会指向这些目录,如何处理?重要信息——在上述官方网页中,找到命令行启动的要点,即通过下面命令行成功启动:
GITEA_WORK_DIR=/var/lib/gitea/ ./gitea-1.19-linux-amd64 web -c /etc/gitea/app.ini
2023/02/25 16:34:24 cmd/web.go:105:runWeb() [I] Starting Gitea on PID: 17035
2023/02/25 16:34:24 ...s/install/setting.go:21:PreloadSettings() [I] AppPath: /root/program/gitea-1.19-linux-amd64
2023/02/25 16:34:24 ...s/install/setting.go:22:PreloadSettings() [I] AppWorkPath: /var/lib/gitea/
2023/02/25 16:34:24 ...s/install/setting.go:23:PreloadSettings() [I] Custom path: /var/lib/gitea/custom
2023/02/25 16:34:24 ...s/install/setting.go:24:PreloadSettings() [I] Log path: /var/lib/gitea/log
2023/02/25 16:34:24 ...s/install/setting.go:25:PreloadSettings() [I] Configuration file: /etc/gitea/app.ini
2023/02/25 16:34:24 ...s/install/setting.go:26:PreloadSettings() [I] Prepare to run install page
2023/02/25 16:34:24 ...s/install/setting.go:29:PreloadSettings() [I] SQLite3 is supported
2023/02/25 16:34:24 cmd/web.go:220:listen() [I] [63f9c810-6] Listen: http://0.0.0.0:3000
2023/02/25 16:34:24 cmd/web.go:224:listen() [I] [63f9c810-6] AppURL(ROOT_URL): http://localhost:3000/
2023/02/25 16:34:24 ...s/graceful/server.go:62:NewServer() [I] [63f9c810-6] Starting new Web server: tcp:0.0.0.0:3000 on PID: 17035
可以设置GITEA_WORK_DIR的环境变量。
现在看来,CPU的消耗比较docker+gitlab少了很多,希望不到撑到阿里云说CPU分消耗完而几近断服。
0[* 0.7%] Tasks: 50, 93 thr; 1 running
1[ 0.0%] Load average: 0.04 0.02 0.00
Mem[||||||||||||||||||||#####*********************************************************358M/1.64G] Uptime: 22:59:17
Swp[ 0K/0K]
把gitea配置为自启服务,参考官方文档,链接在这里
root@daniel:~/program# cp gitea-1.19-linux-amd64 /usr/local/bin/gitea # 先把gitea拷贝到自启服务中指定的目录
root@daniel:~/program# chown -R git:git /usr/local/bin/gitea
root@daniel:~/program# systemctl enable gitea # 执行需要一点时间
Created symlink /etc/systemd/system/multi-user.target.wants/gitea.service → /etc/systemd/system/gitea.service.
root@daniel:~/program# sudo systemctl start gitea
初次访问gitea,进入了一个配置页面,主要要求配置mysql,这样接下来安装mysql
其它配置信息:
仓库根目录:/var/lib/gitea/data/gitea-repositories
LFS根目录:/var/lib/gitea/data/lfs
日志根目录:/var/lib/gitea/log
2.3 gitea钩子搞定自动发布博文
也想像之前搞的gitlab一样,做一个hook,捕获push event,然后check out代码至hugo目录,这样hugo会自动刷新站点。
以下参考自这里。
实现更新md自动checkout到hugo的content目录,以实现自动发布更新。代码库路径:/var/lib/gitea/data/gitea-repositories/daniel/roadl.com.git
,其子目录:cd hooks/post-receive.d/
。
钩子文件post-receive的内容(注意这个文件的所有者设为git,且打开执行权限):
#!/bin/bash
gbError="\033[1;31m[ERROR]\033[0m"
gbWarning="\033[1;33m[WARNING]\033[0m"
gbInfo="\033[1;32m[INFO]\033[0m"
gbGood="\033[1;32m[GOOD]\033[0m"
echo -e "\n$gbInfo Hugo blog post-receive git hook is running...\n"
# markdown工程代码库
bare_repo=/var/lib/gitea/data/gitea-repositories/daniel/roadl.com.git
# 先把东西全部checkout出来,TODO是否能部分checkout?
cloned_repo=/var/lib/gitea/data/gitea-repositories/daniel/roadl.com
# 仅处理博文目录
blog_dir=/var/www/roadl.com/content/posts
# 先删掉历史checkout
rm -rf $cloned_repo
git clone $bare_repo $cloned_repo
cd $cloned_repo
# 下面两行不执行了,hugo不像hexo,可以先走develop模式
#chmod +x deploy.sh
#./deploy.sh
#if [ $? -eq 0 ]; then
# 删掉站点内容
rm -rf ${blog_dir}/*
# 仅拷贝部分checkout内容至站点
cp -rf content/posts/* ${blog_dir}/
#fi
把目录文件夹blog_dir设为git用户所有,因为他要在里面进行复制、以及删除操作:
sudo chown -R git:git /var/root/roadl.com/content/posts
上述变更所有者还是没有用,因为父级等还是属于root的。后来把roadl.com移动到/var/www下就可以了。这时,一旦在idea提交md的更新,就立即能看到最新的网页。
附,人家的deploy.sh是放在工程根目录下的,内容为:
#!/bin/bash
file_log=deploy.log
file_fifo=run.fifo
rm -f "$file_log" "$file_fifo"
mkfifo $file_fifo
cat $file_fifo | tee -a $file_log &
exec 3>&1
exec 4>&2
exec 1>$file_fifo
exec 2>&1
gbError="\033[1;31m[ERROR]\033[0m"
gbWarning="\033[1;33m[WARNING]\033[0m"
gbInfo="\033[1;32m[INFO]\033[0m"
gbGood="\033[1;32m[GOOD]\033[0m"
current_time=$(date "+%Y-%m-%d %H:%M:%S")
echo -e "\n <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $current_time >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \n"
echo -e "$gbInfo Start to build and deploy hexo blog...\n"
hexo clean
hexo douban -b
hexo g
# hexo deploy
if [ $? -eq 0 ]; then
echo -e "\n$gbGood Successfully built and deployed hexo blog!"
else
echo -e "\n$gbError Faild to deploy hexo blog, please check it!"
fi
printf "\015"
exec 1>&3
exec 2>&4
rm -f "$file_fifo"
3 安装mysql
见另外的文章,链接在这里,后来在配置gitea时,发现字符集超出限定范围,于是重装5.7,安装方法有点不同,类似于mysql 8的安装:
bin/mysqld --initialize-insecure --user=root --basedir=/root/program/mysql-5.7.37-linux-glibc2.12-x86_64 --datadir=/root/program/mysql-5.7.37-linux-glibc2.12-x86_64/data
然后设定为自启:
root@daniel:~/program/mysql-5.7.37-linux-glibc2.12-x86_64# cp support-files/mysql.server /etc/init.d/mysql.server ## 拷贝前修改basedir、datadir
root@daniel:~/program/mysql-5.7.37-linux-glibc2.12-x86_64# update-rc.d mysql.server defaults # 需要一点时间
root@daniel:~/program/mysql-5.7.37-linux-glibc2.12-x86_64# systemctl daemon-reload # 使修改生效,需要一点时间