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