Scope: apt-install Ansible, create an ansible
user on the controller, provision remotes, and run a small project.
- Install Ansible and create the controller user
# as administrator
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
# create the local ops user that will run playbooks
sudo adduser --gecos "" ansible
- Generate the controller SSH key (run as ansible)
sudo su - ansible
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
mkdir -p ~/.ansible/facts # for fact cache path used below
- Bootstrap each remote (run as controller ansible)
Replace jenkins.maksonlee.com
as needed and repeat per host.
SERVER=jenkins.maksonlee.com # or your target host
ssh -tt administrator@"$SERVER" 'sudo bash -c "
set -euo pipefail
id -u ansible >/dev/null 2>&1 || adduser --disabled-password --gecos \"\" ansible
passwd -l ansible || true
printf \"%s\n\" \"ansible ALL=(ALL) NOPASSWD:ALL\" > /etc/sudoers.d/90-ansible
chmod 440 /etc/sudoers.d/90-ansible
visudo -cf /etc/sudoers.d/90-ansible >/dev/null
"'
scp ~/.ssh/id_ed25519.pub administrator@"$SERVER":/tmp/ansible.pub
ssh -tt administrator@"$SERVER" 'sudo bash -c "
set -euo pipefail
mkdir -p /home/ansible/.ssh
chmod 700 /home/ansible/.ssh
chown ansible:ansible /home/ansible/.ssh
install -o ansible -g ansible -m 600 /tmp/ansible.pub /home/ansible/.ssh/authorized_keys
rm -f /tmp/ansible.pub
"'
Smoke test:
ssh ansible@"$SERVER" 'whoami && sudo whoami && hostname'
# expect: ansible / root / <hostname>
- Use this project layout
ansible-playbooks/
├─ .ansible/
├─ .vscode/
│ └─ settings.json
├─ group_vars/
│ └─ .gitkeep
├─ host_vars/
│ └─ .gitkeep
├─ playbooks/
│ ├─ haproxy.yml
│ ├─ letsencrypt.yml
│ └─ test.yml
├─ roles/
│ └─ .gitkeep
├─ .gitignore
├─ ansible.cfg
└─ hosts.yml
ansible.cfg
[defaults]
inventory = ./hosts.yml
remote_user = ansible
private_key_file = ~/.ssh/id_ed25519
host_key_checking = False
interpreter_python = auto_silent
forks = 20
gathering = smart
fact_caching = jsonfile
fact_caching_connection = ~/.ansible/facts
[ssh_connection]
pipelining = True
Notes:
host_key_checking = False
is fast but less strict; if you prefer verification, set it toTrue
and pre-add host keys withssh-keyscan
.- Ensure the cache dir exists:
mkdir -p ~/.ansible/facts
.
hosts.yml
all:
hosts:
thingsboard.maksonlee.com: {}
kafka.maksonlee.com: {}
jenkins.maksonlee.com: {}
spark.maksonlee.com: {}
client.maksonlee.com: {}
cdlee-miniu.maksonlee.com: {}
children:
haproxy:
hosts:
jenkins.maksonlee.com: {}
thingsboard.maksonlee.com: {}
letsencrypt:
hosts:
jenkins.maksonlee.com: {}
thingsboard.maksonlee.com: {}
- Sample playbooks
playbooks/test.yml
- name: Connectivity + privilege check
hosts: letsencrypt
gather_facts: true
tasks:
- name: Ping
ansible.builtin.ping:
- name: Who am I?
ansible.builtin.command: whoami
changed_when: false
register: who
- ansible.builtin.debug:
msg: "Remote user: {{ who.stdout }}"
- name: Check sudo
become: true
ansible.builtin.command: whoami
changed_when: false
register: rootwho
- ansible.builtin.debug:
msg: "Sudo user: {{ rootwho.stdout }}"
- Run it (controller ansible user)
ansible@client:~/ansible-playbooks$ /usr/bin/ansible-playbook /home/ansible/ansible-playbooks/playbooks/test.yml
PLAY [Connectivity + privilege check] **********************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [jenkins.maksonlee.com]
ok: [thingsboard.maksonlee.com]
TASK [Ping] ************************************************************************************************************************************************************
ok: [thingsboard.maksonlee.com]
ok: [jenkins.maksonlee.com]
TASK [Who am I?] *******************************************************************************************************************************************************
ok: [jenkins.maksonlee.com]
ok: [thingsboard.maksonlee.com]
TASK [ansible.builtin.debug] *******************************************************************************************************************************************
ok: [jenkins.maksonlee.com] => {
"msg": "Remote user: ansible"
}
ok: [thingsboard.maksonlee.com] => {
"msg": "Remote user: ansible"
}
TASK [Check sudo] ******************************************************************************************************************************************************
ok: [jenkins.maksonlee.com]
ok: [thingsboard.maksonlee.com]
TASK [ansible.builtin.debug] *******************************************************************************************************************************************
ok: [jenkins.maksonlee.com] => {
"msg": "Sudo user: root"
}
ok: [thingsboard.maksonlee.com] => {
"msg": "Sudo user: root"
}
PLAY RECAP *************************************************************************************************************************************************************
jenkins.maksonlee.com : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
thingsboard.maksonlee.com : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0