Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ USER ${ADMIN_USER}

RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
./apply-adhoc.sh local-debian markosamuli.linuxbrew,debian_tools
./apply-adhoc.sh local-debian debian_homebrew,debian_tools

WORKDIR /home/${ADMIN_USER}
6 changes: 3 additions & 3 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ tasks:
cmds:
- lsb_release -a
- uname -a
- ansible --version
- terraform --version
- docker --version || true
- 'ansible --version || echo "ansible: not installed"'
- 'terraform --version || echo "terraform: not installed"'
- 'docker --version || echo "docker: not installed"'

backup-config:
desc: Create a compressed backup of the configuration directory
Expand Down
4 changes: 3 additions & 1 deletion ansible/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ https://www.ansible.com/

## Setup steps

1. Install Ansible on the admin workstation with `bootstrap-ansible.sh`. (See: [Ansible control node](https://docs.ansible.com/ansible/latest/network/getting_started/basic_concepts.html#control-node))
1. Install Ansible on the admin workstation with `sudo bootstrap-ansible.sh`. (See: [Ansible control node](https://docs.ansible.com/ansible/latest/network/getting_started/basic_concepts.html#control-node))
Comment thread
coderabbitai[bot] marked this conversation as resolved.
2. Configure variables in `inventory/group_vars/`
3. Add hosts to `inventory/inventory.yaml`
4. Assign roles to hosts in `playbooks/`
Expand All @@ -31,6 +31,8 @@ https://www.ansible.com/
- The playbook will set up passwordless `sudo`, so next time the `--ask-become-pass` parameter will not be required
6. When the administrative user is already created, use that user in the inventory instead of `root` (`ansible_user: <adminuser>`). This is more secure and also required by Homebrew.

For the complete infrastructure setup walkthrough using these playbooks, see [Getting Started](../docs/setup.md).

## Bootstrapping hosts with authentication

1. Copy public SSH key, e.g.:
Expand Down
5 changes: 5 additions & 0 deletions ansible/Taskfile.ansible.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
version: '3'

tasks:
apply-localhost:
desc: Run 'homelab' Ansible playbook for the local host
cmds:
- ansible/apply-localhost.sh

apply-homelab:
desc: Run 'homelab' Ansible playbook (apply configuration to local servers)
cmds:
Expand Down
7 changes: 7 additions & 0 deletions ansible/apply-localhost.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

cd "$(dirname "$0")" || exit
ansible-playbook "playbooks/homelab.yaml" --limit "$(hostname)" \
-e ansible_connection=local \
-e ansible_pipelining=false \
"$@"
Comment thread
bubacoder marked this conversation as resolved.
9 changes: 5 additions & 4 deletions ansible/inventory/group_vars/debian/vars.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---

ansible_python_interpreter: /usr/bin/python3

admin_user: "buba"
admin_name: "Buba"
admin_email: "bubacoder@gmail.com"
Expand All @@ -13,10 +15,7 @@ debian_base_install_crowdsec_bouncer: false

# https://github.com/go-task/task/releases
# renovate: datasource=github-releases depName=go-task/task
debian_base_go_task_version: "v3.50.0"

linuxbrew_use_installer: true
linuxbrew_init_shell: true
debian_base_go_task_version: "v3.51.1"

debian_base_apt_packages:
# Common
Expand All @@ -30,6 +29,7 @@ debian_base_apt_packages:
- htop # https://htop.dev/
- tree # http://mama.indstate.edu/users/ice/tree/
# Network
- openssh-server # https://www.openssh.org/
- curl # https://curl.se/
- net-tools # https://sourceforge.net/projects/net-tools/

Expand Down Expand Up @@ -76,6 +76,7 @@ debian_tools_brew_packages_common:
## Dev Tools
debian_tools_brew_packages_dev:
- act # https://nektosact.com/
- gh # https://cli.github.com/

## AWS Cloud Tools
debian_tools_brew_packages_aws:
Expand Down
19 changes: 19 additions & 0 deletions ansible/inventory/inventory.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,25 @@ debian:
# set 'debian_base_crowdsec_local_api_key' in group_vars/debian/secret.yaml
debian_base_install_crowdsec_bouncer: true
debian_base_crowdsec_local_api_url: http://127.0.0.1:7080/
# packagecloud.io does not yet have CrowdSec packages for Ubuntu 25.10 "resolute"
debian_base_crowdsec_suite: noble

# Enable all brew package groups
debian_tools_brew_install_groups:
common: true
dev: true
aws: true
azure: true
terraform: true
kubernetes: true

colony:
debian_base_install_storage_packages: true

# Crowdsec - configure docker/security/crowdsec/crowdsec.yaml and
# set 'debian_base_crowdsec_local_api_key' in group_vars/debian/secret.yaml
# debian_base_install_crowdsec_bouncer: true
# debian_base_crowdsec_local_api_url: http://127.0.0.1:7080/

# Enable all brew package groups
debian_tools_brew_install_groups:
Expand Down
2 changes: 1 addition & 1 deletion ansible/playbooks/cloud.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
roles:
- role: debian_base
- role: debian_docker_host
- role: markosamuli.linuxbrew
- role: debian_homebrew
- role: debian_tools
7 changes: 5 additions & 2 deletions ansible/playbooks/homelab.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@
- nas
- nest
- hive
- colony
roles:
- role: debian_docker_host

- name: Setup developer tools
- name: Setup Debian tools
hosts:
- nest
- hive
- colony
roles:
- role: markosamuli.linuxbrew
- role: debian_homebrew
- role: debian_tools

- name: Setup Samba client
hosts:
- nest
- colony
roles:
- role: debian_samba_client
7 changes: 0 additions & 7 deletions ansible/requirements.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
# ansible-galaxy install -r requirements.yml
---

# Install roles from Ansible Galaxy
roles:
# Source: https://github.com/markosamuli/ansible-linuxbrew
# Role: https://galaxy.ansible.com/ui/standalone/roles/markosamuli/linuxbrew/
- name: markosamuli.linuxbrew
version: v2.0.2

# Install collections from Ansible Galaxy
collections:
# Source: https://github.com/ansible-collections/community.general
Expand Down
5 changes: 5 additions & 0 deletions ansible/roles/debian_base/handlers/main.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
---
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
become: true

- name: Restart service systemd-resolved
ansible.builtin.service:
name: systemd-resolved
Expand Down
17 changes: 8 additions & 9 deletions ansible/roles/debian_base/tasks/50-crowdsec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@
# Configuration file: /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
# Logs: /var/log/crowdsec-firewall-bouncer.log
---
- name: Add crowdsec apt-key
ansible.builtin.apt_key:
url: https://packagecloud.io/crowdsec/crowdsec/gpgkey
state: present

- name: Add crowdsec apt repository
ansible.builtin.apt_repository:
repo: deb https://packagecloud.io/crowdsec/crowdsec/{{ ansible_facts["distribution"] | lower }}/ {{ ansible_facts["distribution_release"] }} main
ansible.builtin.deb822_repository:
name: crowdsec
types: deb
uris: https://packagecloud.io/crowdsec/crowdsec/{{ ansible_facts["distribution"] | lower }}/
suites: "{{ debian_base_crowdsec_suite | default(ansible_facts['distribution_release']) }}"
components: main
signed_by: https://packagecloud.io/crowdsec/crowdsec/gpgkey
state: present
filename: crowdsec
update_cache: true
notify: Update apt cache

- name: Install crowdsec iptables bouncer
ansible.builtin.apt:
Expand Down
11 changes: 11 additions & 0 deletions ansible/roles/debian_base/tasks/70-user.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,18 @@
group: "{{ admin_user }}"
state: directory
mode: '0700'
- name: Check if SSH key file exists
ansible.builtin.stat:
path: "{{ debian_base_ssh_key_file }}"
register: debian_base_ssh_key_stat
delegate_to: localhost
become: false
- name: Fail if SSH key file is missing and no admin password is set
when: not debian_base_ssh_key_stat.stat.exists and (admin_password | default('') == '')
ansible.builtin.fail:
msg: "SSH key file '{{ debian_base_ssh_key_file }}' not found and no admin_password set for user '{{ admin_user }}' — cannot configure secure access."
- name: Set authorized key for user '{{ admin_user }}'
when: debian_base_ssh_key_stat.stat.exists
Comment thread
coderabbitai[bot] marked this conversation as resolved.
ansible.posix.authorized_key:
user: "{{ admin_user }}"
state: present
Expand Down
17 changes: 9 additions & 8 deletions ansible/roles/debian_docker_host/tasks/10-docker-Debian.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@
- python3-pip
- virtualenv
- python3-setuptools
- python3-debian
- cgroupfs-mount # To solve the issue: Docker failed to start daemon - "Devices cgroup isn't mounted"
state: present

- name: Add Docker GPG Key (on Debian)
ansible.builtin.apt_key:
url: https://download.docker.com/linux/debian/gpg
state: present

- name: Add Docker Repository (on Debian)
ansible.builtin.apt_repository:
repo: deb https://download.docker.com/linux/debian {{ ansible_facts["distribution_release"] }} stable
- name: Add Docker apt repository (on Debian)
ansible.builtin.deb822_repository:
name: docker
types: deb
uris: https://download.docker.com/linux/debian
suites: "{{ ansible_facts['distribution_release'] }}"
components: stable
signed_by: https://download.docker.com/linux/debian/gpg
state: present

- name: Update apt and install Docker packages
Expand Down
16 changes: 8 additions & 8 deletions ansible/roles/debian_docker_host/tasks/10-docker-Ubuntu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
- python3-setuptools
state: present

- name: Add Docker GPG Key (on Ubuntu)
ansible.builtin.apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present

- name: Add Docker Repository (on Ubuntu)
ansible.builtin.apt_repository:
repo: deb https://download.docker.com/linux/ubuntu {{ ansible_facts["distribution_release"] }} stable
- name: Add Docker apt repository (on Ubuntu)
ansible.builtin.deb822_repository:
name: docker
types: deb
uris: https://download.docker.com/linux/ubuntu
suites: "{{ ansible_facts['distribution_release'] }}"
components: stable
signed_by: https://download.docker.com/linux/ubuntu/gpg
state: present

- name: Update apt and install Docker packages
Expand Down
31 changes: 31 additions & 0 deletions ansible/roles/debian_homebrew/tasks/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
# https://brew.sh/
# https://docs.brew.sh/Homebrew-on-Linux

- name: Install Homebrew prerequisites
ansible.builtin.apt:
name:
- build-essential
- procps
- curl
- file
- git
state: present
become: true

- name: Install Homebrew
ansible.builtin.shell: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
args:
creates: /home/linuxbrew/.linuxbrew/bin/brew
environment:
NONINTERACTIVE: "1"
become: false

- name: Add Homebrew to shell init
ansible.builtin.lineinfile:
path: "~/.bashrc"
line: 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"'
create: true
mode: '0644'
become: false
7 changes: 7 additions & 0 deletions ansible/roles/debian_samba_client/tasks/10-samba.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
- cifs-utils
state: present

- name: Warn if admin_password is not set
ansible.builtin.debug:
msg: "WARNING: 'admin_password' is not defined — skipping credentials file creation. Samba mounts may fail."
when: admin_password is not defined

- name: Create credentials file
ansible.builtin.copy:
dest: "{{ debian_samba_client_credentials_file }}"
Expand All @@ -15,6 +20,7 @@
owner: root
group: root
mode: "0600"
when: admin_password is defined

- name: Create mount base directory
ansible.builtin.file:
Expand All @@ -41,3 +47,4 @@
opts: "{{ debian_samba_client_mount_opts }}"
state: mounted
loop: "{{ debian_samba_client_nas_shares }}"
when: admin_password is defined
16 changes: 12 additions & 4 deletions docs/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,17 @@ MacOS is also supported, but only for working with Ansible remotely and applying

Steps:
- Clone the repository on a supported OS: `git clone <repository url>`
- Install Ansible with: `ansible/bootstrap-ansible.sh`
- Edit `ansible/inventory/inventory.yaml` and `ansible/playbooks/homelab.yaml`, include your host with `markosamuli.linuxbrew` and `debian_tools` roles
- Run `ansible/apply-homelab.sh`
- Install Ansible with: `sudo ansible/bootstrap-ansible.sh`
- Complete guide: [Ansible setup steps](../ansible/README.md#setup-steps)
- Update the configuration files:
- `ansible/inventory/group_vars/debian/vars.yaml`
- Place the SSH public key at the path indicated by `debian_base_ssh_key_file` (e.g. `~/.ssh/id_ed25519.pub`)
- `ansible/inventory/inventory.yaml`
- Add your host
- `ansible/playbooks/homelab.yaml`
- Include your host with `debian_tools` and `debian_homebrew` roles; add `debian_docker_host` if this host will also run Docker containers
- Apply the playbook locally: `ansible/apply-localhost.sh --ask-become-pass`
- (After passwordless sudo is configured, the `--ask-become-pass` parameter can be dropped)

### 3. Install Ubuntu Server VM (Docker host)

Expand All @@ -68,7 +76,7 @@ Note - Alternatives:
### 4. Install and configure the required software using Ansible

Required and recommended software (like Docker, tmux, ...) are installed and configured by Ansible.
For details, check the `ansible` / `inventory`|`roles`|`playbooks` folders.
See the [Ansible README](../ansible/README.md) for details on roles, inventories, and useful run options (`--limit`, `--verbose`).

Execute on the admin host:
`ansible/apply-homelab.sh`
Expand Down
Loading