This repository automates my home network setup. The automation is hardware-agnostic, but I like to run it on small single-board computers like Raspberry Pis.
Think: small computers, big network!
This project aims to:
- Maintain a test environment that mirrors my home network for fast, safe deployment
- Deploy across multiple operating-systems and CPU architectures
- Support both on-metal and cloud deployments
- Ensure cross-OS service interoperability
- Track Ansible and Salt configurations in parallel project branches for comparison
Homelab makes use of the following tools:
- Ansible: Playbooks to configure services on each device.
- Docker: Containers that run and manage the services.
- Wrapper Scripts: Simplify working with Ansible and other tools in this project.
Whenever you return to this project, follow these steps first to ensure your environment is in a clean working state.
If this is your first time setting up the development environment, follow the instructions in ubuntu-dev-environment.md first.
The instructions below assume you've done this.
This project uses pyenv to manage and track its Python
version. The current version is specified in the .python-version
file.
Run this command to activate pyenv in your current shell:
eval "$(pyenv init -)"
Once pyenv is activated, it reads the .python-version
file and activates the Python version
specified there.
Important
- This command must be run every time you start a new terminal session before working on this project.
- You can run this command from any folder in the project.
This project uses Pyprojectx and PDM to manage Python dependencies in a consistent, isolated environment:
- Pyprojectx: Provides the
./pw
wrapper script, ensuring all project tools run consistently without needing global installations (including PDM). - PDM: manages the Python dependencies used by this project (including Ansible).
Install the dependencies:
./pw pdm sync --no-update
Tip: Make sure you're using the project's PDM, not a system-wide one:
./pw which pdm
The output should point to a path like:
<path_to_this_project>/Homelab/.pyprojectx/venvs/main-ab061d9d4f9bea1cc2de64816d469baf-py3.13/bin/pdm
After updating Homebrew, running:
+❯ ./pw pdm run --venv in-project ansible unprovisioned_yoshimo -m ping
may produce a dyld
error like:
dyld[74408]: Library not loaded: /opt/homebrew/Cellar/[email protected]/3.13.5/Frameworks/Python.framework/Versions/3.13/Python
...
Cause: the .pyprojectx
environment was boostrapped before activating pyenv, so it used
the Homebrew Python path. Then when Homebrew updated, that Python version was removed, breaking
the virtual environment.
Fix: Rebuild the .pyprojectx
environment using pyenv:
# Activate pyenv:
eval "$(pyenv init -)"
# Remove the broken pyprojectx environment:
rm -rf .pyprojectx/
# Recreate the environment:
pyprojectx bootstrap
After this, your virtual environment will use the pyenv-managed Python, avoiding Homebrew-related breaks.
Ansible uses SSH to connect to managed nodes.
To avoid repeatedly entering the private key passphrase, load your SSH private key into ssh-agent with the following command:
ssh-add ~/.ssh/id_rsa
Other tools may provide an ssh-agent service. I personally use KeePassXC.
Homelab uses Ansible
Vault
for managing secrets. Passwords are managed dynamically via
vault.password.py
, which requires the ANSIBLE_VAULT_PASSWORD
environment variable to be set in your current shell.
Create a file vault.secret
with the following contents:
#!/usr/bin/env bash
export ANSIBLE_VAULT_PASSWORD='xxxxxxxxxxxxxx'
Then load it into your shell with:
source vault.secret
Before you do anything else, verify that you can connect to both the managing node (your
localhost
) and a managed node using Ansible's ping
module:
Managing Node:
./pw pdm run --venv in-project ansible localhost -m ping
Managed Node:
./pw pdm run --venv in-project ansible unprovisioned_yoshimo -m ping
Tip
See inventory.yml
for other managed nodes.
Now you should be good to go!
Follow these steps every time you return to the project. Once done, you’re ready to run Ansible plays or work on the project safely.
This project uses the following Ansible roles. Most of these will eventually be moved to their own repositories.
To run this role, your playbook must include the following:
become: yes
: required to execute tasks requiring administrative access.gather_facts: yes
: to collect essential system details before executing tasks.
For example:
- name: Configure security settings
hosts: yoshimo
become: yes
gather_facts: yes
tasks:
- name: Import security role
ansible.builtin.import_role:
name: security