Orchestration for homelab services.
Deploy any group of services as an application
cd ./apps
./deploy.sh <service_dir>
Plan and apply application configuration
cd ./terraform
./tofu.sh plan
./tofu.sh apply
-
Setup Raspberry Pi
a.
raspi-config
- password
- hostname
- timezone
- culture
b. Static IP
/etc/dhcpcd.conf
-
Setup Docker
a. Install Docker
$ curl -fsSL https://get.docker.com -o get-docker.sh $ sudo sh ./get-docker.sh $ sudo usermod -aG docker pi
b. Expose Docker daemon and metrics
/etc/docker/daemon.json
:{ "hosts": [ "tcp://0.0.0.0:2375", "unix:///var/run/docker.sock" ], "metrics-addr": "0.0.0.0:9323", "experimental": true }
/etc/systemd/system/docker.service.d/override.conf
:[Service] ExecStart= ExecStart=/usr/bin/dockerd
c. Restart daemon service
$ systemctl daemon-reload $ systemctl restart docker.service
-
Configure NFS share on primary/manager node
a. Setup persistent mount for external hard drive
https://www.raspberrypi.org/documentation/configuration/external-storage.md
b. Install NFS server
$ apt install nfs-kernel-server
c. Export NFS share directory via
/etc/exports
/mnt/hdd/share 192.168.42.0/24(rw,sync,no_subtree_check,no_root_squash)
-
Configure git client
$ apt install git
$ ssh-keygen -t ed25519 -C "your_email@example.com"
NOTE: Copy generated public key to github config
- Initialize swarm from manager node
$ docker swarm init
- Add each node to swarm
a. If needed, get the join token from the manager node
$ docker swarm join-token worker
b. Join the worker node to the cluster
$ docker swarm join --token <join-token> <manager-ip:port>
- Clone the repository, including submodules:
$ git clone git@github.com:jeremyhayes/pi-cluster.git --recurse-submodules
- Create any needed
.secret.xxx
files:
$ find ./docker-compose.yml | xargs grep "\.secret\."
# for each ...
nano .secret.xxx
- Copy and update any
env.template
files as needed:
$ find . -name .env.template
# for each...
$ cd <service-dir>
$ cp .env.template .env
$ nano .env
- Deploy each service to a shared stack:
Each service lives in a folder with a
docker-compose.yml
and any supporting configuration.
$ ./deploy.sh <service-dir>
NOTE: The first deploy will create an overlay network
<stack-name>_default
.
IMPORTANT For services with externalized configuration (like credentials),
docker stack
does not resolve template placeholders from.env
files. Instead, pipe the file throughdocker-compose
as a preprocessor:docker stack deploy -c <(docker-compose config) stack-name-here
Create a wildcard A record DNS entry (e.g. *.lab.example.com
). Services should be configured with Traefik labels to expose on a specific domain matching that wildcard (e.g. foo.lab.example.com
).