在短短几个小时里拿回自己数据的隐私和控制权：为自己和朋友们搭建私有云
================================================================================
8年里40'000多次搜索！这是我的Google搜索历史。你的呢？（可以在[这里][1]自己找一下）有经过这么长时间积累下来的这么多数据点，Google已经能非常精确的推测你对什么感兴趣，曾经的想法，担忧过的事情，以及从你第一次获得Google帐号后这些年里所有这些的变化。

### 很多非常私人的信息不受自己控制地存储在世界范围内的服务器上 ###

比如说你也像我一样从2006年到2013年都是Gmail用户，意味着你收到了30'000+的电子邮件以及在这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公司的陌生人（这是他们制造面包的材料）以及[世界级的数据分析专家][2]手里，也许只是因为我们在点击那个绿色的'接受'按钮时根本没有想这么多。

有这么多的高质量信息，这么多年里，Google可能会比你希望自我了解的更了解你自己：尼玛，回想我过去的数字生活，我已经不记得5年前发出的邮件里的一半了。我很高兴能重新发现早在2005年对马克思主义的兴趣以及第二年加入了[ATTAC][3]（一个致力于通过征收金融交易税来限制投机和改善社会公平的组织）。天知道为什么我竟然在2007年这么喜欢跳舞。这些都是无关紧要的信息（你不要指望我能爆出什么猛料，不会吧？;-）。但是，连接起这些高质量数据点，关于你生活的方方面面（做什么，什么时候，和谁一起，在哪里，...），并跨越这么长时间间隔，应该能推测出你的未来状态。比如说，根据一个17岁女孩的购物习惯，超市甚至可以在他父亲听说之前断定这个女孩怀孕了（[真实故事][4]）。谁知道通过像Google所掌握的这些远远超出购物习惯的高质量数据能做些什么？连接起这些点，也许有人能预测你未来几年里口味或政治观点的变化。如今，[你从未听过的公司声称拥有你500项数据点][5]，包括宗教信仰，性取向和政治观点。提到政治，如果说你决定今后10年内进入政坛会怎么样？你的生活会改变，你的观点也一样，甚至你有时候会有所遗忘，但是Google不会。那你会不会担心你的对手会接触一些可以从Google访问你数据的人并会从你过去这些年里积累的个人数据深渊里挖出一些猛料呢？[就像最近Sony被黑][6]一样，多久以后会轮到Google或Facebook，以致让你的个人信息最终永远暴露？

我们大多数人把自己的个人数据托付给这些公司的一个原因就是它们提供免费服务。但是真的免费吗？一般的Google帐号的价值根据评估方式不同会有些差别：你花在写邮件上的时间占到[1000美元/年][7]，你的帐号对于广告产业的价值差不多在[220美元/年][8]到[500美元/年][9]之间。所以这些服务并不是真的免费：会通过广告和我们的数据在未来的一些未知使用来间接付费。

我写的最多的是Google，这是因为这是我托付个人数字信息的，以及目前我所知道做的最好的公司。但是我也提到过Apple或Facebook。这些公司通过它们在设计，工程和我们（曾经）喜欢每天使用的服务方面的神奇进步实实在在地改变了世界。但是这并不是说我们应该把所有我们最私人的个人数据堆积到它们的服务器上并把我们的数字生活托付给它们：潜在的危害实在太大了。

### 只要5小时，拿回自己以及关心的人的隐私权 ###

并不是一定要这样做。你可以生活在21世纪，拿着智能手机，每天都用电子邮件和GPS，却仍然可以保留自己的隐私。你所需要的就是拿回自己个人数据的控制权：邮件、日程、联系人、文件，等等。[Prism-Break.org][10]网站上列出了一些能帮你掌握个人数据命运的软件。除此以外，控制自己个人数据的最安全和最有效的方式是架设自己的服务器并搭建自己的云。不过你也许只是没有时间或精力去研究具体该怎么做以及如何让它能流畅工作。

这也是这篇文章的意义所在。仅仅5个小时内，我们将配置出一台服务器来支撑你的邮件、联系人、日程表和各种文件，为你、你的朋友和你的家人。这个服务器将设计成一个个人数据中心或云，所以你能时刻保留它的完整控制。数据将自动在你的台式机/笔记本、手机和平板之间同步。从根本上来说，**我们将建立一个系统来代替Gmail、Google文件/Dropbox、Google联系人、Google日历和Picasa**。

