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
31 changes: 31 additions & 0 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Use official CentOS Stream 9 as base
FROM quay.io/centos/centos:stream9

# 1. Install system dependencies
RUN dnf -y update && \
dnf install -y \
gcc \
python3.11 \
python3.11-pip \
python3-pip \
git \
rsync \
vim \
iputils \
lorax \
xorriso \
&& dnf clean all


# 2. Install modern Ansible using Python 3.11
RUN python3.11 -m pip install --upgrade pip && \
python3.11 -m pip install \
"ansible-core>=2.16,<2.17" \
netaddr \
six

# 3. Environment setup
RUN mkdir -p /build /mnt/ssh
WORKDIR /build

CMD ["/bin/bash"]
245 changes: 245 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
# SEAPATH CentOS Stream 9 - Automated Deployment Guide


This guide provides a workflow to build custom **SEAPATH ISOs** and deploy them on **Physical Servers (Bare Metal)** or **Virtual Machines (Libvirt)**.

> **Note:** All scripts (`.sh`) and configuration files (`.xml`, `.ks`) mentioned in this guide are located in the root of this repository.


### Prerequisites

- Download the **CentOS Stream 9 ISO** and place it in the root of this repository.

- Download from: [https://centos.org/download/#centos-stream-9](https://centos.org/download/#centos-stream-9)

- **Optional:** The default password for `root` and `virtu` is `toto`. To change it, edit `seapath_kickstart.ks` and replace the hashed passwords.


## 1. Generating Custom ISOs

In this phase, you will create **three unique ISOs** (one for each node). During this process, your host's SSH public key is automatically injected into the images for secure, passwordless access.

### Build the Environment

```Bash
sudo podman build -t centos4seapath .
```

### Generate the ISO

This script creates `seapath-node1.iso`, `seapath-node2.iso`, and `seapath-node3.iso`.



```Bash
sudo podman run --privileged --rm \
--security-opt label=disable \
-v /dev:/dev \
-v $(pwd):/build:Z \
-v /home/$(whoami)/.ssh:/mnt/ssh:ro,Z \
-w /build \
-it centos4seapath bash ./create_vm_isos.sh
```

----------


## 2. Infrastructure Setup **[VM Specific]**

If you are deploying on **Physical Hardware**, ensure your management switch is configured for the `192.168.124.0/24` range and skip this section.

For **Virtual Machine** environments, we provide an automation script that defines the network, creates the bridges and prepares the virtual disks:

```Bash
# This script uses the seapath-network.xml file found in this folder
./prepare_vm_host.sh
```

----------


## 3. Boot the hosts with the ISO files.

### Step 1: Booting the Hosts

- **Physical Hardware:** Flash each ISO to a USB drive and boot the corresponding server.

- **[VM Specific]:** Register and start the virtual nodes using our deployment script:


```Bash
./deploy_node.sh --cluster
sudo virsh -c qemu:///system start seapath-node-1
sudo virsh -c qemu:///system start seapath-node-2
sudo virsh -c qemu:///system start seapath-node-3
```


> The `--cluster` option generates all 3 ISOs. Running `./deploy_node.sh` without parameters only generates 1 ISO.

##### Automated Installation

- Select **"Install CentOS Stream 9"** in the boot menu.
- The installation is 100% automated via Kickstart. The system will reboot once finished.

----------
## 4. SSH Access & Connection

Access is secured via **SSH**. Passwords are disabled for remote login.

### How to Connect

1. **Add your key to your local session:**

```Bash
ssh-add ~/.ssh/your_private_key
```

2. **Login to a node:** **[VM Specific]**

```Bash
ssh root@192.168.124.2 # Node 1
```

#### Troubleshooting: "Identification Has Changed" **[VM Specific]**
If you reinstall a node, your host will detect a fingerprint mismatch. Clear the old record with: `ssh-keygen -R 192.168.124.2`


----------

## 5. SEAPATH Configuration (Ansible)

Once nodes are online, run the SEAPATH hardening playbooks.

### A. Clone the Seapath Ansible repository into the root of our repository:
```Bash
git clone https://github.com/seapath/ansible.git
```

### B. Run the Container with Host Networking **[VM Specific]**

```Bash
sudo podman run --privileged --rm \
--net=host \
--security-opt label=disable \
--mount type=bind,source=$(pwd)/ansible,target=/root/ansible/ \
--mount type=bind,source=/home/$(whoami)/.ssh/,target=/root/.ssh/ \
-it centos4seapath bash

```

### C. Inside Container - Prepare and Execute **[VM Specific]**


```Bash
cd /root/ansible/

python3.9 -m pip install netaddr

git config --global --add safe.directory /root/ansible

./prepare.sh

eval $(ssh-agent -s)

ssh-add /root/.ssh/your_private_key_42

export ANSIBLE_HOST_KEY_CHECKING=False
```

### 6. Inventory Configuration

Before running the playbook, you must customize the inventory file to map the Ansible variables to your virtual infrastructure.

Edit the file `inventories/examples/seapath-standalone.yaml` to match the following configuration (example for **Node 1**):


```Diff
--- a/inventories/examples/seapath-standalone.yaml
+++ b/inventories/examples/seapath-standalone.yaml
node1:

# Admin network settings
- ansible_host: 192.168.200.125 # administration IP. TODO
- network_interface: eno1 # Administration interface name. TODO
- gateway_addr: 192.168.200.1 # Administration Gateway. TODO
- dns_servers: 192.168.200.1 # DNS servers. Remove if not used. TODO
+ ansible_host: 192.168.124.2 # administration IP.
+ network_interface: enp1s0 # Administration interface name.
+ gateway_addr: 192.168.124.1 # Administration Gateway.
+ dns_servers: 192.168.124.1 # DNS servers.
subnet: 24 # Subnet mask in CIDR notation.

# Time synchronisation
- ptp_interface: eno12419 # PTP interface receiving PTP frames. TODO
+ ptp_interface: enp1s0 # PTP interface receiving PTP frames.
ntp_servers:
- "185.254.101.25" # public NTP server example

ansible_connection: ssh
ansible_python_interpreter: /usr/bin/python3
ansible_remote_tmp: /tmp/.ansible/tmp
- ansible_user: ansible
+ ansible_user: virtu
+ ansible_ssh_private_key_file: /root/.ssh/your_private_key_42

```

> **Note:** In this virtual lab setup, `enp1s0` is the default management interface. If you are deploying on different hardware, verify the interface name using `ip addr`.

Now that everything is prepared, run the playbook.
```Bash
ansible-playbook -i inventories/examples/seapath-standalone.yaml playbooks/seapath_setup_main.yaml
```
--------
## 7. Deployment: 3-Node Cluster Mode

This mode enables High Availability and Distributed Storage with Ceph. It uses the Ring Topology simulated by the Linux bridges created in Step 2.

### A. Inventory Configuration

Before running the cluster setup, you must configure the inventory to match our virtual lab's network mapping.

Edit the file `inventories/examples/seapath-cluster.yaml` with the following key values:


| Section | Variable | Value for Virtual Lab
|--|--|-- |
| **All Hosts** | `ansible_host` | `.2` (node1), `.3` (node2), `.4` (node3)|
|**Network** | `gateway_addr`|`192.168.124.1`
| **Interfaces** | `network_interface` |`enp1s0`
| **Ring Links** | `team0_0 / team0_1`| `enp2s0` and `enp3s0` (Data Ring)
| **Storage** | `ceph_osd_disk` | `/dev/disk/by-path/your_disk`
| **SSH** | `ansible_user` |`virtu` |


#### Identifying the Ceph Disk

The Ceph OSD requires a dedicated disk. In this lab, we created a secondary 50GB disk. You need to find its unique path to ensure Ansible targets the correct device.

1. Log into **Node 1** via SSH.

2. Run the following command:

```Bash
ls -l /dev/disk/by-path/ | grep -v "part"
```

3. Look for the disk that points to `sdb` (our secondary disk). **Example for this VM setup:** `ceph_osd_disk: "/dev/disk/by-path/pci-0000:00:1f.2-ata-3"`

**Note:** This ID will vary depending on your virtual controller or physical hardware. Always verify it before running the playbook.


### B. Execution

Inside the automation container, run the main playbook pointing to the cluster inventory:

```Bash
ansible-playbook -i inventories/examples/seapath-cluster.yaml playbooks/seapath_setup_main.yaml
```

--------
### Reset Lab Environment [VM Specific]
```Bash
./cleanup_vm_host.sh
```
29 changes: 29 additions & 0 deletions cleanup_vm_host.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/bash
# [VM Specific] - Cleanup SEAPATH Lab Environment
echo "--- Starting full cleanup ---"

# 1. Destroy and Undefine VMs
for i in 1 2 3; do
echo "Removing seapath-node-$i..."
sudo virsh -c qemu:///system destroy seapath-node-$i 2>/dev/null || true
sudo virsh -c qemu:///system undefine seapath-node-$i --nvram 2>/dev/null || true
done

# 2. Remove Networks
for net in seapath-default hostbridge0 hostbridge1 hostbridge2; do
echo "Removing network $net..."
sudo virsh -c qemu:///system net-destroy $net 2>/dev/null || true
sudo virsh -c qemu:///system net-undefine $net 2>/dev/null || true
done

# 3. Delete Bridges
for b in br0 br1 br2; do
echo "Deleting bridge $b..."
sudo ip link delete $b 2>/dev/null || true
done

# 4. Delete Storage Files (The fix for the sudo rm problem)
echo "Deleting storage files and ISOs..."
sudo bash -c "rm -f /var/lib/libvirt/images/seapath*"

echo "Cleanup complete!"
50 changes: 50 additions & 0 deletions create_vm_isos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/bash
# Script to build SEAPATH ISOs for Nodes 1, 2, and 3
set -e

# --- CONFIGURATION ---
KS_SOURCE="seapath_kickstart.ks"
ISO_BASE="CentOS-Stream-9-latest-x86_64-dvd1.iso"
INTERNAL_SSH_PATH=$(ls /mnt/ssh/*.pub 2>/dev/null | head -n1)

# --- 1. ENVIRONMENT CHECK ---
echo "--- Checking environment ---"
if [ ! -f "$INTERNAL_SSH_PATH" ]; then
echo "ERROR: SSH Public Key not found at /mnt/ssh/"
exit 1
fi

if [ ! -f "$ISO_BASE" ]; then
echo "ERROR: Base ISO ($ISO_BASE) not found."
exit 1
fi

SSH_CONTENT=$(cat "$INTERNAL_SSH_PATH")

# --- 2. GENERATION LOOP ---
for i in 1 2 3; do
echo "--- Preparing ISO for Node $i ---"

KS_TMP="tmp_node$i.ks"
ISO_FINAL="seapath-node$i.iso"

# Calculate IP (Node 1 = .2, Node 2 = .3, Node 3 = .4)
NODE_IP="192.168.124.$((i + 1))"

cp "$KS_SOURCE" "$KS_TMP"

# Inject SSH Keys and Node Specific Identity
sed -i "s|__SSH_KEY_VIRTU__|$SSH_CONTENT|g" "$KS_TMP"
sed -i "s|__SSH_KEY_ANSIBLE__|$SSH_CONTENT|g" "$KS_TMP"
sed -i "s|__SSH_KEY_ROOT__|$SSH_CONTENT|g" "$KS_TMP"
sed -i "s|__HOSTNAME__|node$i|g" "$KS_TMP"
sed -i "s|__NODE_IP__|$NODE_IP|g" "$KS_TMP"

echo "--- Running mkksiso for Node $i ---"
mkksiso --ks "$KS_TMP" "$ISO_BASE" "$ISO_FINAL"

rm "$KS_TMP"
echo "--- SUCCESS: $ISO_FINAL created ---"
done

echo "--- ALL ISOs GENERATED SUCCESSFULLY ---"
Loading