阅读视图

发现新文章,点击刷新页面。
☑️ ☆

如何使用 docker 部署一个 WordPress

很多年前开始,我在 Mac 上调试 Web 应用,就是使用一个 App,叫 MAMP Pro,这是一个德国软件,相当于 Windows 上的 xampp,是 Apache + PHP + MySQL 套装。用起来很方便,主要在一台机器上,可以启动很多个 Web 应用,比较节省资源,当然,这不是什么优点,真正的优点是开箱即用,非常方便。 不过现在,我公司深度采用云计算和 Docker,k8s 等基础设施,在本地使用 AMP 套件,其整体部署和服务器环境相差就比较远了。而且最近开发 Flutter 远多于 PHP,还有一个因素是我刚换了 m1 的 Mac,而 MAMP 还是 x86 架构的,干脆还是尽量用 Docker 吧。 拉取镜像 WordPress 镜像里应该是自带 Web 服务器的,所以,依赖只有一个 MySQL 了。 编排服务 当然,你可以先启动 MySQL,然后再启动 WordPress,手动操作也没什么。不过,启动数据库,你要指定端口,root 密码,而启动 WordPress,你要指定的就多了,数据库相关的配置 4 个,还有一些随机 Key,数据库表前缀等参数,就比较麻烦,还是直接用配置文件比较方便。具体可以参看镜像官网。 下面的编排文件也是从镜像官网得到的: 你可以随便创建一个空文件夹,然后,将上述的文件拷贝到一个名为 docker-compose.yml … Continue reading 如何使用 docker 部署一个 WordPress
☑️ ☆

如何使用Hugo和Github Actions搭建博客

没想到,到了 2023 年的今天,想要找一个能长久免费托管自己个人博客的平台,仍然是一件难事。就在前不久,行业的一位前辈左耳朵耗子逝去,我去他的博客缅怀,发现他的博客托管在 Cloudflare 云计算平台,平台提示,他的博客因为没有续费已经下线。 我不免想到,如果有一天是我,那么我的博客,承载了我在这个世界上公开留下的文字,还能在互联网上存在多久呢?此前我的博客托管在腾讯云服务器上,还比较稳定,较少出现故障等,但是服务器需要人续费维护。后来搬迁到阿里云服务器,比较垃圾,经常会出现故障,还不能自动恢复。而且流量耗光,或者服务器租期到了,我留下的这些内容都会直接下线消失,不复存在。 我想,我需要找一个尽可能长时间免费托管,稳健运行的平台,来备份我的所有博客内容。这样,即使我在相当长一段时间不去维护,不续费,我留下的内容继续存在。所以,我主要的需求,就是一个尽可能免费,稳定运行的平台,托管了博客内容,如果不去维护,也不会出问题。此外,还要满足,撰写方便,发布方便,对开发环境依赖低等等特点。 Github 是我比较熟悉的平台,也已经稳健存在了多年,对个人用户免费。还有一个原因,就是该平台在开发人员中,有比较好的信用。尊重创作和开源,对作者的创作内容没有太多侵犯性的条款。最后一个点,就是我所掌握的技术能力,可以胜任在这个平台进行操作。而 Github Actions 提供的自动化能力,虽然门槛很高,但是在没有人运维的情况下,业已生成的静态化站点,也不会受到生成功能变更的影响。 可能不是最优的选择,但是值得一试,如果事实证明可行,我也不想再去调研更多的方案了。毕竟人都是懒惰的。下面介绍,如何利用 Hugo 和 Github Actions 来搭建一个博客。 1. Hugo Hugo 是一个 Go 语言实现的静态页面生成器,同类产品很多,还有 Jekyll、Hexo 等。选此款有几个原因,一个是在 Github 上的 Star 数量比较多,社区活跃,年头也很长了,比较成熟稳定。另外,学习 Go 语言也一直以来是我的一个计划。当然,这类生成器模式的博客,原理都大同小异,选哪个其实也都无所谓。其实单就个人喜好来说,我见过的几款 Hexo 的皮肤,更符合我的口味一点,而 Hugo 的皮肤往往都不如 Hexo 好看,原因可能是,Hexo 是前端程序员这个群体的制作的产品。 此类生成器,大多是采用某种结构化或者半结构化语言,比如 Markdown,撰写博客的内容,然后用生成器,将其转化为 HTML 静态页面,根据 theme 主题,组织成一个博客网站,然后发布到托管服务器上,供整个互联网查看。 2. Github Actions Github Actions 是 Github 提供的一种自动化工具,可以在 Github 上,通过配置文件,实现一些自动化的功能。比如,当你的代码提交到 … Continue reading 如何使用Hugo和Github Actions搭建博客
☑️ ☆