为自己做这件事情已经是迈出很大一步了。但是，你个人信息的很大一部分将仍然泄漏出去并保存到硅谷的一些主机上，只是因为和你日常来往的太多人在用Gmail和使用智能手机。所以最好是带上你一些比较亲近的人加入这次探险。

我们将构建的系统能够

- **支持任意数目的域名和用户**。这样就能轻易地和你的家人朋友共享这台服务器，所以他们也能掌控自己的个人数据，并且还能和你一起分摊服务费用。和你一起共享服务器的人可以使用他们自己的域名或者共享你的。
- **允许你从任意网络发送和接收电子邮件**，需要成功登录服务器之后。这样，你可以通过任意的邮件地址，任意设备（台式机、手机、平板），任意网络（家里、公司、公共网络、...）来发送电子邮件。
- **在发送和接收邮件的时候加密网络数据**，这样，你不信任的人不能钓出你的密码，也不能看到你的私人邮件。
- **提供最先进的反垃圾邮件技术**，结合了已知垃圾邮件黑名单，自动灰名单，和自适应垃圾邮件过滤。如果邮件被误判了只需要简单地把它拖入或拖出垃圾目录就可以重新配置垃圾邮件过滤器。而且，服务器还会为基于社区的反垃圾邮件努力做出贡献。
- **一段时间里只需要几分钟的维护**，基本上只是安装安全更新和简单地检查一下服务器日志。添加一个新的邮件地址只需要在数据库中插入一条记录。除此之外，你可以忘记它的存在过自己的生活。我在14个月之前搭建了本文描述的这个系统，从那以后就一直顺利运行。所以我完全把它给忘了，直到我最近觉得随便按下手机上的‘检查邮件’会导致电子一路跑到冰岛（我放置服务器的地方）再回来的想法有点好笑才想起来。

要完成这篇文章里的工作，你需要一点基本的技术能力。如果你知道SMTP和IMAP的区别，什么是DNS，以及对TCP/IP有基本了解的话，就够了。你还将需要一点基本的Unix知识（在命令行下和文件一起工作，基本的系统管理）。然后你需要花总共5小时时间来搭建。

下面是我们将要做的事情的概述。

- [申请一个虚拟私人服务器，一个域名，并把它们配置好][11]
- [设置postfix和dovecot来收发电子邮件][12]
- [阻止垃圾邮件进入你的收件箱][13]
- [确保你发出的邮件能通过垃圾邮件过滤器][14]
- [使用Owncloud提供日历，联系人，文件服务并配置webmail][15]
- [在云上同步你的设备][16]

### 这篇文章是受之前工作的启发并以之为基础 ###

本文很大程度参考了两篇文章，由[Xavier Claude][17]和[Drew Crawford][18]写的关于架设私有邮件服务器的介绍。

本文覆盖了Xavier和Drew的文章里所描述的所有功能，除了3个地方Drew有而我没有：邮件推送支持（我喜欢由我主动检查邮件，而其他时候都不会被打扰），邮件全文检索（我一直都没用过），以及使用加密方式存储邮件（我的邮件和数据还没那么重要到要把它们加密后再存到本地服务器上）。如果你需要这些功能，只需要按照Drew的文章里相应部分的说明做就好了，和本文的内容兼容。

和Xavier和Drew的成果比起来，本文有下面几个主要改进：

- 根据我自己按Drew文章操作的经验以及原文的大量回复，修改了一些问题和文字错误。我也把本文所介绍的内容仔细检查了几遍，从头开始设定了几次服务器做重复验证以确保能正常工作。
- 低维护：和Xavier的方式比起来，本文增加了在服务器上支持多个邮件域名。这样做是为了尽可能地减少服务器维护工作：基本上，要添加一个域名或用户，只需要往mysql数据库表里增加一行就好了（不需要增加过滤脚本，等等）。
- 我增加了webmail。
- 我增加了设定云服务器的部分，不仅能收发邮件还能管理文件，地址本/联系人（邮件地址，电话号码，生日，等等等），日程表和图片，供所有设备访问使用。

### 申请一个虚拟私人服务器，一个域名，并把它们配置好 ###

