@Lenciel

First steps on a new server

一般来说,新开张的小团队不会养专职的运维和部署团队。一般服务器开发的项目组会有人兼职做这部分的事情。刚开始的时候这部分的工作量一般也不大,但是随着租用的服务器越来越多,兼职的人就会发现自己是在打上甘岭战役————坡越来越陡。

因此,一个简单而有效的标准流程是非常必要的。ZooM团队的服务器都会配置两个固定的帐号: rootdeploydeploy 这个用户具有 sudo 的权限。开发人员使用deploy但是不通过用户名密码登录而是用 public key 。这样一来,只需要保证所有机器的 authorized_keys 文件同步即可。后面要做的改进是:

  • 在所有机器禁止通过 root 账号进行ssh
  • 在所有机器上限制可以ssh的IP范围

这样的实施方案对 authorized_keys 的保密性和正确性要求是很高的,但是在没有专门IT的时候,对我们这样的小团队基本是够用的。下面是详细的步骤:

我们拿到的第一台机器是Ubuntu的,因为 Gitlab 只有Debian的版本。后面的机器大多会是CentOS,所以使用的命令可能会稍微有调整,但是意思是不变的。

更换root密码

1
passwd

可以很长很复杂(反正也不需要记得),保存在某个地方在你忘记 sudo 密码或者是不能正常 ssh 的时候能找出来用就可以了。

更新系统

1
2
apt-get update
apt-get upgrade

安装Fail2ban

1
apt-get install fail2ban

Fail2ban是一个用来监控登录尝试的 daemon ,可以有效侦测和防止可疑行为的发生。这个工具文档很全,而且出厂配置就很齐全,几乎不需要定制就能投入使用了。

添加deploy用户

1
2
3
4
useradd deploy
mkdir /home/deploy
mkdir /home/deploy/.ssh
chmod 700 /home/deploy/.ssh

配置 public key

使用密码的日子已经慢慢过时了,这方面Github很有贡献。只需要:

1
vim /home/deploy/.ssh/authorized_keys

id_rsa.pub 的内容拷贝进去。然后:

1
2
chmod 400 /home/deploy/.ssh/authorized_keys
chown deploy:deploy /home/deploy -R

当然你也可以使用 id_rsa.pub 之外的key,然后在本地的 ~/.ssh/config 里面对 IdentityFile 做指定。具体方式可以查看 ~/.ssh/config的说明。

测试deploy用户并赋予 Sudo 权限

先测试deploy是否能够正常登录,然后使用 root 账号设置密码:

1
passwd deploy

这是团队要用来 sudo 的账号,所以要弄得有意义好记一点儿。接下来:

1
visudo

注释掉所以已经存在的用户、用户组权限,然后加上:

1
2
root    ALL=(ALL) ALL
deploy  ALL=(ALL) ALL

锁定SSH

设置ssh,禁止使用密码ssh,禁止使用 root 账号ssh。

1
vim /etc/ssh/sshd_config

添加下面的设置:

1
2
PermitRootLogin no
PasswordAuthentication no

如果有需要还可以限定可以ssh的ip地址:

1
AllowUsers deploy@(your-ip) deploy@(another-ip-if-any)

重启ssh:

1
service ssh restart

设置防火墙

Ubuntu提供了 ufw,所以只需要:

1
2
3
4
ufw allow from {your-ip} to any port 22
ufw allow 80
ufw allow 443
ufw enable

打开自动安全更新

虽然很多习惯好的服务器使用者会知道运行apt-get update/upgrade 但是如果服务器很多,总会有一些不那么被经常登录的机器,系统会比较陈旧。特别是做负载均衡的机器,可能很少有人登录。为了保证所有的机器都有足够的安全性需要打开自动更新(作为习惯控制一切的开发人员,自动更新总是一件让我很抗拒的事情,但是安全漏洞更让人抗拒):