使用 Flutter 如何实现客户端证书验证 mtls

SSL 已经成为互联网最重要的基础设施,尤其是最近几年,基本上所有网站都已经部署了 HTTPS。曾几何时,SSL 证书对普通个人网站来说,还是很难取得的,主要是要收费。但是,从 Let’s Encrypt 提供服务开始,几乎整个互联网都用上了免费的 SSL 证书。 使用 HTTPS 可以保证你的网站上提供的服务和用户浏览器之间的链接加密,其内容不必篡改和窃听。SSL 证书有很多等级,一般免费的证书都是域名级别的,即证明网站服务提供商,拥有目标域名的管理权限。当然还有更高级别的。 不过,一般的 HTTPS,只是帮助访问网站的用户认证自己访问的域名没有被篡改。但是在安全等级更高的地方,被访问的服务,也需要证明访问者的身份可靠。当然,一般的网站也都有这个要求,比如要求用户进行登录,提供用户名和密码作为一种验证手段。 客户端证书验证概述 但是在安全等级更高的场合下,光有用户名和密码,也还不够安全,比如你的用户名或者密码失窃了,别人就可以冒用你的身份。这时候,多因素验证就会成为一个重要的验证用户身份的手段。常见的是双因素认证,比如需要用户的手机验证码。 而客户端证书,其实也是一种多因素认证的手段。要求用户使用的客户端,必须给服务器出示证书,以证明自己的身份。仔细想一下,对每个人来说,可能也不太陌生。 比如,网络银行使用的 UKey 就是一种常见的客户端证书,证书被置于一个硬件设备中,通过 USB 插入到使用的终端上来提供给服务器。当然,除了硬件证书,还有软件证书。将 CA 颁发的证书,安装到目标的客户端,一般是安装到操作系统。这样,在浏览器访问目标服务器的时候,就可以从操作系统直接提供此类证书。 大家在使用网银的时候,其实已经远远不是双因素认证了,至少需要用户名,密码,短信验证码和 UKey,经常至少是三因素的。关乎到个人财产安全的网络设施,怎么小心都不为过。 Web 服务部署客户端证书验证 作为非常重视信息安全的金融公司技术人员,我们一开始就非常注重保护公司的信息安全。公司所有内部网站,都采用了 HTTPS 作为基本的部署要求,同时,客户端证书认证,也是我们一直以来所要求的。 在 Web 服务器上部署客户端证书认证,是非常简单的。只要在 Nginx 的虚拟服务器配置上,打开选项: 即可以实现对客户端证书的验证。使用 openssl 套件,自己构建 CA,然后将根证书配置在 Nginx 侧,即可以实现对签发的客户端证书进行验证。如何使用 openssl 套件,颁发客户端证书,这就是一个很长的操作指引,本文不在赘述,网上相关的教程很多,大家也可以看看 easyrsa 套件的文档或者相关介绍(应该是 openssl 的一个友好的命令行界面)。 移动设备环境下的客户端证书 Web 服务实现了客户端证书验证后,所有需要访问受保护网站的客户端,都要安装对应的证书。使用 openssl 生成的 x.509 … Continue reading 使用 Flutter 如何实现客户端证书验证 mtls
☑️ ⭐

如何使用 Flutter 实现一个 OTP 验证器

