树莓派 zero 系统配置和 autossh 安装配置

树莓派 zero headless 安装 Raspberry Pi OS Lite 设置 ssh 安装了基础系统。

系统还需要做一些基本配置,使用 ansible 让这个过程自动化,也方便以后重做。

完整代码见:MarshalW/device-management(私有)

系统基本设置

主要的基本设置是:

  • 修改设备主机名
  • 设置 apt 镜像
  • 本地 ssh public key 加入到 rpi authorized_keys (无密码登录)
  • 禁用 rpi ssh 密码登录
  • 关闭 swap
  • 设置时区

ansible playbook 代码 (basic-settings.yml) 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
---
- hosts: raspberrypi
gather_facts: no
tasks:
- name: Change host name
become: yes
shell: |
echo {{new_hostname}} | tee /etc/hostname

sed -i -E 's/^127.0.1.1.*/127.0.1.1\t'"{{new_hostname}}"'/' /etc/hosts
hostnamectl set-hostname {{new_hostname}}

systemctl restart avahi-daemon
- name: Set apt mirror
become: yes
shell: |
cp /etc/apt/sources.list{,.ori}

cat >/etc/apt/sources.list <<EOF
deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ bullseye main contrib non-free rpi
EOF
- name: Set authorized key took from file
vars:
file: ~/.ssh/id_rsa.pub
authorized_key:
user: "{{ansible_user}}"
state: present
key: "{{ lookup('file', file) }}"
- name: Generate an OpenSSH rsa keypair with a different size (2048 bits)
shell: |
ssh-keygen -q -t rsa -b 4096 -N '' -f ~/.ssh/id_rsa
- name: Config others
become: yes
shell: |
# Disable swap
swapoff -a
sed -i '/swap/d' /etc/fstab

# Set timezone
timedatectl set-timezone Asia/Shanghai
- name: "Disable ssh password authentication"
become: yes
shell: sed -i "s/.*PasswordAuthentication.*/PasswordAuthentication no/g" /etc/ssh/sshd_config

执行:

1
2
3
ansible-playbook basic-settings.yml -vvvv \
--extra-vars "ansible_user=zhangsan \
new_hostname=a01"

autossh 安装配置

安装和配置 autossh 的步骤:

  • 树莓派安装 autossh
  • 跳板机安装 acl
  • 设置树莓派到跳板机免密码登录(pulic key)
  • 树莓派设置 ssh config,跳板机参数
  • 树莓派创建 autossh.service 服务配置文件,并启动 autossh.service

安装和配置 autossh 的 ansible playbook 代码 (autossh.yml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
---
---
- hosts: "{{hostname}}"
gather_facts: no
tasks:
- name: Install autossh
become: yes
shell: |
apt-get update
apt-get install autossh -y -qq
- name: Slurp ssh key file
slurp:
src: "~/.ssh/id_rsa.pub"
register: slurpfile

- hosts: "{{jump_server}}"
gather_facts: no
tasks:
- name: Install acl
become: yes
shell: |
apt-get install acl -y -qq
- name: "Set authorized key took from file"
become: yes
become_user: jumper
authorized_key:
user: "jumper"
state: present
key: "{{ hostvars[hostname]['slurpfile'].content | b64decode }}"

- hosts: "{{hostname}}"
gather_facts: no
tasks:
- name: add content to ~/.ssh/config
blockinfile:
path: ~/.ssh/config
backup: yes
create: yes
block: |
Host {{jump_server}}
User {{hostvars[jump_server]['ansible_ssh_user']}}
HostName {{hostvars[jump_server]['ansible_ssh_host']}}
Port {{hostvars[jump_server]['ansible_ssh_port']}}
StrictHostKeyChecking no
LogLevel ERROR
UserKnownHostsFile /dev/null
- name: create autossh service
become: yes
shell: |
cat >/tmp/autossh.service <<EOF
[Unit]
Description=AutoSSH service for a reverse tunnel from some.example.com to localhost
After=network-online.target

[Service]
User={{hostvars[hostname]['ansible_ssh_user']}}
Group=adm
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 22001 -N -T -q -o ServerAliveInterval=30 -o ServerAliveCountMax=10 -R {{hostvars[hostname]['jump_server_port']}}:localhost:22 {{jump_server}}
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target
EOF

cp /tmp/autossh.service /etc/systemd/system
systemctl enable autossh.service
systemctl start autossh.service

执行:

1
2
3
ansible-playbook autossh.yml -vvvv \
--extra-vars "hostname=zhangsan \
jump_server=j01"