1
2
apt-get install unattended-upgrades
vim /etc/apt/apt.conf.d/10periodic

在文件里面修改成:

1
2
3
4
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";

接着修改:

1
vim /etc/apt/apt.conf.d/50unattended-upgrades

修改文件成:

1
2
3
4
Unattended-Upgrade::Allowed-Origins {
    "Ubuntu lucid-security";
    //"Ubuntu lucid-updates"; 只更新安全更新
};

安装Logwatch

Logwatch是一个监控你的日志并发送邮件通知的daemon。

1
2
apt-get install logwatch
vim /etc/cron.daily/00logwatch

在文件中添加:

1
/usr/sbin/logwatch --output mail --mailto lenciel@gmail.com --detail high

What’s Next

  • 使用Puppet自动化这些配置
  • 在基础的配置上,把一个fresh的机器如果配置成各种形态的(Django/Web/Database/LoadBalance/…)

Boxen introduction

如果列举开发人员在工作中最讨厌的部分,估计搭建开发环境得票率肯定可以排进前三。年初Github开源了自己内部的Privision框架Boxen,趁着新笔记本需要起轿,尝试了一把。

Boxen框架简介

Boxen基于大红大紫的Puppet,但和后者目前主要侧重于服务器的Privision不同,Boxen更主要是用于组织内工作人员使用的机器的配置和管理流程标准化。

配置流程标准化比较好理解:拿到一台机器,敲一个命令就把所有需要的软件装上并且把环境配置好。按Boxen主页上的说法,Github新员工入职后领到电脑后,用Boxen配置环境到开始写代码只需要30分钟。

管理流程标准化听起来比较抽象,你可以想象这么一个场景:如果公司里面所有的机器都是是用Boxen来配置的。当发现Chrome浏览器的Java插件会导致安全问题的时候,IT部门可以push一个禁用Chrome里Java插件的change到boxen repo。所有的员工只需要和repo做一次sync,自己的Chrome里的Java插件就被禁用了。这显然比传统的发邮件要求大家去禁用Chrome浏览器Java插件简单有效。

简单地概括Boxen的思路,就是像对待产品一样对待开发环境。使用包括版本控制,持续集成这些手段,在团队中维护一个开发环境的仓库。如果你想更深入地了解Boxen的设计哲学,可以看看这个slide:BOXEN by Will Farrington

使用Boxen

首先确保你的初始环境是干净的:

  • 如果你手上是台新机器,它是干净的
  • 如果不是一台新机器,请先备份,然后:

    • 卸载Homebrew
    • 删除所有的 dotfilesvimfiles ,比如Oh my zsh或者spf13 vim
    • 删除 .rbenv 或者 .rvm 文件夹
    • chsh -s /bin/bash 把SHELL改回 bash

接下来就是安装一些必须的软件,比如Git和Xcode的 Command Line Tools

Xcode CLT

  • 升级Xcode
  • 启动Xcode,在Preferences里面选择下载
  • 安装"Command Line Tools"

Xcode Command Line Tools

打开FireVault2

Boxen默认会希望硬盘信息是被加密的:

Turn on FireVault2

Fork our-boxen

our-boxen是Boxen提供的基线repo,也是整个Boxen框架里面文档最全的一个repo。

首先按照repo说明中的方式来clone和配置本地repo:

1
2
3
4
5
6
7
sudo mkdir -p /opt/boxen
sudo chown ${USER}:admin /opt/boxen
git clone https://github.com/boxen/our-boxen /opt/boxen/repo
cd /opt/boxen/repo
git remote rm origin
git remote add origin
git push -u origin master

这种clone下来再配置origin的方式类似于fork,区别是fork下来的repo一定是public的,而这样得到的repo可以是private的。可以想象如果你使用boxen来完成对公司电脑的配置,多少都会有一些敏感信息在repo里面,所以private的repo是非常必要的。