我刚入职的时候,公司使用 RSA 公司的 token,所谓的 token 就是一个像优盘一样的硬件,每隔 30 秒会产生一个 6 位数字,这个数字作为一次性密码,也即标题里提到的 OTP,one-time-password 的缩写。 后来手机普及后,出现了很多软件实现的 OTP,比如 QQ 安全中心,微软的 Authenticator,以及 Google Authenticator。这些验证器和一次性密码,成为两步验证一种比较流行的方式。我个人也很喜欢,至少我觉得比短信验证码体验要好一些。 什么是 OTP? OTP (One-Time Password),翻译成中文为一次性密码,是一种加强网络安全的方法。在使用传统的用户名和密码进行登录时,由于密码可能被泄露或者猜测,因此使用 OTP 能够在一定程度上防止网络攻击和不法分子的破坏。 OTP 常见的实现方式有 HOTP 和 TOTP。而HOTP (HMAC-based One-Time Password),利用哈希算法来生成密码。HMAC(Hash-based Message Authentication Code,中文名:基于哈希的消息认证码),这个算法主要是用于验证消息的合法性,与常见的哈希算法的唯一区别是,在计算哈希摘要时,还需要额外提供一串密钥,俗称加盐(salt 或 nonce)。这串密钥只有客户端和服务端双方知道,被计算摘要的消息要求双方都能知道并保持相同,一般是一个自增计数器,比如:0, 1, 2, 3, 4。被计算出的一次性口令每使用一次,这个计数器就加一,由于密钥只有双方才知道,故双方都可以计算出一样的一次性口令,而第三方不知道这串密钥的,无法计算出一样的口令。RFC 4226 描述了其技术规范。 验证与被验证两方,怎么能保证用于验证的消息始终保持同步呢?在现实世界中,确实是一个麻烦的事情,所以,就有 TOTP。TOTP (Time-based One-Time Password),时间同步动态口令,是一种基于时间的 OTP,也就是说 TOTP 通过计算当前时间和一个密钥来生成密码。这样,验证与被验证两方,共同使用的用于验证的消息,就是时间。其实就是将消息建立在全球时间服务的基础上,实现共识。不但各方得到的时间是一致的,而且时间在单向向前改变数字,成为了 OTP 的很好基础。 … Continue reading 如何使用 Flutter 实现一个 OTP 验证器
☑️ ☆

WordPress 数据库损坏

常在河边走,哪能不湿鞋。没想到,从 2008 年开始深入玩 WordPress 博客到现在,竟然第一遇到了数据库损坏,真是闻所未闻,见所未见啊……一个个人博客而已,毫无访问和压力,竟然也可以搞成这样。 我不得不怀疑是阿里云搞得鬼。随便了。 现象是访问首页,展示错误信息,“建立数据库连接时出错”。诊断方法,我登录服务器,重启了 mysqld 服务和 php-fpm 服务,毕竟重启大法好,然后发现问题没有恢复。检查 php 配置文件,查看 mysqld 的服务端口,检查磁盘容量,基本没有什么异常现象。 尝试从 shell 直接登录 mysql,使用应用配置的用户名密码,竟然也完全正常,那么为什么就是连不上呢?然后我又到前台,访问了一下 wp-admin/ 目录,这时,展示了一个提示信息,告诉我数据库需要 repair。我摸不着头脑。 点了一下,提示我 repair 的方法,在 wp-config.php 文件中增加一行配置信息: 然后,刷新当前页面。我试了一下,果然出现了“修复数据库”,“修复并优化数据库”,我点击了后者,看到错误信息是,wp_options 表不知道怎么损坏了,原来 xx 行,现在 xx – 2 行。字面意思就是数据丢了两行。原因不详。 然后去前台刷新页面,熟悉的首页出来了。莫名奇妙。其实我最莫名其妙的,不是说这个东西会坏。而是我在同一台服务器上的三个博客,全挂了。死因完全一样,都是这个数据库建立连接时出错。 你说,三个博客各不相同,内容也不同,访问量也不同,怎么可能会死于完全相同的原因呢?访问压力什么的完全说不过去。黑客入侵也不像。所以,难道不是阿里云太垃圾么? 标签: WordPress
☑️ ☆

Shell 编程的备忘录

