前言
還記得當年修計算機系統管理時曾經為了做 NFS + NIS 的作業自行開了三台虛擬機設定環境,同時灌三台電腦實在是煞費精力。在此之後雖然比較少遇到此情形,但還是得常常重灌電腦。像是研究所期間,自己的桌機、筆電,以及實驗室的桌機都是自己裝的 Ubuntu,而每次升級病發就會想重灌成新的版本,久了以後慢慢把安裝的東西寫成 Bash scripts,可是還是相當繁瑣。
就在最近的時候,偷聽大大們聊天,得知了 Ansible 這個方便的自動化部屬工具。由於它使用時目的端完全不須安裝任何套件,而是從本地端完全使用 SSH 進去目的端安裝設定軟體,感覺也挺適合個人重灌的需求。於是就花了一點時間研究了一下。在此同時,也得知了 yadm 這個 dotfiles 管理套件,也花了一點時間把原本用 Makefile 來安裝的 dotfiles 改成用 yadm 管理了。
Ansible 設定
實際上 Ansible 的功用是用來自動化部署而不是拿來重灌個人電腦的,所以尋找文件時常常看到許多複雜功能。這份文件只挑些用在重灌上有用的部份。
安裝 Ansible 的方法非常簡單,只要使用 pip install ansible
或者是 sudo apt install ansible
即可。
然後我建立一個資料夾放置設定檔,組織成如下所示:
.
├── ansible.cfg
├── hosts
├── anaconda.yml
├── desktop.yml
└── roles
├── anaconda
│ └── tasks
│ └── main.yml
├── base
│ └── tasks
│ └── main.yml
└── desktop
└── tasks
└── main.yml
首先在 ansible.cfg
裡指定用來設定有哪些機器的 hostfile 的位置:
[defaults]
hostfile = hosts
然後在 hosts
裡設定機器位址,例如:
[host1]
192.168.1.2
[host2]
192.168.1.3 ansible_ssh_user=bob ansible_ssh_private_key_file=~/.ssh/bob.pem
[servers]
192.168.1.4
192.168.1.5
192.168.1.6
每個 group 可以設定多個機器,也可以指定使用者名稱和登入方法等等,見:〈Inventory〉。
deploy
則是一個簡單的 Bash script,用來方便執行。使用方法為:
./deploy HOST YML
利用 HOST
指定要設定的機器名稱,例如之前設定的 host1
或者 localhost
,YML
則是要執行的 playbook 設定檔,例如最上層的 anaconda.yml
或者 desktop.yml
。
#!/bin/bash
HOST=${1:-localhost}
YML=${2:-desktop.yml}
ansible-playbook --ask-become-pass --extra-vars="hosts=$HOST" $YML
desktop.yml
和 anaconda.yml
則是簡單的 Playbooks,用來指定要執行哪些 tasks。例如我在 desktop.yml
寫要用 root 權限執行 base
和 desktop
兩個 roles:
---
- hosts: '{{ hosts }}'
become: true
become_user: root
roles:
- base
- desktop
anaconda.yml
則寫要用正常使用者權限執行 anaconda
這個 role:
---
- hosts: '{{ hosts }}'
roles:
- anaconda
Roles
最後的 roles
資料夾底下把相關的設定項目放在一起,這樣分開設定的好處是,可以根據不同機器的需求指定要執行哪些 roles,此外,也可以用 git submodule
之類的方法直接利用別人寫好的 roles。
先從 base.yml
開始,這個檔案裡我設置了一些基本的系統設定:
---
# 建立 sudoers.d 資料夾,以放置設定檔
- name: mkdir for configure files
file:
dest: '{{ item.dest }}'
owner: root
group: root
mode: '{{ item.mode | default("0755") }}'
state: directory
with_items:
- dest: /etc/sudoers.d
# 因為我自己的使用者 umask 設的比較嚴格,避免 sudo 受影響所以加上這個把 sudo 的 umask 轉回來
- name: set sudo umask
copy:
dest: '{{ item.dest }}'
owner: root
group: root
mode: '{{ item.mode | default("0644") }}'
content: '{{ item.content }}'
with_items:
- dest: /etc/sudoers.d/umask
mode: '0400'
content: |
# This file is managed by Ansible. DO NOT EDIT.
Defaults umask_override
Defaults umask = 0002
# 更新系統
- name: upgrade packages
apt:
upgrade: dist
update_cache: yes
# 安裝常用套件
- name: install core packages
apt:
name: '{{ item.name }}'
state: '{{ item.state | default("present") }}'
purge: yes
with_items:
- name: git-core
- name: gufw
- name: htop
- name: p7zip-full
- name: p7zip-rar
- name: screen
- name: tmux
- name: yadm
desktop.yml
則用來放個人桌機常用的設定:
---
# 建立資料夾來放之後的設定檔
- name: mkdir for configure files
file:
dest: '{{ item.dest }}'
owner: root
group: root
mode: '{{ item.mode | default("0755") }}'
state: directory
with_items:
- dest: /usr/share/lightdm/lightdm.conf.d
# 取消訪客登入
- name: disable guest login
copy:
dest: '{{ item.dest }}'
owner: root
group: root
mode: '{{ item.mode | default("0644") }}'
content: '{{ item.content }}'
with_items:
- dest: /usr/share/lightdm/lightdm.conf.d/50-no-guest.conf
mode: '0400'
content: |
# This file is managed by Ansible. DO NOT EDIT.
[SeatDefaults]
allow-guest=false
# 安裝一些我常用的軟體
- name: install desktop apps
apt:
name: '{{ item.name }}'
state: '{{ item.state | default("present") }}'
purge: yes
update_cache: yes
with_items:
- name: ibus-chewing
- name: keepassx
- name: libappindicator1 # For Dropbox
- name: python-gpgme # For Dropbox
- name: nautilus-dropbox
- name: workrave
# 安裝 Google Chrome
- name: install Google Chrome
apt:
deb: 'https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb'
update_cache: yes
最後則是安裝 Anaconda 的部份,我會先安裝 Anaconda 2:
:::yml
---
- name: download Anaconda
get_url:
url: 'https://repo.continuum.io/archive/Anaconda2-4.3.1-Linux-x86_64.sh'
dest: /tmp/Anaconda2-4.3.1-Linux-x86_64.sh
mode: '0755'
- name: install Anaconda
command: bash /tmp/Anaconda2-4.3.1-Linux-x86_64.sh -b -p {{ ansible_env.HOME }}/anaconda2
args:
creates: '{{ ansible_env.HOME}}/anaconda2'
- name: add Anaconda to PATH
lineinfile:
name: '{{ ansible_env.HOME }}/.bashrc'
line: 'export PATH=$HOME/anaconda2/bin:${PATH}'
然後再進到目的機器額外安裝 Python 3 的環境:
conda create -n py3 python=3.6 anaconda
不過還不確定以上這件事怎麼寫成 Ansible playbook 比較好。
實際執行
假設新安裝的電腦是 host1
的話,那我就執行以下指令來安裝設定:
./deploy host1 desktop.yml
當然也可以直接登入該電腦,然後把 host1
改成 localhost
直接在本地執行。
yadm
至於 yadm 使用起來就非常簡單了。基本上就是一個可以把家目錄直接當成 git repository 的簡單套件。首先安裝:
sudo apt install yadm
然後剛開始可以直接:
yadm init
yadm add ~/.vimrc
yadm add ~/.tmux.conf
# ...
yadm commit -m 'first commit!'
如果要同步已經有的 repository 則是:
yadm clone <url>
# ...
yadm pull
跟正常的 git 一模一樣。
其他比較有用的功能大概是 Boostrap,可以取代我原本用 Makefile 手動打指令的部份。
結語
本次設定檔放在 shaform/experiments/ansible。其他還可以參考:
- Ansible Documentation
- Ansible 自動化部署工具
- 現代 IT 人一定要知道的 Ansible 自動化組態技巧
- Yet Another Dotfiles Manager
- Awesome dotfiles
- Git - Book