<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Julian's Awesome Life]]></title><description><![CDATA[Thoughts, stories and ideas.]]></description><link>https://www.datarepo.cn/</link><image><url>http://www.datarepo.cn/favicon.png</url><title>Julian&apos;s Awesome Life</title><link>https://www.datarepo.cn/</link></image><generator>Ghost 3.11</generator><lastBuildDate>Tue, 10 Feb 2026 12:30:00 GMT</lastBuildDate><atom:link href="https://www.datarepo.cn/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[读《三体》]]></title><description><![CDATA[<p>听说三体是在它获得雨果奖之后，身边有很多人看，并且评价很好。当时我也看了几天，发现没有很吸引我的地方，就放下没有继续看了。今年六七月份听《晓说2017》，矮大紧用了四期来讲三体，引起了我再看下去的兴趣。断断续续用了两个多月时间终于把它看完，现在仍感觉意犹未尽。文中天马行空的想象，却不感觉虚无缥缈，跌宕起伏的剧情，又总能看到现实的影子。下面对我读后的感受进行简要的总结。</p><h2 id="-">科学与想象的融合</h2><p>三体三部曲一步步为我们勾勒出了作者想象中宇宙的样子。宇宙中存在着无数的文明，从三体文明到毁灭三体星系的文明，再到如“神”一般存在的“歌者”，他们的科技水平都远远高于地球。作者为这些文明制定了两条基本的宇宙社会学公理，“第一，生存是文明的第一需要；第二，文明不断增长和扩张，但宇宙中的物质总量保持不变”，同时还引入了两个重要的概念：猜疑链和技术爆炸。基于这两条公理和两个概念，推导出了宇宙中零道德的黑暗森林状态。为了实施黑暗森林打击，打击者不惜以试图毁灭所有其他文明为代价，让整个宇宙降低维度（打击者首先适应低维空间）。因为降维攻击的存在，作者预测了宇宙经过不断降维后的多种可能，并将一百多亿年前没有战争的“田园时代”定义为十维空间。至此，作者建立起了一个宏大的、能够自圆其说的宇宙框架，将无限的时空、无数的文明，</p>]]></description><link>https://www.datarepo.cn/2018/09/26/book-review-of-three-body/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55cf</guid><category><![CDATA[Reading]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Wed, 26 Sep 2018 05:58:16 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-three-body.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-three-body.jpg" alt="读《三体》"><p>听说三体是在它获得雨果奖之后，身边有很多人看，并且评价很好。当时我也看了几天，发现没有很吸引我的地方，就放下没有继续看了。今年六七月份听《晓说2017》，矮大紧用了四期来讲三体，引起了我再看下去的兴趣。断断续续用了两个多月时间终于把它看完，现在仍感觉意犹未尽。文中天马行空的想象，却不感觉虚无缥缈，跌宕起伏的剧情，又总能看到现实的影子。下面对我读后的感受进行简要的总结。</p><h2 id="-">科学与想象的融合</h2><p>三体三部曲一步步为我们勾勒出了作者想象中宇宙的样子。宇宙中存在着无数的文明，从三体文明到毁灭三体星系的文明，再到如“神”一般存在的“歌者”，他们的科技水平都远远高于地球。作者为这些文明制定了两条基本的宇宙社会学公理，“第一，生存是文明的第一需要；第二，文明不断增长和扩张，但宇宙中的物质总量保持不变”，同时还引入了两个重要的概念：猜疑链和技术爆炸。基于这两条公理和两个概念，推导出了宇宙中零道德的黑暗森林状态。为了实施黑暗森林打击，打击者不惜以试图毁灭所有其他文明为代价，让整个宇宙降低维度（打击者首先适应低维空间）。因为降维攻击的存在，作者预测了宇宙经过不断降维后的多种可能，并将一百多亿年前没有战争的“田园时代”定义为十维空间。至此，作者建立起了一个宏大的、能够自圆其说的宇宙框架，将无限的时空、无数的文明，以及文明在宇宙中的生存发展状态囊括其中。</p><p>作者构建的宇宙基于上述假设并融合了大量的想象，而这些想象又建立在牢固、全面而综合的知识大厦上。从物理学到宇宙学，从心理学到社会学，从脑科学到信息学等等，大量的知识细节十分真实和严密，依托的现代科技和社会现象更让人感到真实感。作者几乎对每一个新技术、新概念，以及事件发生的合理性给出了解释，如三体使用“智子”监控地球的实现原理、“思想钢印”的原理、对“光粒”预警时间的解释、曲率驱动飞船的驱动原理等等，在故事发展中，作者通过一系列的铺垫将读者引入到设计好的陷阱中，并结合作者对人性的理解，构造出一个个出人意料又合乎情理的结局。此外，就宇宙社会学的两条公理来说，假使将宇宙映射为地球或生存环境，将宇宙文明映射为地球中的国家或组织，在一定程度上也适用于人类社会。并由此可推导出一系列的结论，如：没有永远的朋友，只有永远的利益；落后就要挨打；闭关锁国将受到他国侵犯等。</p><p>每个人都有想象宇宙的权利。在三体中，作者描绘了他心中的宇宙，多文明、多维空间、充满黑暗的斗争，作者怀着巨大的勇气质疑我们世界的科学规律，认为它们不过是宇宙斗争到现阶段的产物，恒定的光速会不断降低，数学定律也可能被打破。作者将科学与极限的想象完美融合，让人拍案叫绝。</p><h2 id="--1">‌‌生命与人生观的依存</h2><p>三体在发现和了解了地球文明后，决定从生存条件残酷的三体星系向地球移民，并向地球发送了使用量子技术控制的“智子”，通过改变地球中高能粒子对撞的结果，影响前沿物理学的基础实验，防止经过四百地球年的星际航行后，三体舰队难以对抗人类社会因为“技术爆炸”发展的科技。技术封锁使得“地球人对微观维度的控制，被限制在五维以下”，粒子物理、量子力学、材料科学等众多科学领域无法发展。同时还有一个现象不能忽视，那就是大量的理论物理科学家也被这种封锁摧毁了，有些甚至选择了自杀。</p><p>“超弦模型”的提出者杨冬在她的遗书中写到：“一切的一切都导向这样一个结果：物理学从来就没有存在过，将来也不会存在。我知道自己这样做是不负责任的，但别无选择”。是的，她还有什么选择呢？一个将毕生的精力都放在物理学上的人，突然有一天她发现，她学习的、探索的这些物理规律竟然在时空上不是均匀分布的，相当于1+1=2在中国成立，在美国却不成立，这是怎样的可笑与荒谬。对于这些物理学家来说，物理学是他们思想世界的重要组成部分，是搭建起他们人生观的重要基石，而这时，这个基石动摇了、破碎了，导致的结果只能是人生观的轰然倒塌。胡适先生说人生观是对人生这场戏的看法；唐擘黄先生说人生观是一个人对于世界万物同人类的态度。当一个人的人生观倒塌了，也就是对于人生和世间万物的原有观念不成立了，这对一个人是怎样的催残，这时，离开这个世界或许是最轻松的选择。</p><h2 id="--2">‌‌道德与生存的矛盾</h2><p>三体故事中出现了多次地球文明生死存亡的时刻。当死亡的威胁来自未来时，大多数的人类寄希望于领导者出谋划策。但每个人等待的都是自己的出路，逃亡计划、光速飞船计划等等这些只能让部分人活下去的计划，都在民众舆论的压力下被法律禁止了。而当死亡的威胁就在眼前时，保命几乎是所有人的第一反应。这种反应超过了理智，也盖过了道德，就像在“假警报”响起后，人们奋不顾身的冲向发射台，挤进穿梭机，其实大家都知道，收到警报就是收到了死亡的信号，即使上了穿梭机也难逃死亡的命运。更严重的是，人们在人群中启动发射穿梭机，而不顾被烧成了焦炭的人群。</p><p>生命权是人的基本人权，人们可以允许因为身份、地位、财富的不同而过不同的生活，但不允许出现在死亡面前的不平等。在追求自由、民主、平等的人类社会中，面对死亡时的这种现象几乎是必然的，于是当太阳系被“二向箔”攻击时，人们乘着远远达不到逃逸速度（光速）的飞船妄想逃亡，当看到光速飞船时，人们的反应不是庆幸人类没有灭绝，而是狰狞着企图拦截光速飞船。作者无情的披露着这种社会现象，又将宇宙中科技高度发达的文明定义为零道德的。似乎作者对想象中的未来充满了悲观的预测，于是外太空中幸存的战舰之间发生了黑暗战役，同伴间为了生存进行自相残杀，而这种从地球人到宇宙人的转变仅仅只需要五分钟。但是作者终究是现代的地球人，他多次让人类的代表程心在生存与道德之间选择，而她都“幼稚”得选择了道德。因为这些选择，绝大多数的人类都随着太阳系的毁灭而死亡，但程心作为地球人活了下来，并在最后为了大宇宙可能的美好未来，放弃了安逸的小宇宙生活。作者最终选择了责任，选择了道德，选择了宇宙中那个大写的人。</p><h2 id="--3">无知与傲慢的可悲</h2><p>在作者描述的宇宙中，人类是何等的弱小。就像“射手假说”中的二维智能生物和“农场主假说”中的火鸡一样，人类科学家发现的定律、现象，可能只是更高等的生物给我们开的玩笑罢了，而人类以为掌握了真理。当人类第一次与三体文明的物质实体-水滴-进行接触时，因为拥有星际战舰而信心爆棚的人类以为这是三体发送过来和谈的礼物，却不知人类的太空力量即将面临灭顶之灾；当人类为黑暗森林打击做准备时，不顾从云天明故事中分析出的曲率驱动飞船和降低光速计划，认为掩体计划足够让人类永远的生存下去，却不知整个太阳系将会在三维世界消失。</p><p>从前的弱小和无知虽然限制了人类对科学的探索能力，但能够在宇宙中隐藏自己，可是傲慢却成为生存的障碍。作者怀着对人类聪明才智的充分肯定，描绘出科技不断发展进步的未来世界，但是远离了无知却走近了傲慢，带来的是人类在其他文明面前的绝望。作者充满了对宇宙的敬畏之心，无情的揭示了人类的傲慢是多么可悲的一件事。同时，作者用一个一个故事告诉我们，历史留给人类的教训是：人类永远不接受教训。</p><p>三体系列描述了作者对宇宙、对道德、对诗的理解，也推动着我们建立起自己的理解和思考。</p>]]></content:encoded></item><item><title><![CDATA[使用Docker运行Snort3和OpenAppID]]></title><description><![CDATA[<p><a href="https://www.snort.org/">Snort</a>一款开源的网络入侵防御系统（IPS），可以实时分析和记录网络数据包。由Cisco在2013年将其收购，收购后对其源代码进行了重写，发布了Snort3或称Snort++版，带来很多<a href="https://www.snort.org/downloads/snortplus/snort_manual.html">新的特性</a>。Cisco于2014年发布了<a href="https://blogs.cisco.com/security/cisco-announces-openappid-the-next-open-source-game-changer-in-cybersecurity">OpenAppID</a>，作为一个Snort中用于应用识别的组件。根据官方教程，对Snort3源码进行编译较为繁琐，本文介绍使用Docker快速运行Snort3和OpenAppID的方法。</p><h2 id="-">获取镜像</h2><p>可通过如下命令下载Snort3 with OpenAppID的容器镜像：</p><pre><code>$ docker pull traceflight/snort3-with-openappid-docker</code></pre><p>其中的镜像为根据我的<a href="https://github.com/traceflight/snort3-with-openappid-docker">Github项目</a>中编写的Dockerfile文件构造而来，其中的组件和版本见下表。</p><!--kg-card-begin: html--><style>
.post-full-content table th:first-of-type {
    width: 100%;
}
.post-full-content table th:last-of-type{
    width: 100%;
}
</style><!--kg-card-end: html--><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th style="text-align:left">组件</th>
<th style="text-align:left">版本</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">snort</td>
<td style="text-align:left">3.0.0</td>
</tr>
<tr>
<td style="text-align:left">daq</td>
<td style="text-align:left">2.2.2</td></tr></tbody></table>]]></description><link>https://www.datarepo.cn/2018/08/29/use-snort3-with-openappid-in-docker/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55ce</guid><category><![CDATA[Technology]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Information Security]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Wed, 29 Aug 2018 13:25:12 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-snort3-in-docker.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-snort3-in-docker.jpg" alt="使用Docker运行Snort3和OpenAppID"><p><a href="https://www.snort.org/">Snort</a>一款开源的网络入侵防御系统（IPS），可以实时分析和记录网络数据包。由Cisco在2013年将其收购，收购后对其源代码进行了重写，发布了Snort3或称Snort++版，带来很多<a href="https://www.snort.org/downloads/snortplus/snort_manual.html">新的特性</a>。Cisco于2014年发布了<a href="https://blogs.cisco.com/security/cisco-announces-openappid-the-next-open-source-game-changer-in-cybersecurity">OpenAppID</a>，作为一个Snort中用于应用识别的组件。根据官方教程，对Snort3源码进行编译较为繁琐，本文介绍使用Docker快速运行Snort3和OpenAppID的方法。</p><h2 id="-">获取镜像</h2><p>可通过如下命令下载Snort3 with OpenAppID的容器镜像：</p><pre><code>$ docker pull traceflight/snort3-with-openappid-docker</code></pre><p>其中的镜像为根据我的<a href="https://github.com/traceflight/snort3-with-openappid-docker">Github项目</a>中编写的Dockerfile文件构造而来，其中的组件和版本见下表。</p><!--kg-card-begin: html--><style>
.post-full-content table th:first-of-type {
    width: 100%;
}
.post-full-content table th:last-of-type{
    width: 100%;
}
</style><!--kg-card-end: html--><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th style="text-align:left">组件</th>
<th style="text-align:left">版本</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">snort</td>
<td style="text-align:left">3.0.0</td>
</tr>
<tr>
<td style="text-align:left">daq</td>
<td style="text-align:left">2.2.2</td>
</tr>
<tr>
<td style="text-align:left">snort extra</td>
<td style="text-align:left">1.0.0</td>
</tr>
<tr>
<td style="text-align:left">openappid</td>
<td style="text-align:left">8373</td>
</tr>
<tr>
<td style="text-align:left">rules</td>
<td style="text-align:left">community</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><h2 id="--1">监听主机网卡</h2><p>首先获取待监听网卡名称：</p><pre><code>$ ip a</code></pre><p>使用docker的host模式监听指定网卡（假设为eth0），挂载本地路径（/var/log/snort）存放日志信息：</p><pre><code>$ docker run -it --name snort --net=host \
    --cap-add=NET_ADMIN \
    -v /var/log/snort/:/var/log/snort/ \
    traceflight/snort3-with-openappid-docker \
    snort -c /usr/local/etc/snort/snort.lua \
    -A fast \
    -l /var/log/snort \
    -i eth0</code></pre><h2 id="-pcap-">分析Pcap数据</h2><p>假设待分析的数据位于本机的/home/snort/data/文件夹中，运行snort挂载待分析文件，并对其进行分析。</p><pre><code>$ docker run -it --rm -v /home/snort/data:/data \     
    -v /var/log/snort/:/var/log/snort/ \
    traceflight/snort3-with-openappid-docker \
    snort -c /usr/local/etc/snort/snort.lua \
    -A fast \ 
    -l /var/log/snort \
    -r /data/pcapfile.pcap</code></pre><h2 id="--2">修改配置和规则</h2><p>对规则和配置进行修改，需要挂载相应文件到镜像中，规则和配置文件的结构可参考我的<a href="https://github.com/traceflight/snort3-with-openappid-docker">Github项目</a>。首先clone项目代码，获取文件夹结构，并在此基础上进行后续修改。</p><pre><code>$ git clone https://github.com/traceflight/snort3-with-openappid-docker.git</code></pre><h3 id="--3">自定义应用检测器</h3><p>将自定义检测脚本放置在custom/lua文件夹中，然后重新build容器或挂载custom文件夹到/usr/local/etc/snort/appid/文件夹中。</p><h3 id="--4">使用自定义规则</h3><p>配置文件和规则文件分别放置在项目中etc和rules文件夹内，添加自定义规则步骤如下：</p><ul><li>创建规则</li></ul><p>在rules/rules文件夹内创建规则文件local.rules。</p><ul><li>修改配置</li></ul><p>在etc/snort.lua配置文件中第6个部分（6. configure detection）中的rules变量内添加一行规则包含语句。</p><pre><code>include $RULE_PATH/local.rules</code></pre><ul><li>挂载文件 </li></ul><p>运行时挂载</p><pre><code>$ docker run -it -v `pwd`/etc/snort.lua:/usr/local/etc/snort/snort.lua \
    -v `pwd`/rules/:/usr/local/etc/snort/rules/ \
    traceflight/snort3-with-openappid-docker /bin/bash</code></pre><p>或创建Dockerfile生成新的镜像</p><pre><code>FROM traceflight/snort3-with-openappid-docker:latest