作为程序员工作十几年了,Shell 编程这项技能,就好像“你永远得不到的爸爸”一样,每次想用的时候,都觉得自己从来没学会过。本文的编写作为一篇学习笔记,或者一个备忘录,或者一个作弊小抄,我会在每次遇到的时候,不断前来添砖加瓦,说不定有朝一日,能有望凑成一本秘籍。虽然网上类似的内容很多了,但是那些终究是别人的东西,自己用着总是不得劲,所以,做笔记这项技能总是伴随着人类的发展。 内建变量 在大牛写好的脚本里,你是不是看到过$#,#@,等等符号,然后并不认识?关键是,这个系列的变量,长得都差不多,就好像白雪公主的七个小矮人,你总是分不清谁是谁。 这些变量叫做“内建变量”,Built-in Shell Variables,通过内建变量,我们可以方便地引用或者访问一些值。 变量 Variables 用途 Use $# 通过命令行传递给 shell 程序的参数的数量 $? 上一个执行的 shell 命令的 exit value,也即返回值 $0 当前执行命令的第一个字(word),通常是 shell 程序的名字 $* 当前执行命令的所有参数 $@ 当前执行命令的所有参数,每个参数用引号括起来 $- 显示shell使用的当前选项,与set命令功能相同 $! 当前 shell 的最后一个后台进程的 PID $$ 当前正在执行的进程的 PID 以上说明引用自这里,以及这里 参考 Shell Programming 标签: programming, shell
☑️ ⭐

git submodule 的应用

大家有没有发现,有些技术点,我们每次想用的时候,都不会用,然后学会了,用一次,又很久不用,然后到了要用的时候,又开始新一轮的循环。比如 git 的 submodule,对我来说就是这样一个技术点。 为什么使用 submodule? 完全一个人不可能写出来大型的软件项目,不得不站到巨人的肩膀上。另一个方面说,虽然,一个人可以开发出所有软件,但是万事万物都从零做起,也是比较笨拙的一种做法,君子善假于物,如果有人发明了很好的工具,那就应该尽量使用,尤其是在一些专业的领域里。 我常用的语言是 PHP,Python,Dart,这三种语言,在编写项目的时候,都有强大的包和依赖管理工具。比如,PHP 里面,可以使用 Composer,在 Python 里面,可以使用 pip,而在 Dart 里,可以用 pub 命令。 语言,或者框架层面提供的依赖管理,可以很好地解决 90% 以上的问题,非要将源代码引入到自己的项目里,而且不是以分发版本的形态,真的不多见,这也解释了我为什么每次用到 submodule 都不会用的原因,因为真的不常用。 我自己现在遇到的一个场景是这样的,我有个项目,叫 env,这个项目是我用来在一台服务器上初始化我自己常用的环境的一个项目。如果,是一台 Mac,我会安装 oh-my-zsh,然后,如果是 Linux 服务器,我会安装 bash-it(类 oh-my-zsh 的 bash 工具),为了配置 vim,还需要安装一个 vim-plug,有了这个工具,才能有效管理 vim 的依赖插件。 这三个工具,恰巧都是通过 github 来安装和管理的。env 是一个混合代码的项目,有 shell 脚本,python 脚本,vim 配置等等,而且刚提到的三个工具也不是某一种语言的包,所以,就自然而然用 submodule 来管理了。不知道你有没有那种非要用 submodule 管理的项目场景呢?希望能留言告诉我,让我也学习一下。 submodule 是什么? submodule 本质上是一个标准的 git … Continue reading git submodule 的应用
☑️ ☆

无法打开 PopClip 控制面板的问题

PopClip 是我非常喜欢也非常依赖的一个软件,属于 “润物细无声” 这个类目的软件。 软件的功能是,当你用鼠标选中一个文本的时候,弹出来一个浮动菜单,提供一系列的快捷小功能。缺省的功能有,搜索引擎,相当于划词搜索,还有字典查询,可以立刻激活系统的字典,还有拼写检查等。 除了这些基础的功能,还可以识别选中的文本的类型,提供一些特定的功能,比如拼写检查,链接跳转,文本翻译,总之,通过插件,扩展能力近乎是无限的,只要你能想到。 它还有一个小功能,算是一个非功能性需求,就是隐藏 Menu Bar 的图标,软件启动后,会在菜单栏显示一个小图标,可以激活控制面板。不过大家都知道,Mac 的菜单条是非常局促的,尤其是新版的电脑使用了刘海屏,菜单栏的位置更是不够用。隐藏了图标后,就可以节省一个位置。 不过我用了 2021 年生产的 M1 Macbook Pro,默认安装了 Monterey 后,就遇到一个问题,PopClip 的控制面板无法展示出来了。以前,隐藏了 Menu Bar 图标后,在 Applications 目录中,双击 PopClip 应用图标,就会临时在 Menu Bar 展示一次 PopClip 的图标,可以修改配置。现在,竟然怎么都找不到打开控制面板的方法了。软件功能倒是正常,就是无法修改配置。 在网上到处搜索,这个问题的解决,竟然很不好搜,因为这软件本来就是浮动菜单,涉及到现实隐藏的问题,我竟然耗费很长时间才找到了正确的搜索关键字。 This is something I need to look at because it has happened a few times to people on Monterey and above. What … Continue reading 无法打开 PopClip 控制面板的问题
☑️ ☆