让我们从设置基础设施开始：我们的虚拟私人主机和我们的域名。

我用过[1984.is][19]和[Linode][20]提供的虚拟私人主机（VPS），体验非常好。在本文中，我们将使用**Debian Wheezy**，这个在1984和Linode都提供了已经做好的映像文件可以直接布置到你的VPS上。我喜欢1984是因为它的服务器在冰岛，也是唯一使用可再生能源（地热和水力发电）的地方，目前还没有影响过气候变化，不像[大多数美国数据中心目前大多数依赖于烧煤的火力发电站][21]。而且，他们注重[民权，透明，自由][22]以及[免费软件][23]。

最好是在服务器上创建一个文件用来保存后面要用到的各种密码（用户账号，邮件账号，云帐号，数据库帐号）。当然最好是加密一下（可以用[GnuPG][24]），这样就算用来设定服务器的电脑被偷了或被入侵了，你的服务器就不会那么容易被攻击。

关于注册域名，我已经使用[grandi][25]的服务超过10年了，也很满意。在本文中，我们将开辟一个叫**jhausse.net**的域名。然后在上面增加一个叫**cloud.jhausse.net**的二级域名，并绑定MX纪录。在完成之后，设置比较短的纪录生存时间（TTL）比如300秒，这样你在设置服务器的时候，可以修改你的域并很快测试到结果。

最后，设置PTR纪录（反向DNS），这样IP地址可以反向映射回它的域名。如果你不理解前面这句话，看下[这篇文章][26]来获得相关背景知识。如果你使用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远程编辑配置文件。打开自动语法高亮会很有帮助。添加下面这一行到**~/.vimrc**文件中。

    syn on

### 设置postfix和dovecot来收发电子邮件 ###

    apt-get install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-mysql mysql-server dovecot-lmtpd postgrey

在[Postfix][27]的配置菜单里，选择**因特网站点**，把系统邮件名设为**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**域名。如果还需要加入其他域名，也没问题。我们也会为每个域名设置一个邮件管理地址，转寄给**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（一个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，以避免收到一些不必要的垃圾邮件。

现在，我们试一下往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][28]工作正常。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往自己架设的服务器上的帐号发送邮件][29]，来验证你已经没有被postgrey阻挡了。

### 阻止垃圾邮件进入你的收件箱 ###

为了过滤垃圾邮件，我们已经使用了实时黑名单（RBLs）和灰名单（postgrey）。现在我们将增加自适应垃圾邮件过滤来让我们的垃圾邮件过滤能力提高一个等级。这意味着我们将为我们的邮件服务器增加人工智能，这样它就能从经验中学习哪些有件是垃圾哪些不是。我们将使用[dspam][30]来实现这个功能。

    apt-get install dspam dovecot-antispam postfix-pcre dovecot-sieve

dovecot-antispam是一个安装包，可以在我们发现有邮件被dspan误分类了之后让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）是你添加到自己服务器区域里的一份记录，声明了整个因特网上哪些邮件服务器能以你的域名发邮件。设置非常简单，使用[microsoft.com][31]上的SPF向导来生成你的SPF记录，然后作为一个TXT记录添加到自己的服务器区域里。看上去像这样：

    jhausse.net.	300 IN	TXT	v=spf1 mx mx:cloud.jhausse.net -all

#### 反向PTR ####

我们[之前][32]在本文里讨论过这个问题，建议你为自己的服务器正确地设置反向DNS，这样对服务器IP地址的反向查询能返回你服务器的实际名字。

#### OpenDKIM ####

当我们激活[OpenDKIM][33]后，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的邮件测试][34]。发送一封邮件到[Brandon的网页][34]上提供的测试地址，我们可以在服务器上运行下面的命令

    mail -s CloudCheck ihAdmTBmUH@www.brandonchecketts.com

在Brandon的网页上，我们应该可以在'DKIM Signature'部分里看到**result = pass**的文字，以及在'SPF Information'部分看到**Result: pass**的文字。如果我们的邮件通过这个测试，只要不加-t开关重新生成OpenDKIM密钥，上传新的密钥到区域文件里，然后重新测试检查是否仍然可以通过这些测试。如果可以的话，恭喜！你已经在你的服务器上成功配置好OpenDKIM和SPF了！