MAINTAINER yourname
ADD etc/snort.lua /usr/local/etc/snort/
ADD rules /usr/local/etc/snort/rules
RUN snort -V</code></pre><h3 id="-snort-">使用snort注册版规则</h3><p>在snort官方注册后，可下载注册版规则。将规则文件解压缩后，放在本项目对应文件夹中，然后修改etc/snort.lua文件中的appid变量值，指定appid路径。最后将文件夹挂载到路径下即可。</p><pre><code>appid =
{
    -- appid requires this to use appids in rules
    app_detector_dir = '/usr/local/snort/appid',
}</code></pre><h2 id="--5">使用中可能出现错误提示</h2><p><strong>ERROR: Cannot decode data link type 113</strong></p><p>原因：libpcap在对Linux进行抓包时，若对any接口进行抓包，使用的格式为<a href="https://wiki.wireshark.org/SLL">Linux cooked-mode capture (SLL)</a>，snort不支持该格式。</p><p>解决方法：不对any接口进行抓包，对指定接口如eth0抓包即可。</p><p><strong>SIOETHTOOL(ETHTOOL_GUFO) ioctl failed: Operation not permitted</strong></p><p>原因：容器对监听本地网卡的权限不足。</p><p>解决方法：在docker运行时，添加参数`--cap-add=NET_ADMIN`。</p>]]></content:encoded></item><item><title><![CDATA[憩息肩头，栖息心头]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>当你看到这篇文章的时候，一定已经是七夕了。</p>
<p>算下来，我们谈恋爱到今天刚好过了500天。500天的时间不长不短，说它不长是因为也就一年多的时间，这不过是我们美好生活的几十分之一，在我们携手的漫长人生道路上，仅仅迈出了第一步。说它不短是因为这500天的时间里，经历了太多值得纪念和怀念的时刻，如果把纪怀的时间也算作这500天的延续，那将会是一辈子的时间。</p>
<p>我期待着和你走过后面的每一个500天，期待着我对你的每一个承诺实现时的快乐，期待生活中的每一次惊喜，也期待着点点滴滴的甜蜜。承诺很多，但宗旨只有一个，愿我的肩头是你劳累时的憩息，我的心头是你永远的归宿。</p>
<p>情长纸短，吻你万千。</p>
<!--kg-card-end: markdown-->]]></description><link>https://www.datarepo.cn/2018/08/16/chinese-valentines-day/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55cd</guid><category><![CDATA[Life]]></category><category><![CDATA[Sweet Time]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Thu, 16 Aug 2018 14:27:16 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/blog-chinese-valentines-day.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/blog-chinese-valentines-day.jpg" alt="憩息肩头，栖息心头"><p>当你看到这篇文章的时候，一定已经是七夕了。</p>
<p>算下来，我们谈恋爱到今天刚好过了500天。500天的时间不长不短，说它不长是因为也就一年多的时间，这不过是我们美好生活的几十分之一，在我们携手的漫长人生道路上，仅仅迈出了第一步。说它不短是因为这500天的时间里，经历了太多值得纪念和怀念的时刻，如果把纪怀的时间也算作这500天的延续，那将会是一辈子的时间。</p>
<p>我期待着和你走过后面的每一个500天，期待着我对你的每一个承诺实现时的快乐，期待生活中的每一次惊喜，也期待着点点滴滴的甜蜜。承诺很多，但宗旨只有一个，愿我的肩头是你劳累时的憩息，我的心头是你永远的归宿。</p>
<p>情长纸短，吻你万千。</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Let's Encrypt通配符证书申请方法]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Let's Encrypt于2018年3月14日在社区宣布支持通配符证书（Wildcard certificates）。</p>
<ul>
<li><a href="https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579">ACME v2 and Wildcard Certificate Support is Live</a></li>
<li><a href="https://community.letsencrypt.org/t/acme-v2-production-environment-wildcards/55578">ACME v2 Production Environment &amp; Wildcards</a></li>
</ul>
<p>通配符证书可以使同一域名下的所有子域名使用同一个证书，对于拥有大量域名的用户来说，大大减少了证书申请和维护工作。下面简要介绍Let's Encrypt通配符证书的申请方法。</p>
<h2 id>证书申请</h2>
<p>Let's Encrypt使用<a href="https://tools.ietf.org/html/draft-ietf-acme-acme-07">ACME协议</a>验证域名所有权并分配证书，为申请证书首先需要选取实现ACME协议的客户端。</p>
<p>Let's Encrypt证书申请时，需要验证域名的所有权，官方支持三种验证方式：</p>
<ul>
<li><a href="https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.2">http-01</a>: 在域名对应的 Web 服务器下放置一个 HTTP well-known URL 资源文件。</li>
<li><a href="https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3">tls-sni-01</a>: 在域名对应的 Web 服务器下放置一个 HTTPS well-known URL 资源文件。</li>
<li><a href="https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.4">dns-01</a></li></ul>]]></description><link>https://www.datarepo.cn/2018/08/11/usage-of-letsencrypt-wildcard-certificates/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55cb</guid><category><![CDATA[Technology]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Sat, 11 Aug 2018 03:31:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-letsencrypt-wildcard-certificates.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-letsencrypt-wildcard-certificates.jpg" alt="Let's Encrypt通配符证书申请方法"><p>Let's Encrypt于2018年3月14日在社区宣布支持通配符证书（Wildcard certificates）。</p>
<ul>
<li><a href="https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579">ACME v2 and Wildcard Certificate Support is Live</a></li>
<li><a href="https://community.letsencrypt.org/t/acme-v2-production-environment-wildcards/55578">ACME v2 Production Environment &amp; Wildcards</a></li>
</ul>
<p>通配符证书可以使同一域名下的所有子域名使用同一个证书，对于拥有大量域名的用户来说，大大减少了证书申请和维护工作。下面简要介绍Let's Encrypt通配符证书的申请方法。</p>
<h2 id>证书申请</h2>
<p>Let's Encrypt使用<a href="https://tools.ietf.org/html/draft-ietf-acme-acme-07">ACME协议</a>验证域名所有权并分配证书，为申请证书首先需要选取实现ACME协议的客户端。</p>
<p>Let's Encrypt证书申请时，需要验证域名的所有权，官方支持三种验证方式：</p>
<ul>
<li><a href="https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.2">http-01</a>: 在域名对应的 Web 服务器下放置一个 HTTP well-known URL 资源文件。</li>
<li><a href="https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3">tls-sni-01</a>: 在域名对应的 Web 服务器下放置一个 HTTPS well-known URL 资源文件。</li>
<li><a href="https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.4">dns-01</a>: 给域名添加一个 DNS TXT 记录。</li>
</ul>
<p>申请Let's Encrypt通配符证书需要注意的事情如下：</p>
<ul>
<li>必须使用dns-01验证方法。</li>
<li>必须使用支持ACME v2版本的客户端。</li>
<li>需要指定server路径: <a href="https://acme-v02.api.letsencrypt.org/directory">https://acme-v02.api.letsencrypt.org/directory</a></li>
<li>*.example.com不包含example.com，需分别申请。</li>
<li>*.example.com和www.example.com 不可同时申请，因为前者已包含后者。</li>
</ul>
<p>官方给出了<a href="https://letsencrypt.org/docs/client-options/#acme-v2-compatible-clients">支持ACME v2的客户端列表</a>，本文选取官方推荐的客户端<a href="https://certbot.eff.org">Certbot</a>，并使用Docker环境申请证书。</p>
<p>假设证书在本地的存放位置为<code>letsencrypt</code>文件夹，日志存放位置为<code>log</code>文件夹，执行如下命令申请证书：</p>
<pre><code>$ docker run -it --rm \
  -v path/to/letsencrypt/:/etc/letsencrypt/  \
  -v path/to/log/:/var/log/letsencrypt/ \
  certbot/certbot:v0.26.1 \
    certonly \
   --email your@email.com \
   --agree-tos \
   --manual \
   --preferred-challenges dns-01 \
   --server https://acme-v02.api.letsencrypt.org/directory \
   -d *.yourdomain.com \
   -d yourdomain.com
</code></pre>
<p>替换其中的邮件和域名，运行后根据提示为域名添加DNS TXT记录，以验证域名所有权。生成的证书存放在本地<code>letsencrypt</code>文件夹中。</p>
<h2 id>证书使用</h2>
<p>申请的证书保存在<code>letsencrypt/live/youdomain.com</code>文件夹下，其中四个文件的说明如下：</p>
<ul>
<li><code>privkey.pem</code>  : 证书私钥。</li>
<li><code>fullchain.pem</code>: 大多数服务器使用的证书文件。</li>
<li><code>chain.pem</code>    : 用于OCSP stapling（Nginx &gt;=1.3.7）。</li>
<li><code>cert.pem</code>     : 在进一步阅读<a href="https://certbot.eff.org/docs/using.html#where-are-my-certificates">相关文档</a>前不要使用。</li>
</ul>
<p>以Nginx服务器为例，在其配置文件中添加如下配置：</p>
<pre><code>ssl on;
ssl_certificate path/to/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key path/to/letsencrypt/live/yourdomain.com/privkey.pem;
</code></pre>
<h2 id>证书更新</h2>
<p>证书的有效期为90天，在到期前需要手动进行更新，Certbot中可使用<code>renew</code>对申请的证书进行更新，可执行命令如下：</p>
<pre><code>$ docker run -it --rm \
  -v path/to/letsencrypt/:/etc/letsencrypt/  \
  -v path/to/log/:/var/log/letsencrypt/ \
  certbot/certbot:v0.26.1 \
    renew
</code></pre>
<p>当证书有效期小于30天时，该命令会对证书进行更新。为防止手动更新的麻烦，可创建脚本文件<code>certbotrenew.sh</code>如下：</p>
<pre><code>#!/bin/bash
$ docker run -it --rm \
  -v path/to/letsencrypt/:/etc/letsencrypt/  \
  -v path/to/log/:/var/log/letsencrypt/ \
  certbot/certbot:v0.26.1 \
    renew
</code></pre>
<p>若使用的服务器为Nginx，在证书更新完成后，服务器不会自动加载证书，需要重启服务器。可创建crontab计划任务，定期执行脚本检查证书，若证书更新后（通过文件修改时间判断）自动重启服务器。脚本文件(checkservice.sh)如下：</p>
<pre><code>#!/bin/bash
timestamp=`date`
echo $timestamp &quot;====renew certbot====&quot; &gt;&gt; path/to/renew.log
path/to/certbotrenew.sh
modifytime=`stat -c %Y path/to/letsencrypt/live/datarepo.cn/fullchain.pem`
nowtime=`date +%s`
if [ $[ $nowtime-$modifytime ] -lt 1800 ]; then
  echo $timestamp &quot;====restart nginx====&quot; &gt;&gt; path/to/renew.log
  path/to/restartnginx.sh
else
  echo $timestamp &quot;====no need to restart====&quot; &gt;&gt; path/to/renew.log