Docker 常用操作的备忘录

从公有仓库拉取镜像: 查看本地的镜像: 删除一个本地镜像: 查看本地的所有容器: 给本地镜像打上一个 tag: 将镜像推送到私有仓库: 连接一个正在运行的 container: ⚠️ 注意:使用 Apple Silicon 的 MacBook Pro (M1/2) 时候,docker 命令,默认拉取的镜像,构建的镜像,都是 linux/arm64/v8 的,但是,服务器开发的运行环境往往是 linux/amd64 的,注意交叉编译的问题。 ADD 指令和 COPY 指令有什么异同? ADD 指令和 COPY 指令有一些重叠,都是将一个文件从源路径复制到目的路径。不过 ADD 指令会有更多的内涵。 如果源路径是一个网址的话,ADD 指令会下载文件,如果源路径是一个压缩包的话,ADD 指令会解压缩。 最佳实践里,建议尽量使用 COPY 指令而不是 ADD 指令,因为 COPY 指令有更明确的功能。 一般建议,在解压缩的场景使用 ADD 指令,其他场景都是用 COPY 指令。 ENTRYPOINT 和 CMD 有什么异同? 今天我在看 Docker Hub … Continue reading Docker 常用操作的备忘录
☑️ ☆

指令式编程和声明式编程

指令式编程,Imperative Programming,是一种编程泛型,通过编程指令,告诉计算机,每个步骤执行的命令,计算机按照代码的指令,逐行执行,就能得到最终结果。 指令式编程的优点是非常符合直觉,代码发出命令,计算机执行。所以,这种编程泛型也非常容易学习,我们入门学习的 C 语言,Java 语言等等,都是支持指令式编程的,也是这类语言的主要编程泛型。 面向对象编程,也是一种编程泛型,同时,面向对象编程泛型,也是一种指令式编程泛型的特例。所以,指令式编程,是一个更抽象的概念。 声明式编程,Declarative Programming,顾名思义,这种编程泛型,更倾向于告诉计算机,“是什么”,由计算机自行决定如何操作。 声明式编程是很不好理解的,因为有不少无法不言自明的东西。程序,只需要告诉计算机,两个不同的状态,怎么从一个状态,切换到另一个状态,计算机自动就可以完成补充。 比如我正在学习的 Flutter,这个框架在构建一个应用的界面的时候,比如要做一个功能是这样的,界面是一个按钮,点击后,可以隐藏界面的上的数字,切换成星号。 如果用指令式编程,我们可能会这样写(伪代码): 如果是声明式编程,我们可能是这样写: 在指令式编程泛型里,我们给 label 下达了一个命令,让其对内容进行隐藏。而在声明式编程里,我们告诉界面,根据 hide 这个标志决定,是显示星号,还是显示数字。而点击事件里,我们只是重新指定了 hide 的值。那么,界面上本来是 12345,是怎么变成 *** 的呢?代码里没有提及,你也不能期待,代码执行到某一行,界面上的数字就会变成星号。这些都是框架自行决定和调度的。 其实,我们不难想象,框架或者系统底层,肯定会有一个指令,在某个时间,告诉图形引擎,要把数字擦掉,重新绘制上星号,不过这些都跟写上层业务的程序员无关。所以,指令式编程泛型是根本,毕竟 CPU 终究机器代码,或者汇编指令来驱动的,不可能不回归到指令式编程泛型里。 声明式编程泛型,是比指令式编程泛型更高层级的方法论抽象。就好像,一个公司只描述公司的愿景是什么,至于怎么实现,就要从总裁到基层员工每个人努力工作,朝着目标努力,经过漫长时间才能做到。 使用声明式编程泛型,程序员的生产力可以更多地释放,编程效率也更高,但是显然,底层框架或者引擎,都会承担更多的工作,才能做到智能地在程序员声明的界面或者状态中间完成变化。 -完- 标签: flutter, Programming Paradigm
❌