接下来在 /opt/boxen/repo 路径下运行 script/boxen 即可完成boxen默认的模块的安装。默认的模块定义在 /opt/boxen/repo/Puppetfile 中:

1
2
3
4
5
6
7
8
9
10
11
12
github "dnsmasq",  "1.0.0"
github "gcc",      "1.0.0"
github "git",      "1.0.0"
github "homebrew", "1.0.0"
github "hub",      "1.0.0"
github "inifile",  "0.9.0", :repo => "cprice-puppet/puppetlabs-inifile"
github "nginx",    "1.0.0"
github "nodejs",   "1.0.0"
github "nvm",      "1.0.0"
github "ruby",     "1.0.0"
github "stdlib",   "3.0.0", :repo => "puppetlabs/puppetlabs-stdlib"
github "sudo",     "1.0.0"

可以看到Github大量用到 rubynodejs 。在运行boxen的时候,可能会看到大量的警告信息:

1
2
Warning: Could not retrieve fact fqdn
Warning: Host is missing hostname and/or domain: suttlemac

然后伴随着 https://rubygems.org 失败。这些主要是因为GFW,你可以使用镜像,比如淘宝的。具体方式可以查看这里

注意你还应该把下面的脚本加到 ~/.bashrc 或者 ~/.zshrc :

1
[ -f /opt/boxen/env.sh ] && source /opt/boxen/env.sh

然后新开一个shell运行 boxen --env,结果一切正常你的box就配置完毕了。

自定义你的box

默认安装的内容当然不一定对你的口味,如果你用过Puppet那么自定义Boxen的box是非常简单的。不过埋头开干之前还是可以check一下是不是已经有人做好了。这些做好的repo可以直接通过修改配置文件是用,因为Boxen对librarian-puppet做了wrapper,对fetch各种module也做了wrapper。

比如我们要安装Chrome和Skype,打开 /opt/boxen/repo/Puppetfile 并添加两行:

1
2
3
4
5
6
...
github "sudo",     "1.0.0"

# Add new modules
github "skype",    "1.0.2"
github "chrome",   "1.1.0"

这里安装的module的声明规则是 github "{name}", "{version}"。 其中 name 的取法是在 Puppetfile 里面定义的:

1
2
3
4
5
def github(name, version, options = nil)
  options ||= {}
  options[:repo] ||= "boxen/puppet-#{name}"
  mod name, version, :github_tarball => options[:repo]
end

因此puppet-skype对应的就是 skype

version 则是对应具体repo的tag,比如puppet-skype对应的tag有:

Version and tags

如果你的repo不是在github也很简单,只需要指定repo的位置即可。比如如果你自己的Skype是放在Bitbucket上的:

1
   mod "skype", :git => "git@bitbucket.org:yourusername/puppet-skype.git"

Puppetfile 里面完成的声明主要是让Boxen(实际上是Puppet)知道去哪里找安装和配置文件。要告诉Boxen安装Skype还需要在 manifests/site.pp 里面 include 需要安装的module:

1
2
3
4
5
6
7
8
9
10
...
    node default {
        include dnsmasq
        include ruby
        include git
        include hub
        include homebrew
        include skype
    }
...

接下来只需要运行 boxen (如果你运行了 boxen --env 命令会在可执行路径里)或者是 boxen --debug (如果你需要更多的verbose信息),指定的软件就安装上了。

What’s Next

目前为止主要是解释了如何使用Boxen来安装一些基本软件。目前本座机器上使用Boxen安装的软件包括:

1
2
3
4
5
6
github "ccleaner", "1.0.1"
github "iterm2",   "1.0.2"
github "skype",    "1.0.2"
github "chrome",   "1.1.0"
github "sublime_text_2",   "1.1.0"
github "jumpcut",   "1.0.0"

接下来的计划就是建立项目组自己的repo,把诸如输入法、dotfiles、Java开发环境和Django开发环境这些东西的安装和配置都自动化了。