</code></pre>
<p><em>其中<code>restartnginx.sh</code>为重启Nginx服务器的命令。</em></p>
<p>创建crontab计划任务，每周五0点0分执行checkservice.sh。</p>
<pre><code>0 0 * * 5 path/to/checkservice.sh
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[常见开发资源国内加速方法]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>当前主流的软件开发相关资源都保存在国外的服务器中，由于这样或那样的原因，国内开发者在使用某些资源时，存在难以访问或访问较慢的现象，下面总结了一些实际遇到的访问较慢的资源，及对应加速方法。后续如再遇到新的问题，将更新在这里。</p>
<h2 id="linux">Linux软件源</h2>
<p>Linux换用国内软件源后，能够大大提高软件安装速度，下面介绍Ubuntu和Centos使用<a href="https://opsx.alibaba.com/mirror">阿里源</a>的方法。</p>
<h3 id="ubuntu">ubuntu</h3>
<p><strong>图形界面配置</strong><br>
依次选择：系统设置 -&gt; 软件和更新 选择下载服务器 -&gt; &quot;mirrors.aliyun.com&quot;<br>
<strong>手动更改</strong><br>
备份原软件源文件：</p>
<pre><code class="language-shell"># cp /etc/apt/sources.list /etc/apt/sources.list.bak
</code></pre>
<p>使用编辑器打开文件：/etc/apt/sources.list</p>
<pre><code class="language-shell"># vi /etc/apt/sources.</code></pre>]]></description><link>https://www.datarepo.cn/2018/08/05/speed-up-programming-resources/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55ca</guid><category><![CDATA[Technology]]></category><category><![CDATA[Resource]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Sun, 05 Aug 2018 03:30:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-speedup-resource.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-speedup-resource.jpg" alt="常见开发资源国内加速方法"><p>当前主流的软件开发相关资源都保存在国外的服务器中，由于这样或那样的原因，国内开发者在使用某些资源时，存在难以访问或访问较慢的现象，下面总结了一些实际遇到的访问较慢的资源，及对应加速方法。后续如再遇到新的问题，将更新在这里。</p>
<h2 id="linux">Linux软件源</h2>
<p>Linux换用国内软件源后，能够大大提高软件安装速度，下面介绍Ubuntu和Centos使用<a href="https://opsx.alibaba.com/mirror">阿里源</a>的方法。</p>
<h3 id="ubuntu">ubuntu</h3>
<p><strong>图形界面配置</strong><br>
依次选择：系统设置 -&gt; 软件和更新 选择下载服务器 -&gt; &quot;mirrors.aliyun.com&quot;<br>
<strong>手动更改</strong><br>
备份原软件源文件：</p>
<pre><code class="language-shell"># cp /etc/apt/sources.list /etc/apt/sources.list.bak
</code></pre>
<p>使用编辑器打开文件：/etc/apt/sources.list</p>
<pre><code class="language-shell"># vi /etc/apt/sources.list
</code></pre>
<p>将其中的<code>archive.ubuntu.com</code>替换为<code>mirrors.aliyun.com</code>，在vi编辑器中可使用如下命令：</p>
<pre><code class="language-shell">:%s#archive.ubuntu.com#mirrors.aliyun.com#g
</code></pre>
<p>然后保存文件，并运行如下命令更新资源：</p>
<pre><code class="language-shell"># apt update
</code></pre>
<h3 id="centos">Centos</h3>
<p>以Centos7为例，首先备份原软件源文件：</p>
<pre><code class="language-shell"># mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
</code></pre>
<p>下载新的资源文件：</p>
<pre><code class="language-shell"># wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
</code></pre>
<p>更新缓存：</p>
<pre><code class="language-shell"># yum makecache
</code></pre>
<h2 id="docker">Docker镜像</h2>
<p>使用阿里云容器加速器，首先注册阿里云帐号，然后在加速器页面<a href="https://cr.console.aliyun.com/#/accelerator">https://cr.console.aliyun.com/#/accelerator</a> 中获取加速器地址，并按照官方提示进行配置。CentOS和Ubuntu的配置方法如下：</p>
<pre><code>$ sudo mkdir -p /etc/docker
$ sudo tee /etc/docker/daemon.json &lt;&lt;-'EOF'
{
  &quot;registry-mirrors&quot;: [&quot;https://xxxxxxxx.mirror.aliyuncs.com&quot;]
}
EOF
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
</code></pre>
<h2 id="npm">NPM源</h2>
<p>可使用淘宝NPM镜像代替官方版本。安装cnpm命令行工具代替npm：</p>
<pre><code>$ npm install -g cnpm --registry=https://registry.npm.taobao.org
</code></pre>
<h2 id="pip">pip源</h2>
<p>以使用阿里源为例，使用如下命令创建配置文件即可：</p>
<pre><code>$ mkdir ~/.pip
$ tee ~/.pip/pip.conf &lt;&lt;- 'EOF'
[global]
index-url = https://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
EOF
</code></pre>
<h2 id="github">Github</h2>
<p>在使用git clone命令下载github中的项目时，可能会遇到下载速度超级慢的情况，可使用修改Host文件方式，指定<code>github.com</code>和<code>github.global.ssl.fastly.net</code>两个域名的IP地址，以提高访问速度。<br>
<code>github.com</code>和<code>github.global.ssl.fastly.net</code>对应的IP地址可在<a href="https://www.ipaddress.com/dns-lookup">IPAddress.com</a>中查询，当前两个域名对应的IP地址为<code>192.30.253.112</code>和<code>151.101.113.194</code>，因此在<code>/etc/hosts</code>文件中，追加两条记录：</p>
<pre><code>192.30.253.112 github.com
151.101.113.194 github.global.ssl.fastly.net
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[待办事项/时间管理软件初步使用]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>时间是上天给每个人最公平的财富，每个人的资源总量都差不多，但是如果你不珍惜它就会离你而去。总觉得自己还是个毛头小子，转眼间竟已快到而立之年，人生也有了另一半的陪伴。责任愈大压力愈重，越发觉得生活需要计划，人生需要规划。最近尝试使用时间管理软件，下面总结一下使用的体会。</p>
<h2 id>理论方法</h2>
<p>通过搜集资料，遵循如下的事项/时间管理方法：</p>
<h4 id>两分钟原则</h4>
<p>任何事情如果花的时间少于两分钟，那么马上就去做，否则将其记录在待办事项中。两分钟是一个分水岭，这样的时间和正式地推迟一个动作所花的时间差不多。</p>
<h4 id="gtd"><a href="https://en.wikipedia.org/wiki/Getting_Things_Done">GTD</a></h4>
<p>由<a href="https://en.wikipedia.org/wiki/David_Allen_(author)">David Allen</a>于2001年发表的《Getting Things Done》一书中提出的时间管理方法。在这本书的第一版中主要流程为： 搜集（collect）、处理（process）、组织（organize）、计划（plan）和执行（do）。具体流程如下图所示：<br>
<img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-GTDcanonical.png" alt="GTDcanonical"><br>
后来将五个阶段重新定义为：获取（capture）、阐明（clarify）、组织（organize）、回顾（</p>]]></description><link>https://www.datarepo.cn/2018/08/04/time-management-app-usage-experience/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c9</guid><category><![CDATA[Life]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Sat, 04 Aug 2018 03:29:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-time-management.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-time-management.jpg" alt="待办事项/时间管理软件初步使用"><p>时间是上天给每个人最公平的财富，每个人的资源总量都差不多，但是如果你不珍惜它就会离你而去。总觉得自己还是个毛头小子，转眼间竟已快到而立之年，人生也有了另一半的陪伴。责任愈大压力愈重，越发觉得生活需要计划，人生需要规划。最近尝试使用时间管理软件，下面总结一下使用的体会。</p>
<h2 id>理论方法</h2>
<p>通过搜集资料，遵循如下的事项/时间管理方法：</p>
<h4 id>两分钟原则</h4>
<p>任何事情如果花的时间少于两分钟，那么马上就去做，否则将其记录在待办事项中。两分钟是一个分水岭，这样的时间和正式地推迟一个动作所花的时间差不多。</p>
<h4 id="gtd"><a href="https://en.wikipedia.org/wiki/Getting_Things_Done">GTD</a></h4>
<p>由<a href="https://en.wikipedia.org/wiki/David_Allen_(author)">David Allen</a>于2001年发表的《Getting Things Done》一书中提出的时间管理方法。在这本书的第一版中主要流程为： 搜集（collect）、处理（process）、组织（organize）、计划（plan）和执行（do）。具体流程如下图所示：<br>
<img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-GTDcanonical.png" alt="待办事项/时间管理软件初步使用"><br>
后来将五个阶段重新定义为：获取（capture）、阐明（clarify）、组织（organize）、回顾（reflect）、执行（engage）。<br>
<strong>获取</strong>：收集说有需要引起注意的事项。<br>
<strong>阐明</strong>：判断收集的事项是否可执行（actionable），如果不可执行则删除该事项；如果可执行，判断下一步行动能否在2分钟内完成，如果能完成则立即执行，否则若可以指派他人办理则指派他人，其余放置在待办事项中。<br>
<strong>组织</strong>：对待办事项进行分类，如：待打电话、待发邮件、待办差事等。<br>
<strong>回顾</strong>：经常对待办事项进行回顾。<br>
<strong>执行</strong>：按照计划采取适当的方法去做。</p>
<h4 id>四象限法</h4>
<p>四象限法则是时间管理理论的一个重要观念，应有重点地把主要的精力和时间集中地放在处理那些重要但不紧急的工作上，这样可以做到未雨绸缪，防患于未然，四象限分类如下图所示：<br>
<img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-four-quadrant.jpg" alt="待办事项/时间管理软件初步使用"></p>
<h4 id><a href="https://en.wikipedia.org/wiki/Pomodoro_Technique">番茄工作法</a></h4>
<p>番茄工作法（Pomodoro Technique）是二十世纪八十年代末由Francesco Cirillo提出的一种时间管理方法。该方法使用一个定时器来分割出一个一般为25分钟的工作时间和5分钟的休息时间，而那些时间段被称为pomodori，为意大利语单词 pomodoro（中文：番茄）的复数。<br>
番茄工作法有五个基本步骤：</p>
<ol>
<li>决定待完成的任务</li>
<li>设定番茄工作法定时器至 n 分钟（通常为25分钟）。</li>
<li>持续工作直至定时器提示,记下一个x。</li>
<li>短暂休息3-5分钟。</li>
<li>每四个x，休息15-30分钟。</li>
</ol>
<h2 id>软件选择</h2>
<p>为了实践这些管理方法，需要查找具有相应功能的软件。主要的功能包括：</p>
<ul>
<li>能够添加待办事项（todo）</li>
<li>能够添加重复事项</li>
<li>能够设置提醒</li>
<li>能够对待办事项进行四象限分类</li>
<li>能够支持番茄工作法</li>
<li>支持跨设备同步（移动终端、网页）</li>
</ul>
<p>通过搜集试用相关的时间管理软件，发现功能较为完备的主要为<a href="https://www.pomotodo.com/">番茄土豆</a>和<a href="http://qmrc.037622.com/">奇妙日程</a>两个软件。两个软件的简单对比如下：<br>
<strong>番茄土豆</strong><br>
优点：界面简洁、美观，使用方便、易于上手，用户量大、服务稳定，支持添加标签，跨平台支持好。<br>
缺点：四象限需手动添加标签进行分类，部分功能需要付费使用，如子任务、设置提醒。<br>
<strong>奇妙日程</strong><br>
优点：功能丰富，原生支持四象限分类，预设待办事项类别，支持设置重复事项，具有每日回顾功能。<br>
缺点：用户量相对小，网页版体验较差，存在服务不稳定的风险。</p>
<p>为了有效将相关理论付诸实践，最后我选择了功能较为丰富的奇妙日程软件。</p>
<h2 id>一周使用体验</h2>
<p>一周使用下来，对我的主要影响如下：</p>
<ul>
<li>减轻了我的拖延症。将拖了几周的事情记录下来并制定计划后，按时完成了这些事情。</li>
<li>提高了做事的专注度。由于待办事项都记录在软件中，在按照计划做事时，头脑能够专注于当前在做的事情。</li>
</ul>
<p>希望今后能够坚持使用，用科学的理论方法指导实践。</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[恋爱一周年]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>今天是我们恋爱一周年的纪念日，这一年我们经历了很多，学业、工作和生活都掀开了新的篇章。一切都那么快，又那么自然，生活的酸甜苦辣我们一起品尝，人生的喜怒哀乐我们一起感受，脚下的路我们一起探索，欣赏着路边的风景，奔向美好的未来。</p>
<p>制作了一段H5动画，记录我们的点滴回忆，送给我的宝贝，也祝福我们恩爱永远。</p>
<p><a href="https://blog.datarepo.cn/anniversary/index.html">恋爱一周年快乐</a></p>
<!--kg-card-end: markdown-->]]></description><link>https://www.datarepo.cn/2018/04/03/first-anniversary-of-love/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c8</guid><category><![CDATA[Life]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Tue, 03 Apr 2018 03:28:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-anniversary.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-anniversary.jpg" alt="恋爱一周年"><p>今天是我们恋爱一周年的纪念日，这一年我们经历了很多，学业、工作和生活都掀开了新的篇章。一切都那么快，又那么自然，生活的酸甜苦辣我们一起品尝，人生的喜怒哀乐我们一起感受，脚下的路我们一起探索，欣赏着路边的风景，奔向美好的未来。</p>
<p>制作了一段H5动画，记录我们的点滴回忆，送给我的宝贝，也祝福我们恩爱永远。</p>
<p><a href="https://blog.datarepo.cn/anniversary/index.html">恋爱一周年快乐</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[对学院的一些看法（本科）]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>下面是我在南京航空航天大学计算机科学与技术学院读本科快要毕业的时候（2013年4月18日），写给学院陈院长的一封电子邮件。现在又翻出来重新读一读自己写的内容，记下曾经的一些想法，自己也反思反思思考问题的思路哪些还需要改进。</p>
<hr>
<p>陈院长：</p>
<p>您好，我是信息安全专业大三的学生王军。关于我们学院的一些事情，我想跟您谈谈自己的一些看法。其实有没有必要写这封邮件，我也想了很久，一直在犹豫。昨天您上课的时候说了我们学院的一些现状，包括有些老师不愿意要我们南航的研究生之类的情况，也说了一些解决的措施。我想，我在学院学习生活的这三年，虽然对于学院的了解不会有您那么广泛，但是应该会有一些您没有经历过，或者没有注意到的情况。所以我还是决定要给您写这封邮件。</p>
<p>这三年中，我是普通的学生，在班里当过班委，在学院当过部长，也在科协当过半个学期的主席，一个学期的秘书长。感觉自己对于学院学生工作，包括科创这一块了解的还算比较多。</p>
<p>首先我想说说科创的问题，我在科协工作三个学期了，既作为科创申报者，参与申报了科创基金，也作为科创基金管理者，参与了一期科创的整个管理审核过程。我切实感受到学院对于科创的重视程度，也从中发现了学院在科创基金管理上面的一些问题。我们的科创基金应该是我们一直引以为傲的内容，但是每年的花花绿绿总是昙花一现，我觉得问题有下面几个方面。首先，体制建设，这是根本的方面，是建设的基础。现在的科创管理问题很多，如科创中期审查的时间是由科协和辅导员临时决定，学生事先不知道；审查时的评委老师，</p>]]></description><link>https://www.datarepo.cn/2018/04/01/some-suggestions-to-the-college/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c7</guid><category><![CDATA[Life]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Sun, 01 Apr 2018 03:26:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-advise-or-advice.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-advise-or-advice.jpg" alt="对学院的一些看法（本科）"><p>下面是我在南京航空航天大学计算机科学与技术学院读本科快要毕业的时候（2013年4月18日），写给学院陈院长的一封电子邮件。现在又翻出来重新读一读自己写的内容，记下曾经的一些想法，自己也反思反思思考问题的思路哪些还需要改进。</p>
<hr>
<p>陈院长：</p>
<p>您好，我是信息安全专业大三的学生王军。关于我们学院的一些事情，我想跟您谈谈自己的一些看法。其实有没有必要写这封邮件，我也想了很久，一直在犹豫。昨天您上课的时候说了我们学院的一些现状，包括有些老师不愿意要我们南航的研究生之类的情况，也说了一些解决的措施。我想，我在学院学习生活的这三年，虽然对于学院的了解不会有您那么广泛，但是应该会有一些您没有经历过，或者没有注意到的情况。所以我还是决定要给您写这封邮件。</p>
<p>这三年中，我是普通的学生，在班里当过班委，在学院当过部长，也在科协当过半个学期的主席，一个学期的秘书长。感觉自己对于学院学生工作，包括科创这一块了解的还算比较多。</p>
<p>首先我想说说科创的问题，我在科协工作三个学期了，既作为科创申报者，参与申报了科创基金，也作为科创基金管理者，参与了一期科创的整个管理审核过程。我切实感受到学院对于科创的重视程度，也从中发现了学院在科创基金管理上面的一些问题。我们的科创基金应该是我们一直引以为傲的内容，但是每年的花花绿绿总是昙花一现，我觉得问题有下面几个方面。首先，体制建设，这是根本的方面，是建设的基础。现在的科创管理问题很多，如科创中期审查的时间是由科协和辅导员临时决定，学生事先不知道；审查时的评委老师，是由科协或者辅导员在审查前几天一个一个打电话询问，而且还会有很多不确定等等。这就体现在体制不健全上面，在一个被重视的、健全的组织中，事务不应该是由人临时发起的，而应该是由时间、规定发起的。我看到在学院的科创基金管理办法中是有一些规定的，但是实施的时候并没有按照规定实施。对于体制的建设我觉得，首先真正成立科创基金管理委员会，由一位领导牵头，各个研究所都要出老师参与进来，也要有学生，如科协主席，可以给老师一个头衔，叫科创基金管理委员会委员之类，也可以有一个的激励措施，学院承诺的每年20万的科创基金，每年都没有用完过，用它来进行体制建设也是用在合适的方面。委员会先审查通过科创基金管理办法，把它确定下来，科创申报、中期审查、解题审查的时间和形式等等都固定在文字上。委员会委员对于科创基金的运营有相应的责任和义务，例如，担当科创审查时的评委，这应该作为评委老师的一项例行事务。每年要记录学院所有老师带科创的情况，评选优秀科创指导教师，并有奖励机制。关于科创基金，还想说说题目产生的方法，现在是每年由老师出题目，然后同学们去申请，还有一些同学自己想的题目。我觉得这样的题目产生很混乱，不好管理，而且不易出精品。老师的题目当然都很不错，有个问题就是传承问题，这个不必说。我觉得题目产生上，还有一个很好的途径，就是在每期科创申报前由委员会讨论产生，根据近一两年的发展状况，参考一些全国性甚至国际性的比赛中的内容，提出一些更贴近实际的题目，然后委员会指派指导老师。这些题目涉及最新的技术，而且更可能在今后的比赛中派上用场。</p>
<p>其次我还想说说学习风气这个问题，其实问题很早就有了而且很严重。当仅仅是把学习成绩作为学风反馈的工具时，必然会有局限性和滞后性。滞后性是很明显的，学期结束了或者考研结束了才能够意识到出了问题。局限性也是很明显的，首先考试对于学生的考核就是有局限的，其次，老师也总是希望自己的学生能够有好的成绩，选修课且不说，专业课的老师也不想为难大家，因为自己一门课压低了学生的绩点，我觉得作为大学老师这样做是无可厚非的，既然老师无过，那就是成绩作为反馈工具的局限了。所以我希望学院的领导能够在学生学习的过程中，去切实感受学习风气。要了解真实的学风，在查课的前一天就把通知发下去，这样看到的往往是假象。仅仅去查课，看哪些同学没有到，这样的效力是短时的。我觉得任课老师的反馈，比查课更有效。能够更多的从同学那里了解情况，不仅仅是学生代表，每个人都可以是了解的对象，会更贴近现实。除了反馈工具的问题外，不得不说的是管理，因为我觉得这个问题至关重要。我觉得我们的学生经过了初中高中六年的磨练，大多数的学生已经形成了希望被管理的习惯，说得难听一点就是奴性。我不否认有些人确实能够做到严于自律，也不否认自立自主对于一个人成长的重要性，但是现实是很多人不能做到这些。我相信学院很重视对管理人员的选拔，刘xx辅导员，学生会副主席，有丰富的学生工作经验，而且人踏实肯干；唐xx辅导员，更是学生会主席研究生会主席，工作能力毋庸置疑。他们都能够和同学们打成一片，和学生建立良好的关系，但是有些问题是不能回避的，作为本校或者本院的学生，对于学校或者学院的一些陋习他们可能习以为常，从而意识不到，或者意识到了也视而不见。陈院长，恕我不敬，您之前上课时的一个做法我就不能赞同，您对同学们说：现在的事情，往往是“做得好，不如说的好”，让我们把一个简单的作品包装一下，就可以拿去参加比赛。我知道您是鼓励我们大家去参加比赛，但是这样说，我不能赞同。我知道，事实确实是这个样子的，现在的社会就是很浮躁，很形式化。每个人都有自己的生活方式，年轻人更应该试图改变这种浮华。我从阙导那里、刘导那里、唐导那里、段然学长那里都听到过类似的话，我一直以为他们是在投机取巧，或许也能说是一种出成绩的捷径，当您也在向我们宣传这些时，我认识到了，这是我们学院的陋习。结果就是，学院的很多事情都是看上去很华丽，但是事实很空洞，内容很干瘪。我们把大量的时间都放在了宣传上，放在做海报、挂横幅、拍照片、写宣传稿、发新闻上，让别人知道我们都做过什么，和其他院攀比，看到四院搞个活动我们也马上搞一个类似的，可能这个活动根本没有什么影响，只是为了在字面上不比别人少些东西。我固然知道宣传的重要性，但是包装适可而止即可，华而不实的活动，学生不会愿意去参加，我相信如果把更多的精力放在活动的内容上，不会出现在发新闻的时候还要挑照片，看看哪个角度显得人比较多，这种情况。对于两位辅导员，他们管理的是我们学院的希望，我觉得他们还缺少点什么，那就是威望和高度的责任感。三年来给我印象最深、影响最大的一个辅导员是王xx辅导员，这些印象有：不苟言笑、无数的会议、连续好几天查寝查课、每次在院办看到厉声批评人、不厌其烦的说同样的事情等等等等，这些在大一的时候看来不可理解、厌烦的事情，现在想想每一件事都透露着王导的态度与责任，他对每一个学生都有自己深深的责任感，都会尽自己所能去帮助。威望这个东西，可能不是每个人都有，不是通过批评、打骂换来的，您在课堂上一站，我们下面的学生没有人敢翘课；王导的一个眼神，一个在下面谈笑的人会马上严肃、闭嘴、坐好，如果换做刘导，我猜学生可能冲刘导笑一笑然后闭嘴、坐好，虽然都闭嘴坐好了，但前者是一种敬畏，后者可能仅仅是尊敬。一个负责任但没有威望的领导，足以完成一项任务，不足以领导一个团队。我觉得亮剑里的一段话说的很有道理：“英雄或是优秀军人的出现，往往是由集体形式出现，而不是由个体形式出现。理由很简单，他们受到同样传统的影响。养成了同样的性格与气质。任何一支部队都有着它自己的传统。传统是什么？传统是一种性格、是一种气质！这种传统与性格，是由这种部队组建时首任军事首长的性格与气质决定的。他给这支部队注入了灵魂。从此不管岁月流失，人员更迭，这支部队灵魂永在。”</p>
<p>每个人都有自己的生活方式，没有对错。我也只是用一个学生的眼光去客观的看待学院的一些事情，无意伤害任何一个人。只是希望学院能够更好~~</p>
<p align="right">2013年4月18日</p>
<p align="right">王军</p><!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[使用GeoServer作为Kibana离线地图]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://www.elastic.co/cn/products/kibana">Kibana</a>是一个开源的分析与可视化平台，可以用来搜索、查看、交互存放在Elasticsearch索引里的数据，使用各种不同的图表、表格、地图等，kibana能够很轻易地展示高级数据分析与可视化结果。</p>
<p>Kibana提供了Coordinate Map和Region Map两种基于地图的数据可视化方法，其地图由<a href="https://www.elastic.co/elastic-maps-service">Elastic Maps Service</a>提供服务。而在实际的使用场景下，有时无法连接外部互联网，因此无法使用该服务，本文介绍一种通过自行搭建GeoServer为Kibana提供地图服务的方法。</p>
<h2 id="geoserver">GeoServer介绍</h2>
<p><a href="http://geoserver.org/about/">GeoServer</a>是一个基于java开发的软件服务器，使用开放地理空间联盟（Open Geospatial Consortium，OGC）提出的标准，可提供WMS兼容的地图服务。允许用户查看和编辑地图数据。利用 GeoServer 可以方便的发布地图数据，允许用户对特征数据进行更新、删除、插入操作，通过 GeoServer 可以比较容易的在用户之间共享空间地理信息。</p>
<h2 id="kibana">运行Kibana</h2>
<p>为了实验，本文使用Docker搭建了最简单的Kibana环境，运行命令如下：</p>
<pre><code>$ docker run -d --name myelasticsearch</code></pre>]]></description><link>https://www.datarepo.cn/2018/04/01/use-geoserver-with-kibana/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c6</guid><category><![CDATA[Technology]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Sun, 01 Apr 2018 03:24:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-kibana-with-geoserver.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-kibana-with-geoserver.jpg" alt="使用GeoServer作为Kibana离线地图"><p><a href="https://www.elastic.co/cn/products/kibana">Kibana</a>是一个开源的分析与可视化平台，可以用来搜索、查看、交互存放在Elasticsearch索引里的数据，使用各种不同的图表、表格、地图等，kibana能够很轻易地展示高级数据分析与可视化结果。</p>
<p>Kibana提供了Coordinate Map和Region Map两种基于地图的数据可视化方法，其地图由<a href="https://www.elastic.co/elastic-maps-service">Elastic Maps Service</a>提供服务。而在实际的使用场景下，有时无法连接外部互联网，因此无法使用该服务，本文介绍一种通过自行搭建GeoServer为Kibana提供地图服务的方法。</p>
<h2 id="geoserver">GeoServer介绍</h2>
<p><a href="http://geoserver.org/about/">GeoServer</a>是一个基于java开发的软件服务器，使用开放地理空间联盟（Open Geospatial Consortium，OGC）提出的标准，可提供WMS兼容的地图服务。允许用户查看和编辑地图数据。利用 GeoServer 可以方便的发布地图数据，允许用户对特征数据进行更新、删除、插入操作，通过 GeoServer 可以比较容易的在用户之间共享空间地理信息。</p>
<h2 id="kibana">运行Kibana</h2>
<p>为了实验，本文使用Docker搭建了最简单的Kibana环境，运行命令如下：</p>
<pre><code>$ docker run -d --name myelasticsearch \
   docker.elastic.co/elasticsearch/elasticsearch:6.2.3
