moved codex environment scripts to repo
This commit is contained in:
Executable
+122
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "== Refresh Python tools =="
|
||||
python3 -m pip install --break-system-packages --upgrade \
|
||||
pip \
|
||||
yamllint \
|
||||
ansible \
|
||||
ansible-lint
|
||||
|
||||
echo "== Sanity check installed tools =="
|
||||
for cmd in docker terraform tflint ansible-lint yamllint yq jq shellcheck; do
|
||||
if command -v "$cmd" >/dev/null 2>&1; then
|
||||
echo "OK: $cmd -> $(command -v "$cmd")"
|
||||
else
|
||||
echo "MISSING: $cmd"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "== Reconcile dummy secret material =="
|
||||
|
||||
REPO_ROOT="${CODEX_REPO_DIR:-$PWD}"
|
||||
SECRETS_DIR="$REPO_ROOT/secrets"
|
||||
INVENTORY_JSON="$SECRETS_DIR/inventory.json"
|
||||
EXAMPLE_ENV="$SECRETS_DIR/.env.secrets.example"
|
||||
STACK_ENV="$SECRETS_DIR/stack-secrets.env"
|
||||
|
||||
if [[ ! -f "$INVENTORY_JSON" ]]; then
|
||||
echo "Missing inventory file: $INVENTORY_JSON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$EXAMPLE_ENV" ]]; then
|
||||
echo "Missing example env file: $EXAMPLE_ENV"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$SECRETS_DIR"
|
||||
|
||||
dummy_value_for_key() {
|
||||
local key="$1"
|
||||
case "$key" in
|
||||
*EMAIL* ) echo "dummy@example.com" ;;
|
||||
*USER*|*USERNAME* ) echo "dummy-user" ;;
|
||||
*DOMAIN* ) echo "example.lan.ddnsgeek.com" ;;
|
||||
*TZ ) echo "Australia/Brisbane" ;;
|
||||
*URL* ) echo "https://example.lan.ddnsgeek.com" ;;
|
||||
*PORT* ) echo "1234" ;;
|
||||
*PASSWORD*|*PASS*|*TOKEN*|*SECRET*|*KEY*|*JWT* ) echo "dummy-${key,,}" ;;
|
||||
*FINGERPRINT* ) echo "0000000000000000000000000000000000000000" ;;
|
||||
*DB_NAME* ) echo "dummydb" ;;
|
||||
*DB_USER* ) echo "dummyuser" ;;
|
||||
*NAME* ) echo "dummy-name" ;;
|
||||
*ADDRESS* ) echo "dummy" ;;
|
||||
* ) echo "dummy-value" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
rebuild_dummy_stack_env() {
|
||||
local tmp
|
||||
tmp="$(mktemp)"
|
||||
|
||||
cp "$EXAMPLE_ENV" "$tmp"
|
||||
|
||||
while IFS= read -r var; do
|
||||
[[ -z "$var" ]] && continue
|
||||
dummy="$(dummy_value_for_key "$var")"
|
||||
|
||||
if grep -Eq "^[[:space:]]*${var}=" "$tmp"; then
|
||||
sed -i "s|^[[:space:]]*${var}=.*|${var}=${dummy}|" "$tmp"
|
||||
else
|
||||
printf '%s=%s\n' "$var" "$dummy" >> "$tmp"
|
||||
fi
|
||||
done < <(jq -r '.env_template_variables[].variable' "$INVENTORY_JSON")
|
||||
|
||||
mv "$tmp" "$STACK_ENV"
|
||||
chmod 600 "$STACK_ENV" || true
|
||||
echo "Updated $STACK_ENV"
|
||||
}
|
||||
|
||||
reconcile_file_based_secrets() {
|
||||
local wanted existing relpath abspath
|
||||
wanted="$(mktemp)"
|
||||
existing="$(mktemp)"
|
||||
|
||||
jq -r '.file_based_secrets[].path' "$INVENTORY_JSON" | sort -u > "$wanted"
|
||||
|
||||
find "$SECRETS_DIR" -maxdepth 1 -type f -name '*.txt' -printf '%P\n' \
|
||||
| sed "s#^#secrets/#" \
|
||||
| sort -u > "$existing"
|
||||
|
||||
# Create missing listed files
|
||||
while IFS= read -r relpath; do
|
||||
[[ -z "$relpath" ]] && continue
|
||||
abspath="$REPO_ROOT/$relpath"
|
||||
if [[ ! -f "$abspath" ]]; then
|
||||
mkdir -p "$(dirname "$abspath")"
|
||||
printf 'dummy-secret\n' > "$abspath"
|
||||
chmod 600 "$abspath" || true
|
||||
echo "Created $relpath"
|
||||
fi
|
||||
done < <(comm -23 "$wanted" "$existing")
|
||||
|
||||
# Remove stale files no longer listed in inventory.json
|
||||
while IFS= read -r relpath; do
|
||||
[[ -z "$relpath" ]] && continue
|
||||
abspath="$REPO_ROOT/$relpath"
|
||||
if [[ -f "$abspath" ]]; then
|
||||
rm -f "$abspath"
|
||||
echo "Removed stale $relpath"
|
||||
fi
|
||||
done < <(comm -13 "$wanted" "$existing")
|
||||
|
||||
rm -f "$wanted" "$existing"
|
||||
}
|
||||
|
||||
rebuild_dummy_stack_env
|
||||
reconcile_file_based_secrets
|
||||
|
||||
echo "== Dummy secret reconciliation complete =="
|
||||
echo "stack env: $STACK_ENV"
|
||||
jq -r '.file_based_secrets[].path' "$INVENTORY_JSON" | sed 's/^/file secret: /'
|
||||
Executable
+174
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
echo "== Base packages =="
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
bash \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
jq \
|
||||
unzip \
|
||||
wget \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
shellcheck
|
||||
else
|
||||
echo "This script currently expects an apt-based environment."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "== yq =="
|
||||
if ! command -v yq >/dev/null 2>&1; then
|
||||
YQ_VERSION="v4.44.3"
|
||||
ARCH="$(dpkg --print-architecture)"
|
||||
case "$ARCH" in
|
||||
amd64) YQ_ARCH="amd64" ;;
|
||||
arm64) YQ_ARCH="arm64" ;;
|
||||
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
|
||||
esac
|
||||
wget -qO /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${YQ_ARCH}"
|
||||
chmod +x /usr/local/bin/yq
|
||||
fi
|
||||
|
||||
echo "== Docker CLI + Compose plugin =="
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
apt-get install -y docker.io docker-compose-v2 || true
|
||||
fi
|
||||
|
||||
echo "== Python tooling =="
|
||||
python3 -m pip install --break-system-packages --upgrade pip
|
||||
python3 -m pip install --break-system-packages \
|
||||
yamllint \
|
||||
ansible \
|
||||
ansible-lint
|
||||
|
||||
echo "== Terraform =="
|
||||
if ! command -v terraform >/dev/null 2>&1; then
|
||||
TF_VERSION="1.8.5"
|
||||
ARCH="$(dpkg --print-architecture)"
|
||||
case "$ARCH" in
|
||||
amd64) TF_ARCH="amd64" ;;
|
||||
arm64) TF_ARCH="arm64" ;;
|
||||
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
|
||||
esac
|
||||
|
||||
wget -qO /tmp/terraform.zip \
|
||||
"https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_${TF_ARCH}.zip"
|
||||
unzip -o /tmp/terraform.zip -d /tmp
|
||||
install /tmp/terraform /usr/local/bin/terraform
|
||||
fi
|
||||
|
||||
echo "== TFLint =="
|
||||
if ! command -v tflint >/dev/null 2>&1; then
|
||||
TFLINT_VERSION="v0.56.0"
|
||||
ARCH="$(dpkg --print-architecture)"
|
||||
case "$ARCH" in
|
||||
amd64) TFLINT_ARCH="amd64" ;;
|
||||
arm64) TFLINT_ARCH="arm64" ;;
|
||||
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
|
||||
esac
|
||||
|
||||
wget -qO /tmp/tflint.zip \
|
||||
"https://github.com/terraform-linters/tflint/releases/download/${TFLINT_VERSION}/tflint_linux_${TFLINT_ARCH}.zip"
|
||||
unzip -o /tmp/tflint.zip -d /tmp
|
||||
install /tmp/tflint /usr/local/bin/tflint
|
||||
fi
|
||||
|
||||
echo "== Dummy secret material for compose validation =="
|
||||
|
||||
REPO_ROOT="${CODEX_REPO_DIR:-$PWD}"
|
||||
SECRETS_DIR="$REPO_ROOT/secrets"
|
||||
INVENTORY_JSON="$SECRETS_DIR/inventory.json"
|
||||
EXAMPLE_ENV="$SECRETS_DIR/.env.secrets.example"
|
||||
STACK_ENV="$SECRETS_DIR/stack-secrets.env"
|
||||
|
||||
if [[ ! -f "$INVENTORY_JSON" ]]; then
|
||||
echo "Missing inventory file: $INVENTORY_JSON"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$EXAMPLE_ENV" ]]; then
|
||||
echo "Missing example env file: $EXAMPLE_ENV"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$SECRETS_DIR"
|
||||
|
||||
dummy_value_for_key() {
|
||||
local key="$1"
|
||||
case "$key" in
|
||||
*EMAIL* ) echo "dummy@example.com" ;;
|
||||
*USER*|*USERNAME* ) echo "dummy-user" ;;
|
||||
*DOMAIN* ) echo "example.lan.ddnsgeek.com" ;;
|
||||
*TZ ) echo "Australia/Brisbane" ;;
|
||||
*URL* ) echo "https://example.lan.ddnsgeek.com" ;;
|
||||
*PORT* ) echo "1234" ;;
|
||||
*PASSWORD*|*PASS*|*TOKEN*|*SECRET*|*KEY*|*JWT* ) echo "dummy-${key,,}" ;;
|
||||
*FINGERPRINT* ) echo "0000000000000000000000000000000000000000" ;;
|
||||
*DB_NAME* ) echo "dummydb" ;;
|
||||
*DB_USER* ) echo "dummyuser" ;;
|
||||
*NAME* ) echo "dummy-name" ;;
|
||||
*ADDRESS* ) echo "dummy" ;;
|
||||
* ) echo "dummy-value" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
render_dummy_stack_env() {
|
||||
cp "$EXAMPLE_ENV" "$STACK_ENV.tmp"
|
||||
|
||||
while IFS= read -r var; do
|
||||
[[ -z "$var" ]] && continue
|
||||
dummy="$(dummy_value_for_key "$var")"
|
||||
|
||||
if grep -Eq "^[[:space:]]*${var}=" "$STACK_ENV.tmp"; then
|
||||
sed -i "s|^[[:space:]]*${var}=.*|${var}=${dummy}|" "$STACK_ENV.tmp"
|
||||
else
|
||||
printf '%s=%s\n' "$var" "$dummy" >> "$STACK_ENV.tmp"
|
||||
fi
|
||||
done < <(jq -r '.env_template_variables[].variable' "$INVENTORY_JSON")
|
||||
|
||||
mv "$STACK_ENV.tmp" "$STACK_ENV"
|
||||
chmod 600 "$STACK_ENV" || true
|
||||
}
|
||||
|
||||
ensure_dummy_secret_files() {
|
||||
jq -r '.file_based_secrets[].path' "$INVENTORY_JSON" | while IFS= read -r relpath; do
|
||||
[[ -z "$relpath" ]] && continue
|
||||
abspath="$REPO_ROOT/$relpath"
|
||||
mkdir -p "$(dirname "$abspath")"
|
||||
if [[ ! -f "$abspath" ]]; then
|
||||
printf 'dummy-secret\n' > "$abspath"
|
||||
fi
|
||||
chmod 600 "$abspath" || true
|
||||
done
|
||||
}
|
||||
|
||||
render_dummy_stack_env
|
||||
ensure_dummy_secret_files
|
||||
|
||||
echo
|
||||
echo "== Installed versions =="
|
||||
bash --version | head -n 1 || true
|
||||
git --version || true
|
||||
docker --version || true
|
||||
docker compose version || true
|
||||
python3 --version || true
|
||||
ansible --version | head -n 1 || true
|
||||
ansible-lint --version || true
|
||||
terraform version | head -n 1 || true
|
||||
tflint --version || true
|
||||
shellcheck --version | head -n 1 || true
|
||||
yamllint --version || true
|
||||
yq --version || true
|
||||
jq --version || true
|
||||
|
||||
echo
|
||||
echo "== Dummy secret files prepared =="
|
||||
echo "$STACK_ENV"
|
||||
jq -r '.file_based_secrets[].path' "$INVENTORY_JSON" || true
|
||||
+13
-13
@@ -1,13 +1,13 @@
|
||||
22:10:52 INFO: === Update started: 2026-04-20 22:10:52 ===
|
||||
22:10:52 WARNING: Skipping traefik (directory does not exist)
|
||||
22:10:52 WARNING: Skipping nextcloud (directory does not exist)
|
||||
22:10:52 WARNING: Skipping passbolt (directory does not exist)
|
||||
22:10:52 WARNING: Skipping searxng (directory does not exist)
|
||||
22:10:52 WARNING: Skipping gitea (directory does not exist)
|
||||
22:10:52 WARNING: Skipping gotify (directory does not exist)
|
||||
22:10:52 WARNING: Skipping grafana (directory does not exist)
|
||||
22:10:52 WARNING: Skipping gramps (directory does not exist)
|
||||
22:10:52 WARNING: Skipping portainer (directory does not exist)
|
||||
22:10:52 WARNING: Skipping prometheus (directory does not exist)
|
||||
22:10:52 WARNING: Skipping uptime-kuma (directory does not exist)
|
||||
22:10:52 INFO: Pruning unused containers, images, networks, and volumes...
|
||||
10:17:35 INFO: === Update started: 2026-04-21 10:17:35 ===
|
||||
10:17:35 WARNING: Skipping traefik (directory does not exist)
|
||||
10:17:35 WARNING: Skipping nextcloud (directory does not exist)
|
||||
10:17:35 WARNING: Skipping passbolt (directory does not exist)
|
||||
10:17:35 WARNING: Skipping searxng (directory does not exist)
|
||||
10:17:35 WARNING: Skipping gitea (directory does not exist)
|
||||
10:17:35 WARNING: Skipping gotify (directory does not exist)
|
||||
10:17:35 WARNING: Skipping grafana (directory does not exist)
|
||||
10:17:35 WARNING: Skipping gramps (directory does not exist)
|
||||
10:17:35 WARNING: Skipping portainer (directory does not exist)
|
||||
10:17:35 WARNING: Skipping prometheus (directory does not exist)
|
||||
10:17:35 WARNING: Skipping uptime-kuma (directory does not exist)
|
||||
10:17:35 INFO: Pruning unused containers, images, networks, and volumes...
|
||||
|
||||
Reference in New Issue
Block a user