Initial commit
This commit is contained in:
commit
3e9668bad5
150
README.md
Normal file
150
README.md
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# Ansible Starter Kit
|
||||||
|
|
||||||
|
Easy way for my homies to start up an ansible project for their homelab or local machine.
|
||||||
|
|
||||||
|
# Prerequisites
|
||||||
|
|
||||||
|
The ideal setup for a homelab is to have:
|
||||||
|
|
||||||
|
- The same username/password in all vms/hosts so you don't have to type a different password for each host
|
||||||
|
- SSH key auth on each host so you don't have to type a password at all
|
||||||
|
|
||||||
|
# Ansible basics
|
||||||
|
|
||||||
|
I'll explain the basic units of an ansible project. For this example we're going to assume you want to mount
|
||||||
|
an NFS share in all your hosts.
|
||||||
|
|
||||||
|
From bottom to top we have:
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
A task is the lowest unit in an ansible project.
|
||||||
|
|
||||||
|
A task could be:
|
||||||
|
|
||||||
|
- Creating a directory
|
||||||
|
- Installing an os package (curl, docker, nfs-common, etc)
|
||||||
|
- Starting a docker container
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```yml
|
||||||
|
- name: Add SSH key for remote user
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: javi
|
||||||
|
state: present
|
||||||
|
key: "{{ lookup('file', '/home/javi/.ssh/homelab_keypair_ed25519.pub') }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yml
|
||||||
|
- name: Ensure NFS client is installed
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: nfs-common
|
||||||
|
state: present
|
||||||
|
become: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Role
|
||||||
|
|
||||||
|
A role is a self contained, re-usable unit that will give a meaningful result. Think of it like a class in a program.
|
||||||
|
|
||||||
|
Roles have a list of tasks, as well as variables and files associated with those tasks. All contained in a folder.
|
||||||
|
|
||||||
|
A role can look like:
|
||||||
|
|
||||||
|
```
|
||||||
|
roles/
|
||||||
|
portainer/
|
||||||
|
├── defaults/
|
||||||
|
│ └── main.yml # Default variables
|
||||||
|
├── files/
|
||||||
|
│ └── ... # Static files to be copied (e.g., configs, scripts)
|
||||||
|
├── handlers/
|
||||||
|
│ └── main.yml # Handlers (e.g., service restart)
|
||||||
|
├── meta/
|
||||||
|
│ └── main.yml # Role metadata (e.g., dependencies)
|
||||||
|
├── tasks/
|
||||||
|
│ └── main.yml # Main list of tasks to execute
|
||||||
|
├── templates/
|
||||||
|
│ └── ... # Jinja2 templates
|
||||||
|
├── vars/
|
||||||
|
│ └── main.yml # Non-overridable variables
|
||||||
|
└── README.md # Optional: Document what this role does
|
||||||
|
sshkey/
|
||||||
|
├── defaults/
|
||||||
|
│ └── main.yml # Default variables
|
||||||
|
├── files/
|
||||||
|
│ └── ... # Static files to be copied (e.g., configs, scripts)
|
||||||
|
├── handlers/
|
||||||
|
│ └── main.yml # Handlers (e.g., service restart)
|
||||||
|
├── meta/
|
||||||
|
│ └── main.yml # Role metadata (e.g., dependencies)
|
||||||
|
├── tasks/
|
||||||
|
│ └── main.yml # Main list of tasks to execute
|
||||||
|
├── templates/
|
||||||
|
│ └── ... # Jinja2 templates
|
||||||
|
├── vars/
|
||||||
|
│ └── main.yml # Non-overridable variables
|
||||||
|
└── README.md # Optional: Document what this role does
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
However, only the `defaults` and `tasks` subfolders and subsequent `main.yml` are required. Everything else is optional.
|
||||||
|
|
||||||
|
A role can be:
|
||||||
|
|
||||||
|
- Mounting a share
|
||||||
|
- Deploying a docker container with all its requirements like a database and mapped volumes
|
||||||
|
|
||||||
|
# Playbook
|
||||||
|
|
||||||
|
A playbook combines roles and task to create a final state in a host or group of hosts.
|
||||||
|
|
||||||
|
A playbook can be:
|
||||||
|
|
||||||
|
- Make sure all your hosts have sshkey auth, portainer, docker and an nfs share mounted.
|
||||||
|
- Deploy a suite of apps to a host or multiple hosts
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```yml
|
||||||
|
---
|
||||||
|
- name: Deploy apps to apps-1 node
|
||||||
|
hosts: apps
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- role: apps/kan
|
||||||
|
vars:
|
||||||
|
port: 7070
|
||||||
|
- role: apps/memos
|
||||||
|
vars:
|
||||||
|
port: 7071
|
||||||
|
- role: apps/vaultwarden
|
||||||
|
vars:
|
||||||
|
port: 7072
|
||||||
|
- role: apps/erugo
|
||||||
|
vars:
|
||||||
|
port: 7073
|
||||||
|
- role: apps/tianji
|
||||||
|
vars:
|
||||||
|
port: 7074
|
||||||
|
- role: apps/stirling-pdf o
|
||||||
|
vars:
|
||||||
|
port: 7075
|
||||||
|
- role: apps/dumbware-todo
|
||||||
|
vars:
|
||||||
|
port: 7076
|
||||||
|
pin: 8989
|
||||||
|
- role: apps/dumbware-drop
|
||||||
|
vars:
|
||||||
|
port: 7077
|
||||||
|
pin: "8989"
|
||||||
|
```
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
|
||||||
|
1. Clone this repo
|
||||||
|
2. Run `setup.sh` to set up the vault password and become password
|
||||||
|
3. Set up your hosts in `hosts.yml`
|
||||||
|
4. Start making your roles and playbooks
|
||||||
|
|
4
ansible.cfg
Executable file
4
ansible.cfg
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory = hosts.yml
|
||||||
|
roles_path = ./roles
|
||||||
|
vault_password_file = ~/.ansible-test
|
18
group_vars/all.yml
Executable file
18
group_vars/all.yml
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
project_root: "{{ inventory_dir }}" # Useful hack for easier file paths
|
||||||
|
# Postgres
|
||||||
|
# If you have a main database instance all your
|
||||||
|
# services will use (which you should), put
|
||||||
|
# the info here so it's accessible to all
|
||||||
|
# your playbooks.
|
||||||
|
pg_host: 10.89.0.102
|
||||||
|
pg_port: 5432
|
||||||
|
pg_user: postgres
|
||||||
|
pg_password: password
|
||||||
|
# Sudo password for your servers
|
||||||
|
ansible_become_pass: !vault |
|
||||||
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
|
35613633643566323866643465383731343764616539353330366339616433316565306637363062
|
||||||
|
6334333432303337643963616435333165303834333237320a636531363761383736356665613164
|
||||||
|
30616465666565383663626336383764636363303061363731653536313061386333666638326236
|
||||||
|
6264646466383539370a323961613564616665383435303161306163303038633864653631376665
|
||||||
|
3263
|
11
hosts.yml
Executable file
11
hosts.yml
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
all:
|
||||||
|
children:
|
||||||
|
servers:
|
||||||
|
hosts:
|
||||||
|
proxpox_server_1:
|
||||||
|
ansible_host: 10.89.0.13
|
||||||
|
vms:
|
||||||
|
hosts:
|
||||||
|
vm_1:
|
||||||
|
ansible_host: 10.89.0.101
|
6
playbooks/example.yml
Normal file
6
playbooks/example.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
- name: Example playbook
|
||||||
|
hosts: vms
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- role: server/sshkey
|
0
roles/server/ftp/defaults/main.yml
Executable file
0
roles/server/ftp/defaults/main.yml
Executable file
23
roles/server/ftp/tasks/main.yml
Executable file
23
roles/server/ftp/tasks/main.yml
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
- name: Update apt cache
|
||||||
|
ansible.builtin.apt:
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: Install proftpd package
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: proftpd
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure proftpd is enabled and started
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: proftpd
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Allow FTP through UFW firewall (if UFW is enabled)
|
||||||
|
community.general.ufw:
|
||||||
|
rule: allow
|
||||||
|
port: 21
|
||||||
|
proto: tcp
|
||||||
|
ignore_errors: false
|
0
roles/server/sshkey/defaults/main.yml
Executable file
0
roles/server/sshkey/defaults/main.yml
Executable file
6
roles/server/sshkey/tasks/main.yml
Executable file
6
roles/server/sshkey/tasks/main.yml
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
- name: Add SSH key for remote user
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: javi
|
||||||
|
state: present
|
||||||
|
key: "{{ lookup('file', '/home/javi/.ssh/homelab_keypair_ed25519.pub') }}"
|
8
roles/server/webmin/defaults/main.yml
Executable file
8
roles/server/webmin/defaults/main.yml
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
# roles/webmin/defaults/main.yml
|
||||||
|
webmin_repo_url: https://download.webmin.com
|
||||||
|
webmin_dist: stable
|
||||||
|
webmin_section: contrib
|
||||||
|
|
||||||
|
# Optional HTTP auth
|
||||||
|
webmin_auth_user: javi
|
||||||
|
webmin_auth_pass: password
|
66
roles/server/webmin/tasks/main.yml
Executable file
66
roles/server/webmin/tasks/main.yml
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
- name: Remove any old/malformed Webmin sources list
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/apt/sources.list.d/webmin.list
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Remove any old Webmin keyring
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /usr/share/keyrings/webmin-archive-keyring.gpg
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Install Webmin GPG key into its own keyring
|
||||||
|
ansible.builtin.apt_key:
|
||||||
|
url: https://download.webmin.com/developers-key.asc
|
||||||
|
keyring: /usr/share/keyrings/webmin-archive-keyring.gpg
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Add Webmin APT repository
|
||||||
|
ansible.builtin.apt_repository:
|
||||||
|
filename: webmin
|
||||||
|
repo: >-
|
||||||
|
deb [signed-by=/usr/share/keyrings/webmin-archive-keyring.gpg]
|
||||||
|
https://download.webmin.com/download/repository
|
||||||
|
sarge contrib
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure apt prerequisites are installed
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- curl
|
||||||
|
- gnupg
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: Configure APT HTTP auth for Webmin
|
||||||
|
when: webmin_auth_user is defined and webmin_auth_pass is defined
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/apt/auth.conf.d/webmin.conf
|
||||||
|
mode: '0600'
|
||||||
|
content: |
|
||||||
|
machine {{ webmin_repo_url | regex_replace('^https?://','') }}
|
||||||
|
login {{ webmin_auth_user }}
|
||||||
|
password {{ webmin_auth_pass }}
|
||||||
|
|
||||||
|
- name: Remove old Webmin preference file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/apt/preferences.d/webmin-stable-package-priority
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Refresh apt cache
|
||||||
|
ansible.builtin.apt:
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: Install Webmin
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- webmin
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure Webmin service is enabled & started
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: webmin
|
||||||
|
state: started
|
||||||
|
enabled: true
|
28
setup.sh
Executable file
28
setup.sh
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
echo "**Deleting .git so you can start your own repo"
|
||||||
|
rm -rf .git
|
||||||
|
echo "***Ansible vault password***"
|
||||||
|
echo "This is used to encrypt/descrypt secrets in your vault"
|
||||||
|
echo "We'll save it to a file in ~/.[file name] so it doesn't have to be typed every time"
|
||||||
|
echo
|
||||||
|
read -p "File name (no . prefix): " ansible_vault_pass_filename
|
||||||
|
read -s -p "Password: " ansible_vault_pass
|
||||||
|
|
||||||
|
echo $ansible_vault_pass >~/.$ansible_vault_pass_filename
|
||||||
|
echo "vault_password_file = ~/.$ansible_vault_pass_filename" >>ansible.cfg
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "***Ansible become password***"
|
||||||
|
echo "A lot of actions need sudo. This password will be stored in group_vars/all.yml encrypted"
|
||||||
|
read -s -p "Password: " ansible_become_pass
|
||||||
|
echo "# Sudo password for your servers" >>./group_vars/all.yml
|
||||||
|
ansible-vault encrypt_string "$ansible_become_pass" --name 'ansible_become_pass' >>./group_vars/all.yml
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "Setup complete"
|
||||||
|
echo "You can delete setup.sh since running it again would cause issues"
|
||||||
|
echo "Config for vault password was output to ./ansible.cfg"
|
||||||
|
echo "Config for sudo (become) password was output to ./group_vars/all.yml"
|
Loading…
x
Reference in New Issue
Block a user