$ docker run -d --link myelasticsearch:elasticsearch \
   -p 5601:5601 \
   --name  kiban \
   docker.elastic.co/kibana/kibana:6.2.3
</code></pre>
<h2 id="geoserver">运行GeoServer</h2>
<p>首先在<a href="http://www.naturalearthdata.com/">Natural Earth</a>中下载SHP格式的<a href="http://naciscdn.org/naturalearth/packages/natural_earth_vector.zip">地图数据</a>，将其解压缩到本地，然后运行如下命令：</p>
<pre><code>$ docker run -d --name geoserver \
   -p 8080:8080 \
   -v `pwd`/natural_earth_vector:/opt/geoserver/data_dir/data/ \ 
   kartoza/geoserver
</code></pre>
<h2 id="geoserver">配置GeoServer</h2>
<h3 id="geoserver">登录GeoServer</h3>
<p>通过<code>http://localhost:8080/geoserver</code>访问GeoServer页面，并使用初始用户名密码<strong>admin/geoserver</strong>登录。：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-startup.png" alt="使用GeoServer作为Kibana离线地图"></p>
<h3 id>新建工作区</h3>
<p>点击左侧<strong>工作区</strong>，选择<strong>新建工作区</strong>，并填写相应内容，然后点击<strong>提交</strong>：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-createworkspace.png" alt="使用GeoServer作为Kibana离线地图"></p>
<h3 id>添加数据存储</h3>
<p>点击左侧<strong>数据存储</strong>，选择<strong>添加新的数据存储</strong>，然后在<strong>新建数据源</strong>页面中，选择<strong>Directory of spatial files (shapefiles)</strong>：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-newdatasource.png" alt="使用GeoServer作为Kibana离线地图"></p>
<p>在<strong>编辑的矢量数据源</strong>页面中填写相应内容，并在<strong>Shapefiles文件的目录</strong>选择框中，选择<code>data_dir/data/10m_cultural/</code>文件夹，点击<strong>确定</strong>：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-importdata.png" alt="使用GeoServer作为Kibana离线地图"></p>
<h3 id>发布图层</h3>
<p>依次选择<strong>图层</strong>-&gt;<strong>添加新的资源</strong>，在新建图层中选择刚刚创建的图层，点击图层<strong>ne_10m_admin_0_countries</strong>后面的<strong>发布</strong>按钮：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-newlayer.png" alt="使用GeoServer作为Kibana离线地图"></p>
<p>在<strong>编辑图层</strong>页面的<strong>数据</strong>标签中，填写相应的内容，其中<strong>Native Bounding Box</strong>内容通过点击下面的<strong>从数据中计算</strong>获得，<strong>纬度/经度边框</strong>内容通过点击下面的<strong>Compute from native bounds</strong>获得：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-settings0.png" alt="使用GeoServer作为Kibana离线地图"></p>
<p>在页面上方切换到<strong>发布</strong>标签，选中所有的<strong>Avilable Styles</strong>，然后点击中间的向右侧的箭头，然后点击下方的<strong>保存</strong>按钮：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-settings.png" alt="使用GeoServer作为Kibana离线地图"></p>
<h3 id>查看地图</h3>
<p>点击左侧的<strong>Layer Preview</strong>，然后点击图层后面的<strong>OpenLayers</strong>，即可查看地图：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-openlayers.png" alt="使用GeoServer作为Kibana离线地图"></p>
<h2 id="kibana">配置Kibana</h2>
<h3 id="indexpattern">创建Index Pattern</h3>
<p>使用Kibana需要首先创建<code>Index Pattern</code>，用于收集和检索Elasticsearch中的数据，本文使用Kibana和Elasticsearch中X-pack插件产生的数据作为实验，创建的Index Pattern为<code>.monitoring-*</code>。</p>
<h3 id="geoserver">使用GeoServer</h3>
<p>选择Kibana页面左侧的<strong>Visualize</strong>选项卡，点击<strong>Create a visualization</strong>，然后选择<strong>Coordinate Map</strong>，在左侧选择<code>.monitoring-*</code>作为检索数据源，然后选择<strong>Options</strong>标签，并选中下方的<strong>WMS compliant map server</strong>：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-custommap.png" alt="使用GeoServer作为Kibana离线地图"></p>
<p>然后填写GerServer服务相关的数据，即可使用GeoServer：</p>
<p><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/blog-geoserver-kibana-setting.png" alt="使用GeoServer作为Kibana离线地图"></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[搭建并使用Harbor容器镜像仓库]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://github.com/vmware/harbor/">Harbor</a>是VMWare开源的企业级容器镜像仓库。它扩展了Docker Registry的功能，包括安全性、认证和管理等功能。Harbor支持设置多个仓库并在仓库间复制镜像。另外，Harbor提供了高级的安全属性，包括用户管理、访问控制、行为审计、镜像漏洞扫描等。</p>
<p>官方给出的特点如下：</p>
<ul>
<li>基于角色的访问控制（RBAC）</li>
<li>基于策略的镜像复制</li>
<li>镜像漏洞扫描</li>
<li>LDAP/AD集成支持</li>
<li>镜像删除和垃圾回收</li>
<li>Notary镜像真实性确认</li>
<li>图形用户接口</li>
<li>审计</li>
<li>易于部署</li>
</ul>
<p>下面给出在Linux中进行在线安装的方法。</p>
<h2 id>前期准备</h2>
<p>官方给出了安装Harbor主机的软硬件需求。其中硬件需求基本都能满足，软件需求包括：Python 2.7或更高版本；Docker engine 1.10或更高版本，可根据官方教程安装Docker CE：<a href="https://docs.docker.com/engine/installation/">https://docs.docker.com/engine/installation/</a>；Docker Compose 1.6.0或更高版本，</p>]]></description><link>https://www.datarepo.cn/2018/03/28/deploy-and-use-harbor/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c5</guid><category><![CDATA[Technology]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Wed, 28 Mar 2018 03:23:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-harbor.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-harbor.jpg" alt="搭建并使用Harbor容器镜像仓库"><p><a href="https://github.com/vmware/harbor/">Harbor</a>是VMWare开源的企业级容器镜像仓库。它扩展了Docker Registry的功能，包括安全性、认证和管理等功能。Harbor支持设置多个仓库并在仓库间复制镜像。另外，Harbor提供了高级的安全属性，包括用户管理、访问控制、行为审计、镜像漏洞扫描等。</p>
<p>官方给出的特点如下：</p>
<ul>
<li>基于角色的访问控制（RBAC）</li>
<li>基于策略的镜像复制</li>
<li>镜像漏洞扫描</li>
<li>LDAP/AD集成支持</li>
<li>镜像删除和垃圾回收</li>
<li>Notary镜像真实性确认</li>
<li>图形用户接口</li>
<li>审计</li>
<li>易于部署</li>
</ul>
<p>下面给出在Linux中进行在线安装的方法。</p>
<h2 id>前期准备</h2>
<p>官方给出了安装Harbor主机的软硬件需求。其中硬件需求基本都能满足，软件需求包括：Python 2.7或更高版本；Docker engine 1.10或更高版本，可根据官方教程安装Docker CE：<a href="https://docs.docker.com/engine/installation/">https://docs.docker.com/engine/installation/</a>；Docker Compose 1.6.0或更高版本，安装教程见：<a href="https://docs.docker.com/compose/install/">https://docs.docker.com/compose/install/</a>；Openss最新版。同时需要443、4443和80端口开放。</p>
<h2 id>安装过程</h2>
<p>Harbor安装过程主要为三步：</p>
<ol>
<li>下载安装包；</li>
<li>修改配置文件<code>harbor.cfg</code>；</li>
<li>运行<code>install.sh</code>并启动Harbor。</li>
</ol>
<h3 id>下载安装包</h3>
<p>在Harbor官方项目的<a href="https://github.com/vmware/harbor/releases">release</a>页面下载安装包。本文下载的在线安装包<code>harbor-online-installer-&lt;version&gt;.tgz</code>。然后对其解压：</p>
<pre><code>$ tar xvf harbor-online-installer-&lt;version&gt;.tgz
</code></pre>
<h3 id>修改配置</h3>
<p>在修改配置前首先需要获取证书，为网络传输增加TSL加密。这样不仅可以提高镜像库数据传输的安全性，同时在Harbor中启用Notary进行镜像真实性确认，要求启用https。</p>
<p>使用者可在CA购买授权的证书，也可使用<a href="https://letsencrypt.org/">Let's Encrypt</a>提供的免费证书。</p>
<p>采用文章<a href="https://blog.datarepo.cn/2018/03/22/secure-nginx-with-letsencrypt/">Docker环境中使用Let's Encrypt为Nginx提供免费SSL证书</a>中的方法生成证书。假设证书存放位置为：<code>/data/certbot/letsencrypt</code>。</p>
<p>配置文件为解压后文件夹中的<code>harbor.cfg</code>文件。配置参数很多，详细说明见<a href="https://github.com/vmware/harbor/blob/master/docs/installation_guide.md">官方文档</a>。本文仅做必要的配置如下：</p>
<ul>
<li><strong>hostname</strong>： your.domain.com</li>
<li><strong>ui_url_protocol</strong>： https</li>
<li><strong>ssl_cert</strong>： /data/certbot/letsencrypt/live/your.domain.com/fullchain.pem</li>
<li><strong>ssl_cert_key</strong>： /data/certbot/letsencrypt/live/your.domain.com/privkey.pem</li>
</ul>
<h3 id="harbor">安装和使用Harbor</h3>
<h4 id="harbor">安装Harbor</h4>
<p>使用如下命令安装Harbor，并启用Notary（镜像真实性确认）和Clair（镜像漏洞扫描）。更多关于Notary的信息参考<a href="https://docs.docker.com/engine/security/trust/content_trust/">https://docs.docker.com/engine/security/trust/content_trust/</a>，关于Clair的信息参考<a href="https://coreos.com/clair/docs/2.0.1/">https://coreos.com/clair/docs/2.0.1/</a>。</p>
<pre><code>$ sudo ./install.sh --with-notary --with-clair
</code></pre>
<p>注意：如果运行可能出现错误提示，要求安装Docker Compose，而实际已经安装。这是因为<code>docker-compose</code>文件只放在了<code>/usr/local/bin/</code>文件夹下，不在root用户的环境变量中，因此可将<code>docker-compose</code>复制到<code>/usr/sbin/</code>文件夹中：</p>
<pre><code>sudo cp /usr/local/bin/docker-compose /usr/sbin/docker-compose
</code></pre>
<h4 id="harbor">使用Harbor</h4>
<p>安装完成后即可通过浏览器访问Harbor了，在浏览器中输入<code>your.domain.com</code>，使用初始用户名密码<strong>admin/Harbor12345</strong>登录Harbor。</p>
<p>在<strong>系统管理/用户管理</strong>中创建用户；在项目窗口中新建项目<code>test</code>，访问级别设置为私有，并在项目中新建成员。</p>
<p>在需要使用Harbor的机器中，使用docker login登录仓库，用户名密码为刚创建用户的用户名和密码，并向项目<code>test</code>中推送镜像：</p>
<pre><code>$ docker login your.domain.com
$ docker push your.domain.com/test/image:tag
</code></pre>
<h2 id="harbor">Harbor运行管理</h2>
<p>可以使用docker-compose命令停止或启动Harbor，下面给出相关的命令。（需要在harbor解压缩的文件夹中运行）</p>
<p>停止Harbor：</p>
<pre><code>$ sudo docker-compose stop
Stopping nginx ... done
Stopping harbor-jobservice ... done
Stopping harbor-ui ... done
Stopping harbor-db ... done
Stopping registry ... done
Stopping harbor-log ... done
</code></pre>
<p>重新启动Harbor：</p>
<pre><code>$ sudo docker-compose start
Starting log ... done
Starting ui ... done
Starting mysql ... done
Starting jobservice ... done
Starting registry ... done
Starting proxy ... done
</code></pre>
<p>如修改配置文件，需要在重新启动前执行<code>prepare</code>脚本文件更新Harbor需要的配置信息：</p>
<pre><code>$ sudo docker-compose down -v
$ vim harbor.cfg
$ sudo prepare
$ sudo docker-compose up -d
</code></pre>
<p>删除Harbor容器，同时保留镜像和数据：</p>
<pre><code>$ sudo docker-compose down -v
</code></pre>
<p>删除镜像和数据：</p>
<pre><code>$ rm -r /data/database
$ rm -r /data/registry
</code></pre>
<p>在安装了Clair和Notary时，Harbor的启动和停止需要指定额外的文件：</p>
<pre><code>$ sudo docker-compose -f ./docker-compose.yml \
  -f ./docker-compose.clair.yml \
  -f ./docker-compose.notary.yml [ up|down|ps|stop|start ]
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[搭建安全的本地Docker Registry]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>在很多场景下，需要自行搭建本地Docker镜像库，用于存储和维护开发的应用镜像。Docker官方提供了两种Registry：一种为Docker Registry，另一种为Docker Trusted Registry（DTR），其中后者为商业版本，较前者增加了LDAP集成、安全扫描等功能，为付费套餐的一部分，本文介绍第一种镜像库安装方法。</p>
<h2 id="dockerce">安装Docker CE</h2>
<p>安装方法参考<a href="https://docs.docker.com/install/">官方教程</a>，在Kali Linux中安装可参考博客<a href="https://blog.datarepo.cn/2018/03/21/install-docker-in-kali/">Kali 2018.1 中安装Docker CE</a>。</p>
<h2 id="data">创建data文件夹</h2>
<p>创建文件夹存放镜像库中的内容：</p>
<pre><code>$ mkdir data
</code></pre>
<h2 id>使用基础认证</h2>
<p>创建文件夹存放密码文件，假设创建的用户名为<code>testuser</code>，密码为<code>testpassword</code>：</p>
<pre><code>$ mkdir auth
$ docker run \
  --entrypoint htpasswd \
  registry:2 -Bbn testuser testpassword &gt; auth/htpasswd</code></pre>]]></description><link>https://www.datarepo.cn/2018/03/26/deploy-a-local-docker-registry/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c4</guid><category><![CDATA[Technology]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Mon, 26 Mar 2018 03:22:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-docker-registry.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-docker-registry.jpg" alt="搭建安全的本地Docker Registry"><p>在很多场景下，需要自行搭建本地Docker镜像库，用于存储和维护开发的应用镜像。Docker官方提供了两种Registry：一种为Docker Registry，另一种为Docker Trusted Registry（DTR），其中后者为商业版本，较前者增加了LDAP集成、安全扫描等功能，为付费套餐的一部分，本文介绍第一种镜像库安装方法。</p>
