Cách cấu hình một máy chủ Ubuntu mới với Ansible

1. Những thứ cần chuẩn bị:

  •  Ubuntu (20.04 trở lên) mới được cài đặt.
  • Máy Mac cục bộ, Windows (với Linux được cài đặt qua WSL) hoặc hệ thống Linux (hướng dẫn này sẽ tập trung vào việc sử dụng máy Mac, nhưng các quy trình tương tự đối với bất kỳ nút điều khiển Linux nào).
  • Nếu sử dụng máy Mac, nên cài đặt Homebrew .
  • Khóa SSH đã tạo trước đó cho máy chủ Vultr; khóa công khai SSH phải đã được cài đặt cho người dùng root .
  • Ansible 2.9.x hoặc phiên bản ổn định mới hơn (hướng dẫn này đã được kiểm tra kỹ lưỡng với phiên bản Ansible 2.9.27 trên máy Mac, được cài đặt qua Homebrew).

2. Cài đặt Ansible trên Hệ thống cục bộ

Nếu bạn đang sử dụng máy Mac có cài đặt Homebrew:

$ brew install ansible@2.9
$ brew link --force --overwrite ansible@2.9

Thao tác này sẽ cài đặt Ansible cùng với tất cả các phụ thuộc bắt buộc, bao gồm phiên bản python 3.9.x. Bạn có thể nhanh chóng kiểm tra cài đặt của mình bằng cách thực hiện:

