2016年11月

回到大约两年前,一些曾开发 Skype 的开发人员发行了一个漂亮的新聊天应用个程序:Wire。当我说它漂亮的时候,只是谈论它的“外貌”。Wire 具有一个许多其他聊天应用程序所没有的整洁优美的“外貌”,但这并不是它最大的卖点。

从一开始,Wire 就推销自己是世界上最注重隐私的聊天应用程序。无论是文本、语音电话,还是图表、图像等基本的内容,它都提供端到端的加密。

WhatsApp 也提供‘端到端加密’,但是考虑一下它的所有者 Facebook 为了吸引用户而把 WhatsApp 的数据分享出去。我不太相信 WhatsApp 以及它的加密手段。

使 Wire 对于我们这些 FOSS(自由/开源软件)爱好者来说更加重要的是,几个月前 Wire 开源了。几个月下来我们见到了一个用于 Linux 的 beta 版本 Wire 桌面应用程序。

除了一个包装器以外,桌面版的 Wire 并没有比 web 版多任何东西。感谢 Electron 开源项目提供了一种开发跨平台桌面应用程序的简单方式。许多其他应用程序也通过使用 Electron 为 Linux 带去了一个本地桌面应用程序,包括 Skype

WIRE 的特性:

在我们了解有关 Linux 版 Wire 应用程序的更多信息之前,让我们先快速看一下它的一些主要特性。

  • 开源应用程序
  • 针对所有类型内容的全加密
  • 无广告,无数据收集,无数据分享
  • 支持文本,语音以及视频聊天
  • 支持群聊和群电话
  • 音频过滤器(不需要吸入氦元素,只需要使用过滤器就可以用有趣的声音说话)
  • 不需要电话号码,可以使用邮箱登录
  • 优美、现代化的界面
  • 跨平台聊天应用程序,iOS,Android,Web,Mac,Windows 和 Linux 客户机均有相应版本
  • 欧洲法保护(欧洲法比美国法更注重隐私)

Wire 有一些更棒的特性,尤其是和Snapchat类似的音频过滤器。

在 Linux 上安装 WIRE

在安装 Wire 到 Linux 上之前,让我先警告你它目前还处于 beta 阶段。所以,如果你遇到一些故障,请不要生气。

Wire 有一个 64 位系统可使用的 .deb 客户端。如果你有一台 32 位或者 64 位系统的电脑,你可以使用这些技巧来找到它。你可以从下面的链接下载 .deb 文件。

如果感兴趣的话,你也可以看一看它的源代码:

这是 Wire 的默认界面,看起来像 elementary OS Loki:

你看,他们甚至还弄了一个机器人:)

你已经开始使用 Wire 了吗?如果是,你的体验是什么样的?如果没有,你将尝试一下吗?因为它现在是开源的并且可以在 Linux 上使用。


via: https://itsfoss.com/wire-messaging-linux/

作者:Abhishek Prakash 译者:ucasFL 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

前几天我尝试去创建一个仅包含我们经常在 CentOS 7 下使用的软件的本地仓库。当然,我们可以使用 curl 或者 wget 下载任何软件包,然而这些命令并不能下载要求的依赖软件包。你必须去花一些时间而且手动的去寻找和下载被安装的软件所依赖的软件包。然而,我们并不是必须这样。在这个简短的教程中,我将会带领你以两种方式下载软件包及其所有依赖包。我已经在 CentOS 7 下进行了测试,不过这些相同的步骤或许在其他基于 RPM 管理系统的发行版上也可以工作,例如 RHEL,Fedora 和 Scientific Linux。

方法 1 利用 “Downloadonly” 插件下载 RPM 软件包及其所有依赖包

我们可以通过 yum 命令的 “Downloadonly” 插件下载 RPM 软件包及其所有依赖包。

为了安装 Downloadonly 插件,以 root 身份运行以下命令。

yum install yum-plugin-downloadonly

现在,运行以下命令去下载一个 RPM 软件包。

yum install --downloadonly <package-name>

默认情况下,这个命令将会下载并把软件包保存到 /var/cache/yum/rhel-{arch}-channel/packageslocation 目录,不过,你也可以下载和保存软件包到任何位置,你可以通过 –downloaddir 选项来指定。

yum install --downloadonly --downloaddir=<directory> <package-name>

例子:

yum install --downloadonly --downloaddir=/root/mypackages/ httpd

终端输出:

Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: centos.excellmedia.net
 * epel: epel.mirror.angkasa.id
 * extras: centos.excellmedia.net
 * updates: centos.excellmedia.net
Resolving Dependencies
--> Running transaction check
---> Package httpd.x86_64 0:2.4.6-40.el7.centos.4 will be installed
--> Processing Dependency: httpd-tools = 2.4.6-40.el7.centos.4 for package: httpd-2.4.6-40.el7.centos.4.x86_64
--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-40.el7.centos.4.x86_64
--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-40.el7.centos.4.x86_64
--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-40.el7.centos.4.x86_64
--> Running transaction check
---> Package apr.x86_64 0:1.4.8-3.el7 will be installed
---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed
---> Package httpd-tools.x86_64 0:2.4.6-40.el7.centos.4 will be installed
---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=======================================================================================================================================
 Package Arch Version Repository Size
=======================================================================================================================================
Installing:
 httpd x86_64 2.4.6-40.el7.centos.4 updates 2.7 M
Installing for dependencies:
 apr x86_64 1.4.8-3.el7 base 103 k
 apr-util x86_64 1.5.2-6.el7 base 92 k
 httpd-tools x86_64 2.4.6-40.el7.centos.4 updates 83 k
 mailcap noarch 2.1.41-2.el7 base 31 k