<h2 id="dockerce">安装Docker CE</h2>
<p>安装方法参考<a href="https://docs.docker.com/install/">官方教程</a>，在Kali Linux中安装可参考博客<a href="https://blog.datarepo.cn/2018/03/21/install-docker-in-kali/">Kali 2018.1 中安装Docker CE</a>。</p>
<h2 id="data">创建data文件夹</h2>
<p>创建文件夹存放镜像库中的内容：</p>
<pre><code>$ mkdir data
</code></pre>
<h2 id>使用基础认证</h2>
<p>创建文件夹存放密码文件，假设创建的用户名为<code>testuser</code>，密码为<code>testpassword</code>：</p>
<pre><code>$ mkdir auth
$ docker run \
  --entrypoint htpasswd \
  registry:2 -Bbn testuser testpassword &gt; auth/htpasswd
</code></pre>
<h2 id="tls">增加TLS加密支持</h2>
<p>使用基础认证时，必须要增加TLS加密支持，否则用户的登录信息将通过明文传输。下面分别介绍持有证书、使用Let's Encrypt免费证书和使用自签名证书的配置方法。</p>
<h3 id>持有证书</h3>
<p>满足下列条件条件：</p>
<ul>
<li>拥有注册的域名<code>https://your.domain.com</code>。</li>
<li>域名指向的主机443端口可访问</li>
<li>从认证机构（CA）获取证书</li>
</ul>
<ol>
<li>创建<code>certs</code>文件夹</li>
</ol>
<pre><code>$ mkdir certs
</code></pre>
<p>讲证书<code>.crt</code>和<code>.key</code>文件复制到<code>certs</code>文件夹中，下文假设文件名分别为<code>domian.crt</code>和<code>domain.key</code>。</p>
<ol start="2">
<li>启动registry容器</li>
</ol>
<pre><code>$ sudo docker run -d \
  --restart=always \
  --name registry \
  -v `pwd`/data:/var/lib/registry \
  -v `pwd`/auth:/auth \
  -v `pwd`/certs:/certs \
  -e &quot;REGISTRY_AUTH=htpasswd&quot; \
  -e &quot;REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm&quot; \
  -e &quot;REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd&quot; \
  -e &quot;REGISTRY_HTTP_ADDR=0.0.0.0:443&quot; \
  -e &quot;REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt&quot; \
  -e &quot;REGISTRY_HTTP_TLS_KEY=/certs/domain.key&quot; \
  -p 443:443 \
  registry:2
