硬核观察 #1186 每月 5 美元的虚拟机性能超过了 30 年前的第三快的超算
每月 5 美元的虚拟机性能超过了 30 年前的第三快的超算今年是全球公开的最快超级计算机 TOP500 排行榜发布 30 周年。1993 年，当时的超算榜首是位于日本国家航空航天实验室的富士通数值风洞，该系统拥有多达 140 个 CPU 内核，可实现 124 gigaFLOPS 的双精度性能。有人做了一个有趣的测试，结果表明，每月只需要 5 美元的单个 vCPU 线程的虚拟机可以与 1993 年排名第三的超级计算机明尼苏达超级计算中心相抗衡，而该系统拥有 544 个 SuperSPARC 处理器。如果升级到 4 个 vCPU 虚拟机，就可以击败当年的榜首，每个月仅需要花费 48 美元。消息来源：The Register老王点评：不算意外，只是有些吃惊。不敢想象三十年后计算机能强大到什么程度，或许地球会爆炸吧。Canonical 发布快速部署全功能私有云的 MicroCloudCanonical 公司今天发布了最新的软件产品 MicroCloud，它的目标是在 Ubuntu Linux 上轻松部署一个 “几分钟内就能实现全功能云” 的私有云。他们宣传自己的私有云部署就像使用 Snap 命令一样简单。其代码以 AGPL-3.0 许可托管在 GitHub 上。据介绍，MicroCloud 至少需要三台机器，目前可扩展到 50 台机器。消息来源：Phoronix老王点评：现在看起来，私有云有公有云不可比拟的好处，最起码重启起来比较快~DeepMind 能更快更准确地预测极端天气根据一份研究，谷歌 DeepMind 的模型 GraphCast 能够提前 10 天预测天气状况，比目前的黄金标准更准确、更快速。在 1300 多个测试区域中，GraphCast 在 90% 以上的测试中都优于欧洲中期天气预报中心的模型。最重要的是，GraphCast 还能比标准模型更早地为气象学家提供有关极端气温和气旋路径等情况的准确预警。GraphCast 使用图神经网络，将地球表面映射成 100 多万个网格点。它不使用物理方程，而是根据四十年的历史天气数据进行预测，可以利用机器学习在一分钟内完成这些计算。消息来源：Technology Review老王点评：没想到不是超算，而是人工智能拯救了天气预测难题。
像主流云提供商的处理方式一样，在家中添加机器到你的私有云。Cloud-init 是一种广泛使用的行业标准方法，用于初始化云实例。云提供商使用 Cloud-init 来定制实例的网络配置、实例信息，甚至用户提供的配置指令。它也是一个可以在你的“家庭私有云”中使用的很好的工具，可以为你的家庭实验室的虚拟机和物理机的初始设置和配置添加一点自动化 —— 并了解更多关于大型云提供商是如何工作的信息。关于更多的细节和背景，请看我之前的文章《在你的树莓派家庭实验室中使用 Cloud-init》。运行 Cloud-init 的 Linux 服务器的启动过程（Chris Collins，CC BY-SA 4.0）诚然，Cloud-init 对于为许多不同客户配置机器的云提供商来说，比对于由单个系统管理员运行的家庭实验室更有用，而且 Cloud-init 解决的许多问题对于家庭实验室来说可能有点多余。然而，设置它并了解它的工作原理是了解更多关于这种云技术的好方法，更不用说它是首次启动时配置设备的好方法。本教程使用 Cloud-init 的 NoCloud 数据源，它允许 Cloud-init 在传统的云提供商环境之外使用。本文将向你展示如何在客户端设备上安装 Cloud-init，并设置一个运行 Web 服务的容器来响应客户端的请求。你还将学习如何审查客户端从 Web 服务中请求的内容，并修改 Web 服务的容器，以提供基本的、静态的 Cloud-init 服务。在现有系统上设置 Cloud-initCloud-init 可能在新系统首次启动时最有用，它可以查询配置数据，并根据指令对系统进行定制。它可以包含在树莓派和单板计算机的磁盘镜像中，也可以添加到用于 配给 provision 虚拟机的镜像中。对于测试用途来说，无论是在现有系统上安装并运行 Cloud-init，还是安装一个新系统，然后设置 Cloud-init，都是很容易的。作为大多数云提供商使用的主要服务，大多数 Linux 发行版都支持 Cloud-init。在这个例子中，我将使用 Fedora 31 Server 来安装树莓派，但在 Raspbian、Ubuntu、CentOS 和大多数其他发行版上也可以用同样的方式来完成。安装并启用云计算初始服务在你想作为 Cloud-init 客户端的系统上，安装 Cloud-init 包。如果你使用的是 Fedora：# Install the cloud-init package dnf install -y cloud-init Cloud-init 实际上是四个不同的服务（至少在 systemd 下是这样），这些服务负责检索配置数据，并在启动过程的不同阶段进行配置更改，这使得可以做的事情更加灵活。虽然你不太可能直接与这些服务进行太多交互，但在你需要排除一些故障时，知道它们是什么还是很有用的。它们是：cloud-init-local.servicecloud-init.servicecloud-config.servicecloud-final.service启用所有四个服务：# Enable the four cloud-init services systemctl enable cloud-init-local.service systemctl enable cloud-init.service systemctl enable cloud-config.service systemctl enable cloud-final.service 配置数据源以查询启用服务后，请配置数据源，客户端将从该数据源查询配置数据。有许多数据源类型，而且大多数都是为特定的云提供商配置的。对于你的家庭实验室，请使用 NoCloud 数据源，（如上所述）它是为在没有云提供商的情况下使用 Cloud-init 而设计的。NoCloud 允许以多种方式包含配置信息：以内核参数中的键/值对，用于在启动时挂载的 CD（或虚拟机中的虚拟 CD）；包含在文件系统中的文件中；或者像本例中一样，通过 HTTP 从指定的 URL（“NoCloud Net” 选项）获取配置信息。数据源配置可以通过内核参数提供，也可以在 Cloud-init 配置文件 /etc/cloud/cloud.cfg 中进行设置。该配置文件对于使用自定义磁盘镜像设置 Cloud-init 或在现有主机上进行测试非常方便。Cloud-init 还会合并在 /etc/cloud/cloud.cfg.d/ 中找到的任何 *.cfg 文件中的配置数据，因此为了保持整洁，请在 /etc/cloud/cloud.cfg.d/10_datasource.cfg 中配置数据源。Cloud-init 可以通过使用以下语法从 seedfrom 键指向的 HTTP 数据源中读取数据。seedfrom: http://ip_address:port/ IP 地址和端口是你将在本文后面创建的 Web 服务。我使用了我的笔记本电脑的 IP 和 8080 端口。这也可以是 DNS 名称。创建 /etc/cloud/cloud.cfg.d/10_datasource.cfg 文件：# Add the datasource: # /etc/cloud/cloud.cfg.d/10_datasource.cfg # NOTE THE TRAILING SLASH HERE! datasource: NoCloud: seedfrom: http://ip_address:port/ 客户端设置就是这样。现在，重新启动客户端后，它将尝试从你在 seedfrom 键中输入的 URL 检索配置数据，并进行必要的任何配置更改。下一步是设置一个 Web 服务器来侦听客户端请求，以便你确定需要提供的服务。设置网络服务器以审查客户请求你可以使用 Podman 或其他容器编排工具（如 Docker 或 Kubernetes）快速创建和运行 Web 服务器。这个例子使用的是 Podman，但同样的命令也适用于 Docker。要开始，请使用 fedora:31 容器镜像并创建一个容器文件（对于 Docker 来说，这会是一个 Dockerfile）来安装和配置 Nginx。从该容器文件中，你可以构建一个自定义镜像，并在你希望提供 Cloud-init 服务的主机上运行它。创建一个包含以下内容的容器文件：FROM fedora:31 ENV NGINX_CONF_DIR "/etc/nginx/default.d" ENV NGINX_LOG_DIR "/var/log/nginx" ENV NGINX_CONF "/etc/nginx/nginx.conf" ENV WWW_DIR "/usr/share/nginx/html" # Install Nginx and clear the yum cache RUN dnf install -y nginx \ && dnf clean all \ && rm -rf /var/cache/yum # forward request and error logs to docker log collector RUN ln -sf /dev/stdout ${NGINX_LOG_DIR}/access.log \ && ln -sf /dev/stderr ${NGINX_LOG_DIR}/error.log # Listen on port 8080, so root privileges are not required for podman RUN sed -i -E 's/(listen)([[:space:]]*)(\[\:\:\]\:)?80;$/\1\2\38080 default_server;/' $NGINX_CONF EXPOSE 8080 # Allow Nginx PID to be managed by non-root user RUN sed -i '/user nginx;/d' $NGINX_CONF RUN sed -i 's/pid \/run\/nginx.pid;/pid \/tmp\/nginx.pid;/' $NGINX_CONF # Run as an unprivileged user USER 1001 CMD ["nginx", "-g", "daemon off;"] 注：本例中使用的容器文件和其他文件可以在本项目的 GitHub 仓库中找到。上面容器文件中最重要的部分是改变日志存储方式的部分（写到 STDOUT 而不是文件），这样你就可以在容器日志中看到进入该服务器的请求。其他的一些改变使你可以在没有 root 权限的情况下使用 Podman 运行容器，也可以在没有 root 权限的情况下运行容器中的进程。在 Web 服务器上的第一个测试并不提供任何 Cloud-init 数据；只是用它来查看 Cloud-init 客户端的请求。创建容器文件后，使用 Podman 构建并运行 Web 服务器镜像：# Build the container image $ podman build -f Containerfile -t cloud-init:01 . # Create a container from the new image, and run it # It will listen on port 8080 $ podman run --rm -p 8080:8080 -it cloud-init:01 这会运行一个容器，让你的终端连接到一个伪 TTY。一开始看起来什么都没有发生，但是对主机 8080 端口的请求会被路由到容器内的 Nginx 服务器，并且在终端窗口中会出现一条日志信息。这一点可以用主机上的 curl 命令进行测试。# Use curl to send an HTTP request to the Nginx container $ curl http://localhost:8080 运行该 curl 命令后，你应该会在终端窗口中看到类似这样的日志信息：127.0.0.1 - - [09/May/2020:19:25:10 +0000] "GET / HTTP/1.1" 200 5564 "-" "curl/7.66.0" "-" 现在，有趣的部分来了：重启 Cloud-init 客户端，并观察 Nginx 日志，看看当客户端启动时， Cloud-init 向 Web 服务器发出了什么请求。当客户端完成其启动过程时，你应该会看到类似的日志消息。2020/05/09 22:44:28 [error] 2#0: *4 open() "/usr/share/nginx/html/meta-data" failed (2: No such file or directory), client: 127.0.0.1, server: _, request: "GET /meta-data HTTP/1.1", host: "instance-data:8080" 127.0.0.1 - - [09/May/2020:22:44:28 +0000] "GET /meta-data HTTP/1.1" 404 3650 "-" "Cloud-Init/17.1" "-" 注：使用 Ctrl+C 停止正在运行的容器。你可以看到请求是针对 /meta-data 路径的，即 http://ip_address_of_the_webserver:8080/meta-data。这只是一个 GET 请求 —— Cloud-init 并没有向 Web 服务器发送任何数据。它只是盲目地从数据源 URL 中请求文件，所以要由数据源来识别主机的要求。这个简单的例子只是向任何客户端发送通用数据，但一个更大的家庭实验室应该需要更复杂的服务。在这里，Cloud-init 请求的是实例元数据信息。这个文件可以包含很多关于实例本身的信息，例如实例 ID、分配实例的主机名、云 ID，甚至网络信息。创建一个包含实例 ID 和主机名的基本元数据文件，并尝试将其提供给 Cloud-init 客户端。首先，创建一个可复制到容器镜像中的 meta-data 文件。instance-id: iid-local01 local-hostname: raspberry hostname: raspberry 实例 ID（instance-id）可以是任何东西。但是，如果你在 Cloud-init 运行后更改实例 ID，并且文件被送达客户端，就会触发 Cloud-init 再次运行。你可以使用这种机制来更新实例配置，但你应该意识到它是这种工作方式。local-hostname 和 hostname 键正如其名，它们会在 Cloud-init 运行时为客户端设置主机名信息。在容器文件中添加以下行以将 meta-data 文件复制到新镜像中。# Copy the meta-data file into the image for Nginx to serve it COPY meta-data ${WWW_DIR}/meta-data 现在，用元数据文件重建镜像（使用一个新的标签以方便故障排除），并用 Podman 创建并运行一个新的容器。# Build a new image named cloud-init:02 podman build -f Containerfile -t cloud-init:02 . # Run a new container with this new meta-data file podman run --rm -p 8080:8080 -it cloud-init:02 新容器运行后，重启 Cloud-init 客户端，再次观察 Nginx 日志。127.0.0.1 - - [09/May/2020:22:54:32 +0000] "GET /meta-data HTTP/1.1" 200 63 "-" "Cloud-Init/17.1" "-" 2020/05/09 22:54:32 [error] 2#0: *2 open() "/usr/share/nginx/html/user-data" failed (2: No such file or directory), client: 127.0.0.1, server: _, request: "GET /user-data HTTP/1.1", host: "instance-data:8080" 127.0.0.1 - - [09/May/2020:22:54:32 +0000] "GET /user-data HTTP/1.1" 404 3650 "-" "Cloud-Init/17.1" "-" 你看，这次 /meta-data 路径被提供给了客户端。成功了！然而，客户端接着在 /user-data 路径上寻找第二个文件。该文件包含实例所有者提供的配置数据，而不是来自云提供商的数据。对于一个家庭实验室来说，这两个都是你自己提供的。你可以使用许多 user-data 模块来配置你的实例。对于这个例子，只需使用 write_files 模块在客户端创建一些测试文件，并验证 Cloud-init 是否工作。创建一个包含以下内容的用户数据文件：#cloud-config # Create two files with example content using the write_files module write_files: - content: | "Does cloud-init work?" owner: root:root permissions: '0644' path: /srv/foo - content: | "IT SURE DOES!" owner: root:root permissions: '0644' path: /srv/bar 除了使用 Cloud-init 提供的 user-data 模块制作 YAML 文件外，你还可以将其制作成一个可执行脚本供 Cloud-init 运行。创建 user-data 文件后，在容器文件中添加以下行，以便在重建映像时将其复制到镜像中：# Copy the user-data file into the container image COPY user-data ${WWW_DIR}/user-data 重建镜像，并创建和运行一个新的容器，这次使用用户数据信息：# Build a new image named cloud-init:03 podman build -f Containerfile -t cloud-init:03 . # Run a new container with this new user-data file podman run --rm -p 8080:8080 -it cloud-init:03 现在，重启 Cloud-init 客户端，观察 Web 服务器上的 Nginx 日志：127.0.0.1 - - [09/May/2020:23:01:51 +0000] "GET /meta-data HTTP/1.1" 200 63 "-" "Cloud-Init/17.1" "-" 127.0.0.1 - - [09/May/2020:23:01:51 +0000] "GET /user-data HTTP/1.1" 200 298 "-" "Cloud-Init/17.1" "- 成功了！这一次，元数据和用户数据文件都被送到了 Cloud-init 客户端。验证 Cloud-init 已运行从上面的日志中，你知道 Cloud-init 在客户端主机上运行并请求元数据和用户数据文件，但它用它们做了什么？你可以在 write_files 部分验证 Cloud-init 是否写入了你在用户数据文件中添加的文件。在 Cloud-init 客户端上，检查 /srv/foo 和 /srv/bar 文件的内容：# cd /srv/ && ls bar foo # cat foo "Does cloud-init work?" # cat bar "IT SURE DOES!" 成功了！文件已经写好了，并且有你期望的内容。如上所述，还有很多其他模块可以用来配置主机。例如，用户数据文件可以配置成用 apt 添加包、复制 SSH 的 authorized_keys、创建用户和组、配置和运行配置管理工具等等。我在家里的私有云中使用它来复制我的 authorized_keys、创建一个本地用户和组，并设置 sudo 权限。你接下来可以做什么Cloud-init 在家庭实验室中很有用，尤其是专注于云技术的实验室。本文所演示的简单服务对于家庭实验室来说可能并不是超级有用，但现在你已经知道 Cloud-init 是如何工作的了，你可以继续创建一个动态服务，可以用自定义数据配置每台主机，让家里的私有云更类似于主流云提供商提供的服务。在数据源稍显复杂的情况下，将新的物理（或虚拟）机器添加到家中的私有云中，可以像插入它们并打开它们一样简单。via: https://opensource.com/article/20/5/create-simple-cloud-init-service-your-homelab作者：Chris Collins 选题：lujun9972 译者：wxy 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
简介Syncthing是一个免费开源的工具，它能在你的各个网络计算机间同步文件/文件夹。它不像其它的同步工具，如BitTorrent Sync和Dropbox那样，它的同步数据是直接从一个系统中直接传输到另一个系统的，并且它是完全开源的，安全且私密的。你所有的珍贵数据都会被存储在你的系统中，这样你就能对你的文件和文件夹拥有全面的控制权，没有任何的文件或文件夹会被存储在第三方系统中。此外，你有权决定这些数据该存于何处，是否要分享到第三方，或这些数据在互联网上的传输方式。所有的信息通讯都使用TLS进行加密，这样你的数据便能十分安全地逃离窥探。Syncthing有一个强大的响应式的网页管理界面(WebGUI，下同)，它能够帮助用户简便地添加、删除和管理那些通过网络进行同步的文件夹。通过使用Syncthing，你可以在多个系统上一次同步多个文件夹。在安装和使用上，Syncthing是一个可移植的、简单而强大的工具。即然文件或文件夹是从一部计算机中直接传输到另一计算机中的，那么你就无需考虑向云服务供应商支付金钱来获取额外的云空间。你所需要的仅仅是非常稳定的LAN/WAN连接以及在你的系统中有足够的硬盘空间。它支持所有的现代操作系统，包括GNU/Linux, Windows, Mac OS X, 当然还有Android。安装基于本文的目的，我们将使用两个系统，一个是Ubuntu 14.04 LTS, 一个是Ubuntu 14.10 server。为了简单辨别这两个系统，我们将分别称其为系统1和系统2。系统1细节：操作系统: Ubuntu 14.04 LTS server;主机名: server1.unixmen.local;IP地址: 192.168.1.150.系统用户: sk (你可以使用你自己的系统用户)同步文件夹: /home/Sync/ (Syncthing会默认创建)系统2细节：操作系统: Ubuntu 14.10 server;主机名: server.unixmen.local;IP地址: 192.168.1.151.系统用户: sk (你可以使用你自己的系统用户)同步文件夹: /home/Sync/ (Syncthing会默认创建)在系统1和系统2上为Syncthing创建用户在两个系统上运行下面的命令来为Syncthing创建用户以及两系统间的同步文件夹。sudo useradd sk sudo passwd sk 为系统1和系统2安装Syncthing在系统1和系统2上遵循以下步骤进行操作。从官方下载页上下载最新版本。我使用的是64位版本，因此下载64位版的软件包。wget https://github.com/syncthing/syncthing/releases/download/v0.10.20/syncthing-linux-amd64-v0.10.20.tar.gz 解压缩下载的文件：tar xzvf syncthing-linux-amd64-v0.10.20.tar.gz 切换到解压缩出来的文件夹:cd syncthing-linux-amd64-v0.10.20/ 复制可执行文件"syncthing"到$PATH：sudo cp syncthing /usr/local/bin/ 现在，执行下列命令来首次运行Syncthing：syncthing 当你执行上述命令后，syncthing会生成一个配置以及一些配置键值，并且在你的浏览器上打开一个管理界面。输入示例:[monitor] 15:40:27 INFO: Starting syncthing 15:40:27 INFO: Generating RSA key and certificate for syncthing... [BQXVO] 15:40:34 INFO: syncthing v0.10.20 (go1.4 linux-386 default) unknown-user@syncthing-builder 2015-01-13 16:27:47 UTC [BQXVO] 15:40:34 INFO: My ID: BQXVO3D-VEBIDRE-MVMMGJI-ECD2PC3-T5LT3JB-OK4Z45E-MPIDWHI-IRW3NAZ [BQXVO] 15:40:34 INFO: No config file; starting with empty defaults [BQXVO] 15:40:34 INFO: Edit /home/sk/.config/syncthing/config.xml to taste or use the GUI [BQXVO] 15:40:34 INFO: Starting web GUI on http://127.0.0.1:8080/ [BQXVO] 15:40:34 INFO: Loading HTTPS certificate: open /home/sk/.config/syncthing/https-cert.pem: no such file or directory [BQXVO] 15:40:34 INFO: Creating new HTTPS certificate [BQXVO] 15:40:34 INFO: Generating RSA key and certificate for server1... [BQXVO] 15:41:01 INFO: Starting UPnP discovery... [BQXVO] 15:41:07 INFO: Starting local discovery announcements [BQXVO] 15:41:07 INFO: Starting global discovery announcements [BQXVO] 15:41:07 OK: Ready to synchronize default (read-write) [BQXVO] 15:41:07 INFO: Device BQXVO3D-VEBIDRE-MVMMGJI-ECD2PC3-T5LT3JB-OK4Z45E-MPIDWHI-IRW3NAZ is "server1" at [dynamic] [BQXVO] 15:41:07 INFO: Completed initial scan (rw) of folder default Syncthing已经被成功地初始化了，网页管理接口也可以通过浏览器访问URL: http://localhost:8080。如上面输入所看到的，Syncthing在你的home目录中的Sync目录下自动为你创建了一个名为default**的文件夹。默认情况下，Syncthing的网页管理界面只能在本地端口(localhost)中进行访问，要从远程进行访问，你需要在两个系统中进行以下操作：首先，按下CTRL+C键来终止Syncthing初始化进程。现在你回到了终端界面。编辑config.xml文件，sudo nano ~/.config/syncthing/config.xml 找到下面的指令：[...] <gui enabled="true" tls="false"> 127.0.0.1:8080 <apikey>-Su9v0lW80JWybGjK9vNK00YDraxXHGP</apikey> </gui> [...] 在区域中，把127.0.0.1:8080改为0.0.0.0:8080。结果，你的config.xml看起来会是这样的：<gui enabled="true" tls="false"> 0.0.0.0:8080 <apikey>-Su9v0lW80JWybGjK9vNK00YDraxXHGP</apikey> </gui> 保存并关闭文件。在两个系统上再次执行下述命令：syncthing 访问网页管理界面现在，在你的浏览器上打开http://ip-address:8080/。你会看到下面的界面：网页管理界面分为两个窗格，在左窗格中，你应该可以看到同步的文件夹列表。如前所述，文件夹default在你初始化Syncthing时被自动创建。如果你想同步更多文件夹，点击Add Folder按钮。在右窗格中，你可以看到已连接的设备数。现在这里只有一个，就是你现在正在操作的计算机。网页管理界面上设置Syncthing为了提高安全性，让我们启用TLS，并且设置访问网页管理界面的管理员用户和密码。要做到这点，点击右上角的齿轮按钮，然后选择Settings输入管理员的帐户名/密码。我设置的是admin/Ubuntu。你应该使用一些更复杂的密码。点击Save按钮，现在，你会被要求重启Syncthing使更改生效。点击Restart。刷新你的网页浏览器。你可以看到一个像下面一样的SSL警告。点击显示我了解风险(I understand the Risks)的按钮。接着，点击“添加例外(Add Exception)“按钮把当前页面添加进浏览器的信任列表中。输入前面几步设置的管理员用户和密码。我设置的是admin/ubuntu。现在，我们提高了网页管理界面的安全性。别忘了两个系统都要执行上面同样的步骤。连接到其它服务器要在各个系统之间同步文件，你必须各自告诉它们其它服务器的信息。这是通过交换设备IDs（device IDs)来实现的。你可以通过选择“齿轮菜单（gear menu)”（在右上角）中的”Show ID（显示ID)“来找到它。例如，下面是我系统1的ID.复制这个ID，然后到另外一个系统（系统2）的网页管理界面，在右边窗格点击Add Device按钮。接着会出现下面的界面。在Device区域粘贴系统1 ID **。输入设备名称（可选）。在地址区域，你可以输入其它系统（ LCTT 译注：即粘贴的ID所属的系统，此应为系统1）的IP地址，或者使用默认值。默认值为dynamic。最后，选择要同步的文件夹。在我们的例子中，同步文件夹为default**。一旦完成了，点击save按钮。你会被要求重启Syncthing。点击Restart按钮重启使更改生效。现在，我们到系统１的网页管理界面，你会看到来自系统２的连接和同步请求。点击Add按钮。现在，系统２会要求系统１分享和同步名为default的文件夹。接着重启系统１的Syncthing服务使更改生效。等待大概６０秒，接着你会看到两个系统之间已成功连接并同步。你可以在网页管理界面中的Add Device区域核实该情况。添加系统２后，系统１网页管理界面中的控制窗口如下：添加系统１后，系统２网页管理界面中的控制窗口如下：现在，在任一个系统中的“default”文件夹中放进任意文件或文件夹。你应该可以看到这些文件/文件夹被自动同步到其它系统。本文完！祝同步愉快！噢耶！！！Syncthing网站via: http://www.unixmen.com/syncthing-private-secure-tool-sync-filesfolders-computers/作者：SK 译者：XLCYun 校对：wxy本文由 LCTT 原创翻译，Linux中国 荣誉推出
权威指南：构建个人私有云，拿回你的数据隐私的控制权！
这篇鸿篇巨制（多达上万字）不但剖析了在你被那些“免费”的服务供养的背后所损失的隐私。事实上，Google、百度、360们比你更了解你自己；而且提出了具体的解决方案，对于稍有技术基础的人来，完整地指导了如何搭建私有云，提供全功能、商业级的邮件服务和云服务。此外，文章中的邮件系统部分相当完善，而且，文章的思路清晰，简明扼要。其中包括基础的 SMTP/IMAP 服务自不必提，反垃圾邮件服务、灰名单、SPF、DKIM、Webmail，应有尽有，可以作为搭建产品环境中的邮件系统参考。8年里40000多次搜索！这是我的Google搜索历史。你的呢？（可以在这里自己找一下）有经过这么长时间积累下来的这么多数据点，Google已经能非常精确的推测你对什么感兴趣、曾经的想法、担忧过的事情，以及从你第一次获得Google帐号后这些年里所有这些的变化！很多非常私人的信息不受自己控制地存储在世界范围内的服务器上比如说你也像我一样从2006年到2013年都是Gmail用户，意味着你收到了30000封以上的电子邮件，以及在这7年里写了差不多5000封电子邮件。这些发送或收到的电子邮件里有很多是非常私人的，私人到你甚至不希望自己的家人或好友可以系统地查看。也许你还写过一些草稿邮件，因为最后一分钟改变主意而从没发出去。但是尽管你从未发出去，这些邮件仍然保存在服务器上的某个地方。结论是，说Google服务器比你最亲密的朋友或家人都更了解你的个人生活一点也不过分。从统计数据来看，我可以很保险地打赌你拥有一部智能手机。如果不使用联系人应用的话手机将基本没法用，而它默认会将你的联系人信息保存到Google服务器上的Google联系人里。所以，现在Google不仅知道了你的电子邮件，还有了你的离线联系人：你喜欢打给谁、谁来过电话、你发过短信给谁，以及发了些什么。你也不需要听我的片面之词，可以自己检查一下，看看你开放给类似Google Play服务的一些应用的权限，用来读取来电信息以及收到的短信。你是否还会用到手机里自带的日历应用？除非你在设置日程的时候明确地去掉同步，那么Google将精确地知道你将要做什么，一天里的每个时段、每一天、每一年。用iPhone代替Android手机也是一样的，只是Apple会代替Google来掌握你的往来邮件、联系人和日程计划。你是否还会非常小心地同步自己的联系人信息，在你朋友，同事或家人换工作或换服务商的时候更新他们的电子邮件地址和手机号？这给Google提供了一副你的社交网络的非常精确的、最新的描绘。还有你非常喜欢手机的GPS功能，经常配合Google地图使用。这意味着Google不仅能从日程里知道你在干什么，还知道你在哪儿、住在哪儿、在哪儿工作。然后再关联用户之间的GPS位置信息，Google还能知道你现在可能正在和哪些人来往。这种泄漏自己私人信息的日常爱好会以一种甚至没人能够预测的方式影响你的生活总结一下，如果你是一个普通的因特网用户，Google拥有过去差不多10年里你最新的、深度的信息，关于你的兴趣、忧虑、热情、疑问。它还收集了一些你很私人的信息（电子邮件、短信），精确到小时的你的日常活动和位置，一副你社交网络的高精度的描绘。关于你的如此私密的数据，很可能已经超越了你最亲密的朋友，家人或爱人对你的了解。不敢想象把这些深度的个人信息交给完全陌生的人，就好像把这些信息拷到一个U盘里，然后随便放到某个咖啡厅的桌上，留张纸条说“Olivier Martin的个人数据，请随便”。谁知道什么人会拿到它以及用来干嘛？然而，我们毫不犹豫地把自己的主要信息交给那些对我们的数据很感兴趣的IT公司的陌生人（这是他们制造面包的材料）以及世界级的数据分析专家手里，也许只是因为我们在点击那个绿色的'接受'按钮时根本没有想这么多。有这么多的高质量信息，这么多年里，Google可能会比你希望自我了解的更了解你自己：尼玛，回想我过去的数字生活，5年前发出的邮件里有一半我已经不记得了。我很高兴能重新发现早在2005年对xxx主义的兴趣以及第二年加入了ATTAC（一个致力于通过征收金融交易税来限制投机和改善社会公平的组织）。天知道为什么我竟然在2007年这么喜欢跳舞。这些都是无关紧要的信息（你不指望我能爆出什么猛料，是吧？;-）。但是，连接起这些高质量数据点，关于你生活的方方面面（做什么、什么时候、和谁一起、在哪里，...），并跨越这么长时间间隔，应该能推测出你的未来状态。比如说，根据一个17岁女孩的购物习惯，超市甚至可以在他父亲听说之前断定这个女孩怀孕了（这是一个真实的故事）。谁知道通过像Google所掌握的这些远远超出购物习惯的高质量数据能做些什么？连接起这些点，也许有人能预测你未来几年里口味或观点的变化。如今，你从未听过的公司声称拥有你500项数据点，包括宗教信仰、性取向和政治观点。提到政治，如果说你决定今后10年内进入政坛会怎么样？你的生活会改变，你的观点也一样，甚至你有时候会有所遗忘，但是Google不会。那你会不会担心你的对手会接触一些可以从Google访问你数据的人并会从你过去这些年里积累的个人数据深渊里挖出一些猛料呢？就像最近Sony被黑一样，多久以后会轮到Google或Facebook，以致让你的个人信息最终永远暴露？我们大多数人把自己的个人数据托付给这些公司的一个原因就是它们提供免费服务。但是真的免费吗？一般的Google帐号的价值根据评估方式不同会有些差别：你花在写邮件上的时间占到1000美元/年，你的帐号对于广告产业的价值差不多在220美元/年到500美元/年之间。所以这些服务并不是真的免费：会通过广告和我们的数据在未来的一些未知使用来间接付费。我写的最多的是Google，这是因为这是我托付个人数字信息的，以及目前我所知道做的最好的公司。但是我也提到过Apple或Facebook。这些公司通过它们在设计、工程和我们（曾经）喜欢每天使用的服务方面的神奇进步实实在在地改变了世界。但是这并不是说我们应该把所有我们最私人的个人数据堆积到它们的服务器上并把我们的数字生活托付给它们：潜在的危害实在太大了。只要5小时，拿回自己以及关心的人的隐私权（题图来自 ttgtmedia.com）但是事实并不是一定必须这样的。你可以生活在21世纪，拿着智能手机，每天都用电子邮件和GPS，却仍然可以保留自己的隐私。你所需要的就是拿回自己个人数据的控制权：邮件、日程、联系人、文件，等等。Prism-Break.org网站上列出了一些能帮你掌握个人数据命运的软件。除此以外，控制自己个人数据的最安全和最有效的方式是架设自己的服务器并搭建自己的云。不过你也许只是没有时间或精力去研究具体该怎么做以及如何让它能流畅工作。这也是这篇文章的意义所在。仅仅5个小时内，我们将配置出一台服务器来支撑你的邮件、联系人、日程表和各种文件，为你、你的朋友和你的家人。这个服务器将设计成一个个人数据中心或云，所以你能时刻保留它的完整控制。数据将自动在你的台式机/笔记本、手机和平板之间同步。从根本上来说，我们将建立一个系统来代替Gmail、Google文件/Dropbox、Google联系人、Google日历和Picasa。为自己做这件事情已经是迈出很大一步了。但是，你个人信息的很大一部分将仍然泄漏出去并保存到硅谷的一些主机上，只是因为和你日常来往的太多人在用Gmail和使用智能手机，所以最好是带上你一些比较亲近的人加入这次探险。我们将构建的系统能够：支持任意数目的域名和用户。这样就能轻易地和你的家人朋友共享这台服务器，所以他们也能掌控自己的个人数据，并且还能和你一起分摊服务费用。和你一起共享服务器的人可以使用他们自己的域名或者共享你的。允许你从任意网络发送和接收电子邮件，需要成功登录服务器之后。这样，你可以通过任意的邮件地址、任意设备（台式机、手机、平板）、任意网络（家里、公司、公共网络、...）来发送电子邮件。在发送和接收邮件的时候加密网络数据，这样，你不信任的人不能钓出你的密码，也不能看到你的私人邮件。提供最先进的反垃圾邮件技术，结合了已知垃圾邮件黑名单、自动灰名单、和自适应垃圾邮件过滤。如果邮件被误判了只需要简单地把它拖入或拖出垃圾目录就可以重新调校垃圾邮件过滤器。而且，服务器还会为基于社区的反垃圾邮件努力做出贡献。一段时间里只需要几分钟的维护，基本上只是安装安全更新和简单地检查一下服务器日志。添加一个新的邮件地址只需要在数据库中插入一条记录。除此之外，你可以忘记它的存在过自己的生活。我在14个月之前搭建了本文描述的这个系统，从那以后就一直顺利运行。所以我完全把它给忘了，直到我最近觉得随便按下手机上的‘检查邮件’会导致电子信号一路跑到冰岛（我放置服务器的地方）再回来的想法有点好笑才想起来。要完成这篇文章里的工作，你需要一点基本的技术能力。如果你知道SMTP和IMAP的区别，什么是DNS，以及对TCP/IP有基本了解的话，就够了。你还将需要一点基本的Unix知识（在命令行下和文件一起工作，基本的系统管理）。然后你需要花总共5小时时间来搭建。下面是我们将要做的事情的概述。申请一个虚拟私人服务器，一个域名，并把它们配置好设置postfix和dovecot来收发电子邮件阻止垃圾邮件进入你的收件箱确保你发出的邮件能通过垃圾邮件过滤器使用Owncloud提供日历，联系人，文件服务并配置webmail在云上同步你的设备这篇文章是受之前工作的启发并以之为基础本文很大程度参考了两篇文章，由Xavier Claude和Drew Crawford写的关于架设私有邮件服务器的介绍。本文覆盖了Xavier和Drew的文章里所描述的所有功能，除了3个地方Drew有而我没有：邮件推送支持（我喜欢由我主动检查邮件，而其他时候都不会被打扰），邮件全文检索（我一直都没用过），以及使用加密方式存储邮件（我的邮件和数据还没那么重要到要把它们加密后再存到本地服务器上）。如果你需要这些功能，只需要按照Drew的文章里相应部分的说明做就好了，和本文的内容兼容。和Xavier和Drew的成果比起来，本文有下面几个主要改进：根据我自己按Drew文章操作的经验以及原文的大量回复，修改了一些问题和文字错误。我也把本文所介绍的内容仔细检查了几遍，从头开始设定了几次服务器做重复验证以确保能正常工作。低维护：和Xavier的方式比起来，本文增加了在服务器上支持多个邮件域名。这样做是为了尽可能地减少服务器维护工作：基本上，要添加一个域名或用户，只需要往mysql数据库表里增加一行就好了（不需要增加过滤脚本，等等）。我增加了webmail。我增加了设定云服务器的部分，不仅能收发邮件还能管理文件，地址本/联系人（邮件地址，电话号码，生日，等等等），日程表和图片，供所有设备访问使用。申请一个虚拟私人服务器，一个域名，并把它们配置好让我们从设置基础设施开始：我们的虚拟私人主机和我们的域名。我用过1984.is和Linode提供的虚拟私人主机（VPS），体验非常好。在本文中，我们将使用Debian Wheezy，这个在1984和Linode都提供了已经做好的映像文件可以直接布置到你的VPS上。我喜欢1984是因为它的服务器在冰岛，也是唯一使用可再生能源（地热和水力发电）的地方，目前还没有影响过气候变化，不像大多数美国数据中心目前大多数依赖于烧煤的火力发电站。而且，他们注重民权，透明，自由以及免费软件。最好是在服务器上创建一个文件用来保存后面要用到的各种密码（用户账号、邮件账号、云帐号、数据库帐号）。当然最好是加密一下（可以用GnuPG），这样就算用来设定服务器的电脑被偷了或被入侵了，你的服务器就不会那么容易被攻击。关于注册域名，我已经使用grandi的服务超过10年了，也很满意。在本文中，我们将开辟一个叫jhausse.net的域名。然后在上面增加一个叫cloud.jhausse.net的二级域名，并绑定MX纪录。在完成之后，设置比较短的纪录生存时间（TTL）比如300秒，这样你在设置服务器的时候，可以修改你的域并很快测试到结果。最后，设置PTR纪录（反向DNS），这样IP地址可以反向映射回它的域名。如果你不理解前面这句话，看下这篇文章来获得相关背景知识。如果你使用Linode的服务，你可以在远程访问这一栏的控制面板里设置PTR纪录。如果是1984，联系一下技术支持来帮你搞定。在服务器上，我们从添加一个普通用户开始，这样我们不用从头到尾一直用root账号。另外，用root登陆也需要额外多一层安全措施。adduser roudy 然后，在文件/etc/ssh/sshd\_config中设置：PermitRootLogin no 然后重启ssh服务：service ssh reload 然后，我们要修改服务器的主机名。编辑文件/etc/hostname，只有一行就是自己的主机名，我们这个例子中是：cloud 然后，编辑ssh服务的公钥文件/etc/ssh/ssh\_host\_rsa\_key.pub, /etc/ssh/ssh\_host\_dsa\_key.pub, /etc/ssh/ssh\_host\_ecdsa\_key.pub，这样文件末尾可以反映你的主机名，比如root@cloud。然后重启系统保证主机名在系统的每个需要它的角落都生效了。reboot 我们将更新系统并移除不必要的服务以降低远程攻击的风险。apt-get update apt-get dist-upgrade service exim4 stop apt-get remove exim4 rpcbind apt-get autoremove apt-get install vim 我喜欢使用vim远程编辑配置文件。打开vim 的自动语法高亮会很有帮助。添加下面这一行到~/.vimrc文件中。syn on 设置postfix和dovecot来收发电子邮件postfixapt-get install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-mysql mysql-server dovecot-lmtpd postgrey 在Postfix的配置菜单里，选择Internet Site，设置这个系统的邮件名称为jhausse.net。现在开始添加一个数据库用于保存主机上管理的域名列表，和每个域名下的用户列表（同时也包括他们各自的密码），以及邮件别名列表（用于从一个地址往另一个地址转发邮件）。mysqladmin -p create mailserver mysql -p mailserver mysql> GRANT SELECT ON mailserver.* TO 'mailuser'@'localhost' IDENTIFIED BY 'mailuserpass'; mysql> FLUSH PRIVILEGES; mysql> CREATE TABLE `virtual_domains` ( `id` int(11) NOT NULL auto_increment, `name` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; mysql> CREATE TABLE `virtual_users` ( `id` int(11) NOT NULL auto_increment, `domain_id` int(11) NOT NULL, `password` varchar(106) NOT NULL, `email` varchar(100) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; mysql> CREATE TABLE `virtual_aliases` ( `id` int(11) NOT NULL auto_increment, `domain_id` int(11) NOT NULL, `source` varchar(100) NOT NULL, `destination` varchar(100) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 这里我们为jhausse.net域名提供邮件服务。如果还需要加入其他域名，也没问题。我们也会为每个域名设置一个邮件管理地址（postmaster），转寄给roudy@jhausse.net。mysql> INSERT INTO virtual_domains (`name`) VALUES ('jhausse.net'); mysql> INSERT INTO virtual_domains (`name`) VALUES ('otherdomain.net'); mysql> INSERT INTO virtual_aliases (`domain_id`, `source`, `destination`) VALUES ('1', 'postmaster', 'roudy@jhausse.net'); mysql> INSERT INTO virtual_aliases (`domain_id`, `source`, `destination`) VALUES ('2', 'postmaster', 'roudy@jhausse.net'); 现在已经添加了一个本地邮件账号roudy@jhausse.net。首先，为它生成一个密码的哈希串：doveadm pw -s SHA512-CRYPT 然后把哈希值加入到数据库中：mysql> INSERT INTO `mailserver`.`virtual_users` (`domain_id`, `password`, `email`) VALUES ('1', '$6$YOURPASSWORDHASH', 'roudy@jhausse.net'); 现在我们的域名、别名和用户列表都设置好了，然后开始设置postfix（这是一个SMTP服务器，用来发送邮件）。把文件/etc/postfix/main.cf替换为下面的内容：myhostname = cloud.jhausse.net myorigin = /etc/mailname mydestination = localhost.localdomain, localhost mynetworks_style = host # We disable relaying in the general case smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination # Requirements on servers that contact us: we verify the client is not a # known spammer (reject_rbl_client) and use a graylist mechanism # (postgrey) to help reducing spam (check_policy_service) smtpd_client_restrictions = permit_mynetworks, reject_rbl_client zen.spamhaus.org, check_policy_service inet:127.0.0.1:10023 disable_vrfy_command = yes inet_interfaces = all smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) biff = no append_dot_mydomain = no readme_directory = no # TLS parameters smtpd_tls_cert_file=/etc/ssl/certs/cloud.crt smtpd_tls_key_file=/etc/ssl/private/cloud.key smtpd_use_tls=yes smtpd_tls_auth_only = yes smtp_tls_security_level=may smtp_tls_loglevel = 1 smtpd_tls_loglevel = 1 smtpd_tls_received_header = yes smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache # Delivery alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases message_size_limit = 50000000 recipient_delimiter = + # The next lines are useful to set up a backup MX for myfriendsdomain.org # relay_domains = myfriendsdomain.org # relay_recipient_maps = # Virtual domains virtual_transport = lmtp:unix:private/dovecot-lmtp virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf local_recipient_maps = $virtual_mailbox_maps 现在我们要让postfix知道如何从我们设定的数据库里找出需要接收邮件的域名。建立一个新文件/etc/postfix/mysql-virtual-mailbox-domains.cf并添加以下内容：user = mailuser password = mailuserpass hosts = 127.0.0.1 dbname = mailserver query = SELECT 1 FROM virtual_domains WHERE name='%s' 我们可以让postfix判断给定的电子邮件账号是否存在，创建文件/etc/postfix/mysql-virtual-mailbox-maps.cf并写入以下内容：user = mailuser password = mailuserpass hosts = 127.0.0.1 dbname = mailserver query = SELECT 1 FROM virtual_users WHERE email='%s' 最后，postfix会根据文件/etc/postfix/mysql-virtual-alias-maps.cf的内容来查找邮件别名user = mailuser password = mailuserpass hosts = 127.0.0.1 dbname = mailserver query = SELECT virtual_aliases.destination as destination FROM virtual_aliases, virtual_domains WHERE virtual_aliases.source='%u' AND virtual_aliases.domain_id = virtual_domains.id AND virtual_domains.name='%d' 在配置好这些后，现在要测试一下postfix是否能正常查询数据库。我们可以用postmap命令测试：postmap -q jhausse.net mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf postmap -q roudy@jhausse.net mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf postmap -q postmaster@jhausse.net mysql:/etc/postfix/mysql-virtual-alias-maps.cf postmap -q bob@jhausse.net mysql:/etc/postfix/mysql-virtual-alias-maps.cf 如果一切都正常配置了的话，头两个查询应该输出1，第3个查询应该输出roudy@jhausse.net，而最后一个应该什么都不输出。dovecot现在，让我们设置一下dovecot（一个IMAP服务程序，用来在我们的设备上从服务器获取收到的邮件）。编辑文件/etc/dovecot/dovecot.conf设置以下参数：# Enable installed protocol # !include_try /usr/share/dovecot/protocols.d/*.protocol protocols = imap lmtp 这样将只打开imap（让我们可以获取邮件）和lmtp（postfix用来将收件箱里的邮件转给dovecot）。编辑/etc/dovecot/conf.d/10-mail.conf并设置以下参数：mail_location = maildir:/var/mail/%d/%n [...] mail_privileged_group = mail [...] first_valid_uid = 0 这样邮件将被保存到目录 /var/mail/domainname/username 下。注意下这几个选项散布在配置文件的不同位置，有时已经在那里写好了：我们只需要取消注释即可。文件里的其他设定选项，可以维持原样。在本文后面还有很多文件需要用同样的方式更新设置。在文件/etc/dovecot/conf.d/10-auth.conf里，设置以下参数：disable_plaintext_auth = yes auth_mechanisms = plain #!include auth-system.conf.ext !include auth-sql.conf.ext 在文件/etc/dovecot/conf.d/auth-sql.conf.ext里，设置以下参数：passdb { driver = sql args = /etc/dovecot/dovecot-sql.conf.ext } userdb { driver = static args = uid=mail gid=mail home=/var/mail/%d/%n } 这是告诉dovecot用户的邮件保存在目录/var/mail/domainname/username下，以及如何从我们刚建立的数据库里查找密码。现在我们还需要告诉dovecot具体如何使用数据库。这样需要把下面的内容加入/etc/dovecot/dovecot-sql.conf.ext文件：driver = mysql connect = host=localhost dbname=mailserver user=mailuser password=mailuserpass default_pass_scheme = SHA512-CRYPT password_query = SELECT email as user, password FROM virtual_users WHERE email='%u'; 我们现在修改一下配置文件的权限chown -R mail:dovecot /etc/dovecot chmod -R o-rwx /etc/dovecot 基本差不多了！只是还需要再多编辑几个文件。在文件/etc/dovecot/conf.d/10-master.conf里，设置以下参数：service imap-login { inet_listener imap { #port = 143 port = 0 } inet_listener imaps { port = 993 ssl = yes } } service pop3-login { inet_listener pop3 { #port = 110 port = 0 } inet_listener pop3s { #port = 995 #ssl = yes port = 0 } } service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { mode = 0666 group = postfix user = postfix } user = mail } service auth { unix_listener auth-userdb { mode = 0600 user = mail #group = } # Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix } # Auth process is run as this user. #user = $default_internal_user user = dovecot } service auth-worker { user = mail } 注意下我们把除了imaps之外所有服务的端口都设置成了0，这样可以有效地禁止这些服务。然后，在文件/etc/dovecot/conf.d/15-lda.conf里，指定一个邮箱管理地址：postmaster_address = postmaster@jhausse.net 最后但很重要的一点，我们为服务器需要生成一对公钥和私钥，可以同时用于dovecot和postfix：openssl req -new -newkey rsa:4096 -x509 -days 365 -nodes -out "/etc/ssl/certs/cloud.crt" -keyout "/etc/ssl/private/cloud.key" 请确保你指定了服务器的完全限定域名（FQDN），在本文的例子里：Common Name (e.g. server FQDN or YOUR name) []:cloud.jhausse.net 如果没有的话，我们的客户端会抱怨在SSL证书里的服务器名字和所连接的服务器名字不一致。我们将通过修改配置文件/etc/dovecot/conf.d/10-ssl.conf里的如下选项来告诉dovecot使用刚生成的密钥：ssl = required ssl_cert = </etc/ssl/certs/cloud.crt ssl_key = </etc/ssl/private/cloud.key 测试就这些了！现在开始测试postfix和dovecot服务！service dovecot restart service postfix restart 在服务器上，尝试发送邮件给本地用户：telnet localhost 25 EHLO cloud.jhausse.net MAIL FROM:youremail@domain.com RCPT TO:roudy@jhausse.net data Subject: Hallo! This is a test, to check if cloud.jhausse.net is ready to be an MX! Cheers, Roudy . QUIT 服务器应该接受我们的邮件并返回类似消息：250 2.0.0 Ok: queued as 58D54101DB 如果一切正常的话，检查一下/var/log/mail.log里的日志。应该有类似下面的一行：Nov 14 07:57:06 cloud dovecot: lmtp(4375, roudy@jhausse.net): ... saved mail to INBOX 到这里一切都正常吗？不错。现在，让我尝试从不同的机器发邮件，比如说我们用来设定服务器的电脑。这次我们使用加密方式（TLS）和服务器对话：openssl s_client -connect cloud.jhausse.net:25 -starttls smtp EHLO cloud.jhausse.net MAIL FROM:roudy@jhausse.net rcpt to:bob@gmail.com 服务器应该有这样的响应：554 5.7.1 <bob@gmail.com>: Relay access denied 这个没问题：如果服务器能接受这封邮件而不是返回如上的拒绝消息，那意味着我们架设的postfix是一个对全世界所有垃圾邮件都开放的中继，这将完全没法使用。除了'Relay access denied'消息，你也可能会收到这样的响应：554 5.7.1 Service unavailable; Client host [87.68.61.119] blocked using zen.spamhaus.org; http://www.spamhaus.org/query/bl?ip=87.68.61.119 意思是你正尝试从一个被标记成垃圾邮件发送者的IP地址连接服务器。我在通过普通的因特网服务提供商（ISP）连接服务器时曾收到过这样的消息。要解决这个问题，可以试着从另一个主机发起连接，比如另外一个你可以SSH登录的主机。另外一种方式是，你可以修改postfix的main.cf配置文件，不要使用Spamhous的RBL，重启postfix服务，然后再检查上面的测试是否正常。不管用哪种方式，最重要的是你要确定一个能工作的，因为我们后面马上要测试其他功能。如果你选择了重新配置postfix不使用RBL，别忘了在完成本文后重新开启RBL并重启postfix，以避免收到一些不必要的垃圾邮件。（LCTT 译者注：在国内可以使用 CASA 的 RBL：cblplus.anti-spam.org.cn，参见：http://www.anti-spam.org.cn/ 。）现在，我们试一下往SMTP端口25发送一封有效的邮件，这是一般正常的邮件服务器用来彼此对话的方式：openssl s_client -connect cloud.jhausse.net:25 -starttls smtp EHLO cloud.jhausse.net MAIL FROM:youremail@domain.com RCPT TO:roudy@jhausse.net 服务器应该有这样的响应：Client host rejected: Greylisted, see http://postgrey.schweikert.ch/help/jhausse.net.html 这意味着postgrey工作正常。postgrey做的是用临时错误拒绝未知发送者的邮件。邮件的技术规则是要求邮件服务器尝试重新发送邮件。在5分钟后，postgrey就会接收这封邮件。一般世界范围内遵守规则的邮件服务器都会尝试为我们重复投递邮件，但大多数垃圾邮件发送者不会这样做。所以，等上5分钟，再次通过上面的命令发送一次，然后检查postfix应该正常接收了邮件。之后，我们检查一下我们可以通过IMAP和dovecot对话获取刚才发送的两封邮件。openssl s_client -crlf -connect cloud.jhausse.net:993 1 login roudy@jhausse.net "mypassword" 2 LIST "" "*" 3 SELECT INBOX 4 UID fetch 1:1 (UID RFC822.SIZE FLAGS BODY.PEEK[]) 5 LOGOUT 这里，你应该把mypassword替换为你自己为这个邮件账号设定的密码。如果能正常工作，基本上我们已经拥有一个能接收邮件的邮件服务器了，通过它我们可以在各种设备（PC/笔记本、平板、手机...）上收取邮件了。外发（中继）邮件但是我们不能把邮件给它发送出去，除非我们自己从服务器发送。现在我们将让postfix为我们转发邮件，但是这个只有成功登录才可以，这是为了保证邮件是由服务器上的某个有效帐号发出来的。要做到这个，我们要打开一个特殊的，全程SSL连接的，SASL鉴权的邮件提交服务。在文件/etc/postfix/master.cf里设置下面的参数：submission inet n - - - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth -o smtpd_sasl_security_options=noanonymous -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject_non_fqdn_recipient,reject_unauth_destination 然后重启postfix服务：service postfix reload 现在，让我们试试从一台不同的机器连接这个服务，确定一下postfix现在能够正常中继我们自己的而不是其他任何人的邮件：openssl s_client -connect cloud.jhausse.net:587 -starttls smtp EHLO cloud.jhausse.net 注意一下服务器建议的'250-AUTH PLAIN'功能，在从端口25连接的时候不会出现。MAIL FROM:asdf@jkl.net rcpt to:bob@gmail.com 554 5.7.1 <bob@gmail.com>: Relay access denied QUIT 这个没问题，postfix在不认识我们的时候是不会中继邮件的。所以，首先让我们先鉴定一下自己的身份。要这样做，我们首先需要生成一个鉴权字符串：echo -ne '\000roudy@jhausse.net\000mypassword'|base64 然后让我们尝试再次通过服务器发送邮件：openssl s_client -connect cloud.jhausse.net:587 -starttls smtp EHLO cloud.jhausse.net AUTH PLAIN DGplYW5AMTk4NGNsb3VQLm5ldAA4bmFmNGNvNG5jOA== MAIL FROM:asdf@jkl.net rcpt to:bob@gmail.com 现在postfix应该能正常接收。最后完成这个测试，来检查一下我们的虚拟别名能正常工作，给postmaster@jhausse.net发送一封邮件然后确认一下它会被送到roudy@jhausse.net：telnet cloud.jhausse.net 25 EHLO cloud.jhausse.net MAIL FROM:youremail@domain.com rcpt to:postmaster@jhausse.net data Subject: Virtual alias test Dear postmaster, Long time no hear! I hope your MX is working smoothly and securely. Yours sincerely, Roudy . QUIT 让我们检查一下邮件是否被正常送到正确的收件箱了：openssl s_client -crlf -connect cloud.jhausse.net:993 1 login roudy@jhausse.net "mypassword" 2 LIST "" "*" 3 SELECT INBOX * 2 EXISTS * 2 RECENT 4 LOGOUT 到这里，我们已经拥有一个能正常工作的邮箱服务器了，能收发邮件。我们可以配置自己的设备来使用它。PS：不要忘记再次试试通过端口25往自己架设的服务器上的帐号发送邮件，来验证你已经没有被postgrey阻挡了。阻止垃圾邮件进入你的收件箱为了过滤垃圾邮件，我们已经使用了实时黑名单（RBL）和灰名单（postgrey）。现在我们将增加自适应垃圾邮件过滤来让我们的垃圾邮件过滤能力提高一个等级。这意味着我们将为我们的邮件服务器增加人工智能，这样它就能从经验中学习哪些邮件是垃圾哪些不是。我们将使用来实现这个功能。apt-get install dspam dovecot-antispam postfix-pcre dovecot-sieve dovecot-antispam是一个安装包，可以在我们发现有邮件被dspam误分类了之后让dovecot重新更新垃圾邮件过滤器。基本上，我们所需要做的就只是把邮件放进或拿出垃圾箱。dovecot-antispam将负责调用dspam来更新过滤器。至于postfix-pcre和dovecot-sieve，我们将分别用它们来把接收的邮件传递给垃圾邮件过滤器以及自动把垃圾邮件放入用户的垃圾箱。在配置文件/etc/dspam/dspam.conf里，为以下参数设置相应的值：TrustedDeliveryAgent "/usr/sbin/sendmail" UntrustedDeliveryAgent "/usr/lib/dovecot/deliver -d %u" Tokenizer osb IgnoreHeader X-Spam-Status IgnoreHeader X-Spam-Scanned IgnoreHeader X-Virus-Scanner-Result IgnoreHeader X-Virus-Scanned IgnoreHeader X-DKIM IgnoreHeader DKIM-Signature IgnoreHeader DomainKey-Signature IgnoreHeader X-Google-Dkim-Signature ParseToHeaders on ChangeModeOnParse off ChangeUserOnParse full ServerPID /var/run/dspam/dspam.pid ServerDomainSocketPath "/var/run/dspam/dspam.sock" ClientHost /var/run/dspam/dspam.sock 然后，在配置文件/etc/dspam/default.prefs里，把以下参数改为：spamAction=deliver # { quarantine | tag | deliver } -> default:quarantine signatureLocation=headers # { message | headers } -> default:message showFactors=on 现在我们需要把dspam连接到postfix和dovecot上，在配置文件/etc/postfix/master.cf最后添加这样两行：dspam unix - n n - 10 pipe flags=Ru user=dspam argv=/usr/bin/dspam --deliver=innocent,spam --user $recipient -i -f $sender -- $recipient dovecot unix - n n - - pipe flags=DRhu user=mail:mail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient} 现在我们将告诉postfix通过dspam来过滤所有提交给服务器端口25（一般的SMTP通信）的新邮件，除非该邮件是从服务器本身发出（permit\_mynetworks）。注意下我们通过SASL鉴权提交给postfix的邮件不会通过dspam过滤，因为我们在前面部分里为这种方式设定了独立的提交服务。编辑文件/etc/postfix/main.cf将选项**smtpd\_client\_restrictions**改为如下内容：smtpd_client_restrictions = permit_mynetworks, reject_rbl_client zen.spamhaus.org, check_policy_service inet:127.0.0.1:10023, check_client_access pcre:/etc/postfix/dspam_filter_access 在文件末尾，还需要增加：# For DSPAM, only scan one mail at a time dspam_destination_recipient_limit = 1 现在我们需要指定我们定义的过滤器。基本上，我们将告诉postfix把所有邮件（如下用 /./ 代表）通过unix套接字发给dspam。创建一个新文件/etc/postfix/dspam\_filter\_access并把下面一行写进去：/./ FILTER dspam:unix:/run/dspam/dspam.sock 这是postfix部分的配置。现在让我们为dovecot设置垃圾过滤。在文件/etc/dovecot/conf.d/20-imap.conf里，修改imap mail\_plugin插件参数为下面的方式：mail_plugins = $mail_plugins antispam 并为lmtp增加一个部分：protocol lmtp { # Space separated list of plugins to load (default is global mail_plugins). mail_plugins = $mail_plugins sieve } 我们现在设置dovecot-antispam插件。编辑文件/etc/dovecot/conf.d/90-plugin.conf并把以下内容添加到插件部分：plugin { ... # Antispam (DSPAM) antispam_backend = dspam antispam_allow_append_to_spam = YES antispam_spam = Junk;Spam antispam_trash = Trash;trash antispam_signature = X-DSPAM-Signature antispam_signature_missing = error antispam_dspam_binary = /usr/bin/dspam antispam_dspam_args = --user;%u;--deliver=;--source=error antispam_dspam_spam = --class=spam antispam_dspam_notspam = --class=innocent antispam_dspam_result_header = X-DSPAM-Result } 然后在文件/etc/dovecot/conf.d/90-sieve.conf里指定默认的sieve脚本，这个将对服务器上所有用户有效：sieve_default = /etc/dovecot/default.sieve 什么是sieve以及为什么我们需要为所有用户设置一个默认脚本？sieve可以在IMAP服务器上为我们自动处理任务。在我们的例子里，我们想让所有被确定为垃圾的邮件移到垃圾箱而不是收件箱里。我们希望这是服务器上所有用户的默认行为；这是为什么我们把这个脚本设为默认脚本。现在让我们来创建这个脚本，建立一个新文件/etc/dovecot/default.sieve并写入以下内容：require ["regex", "fileinto", "imap4flags"]; # Catch mail tagged as Spam, except Spam retrained and delivered to the mailbox if allof (header :regex "X-DSPAM-Result" "^(Spam|Virus|Bl[ao]cklisted)$", not header :contains "X-DSPAM-Reclassified" "Innocent") { # Mark as read # setflag "\\Seen"; # Move into the Junk folder fileinto "Junk"; # Stop processing here stop; } 现在我们需要编译这个脚本好让dovecot能运行它。我们也需要给它合适的权限。cd /etc/dovecot sievec . chown mail.dovecot default.siev* chmod 0640 default.sieve chmod 0750 default.svbin 最后，我们需要修改dspam需要读取的两个postfix配置文件的权限：chmod 0644 /etc/postfix/dynamicmaps.cf /etc/postfix/main.cf 就这些！让我们重启dovecot和postfix服务：service dovecot restart service postfix restart 测试然后通过从远程主机（比如我们用来设定服务器的电脑）连接服务器来测试一下反垃圾邮件：openssl s_client -connect cloud.jhausse.net:25 -starttls smtp EHLO cloud.jhausse.net MAIL FROM:youremail@domain.com rcpt to:roudy@jhausse.net DATA Subject: DSPAM test Hi Roudy, how'd you like to eat some ham tonight? Yours, J . QUIT 让我们检查一下邮件是否已经送到：openssl s_client -crlf -connect cloud.jhausse.net:993 1 login roudy@jhausse.net "mypassword" 2 LIST "" "*" 3 SELECT INBOX 4 UID fetch 3:3 (UID RFC822.SIZE FLAGS BODY.PEEK[]) 这个应该返回SPAM为邮件增加了一组标记的数据，看上去像这样：X-DSPAM-Result: Innocent X-DSPAM-Processed: Sun Oct 5 16:25:48 2014 X-DSPAM-Confidence: 1.0000 X-DSPAM-Probability: 0.0023 X-DSPAM-Signature: 5431710c178911166011737 X-DSPAM-Factors: 27, Received*Postfix+with, 0.40000, Received*with+#+id, 0.40000, like+#+#+#+ham, 0.40000, some+#+tonight, 0.40000, Received*certificate+requested, 0.40000, Received*client+certificate, 0.40000, Received*for+roudy, 0.40000, Received*Sun+#+#+#+16, 0.40000, Received*Sun+#+Oct, 0.40000, Received*roudy+#+#+#+Oct, 0.40000, eat+some, 0.40000, Received*5+#+#+16, 0.40000, Received*cloud.jhausse.net+#+#+#+id, 0.40000, Roudy+#+#+#+to, 0.40000, Received*Oct+#+16, 0.40000, to+#+#+ham, 0.40000, Received*No+#+#+requested, 0.40000, Received*jhausse.net+#+#+Oct, 0.40000, Received*256+256, 0.40000, like+#+#+some, 0.40000, Received*ESMTPS+id, 0.40000, how'd+#+#+to, 0.40000, tonight+Yours, 0.40000, Received*with+cipher, 0.40000 5 LOGOUT 很好！你现在已经为你服务器上的用户配置好自适应垃圾邮件过滤。当然，每个用户将需要在开始的几周里培训过滤器。要标记一则信息为垃圾，只需要在你的任意设备（电脑，平板，手机）上将它移动到叫“垃圾箱”或“废纸篓”的目录里。否则它将被标记为有用。确保你发出的邮件能通过垃圾邮件过滤器这个部分我们的目标是让我们的邮件服务器能尽量干净地出现在世界上，并让垃圾邮件发送者们更难以我们的名义发邮件。作为附加效果，这也有助于让我们的邮件能通过其他邮件服务器的垃圾邮件过滤器。发送者策略框架（SPF）发送者策略框架（SPF）是你添加到自己服务器区域里的一份记录，声明了整个因特网上哪些邮件服务器能以你的域名发邮件。设置非常简单，使用microsoft.com上的SPF向导来生成你的SPF记录，然后作为一个TXT记录添加到自己的服务器区域里。看上去像这样：jhausse.net. 300 IN TXT v=spf1 mx mx:cloud.jhausse.net -all 反向PTR我们之前在本文里讨论过这个问题，建议你为自己的服务器正确地设置反向DNS，这样对服务器IP地址的反向查询能返回你服务器的实际名字。OpenDKIM当我们激活OpenDKIM后，postfix会用密钥为每封发出去的邮件签名。然后我们将把这个密钥存储在DNS域中。这样的话，世界上任意一个邮件服务器都能够检验邮件是否真的是我们发出的，或是由垃圾邮件发送者伪造的。让我们先安装opendkim：apt-get install opendkim opendkim-tools 然后按如下方式编辑/etc/opendkim.conf文件的配置：## ## opendkim.conf -- configuration file for OpenDKIM filter ## Canonicalization relaxed/relaxed ExternalIgnoreList refile:/etc/opendkim/TrustedHosts InternalHosts refile:/etc/opendkim/TrustedHosts KeyTable refile:/etc/opendkim/KeyTable LogWhy Yes MinimumKeyBits 1024 Mode sv PidFile /var/run/opendkim/opendkim.pid SigningTable refile:/etc/opendkim/SigningTable Socket inet:8891@localhost Syslog Yes SyslogSuccess Yes TemporaryDirectory /var/tmp UMask 022 UserID opendkim:opendkim 我们还需要几个额外的文件，需保存在目录/etc/opendkim里：mkdir -pv /etc/opendkim/ cd /etc/opendkim/ 让我们建立新文件/etc/opendkim/TrustedHosts并写入以下内容：127.0.0.1 建立新文件/etc/opendkim/KeyTable并写入以下内容：cloudkey jhausse.net:mail:/etc/opendkim/mail.private 这会告诉OpenDKIM我们希望使用一个名叫'cloudkey'的加密密钥，它的内容在文件/etc/opendkim/mail.private里。我们建立另一个名叫/etc/opendkim/SigningTable的文件然后写入下面这一行：*@jhausse.net cloudkey 这会告诉OpenDKIM每封从jhausse.net域发出的邮件都应该用'cloudkey'密钥签名。如果我们还有其他域希望也能签名，我们也可以在这里添加。下一步是生成密钥并修改OpenDKIM配置文件的权限。opendkim-genkey -r -s mail [-t] chown -Rv opendkim:opendkim /etc/opendkim chmod 0600 /etc/opendkim/* chmod 0700 /etc/opendkim 一开始，最好使用-t开关，这样会通知其他邮件服务器你只是在测试模式下，这样他们就不会丢弃基于你的OpenDKIM签名的邮件（目前来说）。你可以从mail.txt文件里看到OpenDKIM密钥：cat mail.txt 然后把它作为一个TXT记录添加到区域文件里，应该是类似这样的：mail._domainkey.cloud1984.net. 300 IN TXT v=DKIM1; k=rsa; p=MIGfMA0GCSqG... 最后，我们需要告诉postfix来为发出的邮件签名。在文件/etc/postfix/main.cf末尾，添加：# Now for OpenDKIM: we'll sign all outgoing emails smtpd_milters = inet:127.0.0.1:8891 non_smtpd_milters = $smtpd_milters milter_default_action = accept 然后重启相关服务：service postfix reload service opendkim restart 测试现在让我们测试一下是否能找到我们的OpenDKIM公钥并和私钥匹配：opendkim-testkey -d jhausse.net -s mail -k mail.private -vvv 这个应该返回：opendkim-testkey: key OK 这个你可能需要等一会直到域名服务器重新加载该区域（对于Linode，每15分钟会更新一次）。你可以用dig来检查区域是否已经重新加载。如果这个没问题，让我们测试一下其他服务器能验证我们的OpenDKIM签名和SPF记录。要做这个，我们可以用Brandon Checkett的邮件测试系统。发送一封邮件到Brandon的网页上提供的测试地址，我们可以在服务器上运行下面的命令mail -s CloudCheck ihAdmTBmUH@www.brandonchecketts.com 在Brandon的网页上，我们应该可以在'DKIM Signature'部分里看到result = pass的文字，以及在'SPF Information'部分看到Result: pass的文字。如果我们的邮件通过这个测试，只要不加-t开关重新生成OpenDKIM密钥，上传新的密钥到区域文件里，然后重新测试检查是否仍然可以通过这些测试。如果可以的话，恭喜！你已经在你的服务器上成功配置好OpenDKIM和SPF了！使用Owncloud提供日历，联系人，文件服务并通过Roundcube配置网页邮件既然我们已经拥有了一流的邮件服务器，让我们再为它增加在云上保存通讯录，日程表和文件的能力。这些是Owncloud所提供的非常赞的服务。在这个弄好后，我们还会设置一个网页邮件，这样就算你没带任何电子设备出去旅行时，或者说在你的手机或笔记本没电的情况下，也可以通过网吧来检查邮件。安装Owncloud非常直观，而且在这里有非常好的介绍。在Debian系统里，归根结底就是把owncloud的仓库添加到apt源里，下载Owncloud的发行密钥并安装到apt钥匙链中，然后通过apt-get安装Owncloud：echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/community/Debian_7.0/ /' >> /etc/apt/sources.list.d/owncloud.list wget http://download.opensuse.org/repositories/isv:ownCloud:community/Debian_6.0/Release.key apt-key add - < Release.key apt-get update apt-get install apache2 owncloud roundcube 在有提示的时候，选择dbconfig并设置roundcube使用mysql。然后，提供一下mysql的root密码并为roundcube的mysql用户设置一个漂亮的密码。然后，按如下方式编辑roundcube的配置文件/etc/roundcube/main.inc.php，这样登录roundcube默认会使用你的IMAP服务器：$rcmail_config['default_host'] = 'ssl://localhost'; $rcmail_config['default_port'] = 993; 现在我们来配置一下apache2网页服务器增加SSL支持，这样我们可以和Owncloud和Roundcube对话时使用加密的方式传输我们的密码和数据。让我们打开Apache的SSL模块：a2enmod ssl 然后编辑文件/etc/apache2/ports.conf并设定以下参数：NameVirtualHost *:80 Listen 80 ServerName [www.jhausse.net](http://www.jhausse.net) <IfModule mod_ssl.c> # If you add NameVirtualHost *:443 here, you will also have to change # the VirtualHost statement in /etc/apache2/sites-available/default-ssl # to <VirtualHost *:443> # Server Name Indication for SSL named virtual hosts is currently not # supported by MSIE on Windows XP. NameVirtualHost *:443 Listen 443 </IfModule> <IfModule mod_gnutls.c> Listen 443 </IfModule> 我们将在目录/var/www下为服务器加密连接https://www.jhausse.net设定一个默认网站。编辑文件/etc/apache2/sites-available/default-ssl：<VirtualHost _default_:443> ServerAdmin webmaster@localhost DocumentRoot /var/www ServerName www.jhausse.net [...] <Directory /var/www/owncloud> Deny from all </Directory> [...] SSLCertificateFile /etc/ssl/certs/cloud.crt SSLCertificateKeyFile /etc/ssl/private/cloud.key [...] </VirtualHost> 然后让我们同时也在目录/var/www下设定一个非加密连接http://www.jhausse.net的默认网站。编辑文件/etc/apache2/sites-available/default：<VirtualHost _default_:443> DocumentRoot /var/www ServerName www.jhausse.net [...] <Directory /var/www/owncloud> Deny from all </Directory> </VirtualHost> 这样的话，我们通过把文件放到/var/www目录下让www.jhausse.net使用它们提供网站服务。名叫'Deny from all'的指令可以阻止通过www.jhausse.net访问Owncloud：我们将设定通过https://cloud.jhausse.net来正常访问。现在我们将设定网页邮件（roundcube），让它可以通过网址https://webmail.jhausse.net来访问。编辑文件/etc/apache2/sites-available/roundcube并写入以下内容：<IfModule mod_ssl.c> <VirtualHost *:443> ServerAdmin webmaster@localhost DocumentRoot /var/lib/roundcube # The host name under which you'd like to access the webmail ServerName webmail.jhausse.net <Directory /> Options FollowSymLinks AllowOverride None </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined # SSL Engine Switch: # Enable/Disable SSL for this virtual host. SSLEngine on # do not allow unsecured connections # SSLRequireSSL SSLCipherSuite HIGH:MEDIUM # A self-signed (snakeoil) certificate can be created by installing # the ssl-cert package. See # /usr/share/doc/apache2.2-common/README.Debian.gz for more info. # If both key and certificate are stored in the same file, only the # SSLCertificateFile directive is needed. SSLCertificateFile /etc/ssl/certs/cloud.crt SSLCertificateKeyFile /etc/ssl/private/cloud.key # Those aliases do not work properly with several hosts on your apache server # Uncomment them to use it or adapt them to your configuration Alias /program/js/tiny_mce/ /usr/share/tinymce/www/ # Access to tinymce files <Directory "/usr/share/tinymce/www/"> Options Indexes MultiViews FollowSymLinks AllowOverride None Order allow,deny allow from all </Directory> <Directory /var/lib/roundcube/> Options +FollowSymLinks # This is needed to parse /var/lib/roundcube/.htaccess. See its # content before setting AllowOverride to None. AllowOverride All order allow,deny allow from all </Directory> # Protecting basic directories: <Directory /var/lib/roundcube/config> Options -FollowSymLinks AllowOverride None </Directory> <Directory /var/lib/roundcube/temp> Options -FollowSymLinks AllowOverride None Order allow,deny Deny from all </Directory> <Directory /var/lib/roundcube/logs> Options -FollowSymLinks AllowOverride None Order allow,deny Deny from all </Directory> <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> <Directory /usr/lib/cgi-bin> SSLOptions +StdEnvVars </Directory> # SSL Protocol Adjustments: # The safe and default but still SSL/TLS standard compliant shutdown # approach is that mod_ssl sends the close notify alert but doesn't wait for # the close notify alert from client. When you need a different shutdown # approach you can use one of the following variables: # o ssl-unclean-shutdown: # This forces an unclean shutdown when the connection is closed, i.e. no # SSL close notify alert is send or allowed to received. This violates # the SSL/TLS standard but is needed for some brain-dead browsers. Use # this when you receive I/O errors because of the standard approach where # mod_ssl sends the close notify alert. # o ssl-accurate-shutdown: # This forces an accurate shutdown when the connection is closed, i.e. a # SSL close notify alert is send and mod_ssl waits for the close notify # alert of the client. This is 100% SSL/TLS standard compliant, but in # practice often causes hanging connections with brain-dead browsers. Use # this only for browsers where you know that their SSL implementation # works correctly. # Notice: Most problems of broken clients are also related to the HTTP # keep-alive facility, so you usually additionally want to disable # keep-alive for those clients, too. Use variable "nokeepalive" for this. # Similarly, one has to force some clients to use HTTP/1.0 to workaround # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and # "force-response-1.0" for this. BrowserMatch "MSIE [2-6]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 # MSIE 7 and newer should be able to use keepalive BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown </VirtualHost> </IfModule> 然后在你的DNS服务商那里声明一下服务器，例如：webmail.jhausse.net. 300 IN CNAME cloud.jhausse.net. 现在让我激活这三个网站：a2ensite default default-ssl roundcube service apache2 restart 关于网页邮件，可以通过网址https://webmail.jhausse.net来访问，基本上能工作。之后使用邮箱全名（例如roudy@jhausse.net）和在本文一开始在邮件服务器数据库里设定的密码登录。第一次连接成功，浏览器会警告说证书没有可靠机构的签名。这个没什么关系，只要添加一个例外即可。最后但很重要的是，我们将通过把以下内容写入到/etc/apache2/sites-available/owncloud来为Owncloud创建一个虚拟主机。<IfModule mod_ssl.c> <VirtualHost *:443> ServerAdmin webmaster@localhost DocumentRoot /var/www/owncloud ServerName cloud.jhausse.net <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/owncloud> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined # SSL Engine Switch: # Enable/Disable SSL for this virtual host. SSLEngine on # do not allow unsecured connections # SSLRequireSSL SSLCipherSuite HIGH:MEDIUM SSLCertificateFile /etc/ssl/certs/cloud.crt SSLCertificateKeyFile /etc/ssl/private/cloud.key <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> <Directory /usr/lib/cgi-bin> SSLOptions +StdEnvVars </Directory> BrowserMatch "MSIE [2-6]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 # MSIE 7 and newer should be able to use keepalive BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown </VirtualHost> </IfModule> 然后通过执行以下命令激活Owncloud：a2ensite owncloud service apache2 reload 之后通过在浏览器里打开链接https://cloud.jhausse.net/配置一下Owncloud。就这些了！现在你已经拥有自己的Google Drive，日程表，联系人，Dropbox，以及Gmail！好好享受下新鲜恢复保护的隐私吧！:-)在云上同步你的设备要同步你的邮件，你只需用你喜欢的邮件客户端即可：Android或iOS自带的默认邮件应用，k9mail，或者电脑上的Thunderbird。或者你也可以使用我们设置好的网页邮件。在Owncloud的文档里描述了如何与云端同步你的日程表和联系人。在Android系统中，我用的是CalDAV-Sync，CardDAV-Sync应用桥接了手机上Android自带日历以及联系人应用和Owncloud服务器。对于文件，有一个叫Owncloud的Android应用可以访问你手机上的文件，然后自动把你拍的图片和视频上传到云中。在你的Mac/PC上访问云端文件也很容易，在Owncloud文档里有很好的描述。最后一点提示在上线后的前几个星期里，最好每天检查一下日志/var/log/syslog和/var/log/mail.log以保证一切都在顺利运行。在你邀请其他人（朋友，家人，等等）加入你的服务器之前这很重要。他们信任你能很好地架设个人服务器维护他们的数据，但是如果服务器突然崩溃会让他们很失望。要添加另一个邮件用户，只要在数据库mailserver的virtual\_users表中增加一行。要添加一个域名，只要在virtual\_domains表中增加一行。然后更新/etc/opendkim/SigningTable为发出的邮件签名，上传OpenDKIM密钥到服务器区域，然后重启OpenDKIM服务。Owncloud有自己的用户数据库，在用管理员帐号登录后可以修改。最后，万一在服务器临时崩溃的时候想办法找解决方案很重要。比如说，在服务器恢复之前你的邮件应该送往哪儿？一种方式是找个能帮你做备份MX的朋友，同时你也可以当他的备份MX（看下postfix的配置文件main.cf里relay\_domains和relay\_recipient\_maps里的设定）。与此类似，如果你的服务器被破解然后一个坏蛋把你所有文件删了怎么办？对于这个，考虑增加一个常规备份系统就很重要了。Linode提供了备份选项。在1984.is里，我用crontabs和scp做了一个基本但管用的自动备份系统。via: https://www.howtoforge.com/tutorial/build-your-own-cloud-on-debian-wheezy/作者：Roudy Jhausse 译者：zpl1025 校对：wxy本文由 LCTT 原创翻译，Linux中国 荣誉推出