Transaction Summary
=======================================================================================================================================
Install 1 Package (+4 Dependent packages)

Total download size: 3.0 M
Installed size: 10 M
Background downloading packages, then exiting:
(1/5): apr-1.4.8-3.el7.x86_64.rpm | 103 kB 00:00:01 
(2/5): apr-util-1.5.2-6.el7.x86_64.rpm | 92 kB 00:00:01 
(3/5): mailcap-2.1.41-2.el7.noarch.rpm | 31 kB 00:00:01 
(4/5): httpd-tools-2.4.6-40.el7.centos.4.x86_64.rpm | 83 kB 00:00:01 
(5/5): httpd-2.4.6-40.el7.centos.4.x86_64.rpm | 2.7 MB 00:00:09 
---------------------------------------------------------------------------------------------------------------------------------------
Total 331 kB/s | 3.0 MB 00:00:09 
exiting because "Download Only" specified

现在去你指定的目录位置下,你将会看到那里有下载好的软件包和依赖的软件。在我这种情况下,我已经把软件包下载到 /root/mypackages/ 目录下。

让我们来查看一下内容。

ls /root/mypackages/

样本输出:

apr-1.4.8-3.el7.x86_64.rpm
apr-util-1.5.2-6.el7.x86_64.rpm
httpd-2.4.6-40.el7.centos.4.x86_64.rpm
httpd-tools-2.4.6-40.el7.centos.4.x86_64.rpm
mailcap-2.1.41-2.el7.noarch.rpm

正如你在上面输出所看到的, httpd软件包已经被依据所有依赖性下载完成了 。

请注意,这个插件适用于 yum install/yum update, 但是并不适用于 yum groupinstall。默认情况下,这个插件将会下载仓库中最新可用的软件包。然而你可以通过指定版本号来下载某个特定的软件版本。

例子:

yum install --downloadonly --downloaddir=/root/mypackages/ httpd-2.2.6-40.el7

此外,你也可以如下一次性下载多个包:

yum install --downloadonly --downloaddir=/root/mypackages/ httpd vsftpd

方法 2 使用 “Yumdownloader” 工具来下载 RPM 软件包及其所有依赖包

“Yumdownloader” 是一款简单,但是却十分有用的命令行工具,它可以一次性下载任何 RPM 软件包及其所有依赖包。

以 root 身份运行如下命令安装 “Yumdownloader” 工具。

yum install yum-utils

一旦安装完成,运行如下命令去下载一个软件包,例如 httpd。

yumdownloader httpd

为了根据所有依赖性下载软件包,我们使用 --resolve 参数:

yumdownloader --resolve httpd

默认情况下,Yumdownloader 将会下载软件包到当前工作目录下。

为了将软件下载到一个特定的目录下,我们使用 --destdir 参数:

yumdownloader --resolve --destdir=/root/mypackages/ httpd

或者,

yumdownloader --resolve --destdir /root/mypackages/ httpd

终端输出:

Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: centos.excellmedia.net
 * epel: epel.mirror.angkasa.id
 * extras: centos.excellmedia.net
 * updates: centos.excellmedia.net
--> Running transaction check
---> Package httpd.x86_64 0:2.4.6-40.el7.centos.4 will be installed
--> Processing Dependency: httpd-tools = 2.4.6-40.el7.centos.4 for package: httpd-2.4.6-40.el7.centos.4.x86_64
--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-40.el7.centos.4.x86_64
--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-40.el7.centos.4.x86_64
--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-40.el7.centos.4.x86_64
--> Running transaction check
---> Package apr.x86_64 0:1.4.8-3.el7 will be installed
---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed
---> Package httpd-tools.x86_64 0:2.4.6-40.el7.centos.4 will be installed
---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed
--> Finished Dependency Resolution
(1/5): apr-util-1.5.2-6.el7.x86_64.rpm | 92 kB 00:00:01 
(2/5): mailcap-2.1.41-2.el7.noarch.rpm | 31 kB 00:00:02 
(3/5): apr-1.4.8-3.el7.x86_64.rpm | 103 kB 00:00:02 
(4/5): httpd-tools-2.4.6-40.el7.centos.4.x86_64.rpm | 83 kB 00:00:03 
(5/5): httpd-2.4.6-40.el7.centos.4.x86_64.rpm | 2.7 MB 00:00:19

让我们确认一下软件包是否被下载到我们指定的目录下。

ls /root/mypackages/

终端输出:

apr-1.4.8-3.el7.x86_64.rpm
apr-util-1.5.2-6.el7.x86_64.rpm
httpd-2.4.6-40.el7.centos.4.x86_64.rpm
httpd-tools-2.4.6-40.el7.centos.4.x86_64.rpm
mailcap-2.1.41-2.el7.noarch.rpm

不像 Downloadonly 插件,Yumdownload 可以下载一组相关的软件包。

yumdownloader "@Development Tools" --resolve --destdir /root/mypackages/

在我看来,我喜欢 Yumdownloader 更胜于 Yum 的 Downloadonly 插件。但是,两者都是十分简单易懂而且可以完成相同的工作。

这就是今天所有的内容,如果你觉得这份引导教程有用,清在你的社交媒体上面分享一下去让更多的人知道。

干杯!


via: https://www.ostechnix.com/download-rpm-package-dependencies-centos/

作者:SK 译者:LinuxBars 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