</code></pre>
<h3 id="letsencrypt">使用Let's Encrypt免费证书</h3>
<p>Docker Registry官方支持使用<a href="https://letsencrypt.org/">Let's Encrypt</a>提供<a href="https://docs.docker.com/registry/deploying/#support-for-lets-encrypt">免费的可信证书</a>，但在2018年1月开始，Let's Encrypt出于安全性考虑，<a href="https://community.letsencrypt.org/t/tls-sni-challenges-disabled-for-most-new-issuance/50316">取消了TLS-SNI challenge</a>，因此根据官方教程使用Let's Encrypt为Docker Registry提供认证已经无法工作，见官方<a href="https://github.com/docker/distribution/issues/2545">issue</a>，Docker开发者正在解决该问题。</p>
<p>下面给出按照官方教程，使用Let's Encrypt进行认证的运行命令，现在已<strong>无法正常使用</strong>，待后续有新的进展后更新该部分内容：</p>
<pre><code>$ touch letsencrypt.json
$ sudo docker run -d \
  --restart=always \
  --name registry \
  -v `pwd`/data:/var/lib/registry \
  -v `pwd`/auth:/auth \
  -v `pwd`/certs:/certs \
  -v `pwd`/letsencrypt.json:/etc/docker/registry/letsencrypt.json \
  -e &quot;REGISTRY_AUTH=htpasswd&quot; \
  -e &quot;REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm&quot; \
  -e &quot;REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd&quot; \
  -e &quot;REGISTRY_HTTP_ADDR=0.0.0.0:443&quot; \
  -e &quot;REGISTRY_HTTP_TLS_LETSENCRYPT_CACHEFILE=/etc/docker/registry/letsencrypt.json&quot; \
  -e &quot;REGISTRY_HTTP_HOST=https://your.domain.com&quot; \
  -e &quot;REGISTRY_HTTP_TLS_LETSENCRYPT_EMAIL=your@email.com&quot; \
  -p 443:443 \
  registry:2
</code></pre>
<p>该方法已经无法正常使用，下面给出另一种可用的方法。采用文章<a href="https://blog.datarepo.cn/2018/03/22/secure-nginx-with-letsencrypt/">Docker环境中使用Let's Encrypt为Nginx提供免费SSL证书</a>中的方法生成证书。</p>
<p>然后运行Registry容器</p>
<pre><code>$ sudo docker run -d \
  --restart=always \
  --name registry \
  -v `pwd`/data:/var/lib/registry \
  -v `pwd`/auth:/auth \
  -v /data/certbot/letsencrypt:/certs \
  -e &quot;REGISTRY_AUTH=htpasswd&quot; \
  -e &quot;REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm&quot; \
  -e &quot;REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd&quot; \
  -e &quot;REGISTRY_HTTP_ADDR=0.0.0.0:443&quot; \
  -e &quot;REGISTRY_HTTP_TLS_CERTIFICATE=/certs/live/your.domain.com/fullchain.pem&quot; \
  -e &quot;REGISTRY_HTTP_TLS_KEY=/certs/live/your.domain.com/privkey.pem&quot; \
  -p 443:443 \
  registry:2
</code></pre>
<p>即可成功使用Let's Encrypt证书，证书有效期为90天，其更新方法见文章<a href="https://blog.datarepo.cn/2018/03/22/secure-nginx-with-letsencrypt/">Docker环境中使用Let's Encrypt为Nginx提供免费SSL证书</a>。</p>
<h3 id>使用自签名证书</h3>
<p>在没有CA发布的证书时，可使用自签名证书，该方法仅建议在测试或开发环境中使用。</p>
<ol>
<li>生成自签名证书</li>
</ol>
<pre><code>$ mkdir -p certs
$ openssl req \
  -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
  -x509 -days 365 -out certs/domain.crt
</code></pre>
<p>在交互过程中，使用域名your.domain.com作为CN。如没有注册的域名，可自行选取域名，然后更改本机的<code>hosts</code>文件，添加该域名到自身的解析。</p>
<ol start="2">
<li>使用与持有证书相同的命令运行Registry</li>
</ol>
<pre><code>$ sudo docker run -d \
  --restart=always \
  --name registry \
  -v `pwd`/data:/var/lib/registry \
  -v `pwd`/auth:/auth \
  -v `pwd`/certs:/certs \
  -e &quot;REGISTRY_AUTH=htpasswd&quot; \
  -e &quot;REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm&quot; \
  -e &quot;REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd&quot; \
  -e &quot;REGISTRY_HTTP_ADDR=0.0.0.0:443&quot; \
  -e &quot;REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt&quot; \
  -e &quot;REGISTRY_HTTP_TLS_KEY=/certs/domain.key&quot; \
  -p 443:443 \
  registry:2
</code></pre>
<ol start="3">
<li>DNS设置（仅无注册域名时）</li>
</ol>
<p>对于没有注册域名的用户，可自行选取域名，确保第1步中CN设置与其相同。然后更改<code>hosts</code>文件，添加解析。</p>
<p>本机添加解析记录：在本机的<code>/etc/hosts</code>文件中，127.0.0.1一行后添加<code>your.domain.com</code>。</p>
<p>其他运行Docker daemon的主机：在其<code>/etc/hosts</code>文件中，添加<code>your.domain.com</code>到Registry主机IP地址的解析。</p>
<ol start="4">
<li>其他主机导入证书</li>
</ol>
<p>其他需要使用Docker Registry服务的主机中，需要导入Registry的证书，使其信任Registry主机。</p>
<p>将<code>domain.crt</code>文件复制为其他主机的<code>/etc/docker/certs.d/your.domain.com/ca.crt</code>文件。</p>
<h2 id="registry">使用本地Registry</h2>
<ol>
<li>在Docker Hub中下载镜像</li>
</ol>
<pre><code>$ sudo docker pull alpine
</code></pre>
<ol start="2">
<li>修改tag</li>
</ol>
<p>容器镜像的tag由两个部分构成，第一个部分包括主机名和端口，第二个部分为镜像名和版本号，版本号缺省情况下为<code>latest</code>。</p>
<pre><code>$ sudo docker tag alpine your.domain.com/alpine
</code></pre>
<ol start="3">
<li>登录本地Registry</li>
</ol>
<p>使用创建的用户名<code>testuser</code>和密码<code>testpassword</code>登录本地Registry。</p>
<pre><code>$ sudo docker login your.domain.com
</code></pre>
<ol start="4">
<li>Push镜像到本地Registry</li>
</ol>
<pre><code>$ sudo docker push your.domain.com/alpine
</code></pre>
<ol start="5">
<li>删除本机保存的镜像</li>
</ol>
<pre><code>$ sudo docker rmi alpine
$ sudo docker rmi your.domain.com/alpine
</code></pre>
<ol start="6">
<li>在本地Registry中拉取镜像</li>
</ol>
<pre><code>$ sudo docker pull your.domain.com/alpine
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Docker环境中使用Let's Encrypt为Nginx提供免费SSL证书]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>为网站增加SSL层加密，可以有效保护网站内容，防止包括用户账户等敏感信息泄露事件的发生。在这个隐私泄漏泛滥的社会，很有必要为自己的网站增加SSL加密功能。</p>
<p>获取SSL证书通常需要向权威的证书注册机构（Registry Authority，CA）申请，然后由证书认证机构（Certification Authority，CA）签发，市面上一般的SSL证书价格昂贵，对于个人网站来说负担较重。本文介绍一种在Docker环境中，从认证机构Let's Encrypt获取免费SSL证书，并应用在Nginx服务器中的方法。</p>
<h2 id="letsencrypt">Let's Encrypt简介</h2>
<p><a href="https://letsencrypt.org/">Let's Encrypt</a>作为一个公共且免费的SSL项目逐渐被广大用户传播和使用，由Mozilla、Cisco、Akamai、IdenTrust、EFF、Facebook等组织人员发起，主要的目的也是为了推进网站从HTTP向HTTPS过度的进程，兼容包括FireFox、Chrome在内的主流浏览器。</p>
<h2 id="dockerce">安装Docker CE</h2>
<p>本文运行Nginx和生成证书均在Docker环境中，因此首先需要安装Docker运行环境，安装方法参考<a href="https://docs.docker.com/install/">官方教程</a>，或参考我的博客<a href="https://blog.datarepo.cn/2018/03/21/install-docker-in-kali/">Kali 2018.1 中安装Docker CE</a>，对于Debian系统只需要去掉其中的<strong>修改配置文件</strong>章节即可。</p>]]></description><link>https://www.datarepo.cn/2018/03/22/secure-nginx-with-letsencrypt/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c3</guid><category><![CDATA[Technology]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Thu, 22 Mar 2018 03:20:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-letsencrypt-nginx.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-letsencrypt-nginx.jpg" alt="Docker环境中使用Let's Encrypt为Nginx提供免费SSL证书"><p>为网站增加SSL层加密，可以有效保护网站内容，防止包括用户账户等敏感信息泄露事件的发生。在这个隐私泄漏泛滥的社会，很有必要为自己的网站增加SSL加密功能。</p>
<p>获取SSL证书通常需要向权威的证书注册机构（Registry Authority，CA）申请，然后由证书认证机构（Certification Authority，CA）签发，市面上一般的SSL证书价格昂贵，对于个人网站来说负担较重。本文介绍一种在Docker环境中，从认证机构Let's Encrypt获取免费SSL证书，并应用在Nginx服务器中的方法。</p>
<h2 id="letsencrypt">Let's Encrypt简介</h2>
<p><a href="https://letsencrypt.org/">Let's Encrypt</a>作为一个公共且免费的SSL项目逐渐被广大用户传播和使用，由Mozilla、Cisco、Akamai、IdenTrust、EFF、Facebook等组织人员发起，主要的目的也是为了推进网站从HTTP向HTTPS过度的进程，兼容包括FireFox、Chrome在内的主流浏览器。</p>
<h2 id="dockerce">安装Docker CE</h2>
<p>本文运行Nginx和生成证书均在Docker环境中，因此首先需要安装Docker运行环境，安装方法参考<a href="https://docs.docker.com/install/">官方教程</a>，或参考我的博客<a href="https://blog.datarepo.cn/2018/03/21/install-docker-in-kali/">Kali 2018.1 中安装Docker CE</a>，对于Debian系统只需要去掉其中的<strong>修改配置文件</strong>章节即可。</p>
<h2 id="certbotssl">使用Certbot生成SSL证书</h2>
<p><a href="https://certbot.eff.org/">Certbot</a>软件实现了Let's Encrypt认证，下面介绍使用Certbot生成SSL证书的方法。</p>
<p>Certbot以插件形式提供<a href="https://certbot.eff.org/docs/using.html#getting-certificates-and-choosing-plugins">多种证书生成方式</a>，包括apache、nginx、webroot、standalone、DNS plugins、manual等。由于本文使用Docker环境下运行Certbot，官方版本中没有安装Nginx插件，本文使用webroot形式产生SSL证书。</p>
<h3 id>创建文件/文件夹</h3>
<ol>
<li>使用webroot插件需要在<code>${webroot-path}/.well-known/acme-challenge</code>路径下创建临时文件，且需要能够通过网络访问该文件夹。本文中Nginx和Certbot在Docker环境中运行，因此可以在本地创建该文件，然后挂载到Nginx和Certbot容器中指定的路径下。创建文件夹：</li>
</ol>
<pre><code>$ mkdir -p ./nginx/html/.well-known/acme-challenge/
</code></pre>
<ol start="2">
<li>创建文件夹certbot用于存放生成的秘钥信息。</li>
</ol>
<pre><code>$ mkdir ./certbot/
</code></pre>
<h3 id="nginx">启动Nginx容器</h3>
<p>为了能够通过网络访问<code>${webroot-path}/.well-known/acme-challenge</code>文件夹，需要启动Nginx服务器，并进行相应的配置。</p>
<p>创建文件夹存放配置文件：</p>
<pre><code>$ mkdir -p ./nginx/conf.d/
</code></pre>
<p>创建Nginx配置文件：</p>
<pre><code>$ touch ./nginx/conf.d/default.conf
$ vi ./nginx/conf.d/default.conf
</code></pre>
<p>在<code>default.conf</code>文件中编辑如下内容：</p>
<pre><code>server {
    listen 80;
    server_name your.domain.com;
    location ^~ /.well-known/acme-challenge/ {
        root  /usr/share/nginx/html;
    }
}
</code></pre>
<p>然后启动Nginx容器：</p>
<pre><code>$ sudo docker run -d --name nginx -p 80:80 -p 443:443 \
  -v `pwd`/nginx/conf.d/:/etc/nginx/conf.d/ \
  -v `pwd`/nginx/html/:/usr/share/nginx/html/ \
  -v `pwd`/certbot/letsencrypt/:/etc/nginx/letsencrypt/ \
  nginx:alpine
</code></pre>
<h3 id="ssl">生成SSL证书</h3>
<p>假设Nginx容器挂载了本地的文件夹，用于存放其部署的网页信息，文件夹路径为：<code>./nginx/html/</code>。生成SSL证书的命令如下：</p>
<p>（更改其中的<code>your.domain.com</code>和<code>your@email.com</code>）</p>
<pre><code>$ sudo docker run -it --rm \
  -v `pwd`/certbot/letsencrypt/:/etc/letsencrypt/ \
  -v `pwd`/nginx/html/.well-known/acme-challenge/:/var/www/acm-challenge/ \
  -v `pwd`/nginx/html/:/var/www/html/ \
  -v `pwd`/certbot/log/:/var/log/letsencrypt/ \
  certbot/certbot \
    certonly --webroot -w /var/www/html/ \
    -d your.domain.com --renew-by-default \
    --email your@email.com --agree-tos
