mirror of
https://github.com/spantaleev/matrix-docker-ansible-deploy.git
synced 2026-07-12 18:04:24 +03:00
80c2624454
Running `just add-inventory-host example.com 1.2.3.4` (or `make add-inventory-host domain=example.com ip=1.2.3.4`) adds a new host to the inventory, creating inventory/hosts and inventory/host_vars/matrix.DOMAIN/vars.yml from the example files, with strong secrets generated automatically. Existing configuration is never overwritten. The command refuses to run if the host is already in the inventory, so it can also be used for adding more hosts later. Based on the idea proposed in https://github.com/spantaleev/matrix-docker-ansible-deploy/pull/4682 by @Ser5 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
121 lines
4.2 KiB
Bash
Executable File
121 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# SPDX-FileCopyrightText: 2026 MDAD project contributors
|
|
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
# Adds a new host to the inventory, based on the example files in `examples/`:
|
|
# - creates `inventory/hosts` (or adds the host to it, if it already exists)
|
|
# - creates `inventory/host_vars/matrix.DOMAIN/vars.yml` with strong secrets generated automatically
|
|
#
|
|
# Existing configuration for the same host is never overwritten - the script refuses to run instead.
|
|
#
|
|
# Usage: bin/add-inventory-host.sh <base-domain> <server-address>
|
|
#
|
|
# - <base-domain> is the base domain (`example.com`), not the Matrix server hostname (`matrix.example.com`)
|
|
# - <server-address> is the server's external IP address or domain name
|
|
|
|
set -euo pipefail
|
|
|
|
base_path="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
|
if [ $# -ne 2 ]; then
|
|
echo "Usage: $0 <base-domain> <server-address>" >&2
|
|
echo "Example: $0 example.com 1.2.3.4" >&2
|
|
exit 1
|
|
fi
|
|
|
|
domain="$1"
|
|
server_address="$2"
|
|
|
|
if ! printf '%s' "${domain}" | grep -Eq '^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)+$'; then
|
|
echo "Error: '${domain}' does not look like a valid domain name" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! printf '%s' "${server_address}" | grep -Eq '^[A-Za-z0-9.:_-]+$'; then
|
|
echo "Error: '${server_address}' does not look like a valid server address (IP address or domain name)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
case "${domain}" in
|
|
matrix.*)
|
|
echo "Warning: you likely need to pass your base domain (example.com), not the Matrix server hostname (matrix.example.com)." >&2
|
|
echo "Proceeding anyway. Your Matrix server hostname will be: matrix.${domain}" >&2
|
|
;;
|
|
esac
|
|
|
|
matrix_hostname="matrix.${domain}"
|
|
hosts_file="${base_path}/inventory/hosts"
|
|
vars_dir="${base_path}/inventory/host_vars/${matrix_hostname}"
|
|
vars_file="${vars_dir}/vars.yml"
|
|
hosts_entry="${matrix_hostname} ansible_host=${server_address} ansible_ssh_user=root"
|
|
|
|
if [ -e "${vars_dir}" ]; then
|
|
echo "Error: ${vars_dir} already exists. Refusing to overwrite it." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ -f "${hosts_file}" ]; then
|
|
if ! grep -q '^\[matrix_servers\]' "${hosts_file}"; then
|
|
echo "Error: ${hosts_file} exists, but does not contain a [matrix_servers] section." >&2
|
|
echo "Unrecognized inventory format. Add the host to it manually:" >&2
|
|
echo "${hosts_entry}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
matrix_hostname_pattern="$(printf '%s' "${matrix_hostname}" | sed 's|\.|\\.|g')"
|
|
if grep -Eq "^${matrix_hostname_pattern}([[:space:]]|$)" "${hosts_file}"; then
|
|
echo "Error: ${hosts_file} already contains an entry for ${matrix_hostname}. Refusing to modify it." >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
generate_secret() {
|
|
if command -v pwgen >/dev/null 2>&1; then
|
|
pwgen -s 64 1
|
|
elif command -v openssl >/dev/null 2>&1; then
|
|
openssl rand -base64 192 | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 64
|
|
else
|
|
head -c 4096 /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 64
|
|
fi
|
|
}
|
|
|
|
generic_secret_key="$(generate_secret)"
|
|
postgres_password="$(generate_secret)"
|
|
|
|
for secret in "${generic_secret_key}" "${postgres_password}"; do
|
|
if [ "${#secret}" -lt 64 ]; then
|
|
echo "Error: failed to generate a secret" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
mkdir -p "${vars_dir}"
|
|
|
|
sed \
|
|
-e "s|^matrix_domain:.*|matrix_domain: ${domain}|" \
|
|
-e "s|^matrix_homeserver_generic_secret_key:.*|matrix_homeserver_generic_secret_key: '${generic_secret_key}'|" \
|
|
-e "s|^postgres_connection_password:.*|postgres_connection_password: '${postgres_password}'|" \
|
|
"${base_path}/examples/vars.yml" > "${vars_file}"
|
|
|
|
if [ -f "${hosts_file}" ]; then
|
|
# Insert the new host right after the [matrix_servers] section header.
|
|
hosts_file_tmp="$(mktemp "${hosts_file}.XXXXXX")"
|
|
awk -v entry="${hosts_entry}" '{print} $0 ~ /^\[matrix_servers\]/ && !done {print entry; done=1}' \
|
|
"${hosts_file}" > "${hosts_file_tmp}"
|
|
mv "${hosts_file_tmp}" "${hosts_file}"
|
|
else
|
|
sed \
|
|
-e "s|^matrix\.example\.com .*|${hosts_entry}|" \
|
|
"${base_path}/examples/hosts" > "${hosts_file}"
|
|
fi
|
|
|
|
echo "Added host ${matrix_hostname} to the inventory:"
|
|
echo "- ${hosts_file}"
|
|
echo "- ${vars_file}"
|
|
echo ""
|
|
echo "Secrets were generated automatically for matrix_homeserver_generic_secret_key and postgres_connection_password."
|
|
echo "Review and adjust these files before installing."
|