$ ansible --version
ansible 2.9.27
config file = /Users/george/.ansible.cfg
configured module search path = ['/Users/george/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/Cellar/ansible@2.9/2.9.27_1/libexec/lib/python3.9/site-packages/ansible
executable location = /usr/local/bin/ansible
python version = 3.9.7 (default, Oct 13 2021, 06:45:31) [Clang 13.0.0 (clang-1300.0.29.3)]

Tạo một cấu hình dễ nhận biết đơn giản

Tạo .ansible.cfgtệp cấu hình trong thư mục chính local_user . Điều này sẽ cho Ansible biết cách xác định tệp hàng tồn kho của máy chủ lưu trữ.

Nếu bạn đang sử dụng máy Mac, hãy thêm nội dung sau:

[defaults]
inventory  = /Users/user/ansible/hosts.yml
interpreter_python = auto

Đảm bảo thay thế người dùng bằng tên người dùng thực của bạn.

Tạo thư mục để lưu trữ hosts.ymltệp kiểm kê máy chủ:

$ mkdir ~/ansible
$ cd ~/ansible

Tất nhiên, bạn có thể đặt nó ở bất cứ đâu bạn muốn và đặt tên cho nó. Chỉ cần đảm bảo rằng .ansible.cfgtệp của bạn trỏ đến đúng vị trí. Tôi thích lưu trữ tất cả các tệp có thể đọc được của mình trong một thư mục Dropbox, nơi tôi cũng có thể chạy playbook cài đặt của mình từ các máy Mac khác.

Thêm nội dung sau vào ~/ansible/hosts.yml:

all:
  vars:
    ansible_python_interpreter: /usr/bin/python3
    ansible_become: yes
    ansible_become_method: sudo 
  children:
    vultr:
      hosts:
        host.example.com:
          user: user
          user_passwd: "{{ host_user_passwd }}"
          root_passwd: "{{ host_root_passwd }}"
          ssh_pub_key: "{{ lookup('file', '~/.ssh/host_ed25519.pub')  }}"
          ansible_become_pass: "{{ host_user_passwd }}"
          cfg_static_network: false
    vmware:
      hosts:
        ubuntu1.local:
          user: george
          user_passwd: "{{ ubuntu1_user_passwd }}"
          root_passwd: "{{ ubuntu1_root_passwd }}"
          ssh_pub_key: "{{ lookup('file', '~/.ssh/ubuntu1_ed25519.pub')  }}"
          ansible_become_pass: "{{ ubuntu1_user_passwd }}"
          cfg_static_network: true

Khối đầu tiên xác định các biến Ansible có tính toàn cục đối với tệp khoảng không quảng cáo của máy chủ. Máy chủ được liệt kê dưới các nhóm con .

Thay thế host.example.combằng tên máy chủ thực tế của bạn. Nhóm vmwarenày đưa ra một ví dụ làm việc để thiết lập máy chủ VMware trên máy Mac của tôi.

Đây userlà người dùng thông thường được tạo. Và là người dùng host_user_passwdvà host_root_passwdmật khẩu gốc được lưu trữ trong Ansible vault (mô tả bên dưới). ssh_pub_keytrỏ đến khóa công khai SSH cho máy chủ Vultr. Các ansible_becomedòng cung cấp khả năng cho người dùng mới được tạo để thực thi các lệnh sudo (trong các sách phát có thể trả được trong tương lai).

Đây cfg_static_networklà một biến boolean được đặt thành truenếu bạn đang định cấu hình mạng tĩnh trong /etc/netplan. Trừ khi bạn đã tạo riêng một cấu hình mạng tĩnh, bạn nên để nguyên thiết lập này false. Cấu hình mạng tĩnh nằm ngoài phạm vi của hướng dẫn này.

Sử dụng Ansible Vault

Tạo thư mục cho kho mật khẩu Ansible và playbook cài đặt:

$ mkdir -p ~/ansible/ubuntu
$ cd ~/ansible/ubuntu

Tạo kho mật khẩu Ansible:

$ ansible-vault create passwd.yml
New Vault password: 
Confirm New Vault password:

Thao tác này sẽ khởi động trình soạn thảo hệ thống mặc định của bạn. Thêm nội dung sau:

host_user_passwd: ELqZ9L70SSOTjnE0Jq
host_root_passwd: tgM2Q5h8WCeibIdJtd

Thay thế hostbằng tên máy chủ thực tế của bạn. Tạo mật khẩu an toàn của riêng bạn. Lưu và thoát khỏi trình chỉnh sửa của bạn. Điều này tạo ra một tệp được mã hóa mà chỉ Ansible mới có thể đọc được. Bạn có thể thêm mật khẩu máy chủ lưu trữ khác vào cùng các tệp.

pwgenlà một công cụ rất tiện dụng mà bạn có thể sử dụng để tạo mật khẩu an toàn. brew install pwgenCài đặt nó trên máy Mac thông qua Homebrew:. Sử dụng nó như sau:

$ pwgen -s 18 2
ELqZ9L70SSOTjnE0Jq tgM2Q5h8WCeibIdJtd

Bạn có thể xem nội dung của tệp ansible-vault bằng:

$ ansible-vault view passwd.yml
Vault password:

Bạn có thể chỉnh sửa tệp bằng:

$ ansible-vault edit passwd.yml                
Vault password: 

3. Tạo tệp cấu hình SSH cho Máy chủ lưu trữ Vultr

Cấu hình SSH cho máy chủ lưu trữ được lưu trữ trong ~/.ssh/config. Một cấu hình ví dụ trông như thế này (trên máy Mac):

Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentitiesOnly yes
  AddressFamily inet

Host host.example.com host
  Hostname host.example.com
  Port 22
  User user
  IdentityFile ~/.ssh/host_ed25519

Sử dụng tệp cấu hình SSH này, bạn có thể thay đổi số cổng SSH mặc định (nếu thay đổi bởi sách phát Ansible). (Playbook luôn được thực thi lần đầu tiên với cổng SSH 22.) Nếu playbook thay đổi số cổng SSH, thì số cổng SSH trong tệp cấu hình SSH cần được thay đổi sau khi playbook chạy hoặc trong quá trình khởi động lại máy chủ do sách vở .

Với tệp cấu hình SSH này, bạn có thể sử dụng tên máy chủ viết tắt để đăng nhập vào máy chủ.

Đối với người dùng đăng nhập:

$ ssh host

Đối với đăng nhập gốc:

$ ssh root@host

UserKeychaindành riêng cho macOS. Nó lưu trữ khóa công khai SSH trong chuỗi khóa macOS.

host.example.comlà máy chủ Vultr của bạn FQDN (Tên miền Đủ điều kiện) cần được xác định trong tệp DNS hoặc / etc / hosts trên hệ thống cục bộ của bạn. Port 22là tùy chọn nhưng bắt buộc nếu bạn xác định một cổng SSH không chuẩn.

Quan trọng: Cài đặt Khóa SSH của bạn cho người dùng root nếu bạn chưa làm như vậy:

$ ssh-copy-id -i ~/.ssh/host_ed25519 root@host

Xác minh rằng bạn có thể đăng nhập mà không cần sử dụng mật khẩu.

Lưu ý: Nếu bạn cài đặt lại phiên bản Vultr của mình, hãy đảm bảo xóa tên máy chủ Vultr khỏi ~/.ssh/known_hostsnút điều khiển cục bộ của bạn. Nếu không, bạn sẽ thấy lỗi SSH khi cố gắng đăng nhập vào máy chủ được cài đặt lại của mình. Tên máy chủ được thêm vào tệp này trong lần đăng nhập đầu tiên:

$ ssh root@ap1
The authenticity of host 'ap1.altoplace.org (216.128.149.25)' can't be established.
ECDSA key fingerprint is SHA256:oNczYD+xuXx0L6CM17Ciy+DWu3jOEbfVclIj9wUT7Y8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

Trả lời  cho câu hỏi. Nếu bạn không xóa tên máy chủ khỏi tệp này sau khi cài đặt lại phiên bản của mình, bạn sẽ thấy lỗi như:

$ ssh root@ap1
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
o o o

Nếu điều này xảy ra, hãy xóa dòng đã nhập cho tên máy của bạn trong tệp known_hosts và chạy lại lệnh ssh.

3. Kiểm tra cấu hình SSH / Ansible của bạn

Trước khi cố gắng chạy playbook Ansible thiết lập, chúng tôi cần xác minh rằng Ansible đang hoạt động chính xác, bạn có thể truy cập vào Ansible vault của mình và có thể kết nối với máy chủ Vultr của bạn. Trước tiên, hãy xác minh rằng Ansible được cài đặt đúng trên máy Mac:

$ ansible --version
ansible 2.9.27 
  config file = /Users/user/.ansible.cfg
  o o o

Đây là phiên bản mới nhất của Ansible trên máy Mac / Homebrew khi hướng dẫn này được viết.

Chạy lệnh này để kiểm tra cấu hình Ansible của bạn (cũng như cấu hình SSH của bạn):

$ cd ~/ansible/ubuntu
$ ansible -m ping --ask-vault-pass --extra-vars '@passwd.yml' vultr -u root
Vault password: 
host.example.com | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Nếu bạn thấy đầu ra ở trên, thì mọi thứ đang hoạt động tốt. Nếu không, hãy quay lại và kiểm tra kỹ tất cả các cài đặt cấu hình SSH và Ansible của bạn. Bắt đầu bằng cách xác minh rằng bạn có thể thực thi:

$ ssh root@host

Đăng nhập mà không cần mật khẩu (bạn đã cài đặt khóa SSH cho root).

4. Chạy Playbook cấu hình máy chủ Ubuntu Ansible

Bạn đã sẵn sàng để chạy playbook; khi bạn thực thi playbook, bạn sẽ được nhắc nhập mật khẩu vault của mình. Playbook sẽ thực hiện một số nhiệm vụ có dấu PLAY RECAPở cuối. Bạn có thể chạy lại playbook nhiều lần; ví dụ: bạn có thể muốn chạy lại playbook để thay đổi một số thứ như số cổng SSH. Nó sẽ chỉ thực thi các tác vụ khi cần thiết. Đảm bảo cập nhật các biến ở đầu playbook, chẳng hạn như số cổng SSH và địa chỉ IP máy khách cục bộ của bạn, trước khi chạy playbook. Đặt địa chỉ IP máy khách cục bộ của bạn giúp bạn không bị fail2ban vô tình khóa.

Bạn có thể dễ dàng xác định địa chỉ IP máy khách của mình bằng cách đăng nhập vào máy chủ của bạn và thực hiện wholệnh:

root@host:~# who
root     pts/1        2021-10-11 20:24 (12.34.56.78)

Địa chỉ IP máy khách của bạn, 12.34.56.78 , sẽ được liệt kê trong đầu ra.

Cuối cùng thì chúng tôi cũng đã sẵn sàng chạy playbook Ansible mà tôi liệt kê bên dưới. Hãy chắc chắn rằng bạn đang ở trong ~/ansible/ubuntudanh bạ. Đây là lệnh để chạy:

$ ansible-playbook --ask-vault-pass --extra-vars '@passwd.yml' setup-pb.yml -l vultr -u root
Vault password:

Tùy thuộc vào tốc độ của máy Mac, có thể mất vài giây để khởi động. Nếu nó hoàn thành thành công, bạn sẽ thấy PLAY RECAPnhư sau:

PLAY RECAP *************************************************************************************************************************
ap1.altoplace.org          : ok=37   changed=26   unreachable=0    failed=0    skipped=2    rescued=0    ignored=0

Điều quan trọng nhất cần lưu ý là không được có nhiệm vụ thất bại.

Tiếp theo, tôi sẽ mô tả một số kiểm tra cơ bản mà bạn có thể chạy để xác minh thiết lập máy chủ của mình.

5. Xác minh máy chủ Ubuntu

Sau khi bạn đã thực hiện thành công playbook thiết lập Ansible, đây là một số kiểm tra cơ bản mà bạn có thể thực hiện để xác minh thiết lập máy chủ của mình. Tôi sẽ hiển thị một số ví dụ thực tế với máy chủ lưu trữ máy chủ mà tôi đã sử dụng để kiểm tra playbook thiết lập (tên máy chủ cục bộ của tôi là ap1và tên người dùng george). Tôi đã thực hiện các bài kiểm tra này trên Ubuntu 21.10.

6. Xác minh thông tin đăng nhập người dùng của bạn

Xác minh rằng bạn có thể đăng nhập vào tài khoản người dùng mới của mình bằng khóa SSH công khai của máy chủ của bạn:

╭─george@imac1 ~/Dropbox/ansible/ubuntu 
╰─$ ssh ap1
Welcome to Ubuntu 21.10 (GNU/Linux 5.13.0-20-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri Nov  5 11:35:01 AM CDT 2021

  System load:             0.08
  Usage of /:              8.7% of 127.41GB
  Memory usage:            8%
  Swap usage:              0%
  Processes:               147
  Users logged in:         0
  IPv4 address for enp1s0: 149.28.116.218
  IPv4 address for enp1s0: 216.128.149.25
  IPv6 address for enp1s0: 2001:19f0:5c01:59a:5400:3ff:fe8d:a5ae
  IPv6 address for enp1s0: 2001:19f0:5c01:59a:5400:3ff:fe8d:a5b0

 * Super-optimized for small spaces - read how we shrank the memory
   footprint of MicroK8s to make it the smallest full K8s around.

   https://ubuntu.com/blog/microk8s-memory-optimisation

0 updates can be applied immediately.


Last login: Fri Nov  5 11:20:55 2021 from 72.34.15.207
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details. 

Lưu ý lời nhắc hai dòng. Dòng đầu tiên hiển thị user@hostvà thư mục hiện tại. Lưu ý: Trên máy chủ của mình, tôi đã định cấu hình các địa chỉ IPv4 & IPv6 bổ sung.

Bây giờ, hãy lưu ý cách hoạt động của bí danh llavà lsLS:

george@ap1:~
$ touch tmpfile
george@ap1:~
$ l
tmpfile
george@ap1:~
$ la
.bash_history  .bash_logout  .bashrc  .cache  .profile  .ssh  tmpfile
george@ap1:~
$ ll
total 32
drwxr-x--- 4 george george 4096 Nov  5 11:40 ./
drwxr-xr-x 4 root   root   4096 Nov  5 11:12 ../
-rw------- 1 george george    9 Nov  5 11:14 .bash_history
-rw-r--r-- 1 george george  220 Oct  7 05:09 .bash_logout
-rw-r--r-- 1 george george 3879 Nov  5 11:12 .bashrc
drwx------ 2 george george 4096 Nov  5 11:14 .cache/
-rw-r--r-- 1 george george  807 Oct  7 05:09 .profile
drwx------ 2 george george 4096 Nov  5 11:12 .ssh/
-rw-rw-r-- 1 george george    0 Nov  5 11:40 tmpfile

Xác minh mật khẩu người dùng của bạn

Mặc dù bạn sử dụng khóa công khai SSH để đăng nhập vào tài khoản người dùng của mình, bạn vẫn cần sử dụng mật khẩu người dùng của mình bằng sudolệnh. Ví dụ: sử dụng lệnh sudo để thay đổi thành tài khoản gốc (nhập mật khẩu người dùng của bạn khi được nhắc):

george@ap1:~
$ sudo -i
[sudo] password for george: 
root@ap1:~
# exit
logout
george@ap1:~
$

7. Xác minh mật khẩu gốc

Khi ở trong tài khoản người dùng của mình, bạn cũng có thể sử dụng su -để thay đổi sang tài khoản gốc. Một điểm khác biệt là bạn sẽ phải nhập mật khẩu gốc của mình :

george@ap1:~
$ su -
Password: 
root@ap1:~
# exit
logout
george@ap1:~
$ 

8. Xác minh tên máy chủ của bạn

Trong khi chúng tôi đang ở trong tài khoản gốc, hãy xác minh tên máy chủ của chúng tôi và một số tính năng khác mà playbook đã thiết lập cho chúng tôi:

root@ap1:~
# hostname
ap1

root@ap1:~
# hostname -f
ap1.altoplace.org

root@ap1:~
# date
Fri Nov  5 11:49:34 AM CDT 2021

Ở đây, chúng tôi đã xác minh cả tên máy chủ ngắn và FQDN. Với lệnh ngày, hãy xác minh rằng múi giờ được đặt chính xác.

9. Xác minh Trình phân giải bộ nhớ đệm DNS cục bộ không liên kết

Một cuộc thảo luận chuyên sâu về Unbound nằm ngoài phạm vi của hướng dẫn này. Tuy nhiên, tôi có thể cung cấp một số thử nghiệm nhanh để xác minh rằng cấu hình trình phân giải bộ nhớ đệm DNS cục bộ Unbound cục bộ mặc định đang hoạt động. Chúng tôi sẽ sử dụng diglệnh.

Để xác minh rằng trình phân giải đang hoạt động, hãy làm, ví dụ:

root@ap1:~
# dig +noall +answer +stats altoplace.com
altoplace.com.      3600    IN  A   216.92.30.76
;; Query time: 16 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Nov 05 11:50:51 CDT 2021
;; MSG SIZE  rcvd: 58

Lưu ý rằng địa chỉ máy chủ là 127.0.0.1. Ngoài ra, hãy lưu ý TTL (Thời gian tồn tại). Đối với ví dụ này, TTL là 3600 giây. Ngoài ra, hãy lưu ý thời gian Truy vấn, 16 mili giây. Bây giờ thực hiện lại lệnh tương tự:

root@ap1:~
# dig +noall +answer +stats altoplace.com
altoplace.com.      3532    IN  A   216.92.30.76
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Nov 05 11:51:59 CDT 2021
;; MSG SIZE  rcvd: 58

Thời gian truy vấn phải bằng hoặc gần 0 mili giây vì kết quả truy vấn thứ hai đến từ bộ đệm cục bộ của chúng tôi. Kết quả được lưu trong bộ nhớ cache sẽ vẫn hoạt động trong khoảng thời gian tồn tại, như bạn có thể thấy, đang đếm ngược.

Một số máy chủ danh sách chặn (email) sẽ giới hạn tỷ lệ truy cập của bạn vào các trình phân giải DNS được xác định trước của chúng. Điều này có thể gây ra sự cố khi sử dụng trình phân giải DNS công cộng. Ví dụ: khi thực hiện lệnh đào sau, bạn sẽ thấy “điểm kiểm tra vĩnh viễn” khi sử dụng trình phân giải DNS cục bộ.

root#ap1:~
# dig test.uribl.com.multi.uribl.com txt +short
"permanent testpoint"

Nếu bạn đang sử dụng trình phân giải DNS công cộng, bạn có thể gặp lỗi như ( sau khi bạn tạo phiên bản Vultr lần đầu tiên, nhưng chưa thực thi playbook thiết lập ):

root@ap1:~# dig test.uribl.com.multi.uribl.com txt +short
"127.0.0.1 -> Query Refused. See http://uribl.com/refused.shtml for more information [Your DNS IP: 149.28.122.136]"

Bạn có thể xem URL đó để đọc thêm về chủ đề này.

10. Xác minh bảo vệ cổng fail2ban và UFW SSH

Tập hợp các bài kiểm tra này sẽ xác minh rằng fail2ban và ufw được tích hợp với nhau để bảo vệ cổng SSH của bạn. Nếu bạn đang sử dụng cổng mặc định 22, sẽ không mất nhiều thời gian để những kẻ tấn công cố gắng đăng nhập vào máy chủ của bạn. Nỗ lực đăng nhập của họ sẽ không thành công và fail2ban sẽ ghi nhận lỗi đó. Nếu có nhiều lần thử không thành công trong một khoảng thời gian ngắn (như đã lưu ý trong cấu hình fail2ban của bạn), fail2ban sẽ cấm IP trong thời gian mà bạn đã định cấu hình trong cấu hình fail2ban của mình. Fail2ban sẽ thông báo cho ufw chặn IP trong thời gian bị cấm.

Để xem trạng thái fail2ban hiện tại, bạn có thể thực thi fail2ban-client status sshd(hoặc f2bst sshdđể lưu một số thao tác nhập):

root@ap1:/var/log
# f2bst sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed: 6
|  `- File list:    /var/log/auth.log
`- Actions
   |- Currently banned: 2
   |- Total banned: 2
   `- Banned IP list:   2600:380:681e:ceee:ed7c:c8b2:66ef:8f25 166.175.56.178

Kết quả này cho thấy rằng hiện có 0 lần đăng nhập không thành công. Đã có tổng cộng 6 lần thất bại. Trong số những lần thất bại đó, có hai địa chỉ IP đáp ứng các tiêu chí bị cấm. Có hai IP đang bị cấm tích cực. Bạn có thể quan sát các lỗi và lệnh cấm IP này tại /var/log/fail2ban.log.

Bạn cũng có thể thực thi iptables -nLvà xem trong đầu ra lệnh rằng địa chỉ IPv4 bị cấm:

 O O O
Chain f2b-sshd (1 references)
target     prot opt source               destination         
REJECT     all  --  166.175.56.178       0.0.0.0/0            reject-with icmp-port-unreachable
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
 O O O  

Lưu ý: Thực hiện ip6tables -nLđể xem địa chỉ IPv6 bị cấm.

Tôi đã tạo ra kết quả ở trên bằng cách chạy kiểm tra từ điện thoại của mình, đăng nhập vào máy chủ của tôi bằng thông tin đăng nhập không hợp lệ và xác minh rằng tôi không thể kết nối nữa sau khi địa chỉ IP của tôi bị cấm. Đầu tiên, nó đã thử một địa chỉ IPv6 và sau đó là địa chỉ IPv4. (Tôi đã tắt Wi-Fi của mình để đảm bảo rằng địa chỉ IP khác với địa chỉ IP của tôi my_client_ip. Nếu điện thoại của tôi đang sử dụng my_client_ip, kết nối sẽ không bao giờ bị lỗi.)

11. Danh sách Playbook Ansible Set-Up Ubuntu

Đây là setup-pb.ymlsách vở:

# Initial server setup
#
---
- hosts: all
  become: yes
  vars:
    ssh_port: "509"
    my_client_ip: 72.34.15.207
    tmzone: America/Chicago
    sudo_timeout: 20
    f2b_jail_local: |
      [DEFAULT]
      ignoreip = 127.0.0.1/8 ::1 {{ my_client_ip }}
      findtime = 1h
      bantime = 2h
      maxretry = 3

      [sshd]
      enabled = true
      port = {{ ssh_port }}

  tasks:
    - name: Get datestamp from the system
      shell: date +"%Y%m%d"
      register: dstamp

    - name: Set current date stamp varible
      set_fact:
        cur_date: "{{ dstamp.stdout }}"

    # Update and install the base software
    - name: Update apt package cache
      apt:
        update_cache: yes
        cache_valid_time: 3600

    - name: Upgrade installed apt packages 
      apt:
        upgrade: dist
      register: upgrade
      retries: 15
      delay: 5
      until: upgrade is success

    - name: Ensure that these software packages are installed
      apt:
        pkg:
          - build-essential
          - fail2ban
          - needrestart
          - pwgen
          - resolvconf
          - unbound
          - unzip
        state: latest

    - name: Disable the systemd-resolve stub DNS resolver (replaced by unbound)..
      lineinfile:
        dest: /etc/systemd/resolved.conf
        regexp: '^#DNSStubListener='
        line: 'DNSStubListener=no'
        state: present
      notify:
        - restart systemd-resolved

    - name: Check if a reboot is needed for Debian-based systems
      stat:
        path: /var/run/reboot-required
      register: reboot_required

    # Host Setup
    - name: Set static hostname
      hostname:
        name: "{{ inventory_hostname_short }}"

    - name: Add FQDN to /etc/hosts
      lineinfile:
        dest: /etc/hosts
        regexp: '^127\.0\.1\.1'
        line: '127.0.1.1 {{ inventory_hostname }} {{ inventory_hostname_short }}'
        state: present

    - name: Check if cloud init is installed.
      stat: path="/etc/cloud/templates/hosts.debian.tmpl"
      register: cloud_installed

    - name: Add FQDN to /etc/cloud/templates/hosts.debian.tmpl
      lineinfile:
        dest: /etc/cloud/templates/hosts.debian.tmpl
        regexp: '^127\.0\.1\.1'
        line: "127.0.1.1 {{ inventory_hostname }} {{ inventory_hostname_short }}"
        state: present
      when: cloud_installed.stat.exists

    - name: set timezone
      timezone:
        name: "{{ tmzone }}"

    - name: Set ssh '{{ ssh_port }}' port number
      lineinfile:
        dest: /etc/ssh/sshd_config
        regexp: 'Port '
        line: 'Port {{ ssh_port }}'
        state: present
      notify:
        - restart sshd

    # Set sudo password timeout (default is 15 minutes)
    - name: Set sudo password timeout.
      lineinfile:
        path: /etc/sudoers
        state: present
        regexp: '^Defaults\tenv_reset'
        line: 'Defaults env_reset, timestamp_timeout={{ sudo_timeout }}'
        validate: '/usr/sbin/visudo -cf %s'

    - name: Create/update regular user with sudo privileges
      user:
        name: "{{ user }}"
        password: "{{ user_passwd | password_hash('sha512') }}"
        state: present
        groups: sudo
        append: true
        shell: /bin/bash

    - name: Ensure authorized keys for remote user is installed
      authorized_key:
        user: "{{ user }}"
        state: present
        key: "{{ ssh_pub_key }}"

    - name: Ensure authorized key for root user is installed
      authorized_key:
        user: root
        state: present
        key: "{{ ssh_pub_key }}"

    - name: Update root user password.
      user:
        name: root
        password: "{{ root_passwd | password_hash('sha512') }}"

    - name: Disable password authentication for root
      lineinfile:
        path: /etc/ssh/sshd_config
        state: present
        regexp: '^#?PermitRootLogin'
        line: 'PermitRootLogin prohibit-password'
      notify:
        - restart sshd

    - name: Disable tunneled clear-text passwords
      lineinfile:
        path: /etc/ssh/sshd_config
        state: present
        regexp: '^#?PasswordAuthentication'
        line: 'PasswordAuthentication no'
      notify:
        - restart sshd

    - name: Set user PS1 to a two-line prompt
      lineinfile:
        dest: "/home/{{ user }}/.bashrc"
        insertafter: EOF
        line: "PS1='${debian_chroot:+($debian_chroot)}\\[\\033[01;32m\\]\\u@\\h\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\n\\$ '"
        state: present

    - name: Set root PS1 to a two-line prompt
      lineinfile:
        path: '/root/.bashrc'
        state: present
        insertafter: EOF
        line: PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\n\$ '

    # Configure a firewall
    - name: Disable and reset ufw firewall to installation defaults.
      ufw:
        state: reset

    - name: Find backup rules to delete
      find:
        paths: /etc/ufw
        patterns: "*.{{ cur_date }}_*"
        use_regex: no
      register: files_to_delete

    - name: Delete ufw backup rules
      file:
        path: "{{ item.path }}"
        state: absent
      with_items: "{{ files_to_delete.files }}"

    - name: Allow ssh port '{{ ssh_port }}'.
      ufw:
        rule: allow
        proto: tcp
        port: '{{ ssh_port }}'
        state: enabled

    - name: Turn UFW logging off
      ufw:
        logging: "off"

    - name: configure fail2ban for ssh
      copy:
        dest: /etc/fail2ban/jail.local
        content: "{{ f2b_jail_local }}"
        owner: root
        group: root
        mode: 0644
      notify:
        - restart fail2ban

    # simple shell script to display fail2ban-client status info; usage:
    #   f2bst
    #   f2bst sshd
    - name: Configure f2bst
      copy:
        dest: /usr/local/bin/f2bst
        content: |
          #!/usr/bin/sh
          fail2ban-client status $*
        owner: root
        group: root
        mode: 0750

    - name: run needrestart
      command: needrestart -r a
      when: not reboot_required.stat.exists and upgrade.changed

    - name: Configure static networking
      copy:
        src: etc/netplan/50-cloud-init.yaml
        dest: /etc/netplan/50-cloud-init.yaml
        owner: root
        group: root
        mode: 0644
      notify:
        - netplan apply
      when: cfg_static_network == true

    - name: Reboot the server if needed
      reboot:
        msg: "Reboot initiated by Ansible because of reboot required file."
        connect_timeout: 5
        reboot_timeout: 600
        pre_reboot_delay: 0
        post_reboot_delay: 30
        test_command: whoami
      when: reboot_required.stat.exists

    - name: Remove old packages from the cache
      apt:
        autoclean: yes

    - name: Remove dependencies that are no longer needed
      apt:
        autoremove: yes
        purge: yes

  handlers:
    - name: restart sshd
      service:
        name: sshd
        state: restarted
      when: reboot_required.stat.exists == false

    - name: restart fail2ban
      service:
        name: fail2ban
        state: restarted
      when: reboot_required.stat.exists == false

    - name: restart systemd-resolved
      service:
        name: systemd-resolved
        state: restarted
      when: reboot_required.stat.exists == false

    - name: netplan apply
      command: netplan apply
      when: cfg_static_network == true 

Bạn có thể đọc Tài liệu Ansible để tìm hiểu thêm về Ansible.

>>>> Xem thêm: Cách cài đặt MYSQL trên UBUNTU

 

Leave a Reply