</code></pre>
<p>当然，Nginx也可只作为反向代理服务器使用，此时可能不需要挂载本地文件夹，这种情况下可直接将<code>/var/www/acm-challenge/</code>作为webroot参数，执行命令如下：</p>
<pre><code>$ sudo docker run -it --rm \
  -v `pwd`/certbot/letsencrypt/:/etc/letsencrypt/ \
  -v `pwd`/nginx/html/.well-known/acme-challenge/:/var/www/acm-challenge/ \
  -v `pwd`/certbot/log/:/var/log/letsencrypt/ \
  certbot/certbot \
    certonly --webroot -w /var/www/acm-challenge/ \
    -d your.domain.com --renew-by-default \
    --email your@email.com --agree-tos
</code></pre>
<p>生成的证书位于<code>./certbot/letsencrypt/</code>文件夹中。该证书的有效期为90天，后文会介绍如何自动的在失效前更新证书。</p>
<h2 id="nginx">配置并启动Nginx容器</h2>
<p>本文将证书所在目录挂载到Nginx容器的<code>/etc/nginx/letsencrypt/</code>路径下，将<code>./nginx/html/</code>挂载到<code>/usr/share/nginx/html</code>路径下，修改Nginx配置文件<code>default.conf</code>如下：</p>
<pre><code>server {
    listen 80;
    server_name your.domain.com;
    # 重定向到443端口
    location / {
      return 301 https://your.domain.com$request_uri;
    } 
    location ^~ /.well-known/acme-challenge/ {
        root  /usr/share/nginx/html;
    }
}
server {
    listen       443 ssl http2;
    server_name  your.domain.com;
    ssl on;
    # 添加SSL证书
    ssl_certificate /etc/nginx/letsencrypt/live/your.domain.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/letsencrypt/live/your.domain.com/privkey.pem;
    
    location / {
        proxy_pass  your.domain.com:port;
        ...
    }
}
</code></pre>
<p>停用并删除运行的Nginx容器，并重新运行：</p>
<pre><code>$ sudo docker stop nginx
$ sudo docker rm nginx
$ sudo docker run -d --name nginx -p 80:80 -p 443:443 \
  -v `pwd`/nginx/conf.d/:/etc/nginx/conf.d/ \
  -v `pwd`/nginx/html/:/usr/share/nginx/html/ \
  -v `pwd`/nginx/log/:/var/log/nginx/ \
  -v `pwd`/certbot/letsencrypt/:/etc/nginx/letsencrypt/ \
  nginx:alpine
</code></pre>
<h2 id>自动更新证书</h2>
<p>基于上述Nginx的配置，使用如下命令可检查证书是否即将失效，如失效则会更新证书，并将日志保存在本地<code>./certbot/log/</code>文件夹中。</p>
<pre><code>$ sudo docker run -it --rm \
  -v `pwd`/certbot/letsencrypt/:/etc/letsencrypt/ \
  -v `pwd`/nginx/html/.well-known/acme-challenge/:/var/www/acm-challenge/ \
  -v `pwd`/nginx/html/:/var/www/html/ \
  -v `pwd`/certbot/log/:/var/log/letsencrypt/ \
  certbot/certbot \
    renew --webroot -w /var/www/html/
</code></pre>
<p>为了使电脑能够自动检查并更新证书，可通过创建计划任务crontab实现。首先创建更新脚本<code>certbotrenew.sh</code>，保存在<code>./certbot/shell/</code>路径下，文件内容为：</p>
<pre><code>#!/bin/bash
docker run -it --rm \
  -v `pwd`/certbot/letsencrypt/:/etc/letsencrypt/  \
  -v `pwd`/nginx/html/.well-known/acme-challenge/:/var/www/acm-challenge/ \
  -v `pwd`/nginx/html/:/var/www/html/ \
  -v `pwd`/certbot/log/:/var/log/letsencrypt/ \
  certbot/certbot \
    renew --webroot -w /var/www/html/
</code></pre>
<p>为该文件增加执行权限：</p>
<pre><code>$ chmod +x path/to/certbotrenew.sh
</code></pre>
<p>然后使用root用户创建crontab：</p>
<pre><code># crontab -e
</code></pre>
<p>添加如下内容：</p>
<pre><code>0 0 * * 5 /path/to/certbotrenew.sh
</code></pre>
<p>即每周五的0点0分执行脚本<code>certbotrenew.sh</code>，检查证书是否即将过期，在有效期还有30天时会更新证书。</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Kali 2018.1 中安装Docker CE]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>最近电脑上重新安装了<a href="https://www.kali.org/">Kali Linux</a>，Kali基于Debian Testing分支进行开发，从2016年开始以滚动版形式发布新版本，版本均命名为Kali Rolling。最新发布的Kali 2018.1使用 Kernel 4.14.12和GNOME 3.26.2，经实验，可安装Debian 9 （stretch）支持的软件。</p>
<p>参考Docker官方在Debian上的<a href="https://docs.docker.com/install/linux/docker-ce/debian/">安装教程</a>和一些资料，下面给出在Kali 2018.1中安装Docker CE的方法。</p>
<h2 id="docker">卸载旧版本Docker</h2>
<p>Docker 从 17.03版本之后分为社区版CE（Community Edition）和企业版EE（Enterprise Edition）。其中社区版为免费版本，包含了完整的Docker平台，非常适合开发人员和运维团队构建容器APP；企业版为付费版本，主要提供了安全性方面的增强。本文安装版本为Docker CE。</p>
<p>首先卸载旧版本Docker：</p>
<pre><code class="language-shell">$ sudo apt-get</code></pre>]]></description><link>https://www.datarepo.cn/2018/03/21/install-docker-in-kali/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c2</guid><category><![CDATA[Technology]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Wed, 21 Mar 2018 03:19:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-kali-dragon-middle.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-kali-dragon-middle.jpg" alt="Kali 2018.1 中安装Docker CE"><p>最近电脑上重新安装了<a href="https://www.kali.org/">Kali Linux</a>，Kali基于Debian Testing分支进行开发，从2016年开始以滚动版形式发布新版本，版本均命名为Kali Rolling。最新发布的Kali 2018.1使用 Kernel 4.14.12和GNOME 3.26.2，经实验，可安装Debian 9 （stretch）支持的软件。</p>
<p>参考Docker官方在Debian上的<a href="https://docs.docker.com/install/linux/docker-ce/debian/">安装教程</a>和一些资料，下面给出在Kali 2018.1中安装Docker CE的方法。</p>
<h2 id="docker">卸载旧版本Docker</h2>
<p>Docker 从 17.03版本之后分为社区版CE（Community Edition）和企业版EE（Enterprise Edition）。其中社区版为免费版本，包含了完整的Docker平台，非常适合开发人员和运维团队构建容器APP；企业版为付费版本，主要提供了安全性方面的增强。本文安装版本为Docker CE。</p>
<p>首先卸载旧版本Docker：</p>
<pre><code class="language-shell">$ sudo apt-get remove docker docker-engine docker.io
</code></pre>
<h2 id="dockerce">安装Docker CE</h2>
<p>Docker官方给出了三种方法：</p>
<ul>
<li>通过设置Docker的仓库（repositories）安装。这种方法使用的最多，且安装后便于升级，推荐使用该方法。</li>
<li>通过下载<a href="https://docs.docker.com/install/linux/docker-ce/debian/#install-from-a-package">DEB包手动安装</a>。这种方法通常在离线环境下使用，通过该方法安装的软件在升级时也需要手动下载安装。</li>
<li>使用<a href="https://docs.docker.com/install/linux/docker-ce/debian/#install-using-the-convenience-script">脚本安装</a>。这种方法通常用在测试和开发环境中。</li>
</ul>
<p>其中第二种方法可在<a href="https://download.docker.com/linux/debian/dists/">官方库</a> Debian stretch版本的<code>pool/stable/</code>路径下，选择对应系统的安装包，然后使用<code>dpkg -i</code>命令进行安装。</p>
<p>第三种方法中，脚本里通过查看<code>/etc/os-release</code>等文件内容，或使用<code>lsb_release</code>等命令获取发行版本进行安装，而Kali中获取的版本均为Kali Rolling，为Docker不支持的版本，需要对相关配置文件进行修改。</p>
<p>本文重点介绍使用第一种方式安装的方法，同样需要修改配置文件，理论上通过修改后，也可使用第三种方法提供的脚本进行安装。</p>
<h3 id>修改配置文件</h3>
<p>切换到root用户:</p>
<ol>
<li>修改<code>/etc/debian_version</code>内容为</li>
</ol>
<pre><code>9.0
</code></pre>
<ol start="2">
<li>修改<code>/etc/lsb-release</code>内容为</li>
</ol>
<pre><code>DISTRIB_ID=Debian
DISTRIB_RELEASE=9
DISTRIB_CODENAME=stretch
DISTRIB_DESCRIPTION=&quot;Debian GNU/Linux 9 (stretch)&quot;
</code></pre>
<ol start="3">
<li>修改<code>/etc/os-release</code>内容为</li>
</ol>
<pre><code>PRETTY_NAME=&quot;Debian GNU/Linux 9 (stretch)&quot;
NAME=&quot;Debian GNU/Linux&quot;
ID=debian
VERSION=&quot;9 (stretch)&quot;
VERSION_ID=&quot;9&quot;
ID_LIKE=debian
ANSI_COLOR=&quot;1;31&quot;
HOME_URL=&quot;https://www.debian.org/&quot;
SUPPORT_URL=&quot;https://www.debian.org/support&quot;
BUG_REPORT_URL=&quot;https://bugs.debian.org/&quot;
</code></pre>
<h3 id="repository">设置Repository</h3>
<ol>
<li>更新apt索引</li>
</ol>
<pre><code>$ sudo apt-get update
</code></pre>
<ol start="2">
<li>添加Docker官方GPG key</li>
</ol>
<pre><code>$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
</code></pre>
<ol start="3">
<li>添加stable版的repository（也可添加其他版本）</li>
</ol>
<pre><code>$ sudo add-apt-repository \
   &quot;deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable&quot;