设置一个高强度的密码是非常重要的,这样才能够很好的保护自己的账号或者服务器以及确保自己的数据的安全。通常来说,一个高强度密码至少有 14 个字符,包括大小写字母、数字和特殊字符,并且要牢记永远不用那些字典中的单词。使用长密码比短密码要来的安全,因为密码越长越难猜测。在本文中,我将给你介绍几个不同方法,让你可以在 Linux 命令行下生成一个高强度密码。

使用 openssl 生成高强度密码

这里使用 openssl 的 rand 方法,它会生成一个 14 位字符的随机字符:

openssl rand -base64 14

使用 urandom 生成高强度密码

这里我们将使用 tr 条件来过滤 /dev/urandom 的输出,从而删掉那些不想要的字符,并打印出第一个出现的 14 位字符。

< /dev/urandom tr -dc A-Za-z0-9 | head -c14; echo

使用 pwgen 生成高强度密码

pwgen 是一个生成随机、无特殊含义但可以正常拼读的密码。

安装 pwgen,运行:

sudo apt-get install pwgen

安装好之后,使用以下命令来生成一个 14 位随机字符:

pwgen 14 1

你也可以使用以下标记:

  • -c 或 --capitalize 生成的密码中至少包含一个大写字母
  • -A 或 --no-capitalize 生成的密码中不含大写字母
  • -n 或 --numerals 生成的密码中至少包含一个数字
  • -0 或 --no-numerals 生成的密码中不含数字
  • -y 或 --symbols 生成的密码中至少包含一个特殊字符
  • -s 或 --secure 生成一个完全随机的密码
  • -B 或 --ambiguous 生成的密码中不含 易混淆字符 ambiguous characters
  • -h 或 --help 输出帮助信息
  • -H 或 --sha1=path/to/file[#seed] 使用指定文件的 sha1 哈希值作为随机生成器
  • -C 按列输出生成的密码
  • -1 不按列输出生成的密码
  • -v 或 --no-vowels 不使用任何元音,以免意外生成让人讨厌的单词

使用 gpg 生成高强度密码

我们也可以使用 gpg 工具来生成一个 14 位字符的密码:

gpg --gen-random --armor 1 14

其它方法

当然,可能还有很多方法可以生成一个高强度密码。比方说,你可以添加以下 bash shell 方法到 ~/.bashrc 文件:

genpasswd() { 
    strings /dev/urandom | grep -o '[[:alnum:]]' | head -n 14 | tr -d '\n'; echo
}

当你想要生成一个高强度的随机密码时,运行 genpasswd 就好了。


via: https://www.rosehosting.com/blog/generate-password-linux-command-line/

作者:RoseHosting 译者:GHLandy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

对于新手来说,Git 是一个自由、开源、高效的分布式版本控制系统(VCS),它是基于速度、高性能以及数据一致性而设计的,以支持从小规模到大体量的软件开发项目。

Git 是一个可以让你追踪软件改动、版本回滚以及创建另外一个版本的目录和文件的软件仓库。

Git 主要是用 C 语言来写的,混杂了少量的 Perl 脚本和各种 shell 脚本。它主要在 Linux 内核上运行,并且有以下列举的卓越的性能:

  • 易于上手
  • 运行速度飞快,且大部分操作在本地进行,因此,它极大的提升了那些需要与远程服务器通信的集中式系统的速度。
  • 高效
  • 提供数据一致性检查
  • 支持低开销的本地分支
  • 提供非常便利的暂存区
  • 可以集成其它工具来支持多种工作流

在这篇操作指南中,我们将介绍在 CentOS/RHEL 7/6 和 Fedora 20-24 Linux 发行版上安装 Git 的必要步骤以及怎么配置 Git,以便于你可以快速开始工作。

使用 Yum 安装 Git

我们将从系统默认的仓库安装 Git,并通过运行以下 YUM 包管理器 的更新命令来确保你系统的软件包都是最新的:

# yum update

接着,通过以下命令来安装 Git:

# yum install git

在 Git 成功安装之后,你可以通过以下命令来显示 Git 安装的版本:

# git --version

检查 Git 的安装版本

检查 Git 安装的版本

注意:从系统默认仓库安装的 Git 会是比较旧的版本。如果你想拥有最新版的 Git,请考虑使用以下说明来编译源代码进行安装。

从源代码安装 Git

开始之前,你首先需要从系统默认仓库安装所需的软件依赖包,以及从源代码构建二进制文件所需的实用工具:

# yum groupinstall "Development Tools"
# yum install gettext-devel openssl-devel perl-CPAN perl-devel zlib-devel

安装所需的软件依赖包之后,转到官方的 Git 发布页面,抓取最新版的 Git 并使用下列命令编译它的源代码:

# wget https://github.com/git/git/archive/v2.10.1.tar.gz -O git.tar.gz
# tar -zxf git.tar.gz
# cd git-2.10.1/
# make configure
# ./configure --prefix=/usr/local
# make install
# git --version

检查 Git 的安装版本

检查 Git 的安装版本

推荐阅读: Linux 下 11 个最好用的 Git 客户端和 Git 仓库查看器

在 Linux 设置 Git 账户

在这个环节中,我们将介绍如何使用正确的用户信息(如:姓名、邮件地址)和 git config 命令来设置 Git 账户,以避免出现提交错误。

注意:确保将下面的 username 替换为在你的系统上创建和使用的 Git 用户的真实名称。

你可以使用下面的 useradd 命令 创建一个 Git 用户,其中 -m 选项用于在 /home 目录下创建用户主目录,-s 选项用于指定用户默认的 shell。

# useradd -m -s /bin/bash username
# passwd username

现在,将新用户添加到 wheel 用户组以启用其使用 sudo 命令的权限:

# usermod username -aG wheel

创建 Git 用户账号

创建 Git 用户账号

然后通过以下命令使用新用户配置 Git:

# su username
$ sudo git config --global user.name "Your Name"
$ sudo git config --global user.email "[email protected]"

现在通过下面的命令校验 Git 的配置。

$ sudo git config --list

如果配置没有错误的话,你应该能够看到类似以下详细信息的输出:

user.name=username
user.email= [email protected]

在 Linux 设置 Git 用户

在 Linux 设置 Git 用户

总结

在这个简单的教程中,我们已经了解怎么在你的 Linux 系统上安装 Git 以及配置它。我相信你应该可以驾轻就熟。


via: http://www.tecmint.com/install-git-centos-fedora-redhat/

作者:Aaron Kili 译者:OneNewLife 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

昨晚偶尔清理 Chrome 插件时发现我的 “HTTP/2 and SPDY indicator”插件好像好久没亮了。这个插件在你访问到一个支持 HTTP/2 (或之前的 SPDY 协议)的网站时会点亮,而我明明记得之前专门让 https://linux.cn/ 支持了 HTTP/2 。

我的第一反应是不是这个插件有问题了?于是打开 Chrome 调试工具,然后发现,真的是请求和响应都是 HTTP/1.1 哎!

经过一番研究,原来是从 Chrome 51 开始,在 2016 年 5 月 31 日之前,对支持 NPN 协商协议的 HTTP/2 网站还会采用 HTTP/2 访问;而之后就只支持 ALPN 协商协议的 HTTP/2 网站了——而目前 ALPN 协议仅被鲜少有发行版支持 openssl-1.0.2 支持。

发生了什么?

服务器端

我们知道,最初的 Web 访问协议是 HTTP/1,包括以前的 HTTP/1.0 和现在大部分网站采用的 HTTP/1.1(HTTP/0.9 是试验性协议,已经废弃)。但是随着 Web 应用越来越复杂,之前的 HTTP/1.x 协议就看起来不能满足日益庞杂的 Web 服务需求了。比如说,明文请求、请求复用等问题。因此,谷歌就开发了一个新的传输层协议,名为 SPDY。由于这个新的协议用了的人都说好,因此谷歌就把这个协议提交到了 IETF,然后大家觉得,SPDY 这名字不好听(SPDY 是谷歌的注册商标),就干脆叫 HTTP/2 吧!

SPDY 协议是基于 SSL/TLS 的,谷歌开发了一个名为 下一代协议协商 Next Protocol Negotiation (NPN)的 SSL/TLS 扩展,用于在客户端连接服务器时协商是否采用 HTTP/2 协议。SPDY 协议是由 Web 服务器所实现支持的,而 NPN 则是由 OpenSSL 等 SSL 实现支持的。

但是,随着 SPDY 被提交到 IETF,然后变成了 HTTP/2 协议,谷歌也放弃了 SPDY 的开发,全力投入到了 HTTP/2 的开发中,之前所采用 NPN 也被一种新的协商协议 ALPN —— 应用层协议协商 Application-Layer Protocol Negotiation 所替代。NPN 和 ALPN 是不兼容的,它们的主要不同是:

  • NPN 是服务器发送所支持的协议列表,由客户端进行选择。而 ALPN 则是客户端发送该列表,由服务端选择。
  • 在 NPN 中,最终的选择结果是在 Change Cipher Spec 之后发送给服务端的,也就是说是被加密了的。而在 ALPN 中,所有的协商都是明文的。

这样做的好处主要是安全性方面的考虑,但是这造成了一个问题就是,NPN 已经广泛地被 OpenSSL 支持,而 ALPN 则目前只有最新的 openssl-1.0.2 才支持。当前的几个主流 Linux 发行版的 OpenSSL 版本以及支持的协商协议如下:

Linux 发行版OpenSSL 版本所支持的协商协议
CentOS/Oracle Linux/RHEL 5.10+0.9.8e不支持
CentOS/Oracle Linux/RHEL 6.5+, 7.0+1.0.1eNPN
Ubuntu 12.04 LTS1.0.1NPN
Ubuntu 14.04 LTS1.0.1fNPN
Ubuntu 16.04 LTS1.0.2gALPN 和 NPN
Debian 7.01.0.1eNPN
Debian 8.01.0.1kNPN

从上面我们可以看到,基本上所有的服务器级的 Linux 发行版都不支持 OpenSSL 及 ALPN,唯一支持的 Ubuntu 16.04 LTS 显然用的不会很多。不要小看这 0.0.1 的版本差异,对于别的软件来说这 0.0.1 的差异基本上可以忽略,但是对于 OpenSSL 来说,那就是两个版本代际。OpenSSL 是个相当底层的库,很多重要的软件都依赖于它,因此各个发行版在升级 OpenSSL 时采用的态度是相当保守,比如我们可以看看 CentOS 系统中有哪些软件使用了 OpenSSL:

$ lsof | grep libssl | awk '{print $1}' | sort | uniq
anvil
fail2ban
gdbus
gmain
httpd
postfix
mysqld
NetworkManager
nginx
php-fpm
puppet
sshd
sudo
tuned
zabbix_agent

没有经过足够的测试,Linux 发行版是不会在产品级(服务器级)的环境中随便升级的。为了解决旧版本(1.0.1)中的安全问题,他们宁可将新的版本(1.0.2)中安全修复移植回旧版本,也不会升级到有新功能的新版本(1.0.2),这就是你见到了各种 1.0.1e、1.0.1k 这样的版本号的原因。

当然,你可以自己编译一个最新 OpenSSL 替代你系统中的 openssl-1.0.1,但是我想你不会这样做的,是吧?

顺便提一句,NPN 和 ALPN 可以并存,但是会客户端会优先选择 ALPN。

浏览器端(Chrome)

从 Chrome 51 开始,谷歌就去掉了对 SPDY 的支持,不过这不是个事,因为不但使用 SPDY 的 Web 服务器比较少,而且从 SPDY 升级到 HTTP/2 也很简单,这方面 Nginx、Apache 等服务器的配置都很简单。

但不幸的是,在 Chrome 51 中,谷歌也去掉了对 NPN 的支持!如果你的 Web 服务器使用的是 openssl-1.0.2 以下的版本,不支持 ALPN 协商,那么 Chrome 51 及以后版本就会以 HTTP/1 协议访问你的网站。

谷歌对放弃 NPN 支持做了一个简短的解释,但是不管怎么说,NPN 协议在 Chrome 51 之后的版本不会再次回来了。而另一方面,OpenSSL 在 2016 年 12 月 31 日之后也不会继续发布 openssl-1.0.1 系列的新版本了,安全修复到此为止。

而在这种情况下,你原本支持 HTTP/2 的网站通过连接复用等 HTTP/2 所提供的新特性,在 Chrome 下访问取得了不错的体验,而现在又跌回了之前的残旧状态。

怎么办呢?

有几种办法:

换浏览器

山不来就我,我去就山。Chrome 51+ 不支持带 NPN 的 HTTP/2 网站,作为浏览者,你可以使用其它的浏览器,比如 Safari、Edge 之类的。这样,你就可以用新的协议来访问世界上那 10% 支持 HTTP/2 的 Web 服务器了。

但是,作为服务器运营者,你却不能忽视高达 50% 以上的 Chrome 用户

换服务器

如上面所示,Ubuntu 16.04 LTS 是目前唯一官方支持 openssl-1.0.2 的 Linux 发行版,如果你一直采用 Ubuntu 做服务器,考虑一下升级吧。LTS 版本的支持期长达五年。

当然,在产品环境中,即便你是 Ubuntu 服务器,更新版本也是一件重大事宜,宜慎思之。

重新编译

既然换服务器不是一个好的选择,那你还有一个方案,就是使用新的 openssl-1.0.2 源代码重新编译你的 Web 服务器,比如 nginx。

下面我简单介绍一下如何用 openssl-1.0.2 来编译 nginx。(1.0.2 系列的最新版本是 1.0.2j,当然你要非用 1.1.0,我也无话可说……)

首先下载并解压 openssl-1.0.2j:

# wget https://www.openssl.org/source/openssl-1.0.2j.tar.gz
# tar -zxvf openssl-1.0.2j.tar.gz

然后在编译 nginx 的时候使用 --with-openssl=../openssl-1.0.2j 选项以及你的其它选项:

./configure --with-openssl=../openssl-1.0.2j --with-http_v2_module --with-http_ssl_module

配置并编译之后,你可以用 nginx -V来看一下你的 nginx 中的 OpenSSL 版本。

这种自行编译的好处是灵活性高,但是你需要随时注意各个组件是否有严重的安全漏洞,并在出了修复版本之后重新编译。

容器

除了自己编译之外,如果你的系统环境中已经有了容器支持,你还可以在容器中运行一个 Ubuntu 16.04 LTS,并将 Web 服务器运行在其中。

总结

以上就是 HTTP/2 和 Chrome 之间的故事,你准备去升级 HTTP/2 支持了吗?要知道相比 HTTP/2 的访问体验,你肯定不会想再回到 HTTP/1 了。

这篇文章基于我之前的文章 .NET Core 入门。首先,我把 RESTful API 从 .NET Core RC1 升级到了 .NET Core 1.0,然后,我增加了对 Docker 的支持并描述了如何在 Linux 生产环境里托管它。

我是首次接触 Docker 并且距离成为一名 Linux 高手还有很远的一段路程。因此,这里的很多想法是来自一个新手。

安装

按照 https://www.microsoft.com/net/core 上的介绍在你的电脑上安装 .NET Core 。这将会同时在 Windows 上安装 dotnet 命令行工具以及最新的 Visual Studio 工具。

源代码

你可以直接到 GitHub 上找最到最新完整的源代码。

转换到 .NET CORE 1.0

自然地,当我考虑如何把 API 从 .NET Core RC1 升级到 .NET Core 1.0 时想到的第一个求助的地方就是谷歌搜索。我是按照下面这两条非常全面的指导来进行升级的:

当你迁移代码的时候,我建议仔细阅读这两篇指导,因为我在没有阅读第一篇指导的情况下又尝试浏览第二篇,结果感到非常迷惑和沮丧。

我不想描述细节上的改变因为你可以看 GitHub 上的提交。这儿是我所作改变的总结:

  • 更新 global.jsonproject.json 上的版本号
  • 删除 project.json 上的废弃章节
  • 使用轻型 ControllerBase 而不是 Controller, 因为我不需要与 MVC 视图相关的方法(这是一个可选的改变)。
  • 从辅助方法中去掉 Http 前缀,比如:HttpNotFound -> NotFound
  • LogVerbose -> LogTrace
  • 名字空间改变: Microsoft.AspNetCore.*
  • Startup 中使用 SetBasePath(没有它 appsettings.json 将不会被发现)
  • 通过 WebHostBuilder 来运行而不是通过 WebApplication.Run 来运行
  • 删除 Serilog(在写文章的时候,它不支持 .NET Core 1.0)

唯一令我真正头疼的事是需要移动 Serilog。我本可以实现自己的文件记录器,但是我删除了文件记录功能,因为我不想为了这次操作在这件事情上花费精力。

不幸的是,将有大量的第三方开发者扮演追赶 .NET Core 1.0 的角色,我非常同情他们,因为他们通常在休息时间还坚持工作但却依旧根本无法接近靠拢微软的可用资源。我建议阅读 Travis Illig 的文章 .NET Core 1.0 发布了,但 Autofac 在哪儿?这是一篇关于第三方开发者观点的文章。

做了这些改变以后,我可以从 project.json 目录恢复、构建并运行 dotnet,可以看到 API 又像以前一样工作了。

通过 Docker 运行

在我写这篇文章的时候, Docker 只能够在 Linux 系统上工作。在 Windows 系统和 OS X 上有 beta 支持 Docker,但是它们都必须依赖于虚拟化技术,因此,我选择把 Ubuntu 14.04 当作虚拟机来运行。如果你还没有安装过 Docker,请按照指导来安装。

我最近阅读了一些关于 Docker 的东西,但我直到现在还没有真正用它来干任何事。我假设读者还没有关于 Docker 的知识,因此我会解释我所使用的所有命令。

HELLO DOCKER

在 Ubuntu 上安装好 Docker 之后,我所进行的下一步就是按照 https://www.microsoft.com/net/core#docker 上的介绍来开始运行 .NET Core 和 Docker。

首先启动一个已安装有 .NET Core 的容器。

docker run -it microsoft/dotnet:latest

-it 选项表示交互,所以你执行这条命令之后,你就处于容器之内了,可以如你所希望的那样执行任何 bash 命令。

然后我们可以执行下面这五条命令来在 Docker 内部运行起来微软 .NET Core 控制台应用程序示例。

mkdir hwapp
cd hwapp
dotnet new
dotnet restore
dotnet run

你可以通过运行 exit 来离开容器,然后运行 Docker ps -a 命令,这会显示你创建的那个已经退出的容器。你可以通过上运行命令 Docker rm <container_name> 来清除容器。

挂载源代码

我的下一步骤是使用和上面相同的 microsoft/dotnet 镜像,但是将为我们的应用程序以数据卷的方式挂载上源代码。

首先签出有相关提交的仓库:

git clone https://github.com/niksoper/aspnet5-books.git
cd aspnet5-books/src/MvcLibrary
git checkout dotnet-core-1.0

现在启动一个容器来运行 .NET Core 1.0,并将源代码放在 /book 下。注意更改 /path/to/repo 这部分文件来匹配你的电脑:

docker run -it \
-v /path/to/repo/aspnet5-books/src/MvcLibrary:/books \
microsoft/dotnet:latest

现在你可以在容器中运行应用程序了!

cd /books
dotnet restore
dotnet run

作为一个概念性展示这的确很棒,但是我们可不想每次运行一个程序都要考虑如何把源代码安装到容器里。

增加一个 DOCKERFILE

我的下一步骤是引入一个 Dockerfile,这可以让应用程序很容易在自己的容器内启动。

我的 Dockerfile 和 project.json 一样位于 src/MvcLibrary 目录下,看起来像下面这样:

FROM microsoft/dotnet:latest

# 为应用程序源代码创建目录
RUN mkdir -p /usr/src/books
WORKDIR /usr/src/books

# 复制源代码并恢复依赖关系
COPY . /usr/src/books
RUN dotnet restore

# 暴露端口并运行应用程序
EXPOSE 5000
CMD [ "dotnet", "run" ]

严格来说,RUN mkdir -p /usr/src/books 命令是不需要的,因为 COPY 会自动创建丢失的目录。

Docker 镜像是按层建立的,我们从包含 .NET Core 的镜像开始,添加另一个从源代码生成应用程序,然后运行这个应用程序的层。

添加了 Dockerfile 以后,我通过运行下面的命令来生成一个镜像,并使用生成的镜像启动一个容器(确保在和 Dockerfile 相同的目录下进行操作,并且你应该使用自己的用户名)。

docker build -t niksoper/netcore-books .
docker run -it niksoper/netcore-books

你应该看到程序能够和之前一样的运行,不过这一次我们不需要像之前那样安装源代码,因为源代码已经包含在 docker 镜像里面了。

暴露并发布端口

这个 API 并不是特别有用,除非我们需要从容器外面和它进行通信。 Docker 已经有了暴露和发布端口的概念,但这是两件完全不同的事。

据 Docker 官方文档

EXPOSE 指令通知 Docker 容器在运行时监听特定的网络端口。EXPOSE 指令不能够让容器的端口可被主机访问。要使可被访问,你必须通过 -p 标志来发布一个端口范围或者使用 -P 标志来发布所有暴露的端口

EXPOSE 指令只是将元数据添加到镜像上,所以你可以如文档中说的认为它是镜像消费者。从技术上讲,我本应该忽略 EXPOSE 5000 这行指令,因为我知道 API 正在监听的端口,但把它们留下很有用的,并且值得推荐。

在这个阶段,我想直接从主机访问这个 API ,因此我需要通过 -p 指令来发布这个端口,这将允许请求从主机上的端口 5000 转发到容器上的端口 5000,无论这个端口是不是之前通过 Dockerfile 暴露的。

docker run -d -p 5000:5000 niksoper/netcore-books

通过 -d 指令告诉 docker 在分离模式下运行容器,因此我们不能看到它的输出,但是它依旧会运行并监听端口 5000。你可以通过 docker ps 来证实这件事。

因此,接下来我准备从主机向容器发起一个请求来庆祝一下:

curl http://localhost:5000/api/books

它不工作。

重复进行相同 curl 请求,我看到了两个错误:要么是 curl: (56) Recv failure: Connection reset by peer,要么是 curl: (52) Empty reply from server

我返回去看 docker run 的文档,然后再次检查我所使用的 -p 选项以及 Dockerfile 中的 EXPOSE 指令是否正确。我没有发现任何问题,这让我开始有些沮丧。

重新振作起来以后,我决定去咨询当地的一个 Scott Logic DevOps 大师 - Dave Wybourn(也在这篇 Docker Swarm 的文章里提到过),他的团队也曾遇到这个实际问题。这个问题是我没有配置过 Kestral,这是一个全新的轻量级、跨平台 web 服务器,用于 .NET Core 。

默认情况下, Kestrel 会监听 http://localhost:5000。但问题是,这儿的 localhost 是一个回路接口。

维基百科

在计算机网络中,localhost 是一个代表本机的主机名。本地主机可以通过网络回路接口访问在主机上运行的网络服务。通过使用回路接口可以绕过任何硬件网络接口。

当运行在容器内时这是一个问题,因为 localhost 只能够在容器内访问。解决方法是更新 Startup.cs 里的 Main 方法来配置 Kestral 监听的 URL:

public static void Main(string[] args)
{
  var host = new WebHostBuilder()
    .UseKestrel()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseUrls("http://*:5000") // 在所有网络接口上监听端口 5000
    .UseIISIntegration()
    .UseStartup<Startup>()
    .Build();

  host.Run();
}

通过这些额外的配置,我可以重建镜像,并在容器中运行应用程序,它将能够接收来自主机的请求:

docker build -t niksoper/netcore-books .
docker run -d -p 5000:5000 niksoper/netcore-books
curl -i http://localhost:5000/api/books

我现在得到下面这些相应:

HTTP/1.1 200 OK
Date: Tue, 30 Aug 2016 15:25:43 GMT
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Kestrel

[{"id":"1","title":"RESTful API with ASP.NET Core MVC 1.0","author":"Nick Soper"}]

在产品环境中运行 KESTREL

微软的介绍

Kestrel 可以很好的处理来自 ASP.NET 的动态内容,然而,网络服务部分的特性没有如 IIS,Apache 或者 Nginx 那样的全特性服务器那么好。反向代理服务器可以让你不用去做像处理静态内容、缓存请求、压缩请求、SSL 端点这样的来自 HTTP 服务器的工作。

因此我需要在我的 Linux 机器上把 Nginx 设置成一个反向代理服务器。微软介绍了如何发布到 Linux 生产环境下的指导教程。我把说明总结在这儿:

  1. 通过 dotnet publish 来给应用程序产生一个自包含包。
  2. 把已发布的应用程序复制到服务器上
  3. 安装并配置 Nginx(作为反向代理服务器)
  4. 安装并配置 supervisor(用于确保 Nginx 服务器处于运行状态中)
  5. 安装并配置 AppArmor(用于限制应用的资源使用)
  6. 配置服务器防火墙
  7. 安全加固 Nginx(从源代码构建和配置 SSL)

这些内容已经超出了本文的范围,因此我将侧重于如何把 Nginx 配置成一个反向代理服务器。自然地,我通过 Docker 来完成这件事。

在另一个容器中运行 NGINX

我的目标是在第二个 Docker 容器中运行 Nginx 并把它配置成我们的应用程序容器的反向代理服务器。

我使用的是来自 Docker Hub 的官方 Nginx 镜像。首先我尝试这样做:

docker run -d -p 8080:80 --name web nginx

这启动了一个运行 Nginx 的容器并把主机上的 8080 端口映射到了容器的 80 端口上。现在在浏览器中打开网址 http://localhost:8080 会显示出 Nginx 的默认登录页面。

现在我们证实了运行 Nginx 是多么的简单,我们可以关闭这个容器。

docker rm -f web

把 NGINX 配置成一个反向代理服务器

可以通过像下面这样编辑位于 /etc/nginx/conf.d/default.conf 的配置文件,把 Nginx 配置成一个反向代理服务器:

server {
  listen 80;

  location / {
    proxy_pass http://localhost:6666;
  }
}

通过上面的配置可以让 Nginx 将所有对根目录的访问请求代理到 http://localhost:6666。记住这里的 localhost 指的是运行 Nginx 的容器。我们可以在 Nginx容器内部利用卷来使用我们自己的配置文件:

docker run -d -p 8080:80 \
-v /path/to/my.conf:/etc/nginx/conf.d/default.conf \
nginx

注意:这把一个单一文件从主机映射到容器中,而不是一个完整目录。

在容器间进行通信

Docker 允许内部容器通过共享虚拟网络进行通信。默认情况下,所有通过 Docker 守护进程启动的容器都可以访问一种叫做“桥”的虚拟网络。这使得一个容器可以被另一个容器在相同的网络上通过 IP 地址和端口来引用。

你可以通过 监测 inspect 容器来找到它的 IP 地址。我将从之前创建的 niksoper/netcore-books 镜像中启动一个容器并 监测 inspect 它:

docker run -d -p 5000:5000 --name books niksoper/netcore-books
docker inspect books

我们可以看到这个容器的 IP 地址是 "IPAddress": "172.17.0.3"

所以现在如果我创建下面的 Nginx 配置文件,并使用这个文件启动一个 Nginx 容器, 它将代理请求到我的 API :

server {
  listen 80;

  location / {
    proxy_pass http://172.17.0.3:5000;
  }
}

现在我可以使用这个配置文件启动一个 Nginx 容器(注意我把主机上的 8080 端口映射到了 Nginx 容器上的 80 端口):

docker run -d -p 8080:80 \
-v ~/dev/nginx/my.nginx.conf:/etc/nginx/conf.d/default.conf \
nginx

一个到 http://localhost:8080 的请求将被代理到应用上。注意下面 curl 响应的 Server 响应头:

DOCKER COMPOSE

在这个地方,我为自己的进步而感到高兴,但我认为一定还有更好的方法来配置 Nginx,可以不需要知道应用程序容器的确切 IP 地址。另一个当地的 Scott Logic DevOps 大师 Jason Ebbin 在这个地方进行了改进,并建议使用 Docker Compose

概况描述一下,Docker Compose 使得一组通过声明式语法互相连接的容器很容易启动。我不想再细说 Docker Compose 是如何工作的,因为你可以在之前的文章中找到。

我将通过一个我所使用的 docker-compose.yml 文件来启动:

version: '2'
services:
    books-service:
        container_name: books-api
        build: .

    reverse-proxy:
        container_name: reverse-proxy
        image: nginx
        ports:
         - "9090:8080"
        volumes:
         - ./proxy.conf:/etc/nginx/conf.d/default.conf

这是版本 2 语法,所以为了能够正常工作,你至少需要 1.6 版本的 Docker Compose。

这个文件告诉 Docker 创建两个服务:一个是给应用的,另一个是给 Nginx 反向代理服务器的。

BOOKS-SERVICE

这个与 docker-compose.yml 相同目录下的 Dockerfile 构建的容器叫做 books-api。注意这个容器不需要发布任何端口,因为只要能够从反向代理服务器访问它就可以,而不需要从主机操作系统访问它。

REVERSE-PROXY

这将基于 nginx 镜像启动一个叫做 reverse-proxy 的容器,并将位于当前目录下的 proxy.conf 文件挂载为配置。它把主机上的 9090 端口映射到容器中的 8080 端口,这将允许我们在 http://localhost:9090 上通过主机访问容器。

proxy.conf 文件看起来像下面这样:

server {
    listen 8080;

    location / {
      proxy_pass http://books-service:5000;
    }
}

这儿的关键点是我们现在可以通过名字引用 books-service,因此我们不需要知道 books-api 这个容器的 IP 地址!

现在我们可以通过一个运行着的反向代理启动两个容器(-d 意味着这是独立的,因此我们不能看到来自容器的输出):

docker compose up -d

验证我们所创建的容器:

docker ps

最后来验证我们可以通过反向代理来控制该 API :

curl -i http://localhost:9090/api/books

怎么做到的?

Docker Compose 通过创建一个新的叫做 mvclibrary_default 的虚拟网络来实现这件事,这个虚拟网络同时用于 books-apireverse-proxy 容器(名字是基于 docker-compose.yml 文件的父目录)。

通过 docker network ls 来验证网络已经存在:

你可以使用 docker network inspect mvclibrary_default 来看到新的网络的细节:

注意 Docker 已经给网络分配了子网:"Subnet": "172.18.0.0/16"/16 部分是无类域内路由选择(CIDR),完整的解释已经超出了本文的范围,但 CIDR 只是表示 IP 地址范围。运行 docker network inspect bridge 显示子网:"Subnet": "172.17.0.0/16",因此这两个网络是不重叠的。

现在用 docker inspect books-api 来确认应用程序的容器正在使用该网络:

注意容器的两个别名("Aliases")是容器标识符(3c42db680459)和由 docker-compose.yml 给出的服务名(books-service)。我们通过 books-service 别名在自定义 Nginx 配置文件中来引用应用程序的容器。这本可以通过 docker network create 手动创建,但是我喜欢用 Docker Compose,因为它可以干净简洁地将容器创建和依存捆绑在一起。

结论

所以现在我可以通过几个简单的步骤在 Linux 系统上用 Nginx 运行应用程序,不需要对主机操作系统做任何长期的改变:

git clone https://github.com/niksoper/aspnet5-books.git
cd aspnet5-books/src/MvcLibrary
git checkout blog-docker
docker-compose up -d
curl -i http://localhost:9090/api/books

我知道我在这篇文章中所写的内容不是一个真正的生产环境就绪的设备,因为我没有写任何有关下面这些的内容,绝大多数下面的这些主题都需要用单独一篇完整的文章来叙述。

  • 安全考虑比如防火墙和 SSL 配置
  • 如何确保应用程序保持运行状态
  • 如何选择需要包含的 Docker 镜像(我把所有的都放入了 Dockerfile 中)
  • 数据库 - 如何在容器中管理它们

对我来说这是一个非常有趣的学习经历,因为有一段时间我对探索 ASP.NET Core 的跨平台支持非常好奇,使用 “Configuratin as Code” 的 Docker Compose 方法来探索一下 DevOps 的世界也是非常愉快并且很有教育意义的。

如果你对 Docker 很好奇,那么我鼓励你来尝试学习它 或许这会让你离开舒适区,不过,有可能你会喜欢它?


via: http://blog.scottlogic.com/2016/09/05/hosting-netcore-on-linux-with-docker.html

作者:Nick Soper 译者:ucasFL 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出