### 使用Owncloud提供日历，联系人，文件服务并通过Roundcube配置网页邮件 ###

既然我们已经拥有了一流的邮件服务器，让我们再为它增加在云上保存通讯录，日程表和文件的能力。这些是[Owncloud][35]所提供的非常赞的服务。在这个弄好后，我们还会设置一个网页邮件，这样就算你没带任何电子设备出去旅行时，或者说在你的手机或笔记本没电的情况下，也可以检查邮件。

安装Owncloud非常直观，而且在[这里][36]有非常好的介绍。在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

    <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][37]，或者电脑上的Thunderbird。或者你也可以使用我们设置好的网页邮件。

在Owncloud的文档里描述了如何与云端同步你的日程表和联系人。在Android系统中，我用的是CalDAV-Sync，CardDAV-Sync应用桥接了手机上Android自带日历以及联系人应用和Owncloud服务器。

对于文件，有一个叫Owncloud的Android应用可以访问你手机上的文件，然后自动把你拍的图片和视频上传到云中。在你的Mac/PC上访问云端文件也很容易，在[Owncloud文档里有很好的描述][38]。

### 最后一点提示 ###

在上线后的前几个星期里，最好每天检查一下日志**/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 ][a]
译者：[zpl1025](https://github.com/zpl1025)
校对：[校对者ID](https://github.com/校对者ID)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译，[Linux中国](http://linux.cn/) 荣誉推出

[a]:aboutlinux@free.fr
[1]:https://history.google.com/history/
[2]:http://research.google.com/workatgoogle.html
[3]:http://www.attac.org/
[4]:http://www.nytimes.com/2012/02/19/magazine/shopping-habits.html?pagewanted=all
[5]:http://vimeo.com/ondemand/termsandconditions
[6]:http://www.techtimes.com/articles/21670/20141208/sony-pictures-hack-nightmare-week-celebs-data-leak-and-threatening-emails-to-employees.htm
[7]:http://blog.backupify.com/2012/07/25/what-is-my-gmail-account-really-worth/
[8]:http://adage.com/article/digital/worth-facebook-google/293042/
[9]:http://vimeo.com/ondemand/termsandconditions
[10]:https://prism-break.org/en/
[11]:https://www.howtoforge.com/tutorial/build-your-own-cloud-on-debian-wheezy/#VPS
[12]:https://www.howtoforge.com/tutorial/build-your-own-cloud-on-debian-wheezy/#mail
[13]:https://www.howtoforge.com/tutorial/build-your-own-cloud-on-debian-wheezy/#dspam
[14]:https://www.howtoforge.com/tutorial/build-your-own-cloud-on-debian-wheezy/#SPF
[15]:https://www.howtoforge.com/tutorial/build-your-own-cloud-on-debian-wheezy/#owncloud
[16]:https://www.howtoforge.com/tutorial/build-your-own-cloud-on-debian-wheezy/#sync
[17]:http://linuxfr.org/news/heberger-son-courriel
[18]:http://sealedabstract.com/code/nsa-proof-your-e-mail-in-2-hours/
[19]:http://www.1984.is/
[20]:http://www.linode.com/
[21]:http://www.greenpeace.org/international/Global/international/publications/climate/2012/iCoal/HowCleanisYourCloud.pdf
[22]:http://www.1984.is/about/
[23]:http://www.fsf.org/
[24]:https://www.gnupg.org/
[25]:http://www.gandi.net/
[26]:http://www.codinghorror.com/blog/2010/04/so-youd-like-to-send-some-email-through-code.html
[27]:http://www.postfix.org/
[28]:http://postgrey.schweikert.ch/
[29]:https://www.howtoforge.com/tutorial/build-your-own-cloud-on-debian-wheezy/#testPort25
[30]:http://dspam.sourceforge.net/
[31]:http://www.microsoft.com/mscorp/safety/content/technologies/senderid/wizard/
[32]:https://www.howtoforge.com/tutorial/build-your-own-cloud-on-debian-wheezy/#PTR
[33]:http://opendkim.org/opendkim-README
[34]:http://www.brandonchecketts.com/emailtest.php
[35]:http://owncloud.org/
[36]:http://owncloud.org/install/
[37]:https://code.google.com/p/k9mail/
[38]:http://doc.owncloud.org/server/7.0/user_manual/files/files.html