</code></pre>
<h3 id="dockerce">安装Docker CE</h3>
<ol>
<li>更新apt索引</li>
</ol>
<pre><code>$ sudo apt-get update
</code></pre>
<ol start="2">
<li>安装最新版本Docker CE</li>
</ol>
<pre><code>$ sudo apt-get install docker-ce
</code></pre>
<ol start="3">
<li>在生产系统中应安装指定版本Docker CE</li>
</ol>
<p>首先获取可用的版本：</p>
<pre><code>$ apt-cache madison docker-ce
</code></pre>
<p>然后根据获取的版本号安装：</p>
<pre><code>$ sudo apt-get install docker-ce=&lt;版本号&gt;
</code></pre>
<ol start="4">
<li>验证</li>
</ol>
<p>通过运行<code>hello-world</code>镜像验证是否成功安装。</p>
<pre><code>$ sudo docker run hello-world
</code></pre>
<p>运行上述命令如果出现如下错误：</p>
<p><code>docker: Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers).</code></p>
<p>如不是因为设置代理等造成的错误，可重新启动docker，再次尝试。</p>
<pre><code>$ sudo systemctl daemon-reload 
$ sudo systemctl restart docker
$ sudo systemctl status docker
$ sudo docker pull hello-world
</code></pre>
<ol start="5">
<li>设置Docker开机自启动</li>
</ol>
<pre><code>$ sudo systemctl enable docker
</code></pre>
<ol start="6">
<li>使用非root用户运行docker</li>
</ol>
<pre><code>$ sudo groupadd docker
$ sudo usermod -aG docker $USER
</code></pre>
<p>命令执行后，需要注销当前用户，重新登录后即可使用。</p>
<ol start="7">
<li>使用阿里云容器加速器</li>
</ol>
<p>首先注册阿里云帐号，然后在加速器页面<a href="https://cr.console.aliyun.com/#/accelerator">https://cr.console.aliyun.com/#/accelerator</a> 中获取加速器地址，并按照官方提示进行配置。CentOS和Ubuntu的配置方法如下：</p>
<pre><code>$ sudo mkdir -p /etc/docker
$ sudo tee /etc/docker/daemon.json &lt;&lt;-'EOF'
{
  &quot;registry-mirrors&quot;: [&quot;https://xxxxxxxx.mirror.aliyuncs.com&quot;]
}
EOF
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
</code></pre>
<h2 id="dockerce">更新Docker CE</h2>
<p>首先运行命令更新apt索引：</p>
<pre><code>$ sudo apt-get update
</code></pre>
<p>然后根据上文提到的方法安装新版本。</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[使用Docker搭建Ghost博客]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>对于想搭建自己博客的人来说，可选择的平台有很多，比如功能强大的<a href="https://cn.wordpress.org/">WordPress</a>、可运行在<a href="https://pages.github.com/">GitHub Pages</a>上的静态博客平台<a href="https://hexo.io/">Hexo</a>和<a href="https://jekyllrb.com/">jekyll</a>，以及本文介绍的博客平台<a href="https://github.com/TryGhost/Ghost">Ghost</a>。各平台各有优劣，本文不作赘述，重点介绍如何自己搭建一个可用的Ghost博客。</p>
<p>总体来说可通过两个docker run命令，分别运行Ghost博客和Nginx服务器即可，但运行前需要进行相关的配置。</p>
<h2 id="1">1. 前期准备</h2>
<p>搭建该平台需要准备如下的内容：</p>
<ul>
<li>一个公网可访问的服务器，如可使用<a href="https://www.aliyun.com/product/ecs">阿里云服务器</a>。服务器建议安装64位的Linux系统，并安装docker。</li>
<li>一个域名，也可不使用域名，直接通过IP地址访问。本文以本博客使用的域名blog.datarepo.cn为例。</li>
</ul>
<h2 id="2ghost">2. 配置并运行Ghost博客</h2>
<p>使用Docker安装Ghost可以省掉配置环境的繁琐过程。但需要将配置信息、主题及博客内容存储在本地，以防止Docker运行停止造成的数据丢失。</p>
<p>下面是Ghost中存放这些信息的路径：</p>
<ul>
<li>配置文件：/var/lib/ghost/config.production.json和/var/lib/</li></ul>]]></description><link>https://www.datarepo.cn/2018/03/14/build-ghost-blog-using-docker/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c1</guid><category><![CDATA[Technology]]></category><dc:creator><![CDATA[Julian Wang]]></dc:creator><pubDate>Wed, 14 Mar 2018 03:18:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-ghost-blog.jpeg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-ghost-blog.jpeg" alt="使用Docker搭建Ghost博客"><p>对于想搭建自己博客的人来说，可选择的平台有很多，比如功能强大的<a href="https://cn.wordpress.org/">WordPress</a>、可运行在<a href="https://pages.github.com/">GitHub Pages</a>上的静态博客平台<a href="https://hexo.io/">Hexo</a>和<a href="https://jekyllrb.com/">jekyll</a>，以及本文介绍的博客平台<a href="https://github.com/TryGhost/Ghost">Ghost</a>。各平台各有优劣，本文不作赘述，重点介绍如何自己搭建一个可用的Ghost博客。</p>
<p>总体来说可通过两个docker run命令，分别运行Ghost博客和Nginx服务器即可，但运行前需要进行相关的配置。</p>
<h2 id="1">1. 前期准备</h2>
<p>搭建该平台需要准备如下的内容：</p>
<ul>
<li>一个公网可访问的服务器，如可使用<a href="https://www.aliyun.com/product/ecs">阿里云服务器</a>。服务器建议安装64位的Linux系统，并安装docker。</li>
<li>一个域名，也可不使用域名，直接通过IP地址访问。本文以本博客使用的域名blog.datarepo.cn为例。</li>
</ul>
<h2 id="2ghost">2. 配置并运行Ghost博客</h2>
<p>使用Docker安装Ghost可以省掉配置环境的繁琐过程。但需要将配置信息、主题及博客内容存储在本地，以防止Docker运行停止造成的数据丢失。</p>
<p>下面是Ghost中存放这些信息的路径：</p>
<ul>
<li>配置文件：/var/lib/ghost/config.production.json和/var/lib/ghost/config.development.json</li>
<li>主题：/var/lib/ghost/content/themes/</li>
<li>博客内容：/var/lib/ghost/content/</li>
</ul>
<h3 id>配置修改</h3>
<p>Ghost的官方容器镜像中有默认的配置文件，需要对其进行修改，主要是“url”和“mail”两个字段。配置修改方式为两种，一种是在容器中修改，然后重新打包为新的镜像；另一种为在本地创建文件，然后挂载到容器中，以替换容器中的文件。本文选用第二种方法。</p>
<p>本地创建配置文件：config.production.json和config.development.json</p>
<pre><code class="language-shell"># touch config.production.json 
</code></pre>
<p>在config.production.json文件中添加如下内容，其中邮箱以163邮箱为例。也可直接下载<a href="https://raw.githubusercontent.com/traceflight/Repo4Gitalk/master/config.production.json">config.production.json</a>，并对相应的字段进行修改：</p>
<pre><code class="language-json">{
  &quot;url&quot;: &quot;yoururl&quot;,
  &quot;server&quot;: {
    &quot;port&quot;: 2368,
    &quot;host&quot;: &quot;0.0.0.0&quot;
  },
  &quot;database&quot;: {
    &quot;client&quot;: &quot;sqlite3&quot;,
    &quot;connection&quot;: {
      &quot;filename&quot;: &quot;/var/lib/ghost/content/data/ghost.db&quot;
    }
  },
  &quot;mail&quot;: {
    &quot;transport&quot;: &quot;SMTP&quot;,
    &quot;from&quot;: &quot;youremail&quot;,
    &quot;options&quot;: {
       &quot;host&quot;: &quot;smtp.163.com&quot;,
       &quot;secureConnection&quot;: true,
       &quot;port&quot;: 465,
       &quot;auth&quot;: {
         &quot;user&quot;: &quot;youremail&quot;,
         &quot;pass&quot;: &quot;yourpassword&quot;
       }
    }
  },
  &quot;logging&quot;: {
    &quot;transports&quot;: [
      &quot;file&quot;,
      &quot;stdout&quot;
    ]
  },
  &quot;process&quot;: &quot;systemd&quot;,
  &quot;paths&quot;: {
    &quot;contentPath&quot;: &quot;/var/lib/ghost/content&quot;
  }
}
</code></pre>
<p>然后复制config.production.json文件：</p>
<pre><code class="language-shell"># cp config.production.json config.development.json
</code></pre>
<p><em>在Ghost容器中，config.development.json为指向config.production.json的链接文件，理论上只需要修改config.production.json文件，但如果本地挂载该文件后，config.development.json文件的链接会发生错误，造成无法启动。</em></p>
<h3 id="gitalk">使用Gitalk作为评论组件</h3>
<p>由于国内的多说已经关闭，国外<a href="https://disqus.com/">Disqus</a>访问不稳定，本文选用<a href="https://github.com/gitalk/gitalk">Gitalk</a>作为评论组件。<a href="https://github.com/gitalk/gitalk">Gitalk</a>是基于Github issue和Preact实现的开源评论组件。实现效果见本博客最下方，或Gitalk的<a href="https://gitalk.github.io">Demo</a>。</p>
<p>为了添加评论组件，首先下载Ghost博客的默认主题<a href="https://github.com/TryGhost/Casper">Casper</a>：</p>
<pre><code class="language-shell"># mkdir content/themes/
# cd content/themes/
# git clone https://github.com/TryGhost/Casper.git
</code></pre>
<p>添加评论组件需要创建Github Application，并修改casper/post.hbs文件，配置方法详见Gitalk项目主页<a href="https://github.com/gitalk/gitalk">教程</a>。</p>
<p>修改后的post.hbs可参考文件<a href="https://raw.githubusercontent.com/traceflight/Repo4Gitalk/master/post.hbs">post.hbs</a>中的<code>Gitalk comment component</code>一段，并根据官方教程修改其中的字段。</p>
<p>使用Gitalk需要有github账号，并且在一篇文章发表之后，需要点开文章并初始化评论，其他人才可以使用。</p>
<h3 id="gitalkvalidationerror">解决Gitalk出现validation error错误问题</h3>
<p>需要注意的是，在Gitalk的配置中，<code>id</code> 字段需要格外注意，官方推荐的写法为<code>location.pathname</code> ，确保每一个文章都有不同的<code>id</code> 值。该字段用于在github中创建当前文章对应的issue，作为label添加到issue中，如果该字段设置为固定值，则只能创建一个issue，即所有文章共享相同的评论，显然这样是不可接受的。</p>
<p>同时，还需要注意的是，github在2018年2月份对issue中label的字符长度进行限制，如果<code>id</code> 字段过长(超过50个字符)，则会创建issue失败，打开文章后会显示<code>validation error</code>，详见官方<a href="https://github.com/gitalk/gitalk/issues/102">issue</a> 。</p>
<p>为了解决该问题，可以在创建文章时修改URL，使其总长度小于50字符。或者采用官方issue中DOUBIGROUP给出的方法，将<code>id</code>字段设置为<code>location.pathname</code>的md5值，具体方法为，在casper/post.hbs添加：</p>
<pre><code class="language-javascript">&lt;script src=&quot;https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js&quot;&gt;&lt;/script&gt;
</code></pre>
<p>并将<code>id</code>字段设置为：<code>md5(location.pathname)</code>。</p>
<h3 id>中文摘要截取问题</h3>
<p>当前Ghost博客对中文的支持较差，Casper主题在主页中使用post-card作为单个文章的展示，图片后的文字默认截取33个单词，但是不支持对中文字数的截取，通常会在图片后放大段的文字，展现效果不够美观。</p>
<p>本文参考<a href="http://blog.higan.me/chinese-excerpt-in-ghost/">Ghost 调教日志 - 解决中文摘要的截取问题</a>对Ghost和Casper主题代码进行了修改。包括excerpt.js文件和post-card.hbs文件，修改后的文件见<a href="https://raw.githubusercontent.com/traceflight/Repo4Gitalk/master/excerpt.js">excerpt.js</a>和<a href="https://raw.githubusercontent.com/traceflight/Repo4Gitalk/master/post-card.hbs">post-card.hbs<br>
</a>。</p>
<p>其中excerpt.js文件为Ghost博客中的代码文件，通过本地文件挂载的形式对原文件进行覆盖，post-card.hbs为Casper博客中的文件，可直接替换掉本地文件casper/partials/post-card.hbs。</p>
<h3 id>图片超出文档范围问题</h3>
<p>默认情况下由于Ghost CSS样式文件问题，博客中引入的图片会超出文章的总宽度，本文参考<a href="http://blog.higan.me/wrong-picture-size-in-ghost/">Ghost 调教日志 - 解决图片超过文章宽度</a>方法，在Ghost后台中插入代码解决。</p>
<p>在后台Settings/Code injection的Blog Header中加上如下内容：</p>
<pre><code class="language-css">&lt;style type=&quot;text/css&quot;&gt;
.post-full-content img {
    max-width: none !important;
    width: 100% !important;
}
&lt;/style&gt;
</code></pre>
<h3 id>文章第一段显示字体过大的问题</h3>
<p>Casper主题中文章的第一段字体和正文相比较大，这样浏览起来不够美观，尤其是在手机端浏览时。参考上面的做法，使用代码注入的方式，覆盖原来的CSS文件中的代码片段。</p>
<p>在后台Settings/Code injection的Blog Header中的<code>&lt;/style&gt;</code>前插入如下内容：</p>
<pre><code class="language-css">.post-template .kg-card-markdown &gt; p:first-child {
    font-size: 1em !important;
    line-height: 1.5em;
</code></pre>
<h3 id="ghost">运行Ghost镜像</h3>
<p>切换到config.production.json文件所在的目录，执行docker run命令运行Ghost镜像，并挂载本地文件：</p>
<pre><code class="language-shell"># docker run -d --name blog -p 2368:2368 \
   -v `pwd`/content/:/var/lib/ghost/content/ \
   -v `pwd`/content/themes/:/var/lib/ghost/content/themes/ \
   -v `pwd`/config.production.json:/var/lib/ghost/config.production.json \
   -v `pwd`/config.development.json:/var/lib/ghost/config.development.json \
   -v `pwd`/excerpt.js:/var/lib/ghost/current/core/server/helpers/excerpt.js \
   ghost:alpine
</code></pre>
<p>上述命令指定容器名为<code>blog</code> ，监听端口为默认的<code>2368</code> ，并分别挂载了博客内容、主题、配置文件和更改的代码文件。</p>
<p>运行上述命令之后，即可通过http://yoururl:2368端口访问博客了。</p>
<p><em>如果使用阿里云服务器，还需要设置安全组策略，打开2368端口的访问。</em></p>
<h2 id="3nginx">3. 配置并运行Nginx服务器</h2>
<p>常见的网站一般通过端口80来进行访问，实际上在上述命令中，可直接将端口映射改为<code>-p 80:2368</code> 。但是为了使服务器能够提供尽量多的Web服务，本文没有改变端口映射，而是使用Nginx进行反向代理，将访问二级域名<code>blog.datarepo.cn</code> 80端口的流量转发到Ghost服务端口。</p>
<p>本地创建Nginx配置文件default.conf ：</p>
<pre><code class="language-shell"># mkdir conf.d
# cd conf.d
# touch default.conf
</code></pre>
<p>添加如下内容：</p>
<pre><code>server {
    listen       80;
    server_name  yoururl;
   
    location / {
        proxy_pass  http://yoururl:2368;
        proxy_set_header           Host $host;
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_set_header           X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size  100m;
    }
}
</code></pre>
<p>切换到包含conf.d的文件夹下，运行Nginx服务：</p>
<pre><code class="language-shell"># docker run -d —name webserver -p 80:80 \
   -v `pwd`/conf.d/:/etc/nginx/conf.d/ \
   nginx:alpine
</code></pre>
<p>运行后，即可通过http://yoururl访问博客了。</p>
<h2 id="4">4. 博客使用</h2>
<p>博客的管理页面为http://yoururl/ghost。</p>
<p>登录后可创建用户、通过前文配置的邮箱邀请用户、撰写并发布文章、对博客进行定制等。</p>
<p>需要注意的是，当前Ghost博客的编辑器在iPhone和iPad中无法输入中文，只能在其他地方输入中文后，粘贴到编辑器中，在电脑端不受影响。该问题是Ghost使用的开源markdown编辑器CodeMirror中的bug，详见<a href="https://github.com/codemirror/CodeMirror/issues/3137">issue</a>。遗憾的是，这个问题在2015年就发现了，到现在依然没有解决。</p>
<p>Enjoy the fun of writing.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[3.14白色情人节]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>记得婚后第一次过情人节，还是在河北老家，他说带我去大河堤上兜风，我给的回礼则是四张兑换券，可以凭券兑换相应的服务，嘻嘻…今天是白色情人节，百度上说这是情人节的延续，但是我觉得和他在一起的每一天都是情人节，因为每天都很幸福👻</p>
<!--kg-card-end: markdown-->]]></description><link>https://www.datarepo.cn/2018/03/14/white-valentines-day/</link><guid isPermaLink="false">5cdc0af17a0c7700017a55c0</guid><category><![CDATA[Life]]></category><category><![CDATA[Sweet Time]]></category><dc:creator><![CDATA[Joyceqiu]]></dc:creator><pubDate>Wed, 14 Mar 2018 03:16:00 GMT</pubDate><media:content url="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-white-valentines-day.jpeg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://img-blog-julian.oss-cn-hongkong.aliyuncs.com/ghost/post-cover-white-valentines-day.jpeg" alt="3.14白色情人节"><p>记得婚后第一次过情人节，还是在河北老家，他说带我去大河堤上兜风，我给的回礼则是四张兑换券，可以凭券兑换相应的服务，嘻嘻…今天是白色情人节，百度上说这是情人节的延续，但是我觉得和他在一起的每一天都是情人节，因为每天都很幸福👻</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>