underpost 2.99.4 → 2.99.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.development +0 -3
- package/.env.production +1 -3
- package/.env.test +0 -3
- package/README.md +3 -3
- package/baremetal/commission-workflows.json +93 -4
- package/bin/deploy.js +56 -45
- package/cli.md +45 -28
- package/examples/static-page/README.md +101 -357
- package/examples/static-page/ssr-components/CustomPage.js +1 -13
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +40 -0
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +40 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
- package/package.json +3 -4
- package/scripts/disk-devices.sh +13 -0
- package/scripts/maas-setup.sh +13 -9
- package/scripts/rocky-kickstart.sh +294 -0
- package/src/cli/baremetal.js +657 -263
- package/src/cli/cloud-init.js +120 -120
- package/src/cli/env.js +4 -1
- package/src/cli/image.js +4 -37
- package/src/cli/index.js +56 -11
- package/src/cli/kickstart.js +149 -0
- package/src/cli/repository.js +3 -1
- package/src/cli/run.js +56 -10
- package/src/cli/secrets.js +0 -34
- package/src/cli/static.js +23 -23
- package/src/client/components/core/Docs.js +22 -3
- package/src/index.js +30 -5
- package/src/server/backup.js +11 -4
- package/src/server/client-build-docs.js +1 -1
- package/src/server/conf.js +0 -22
- package/src/server/cron.js +339 -130
- package/src/server/dns.js +10 -0
- package/src/server/logger.js +22 -27
- package/src/server/tls.js +14 -14
- package/examples/static-page/QUICK-REFERENCE.md +0 -481
- package/examples/static-page/STATIC-GENERATOR-GUIDE.md +0 -757
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# disk-devices.sh
|
|
3
|
+
# List block devices with detailed info, including by-id names
|
|
4
|
+
# Usage: sudo ./disk-devices.sh
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
sudo bash -c 'printf "NODE\tTYPE\tSIZE\tFSTYPE\tLABEL\tUUID\tMOUNTPOINT\tBY-ID\n"; \
|
|
8
|
+
lsblk -pnl -o NAME,TYPE,SIZE,FSTYPE,LABEL,UUID,MOUNTPOINT | while read -r DEV TYPE SIZE FS LBL UUID MNT; do \
|
|
9
|
+
node=$(readlink -f "$DEV"); \
|
|
10
|
+
byid=$(find /dev/disk/by-id/ -maxdepth 1 -lname "*${node##*/}" ! -name "nvme-eui*" ! -name "dm-uuid*" 2>/dev/null | head -n 1); \
|
|
11
|
+
[ -z "$byid" ] && byid=$(find /dev/disk/by-id/ -maxdepth 1 -lname "*${node##*/}" 2>/dev/null | head -n 1); \
|
|
12
|
+
printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "$node" "$TYPE" "$SIZE" "$FS" "$LBL" "$UUID" "$MNT" "$(basename "$byid" 2>/dev/null)"; \
|
|
13
|
+
done' | column -s $'\t' -t
|
package/scripts/maas-setup.sh
CHANGED
|
@@ -93,12 +93,16 @@ echo "MAAS setup script completed with new configurations."
|
|
|
93
93
|
|
|
94
94
|
|
|
95
95
|
|
|
96
|
-
echo "Configuring DHCP for fabric
|
|
96
|
+
echo "Configuring DHCP for the subnet's fabric (untagged VLAN)..."
|
|
97
97
|
|
|
98
|
-
#
|
|
98
|
+
# Derive FABRIC_ID and VLAN_VID from the subnet that matches our CIDR
|
|
99
99
|
SUBNET_CIDR="192.168.1.0/24"
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
SUBNET_JSON=$(maas "$MAAS_ADMIN_USERNAME" subnets read | jq -r '.[] | select(.cidr == "'"$SUBNET_CIDR"'")')
|
|
101
|
+
SUBNET_ID=$(echo "$SUBNET_JSON" | jq -r '.id')
|
|
102
|
+
FABRIC_ID=$(echo "$SUBNET_JSON" | jq -r '.vlan.fabric_id')
|
|
103
|
+
VLAN_VID=$(echo "$SUBNET_JSON" | jq -r '.vlan.vid')
|
|
104
|
+
FABRIC_NAME=$(echo "$SUBNET_JSON" | jq -r '.vlan.fabric')
|
|
105
|
+
echo "Detected subnet $SUBNET_CIDR on $FABRIC_NAME (fabric ID: $FABRIC_ID, VLAN VID: $VLAN_VID)"
|
|
102
106
|
RACK_CONTROLLER_ID=$(maas "$MAAS_ADMIN_USERNAME" rack-controllers read | jq -r '[.[] | select(.ip_addresses[] == "'"$IP_ADDRESS"'") | .system_id] | .[0]')
|
|
103
107
|
|
|
104
108
|
if [ -z "$RACK_CONTROLLER_ID" ] || [ "$RACK_CONTROLLER_ID" == "null" ]; then
|
|
@@ -114,8 +118,8 @@ fi
|
|
|
114
118
|
START_IP="192.168.1.191"
|
|
115
119
|
END_IP="192.168.1.254"
|
|
116
120
|
|
|
117
|
-
if [ -z "$FABRIC_ID" ]; then
|
|
118
|
-
echo "Error: Could not find FABRIC_ID for '
|
|
121
|
+
if [ -z "$FABRIC_ID" ] || [ "$FABRIC_ID" == "null" ]; then
|
|
122
|
+
echo "Error: Could not find FABRIC_ID for subnet '$SUBNET_CIDR'. Please ensure the subnet exists in MAAS."
|
|
119
123
|
exit 1
|
|
120
124
|
fi
|
|
121
125
|
|
|
@@ -123,9 +127,9 @@ fi
|
|
|
123
127
|
echo "Creating dynamic IP range from $START_IP to $END_IP..."
|
|
124
128
|
maas "$MAAS_ADMIN_USERNAME" ipranges create type=dynamic start_ip="$START_IP" end_ip="$END_IP" || echo "Dynamic IP range likely already exists or conflicts. Proceeding..."
|
|
125
129
|
|
|
126
|
-
# Enable DHCP on the
|
|
127
|
-
echo "Enabling DHCP on VLAN
|
|
128
|
-
maas "$MAAS_ADMIN_USERNAME" vlan update "$FABRIC_ID"
|
|
130
|
+
# Enable DHCP on the VLAN associated with the subnet
|
|
131
|
+
echo "Enabling DHCP on VLAN $VLAN_VID for $FABRIC_NAME (fabric ID: $FABRIC_ID)..."
|
|
132
|
+
maas "$MAAS_ADMIN_USERNAME" vlan update "$FABRIC_ID" "$VLAN_VID" dhcp_on=true primary_rack="$RACK_CONTROLLER_ID"
|
|
129
133
|
|
|
130
134
|
echo "Setting gateway IP for subnet $SUBNET_CIDR (ID: $SUBNET_ID) to $IP_ADDRESS..."
|
|
131
135
|
maas "$MAAS_ADMIN_USERNAME" subnet update $SUBNET_ID gateway_ip=$IP_ADDRESS
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Rocky Linux 9 - Anaconda %pre Ephemeral Commissioning Script
|
|
3
|
+
# Variables ROOT_PASS, AUTHORIZED_KEYS, ADMIN_USER must be set before this script runs.
|
|
4
|
+
|
|
5
|
+
set +e
|
|
6
|
+
|
|
7
|
+
# 1. Set root password
|
|
8
|
+
if [ -n "$ROOT_PASS" ]; then
|
|
9
|
+
echo "root:$ROOT_PASS" | chpasswd 2>/dev/null || \
|
|
10
|
+
echo "$ROOT_PASS" | passwd --stdin root 2>/dev/null || {
|
|
11
|
+
HASH=$(python3 -c "import crypt; print(crypt.crypt('$ROOT_PASS', crypt.mksalt(crypt.METHOD_SHA512)))" 2>/dev/null || \
|
|
12
|
+
openssl passwd -6 "$ROOT_PASS" 2>/dev/null)
|
|
13
|
+
[ -n "$HASH" ] && sed -i "s|^root:[^:]*:|root:$HASH:|" /etc/shadow 2>/dev/null
|
|
14
|
+
}
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# 2. SSH authorized_keys for root
|
|
18
|
+
if [ -n "$AUTHORIZED_KEYS" ]; then
|
|
19
|
+
mkdir -p /root/.ssh && chmod 700 /root/.ssh
|
|
20
|
+
echo "$AUTHORIZED_KEYS" > /root/.ssh/authorized_keys
|
|
21
|
+
chmod 600 /root/.ssh/authorized_keys
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# 3. Create admin user
|
|
25
|
+
if command -v useradd >/dev/null 2>&1; then
|
|
26
|
+
useradd -m -G wheel "$ADMIN_USER" 2>/dev/null || true
|
|
27
|
+
else
|
|
28
|
+
NEXT_UID=$(awk -F: 'BEGIN{max=999} $3>max && $3<60000{max=$3} END{print max+1}' /etc/passwd 2>/dev/null || echo 1001)
|
|
29
|
+
if ! grep -q "^$ADMIN_USER:" /etc/passwd 2>/dev/null; then
|
|
30
|
+
echo "$ADMIN_USER:x:$NEXT_UID:$NEXT_UID:$ADMIN_USER:/home/$ADMIN_USER:/bin/bash" >> /etc/passwd
|
|
31
|
+
echo "$ADMIN_USER:x:$NEXT_UID:" >> /etc/group 2>/dev/null
|
|
32
|
+
echo "$ADMIN_USER:!:19000:0:99999:7:::" >> /etc/shadow 2>/dev/null
|
|
33
|
+
mkdir -p /home/$ADMIN_USER
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
if [ -n "$ROOT_PASS" ]; then
|
|
38
|
+
echo "$ADMIN_USER:$ROOT_PASS" | chpasswd 2>/dev/null || \
|
|
39
|
+
echo "$ROOT_PASS" | passwd --stdin "$ADMIN_USER" 2>/dev/null || {
|
|
40
|
+
HASH=$(python3 -c "import crypt; print(crypt.crypt('$ROOT_PASS', crypt.mksalt(crypt.METHOD_SHA512)))" 2>/dev/null || \
|
|
41
|
+
openssl passwd -6 "$ROOT_PASS" 2>/dev/null)
|
|
42
|
+
[ -n "$HASH" ] && sed -i "s|^$ADMIN_USER:[^:]*:|$ADMIN_USER:$HASH:|" /etc/shadow 2>/dev/null
|
|
43
|
+
}
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
if [ -n "$AUTHORIZED_KEYS" ]; then
|
|
47
|
+
mkdir -p /home/$ADMIN_USER/.ssh && chmod 700 /home/$ADMIN_USER/.ssh
|
|
48
|
+
echo "$AUTHORIZED_KEYS" > /home/$ADMIN_USER/.ssh/authorized_keys
|
|
49
|
+
chmod 600 /home/$ADMIN_USER/.ssh/authorized_keys
|
|
50
|
+
chown -R $ADMIN_USER:$ADMIN_USER /home/$ADMIN_USER/.ssh 2>/dev/null || true
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
if [ -d /etc/sudoers.d ]; then
|
|
54
|
+
echo "$ADMIN_USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$ADMIN_USER
|
|
55
|
+
chmod 0440 /etc/sudoers.d/$ADMIN_USER
|
|
56
|
+
elif [ -f /etc/sudoers ]; then
|
|
57
|
+
echo "$ADMIN_USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# 4. Configure sshd
|
|
61
|
+
if [ -f /etc/ssh/sshd_config ]; then
|
|
62
|
+
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
|
63
|
+
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
|
|
64
|
+
sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
|
|
65
|
+
sed -i 's/^#*ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
|
|
66
|
+
sed -i 's/^#*UsePAM.*/UsePAM yes/' /etc/ssh/sshd_config
|
|
67
|
+
sed -i 's/^#*KbdInteractiveAuthentication.*/KbdInteractiveAuthentication yes/' /etc/ssh/sshd_config
|
|
68
|
+
grep -q "^PasswordAuthentication" /etc/ssh/sshd_config || echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
|
|
69
|
+
grep -q "^PermitRootLogin" /etc/ssh/sshd_config || echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
|
|
70
|
+
grep -q "^PubkeyAuthentication" /etc/ssh/sshd_config || echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config
|
|
71
|
+
else
|
|
72
|
+
mkdir -p /etc/ssh
|
|
73
|
+
cat > /etc/ssh/sshd_config << 'SSHEOF'
|
|
74
|
+
Port 22
|
|
75
|
+
PermitRootLogin yes
|
|
76
|
+
PubkeyAuthentication yes
|
|
77
|
+
AuthorizedKeysFile .ssh/authorized_keys
|
|
78
|
+
PasswordAuthentication yes
|
|
79
|
+
ChallengeResponseAuthentication yes
|
|
80
|
+
KbdInteractiveAuthentication yes
|
|
81
|
+
UsePAM yes
|
|
82
|
+
Subsystem sftp /usr/libexec/openssh/sftp-server
|
|
83
|
+
SSHEOF
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
if [ -d /etc/ssh/sshd_config.d ]; then
|
|
87
|
+
cat > /etc/ssh/sshd_config.d/00-underpost.conf << 'SSHCONF'
|
|
88
|
+
PermitRootLogin yes
|
|
89
|
+
PasswordAuthentication yes
|
|
90
|
+
PubkeyAuthentication yes
|
|
91
|
+
KbdInteractiveAuthentication yes
|
|
92
|
+
SSHCONF
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
|
|
96
|
+
ssh-keygen -A 2>/dev/null || {
|
|
97
|
+
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" 2>/dev/null
|
|
98
|
+
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" 2>/dev/null
|
|
99
|
+
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" 2>/dev/null
|
|
100
|
+
}
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# 5. Initialize rpmdb and dnf repos
|
|
104
|
+
mkdir -p /var/lib/rpm /var/cache/dnf /var/log/dnf /etc/yum.repos.d /etc/pki/rpm-gpg /etc/dnf/vars
|
|
105
|
+
echo "9" > /etc/dnf/vars/releasever
|
|
106
|
+
|
|
107
|
+
if ! grep -q "^VERSION_ID=" /etc/os-release 2>/dev/null; then
|
|
108
|
+
cat > /etc/os-release << 'OSREL'
|
|
109
|
+
NAME="Rocky Linux"
|
|
110
|
+
VERSION="9"
|
|
111
|
+
ID="rocky"
|
|
112
|
+
ID_LIKE="rhel centos fedora"
|
|
113
|
+
VERSION_ID="9"
|
|
114
|
+
PLATFORM_ID="platform:el9"
|
|
115
|
+
PRETTY_NAME="Rocky Linux 9 (Ephemeral Anaconda)"
|
|
116
|
+
ANSI_COLOR="0;32"
|
|
117
|
+
HOME_URL="https://rockylinux.org/"
|
|
118
|
+
OSREL
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
[ ! -f /etc/system-release ] && echo "Rocky Linux release 9 (Ephemeral)" > /etc/system-release
|
|
122
|
+
|
|
123
|
+
rpm --initdb 2>/dev/null || rpmdb --initdb 2>/dev/null || {
|
|
124
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
125
|
+
python3 -c "
|
|
126
|
+
import sqlite3, os
|
|
127
|
+
db_path = '/var/lib/rpm/rpmdb.sqlite'
|
|
128
|
+
if not os.path.exists(db_path):
|
|
129
|
+
conn = sqlite3.connect(db_path)
|
|
130
|
+
conn.execute('CREATE TABLE IF NOT EXISTS Packages (key BLOB NOT NULL, data BLOB NOT NULL)')
|
|
131
|
+
conn.execute('CREATE TABLE IF NOT EXISTS Name (key BLOB NOT NULL, data BLOB NOT NULL)')
|
|
132
|
+
conn.execute('CREATE TABLE IF NOT EXISTS Basenames (key BLOB NOT NULL, data BLOB NOT NULL)')
|
|
133
|
+
conn.execute('CREATE TABLE IF NOT EXISTS Installtid (key BLOB NOT NULL, data BLOB NOT NULL)')
|
|
134
|
+
conn.execute('CREATE TABLE IF NOT EXISTS Providename (key BLOB NOT NULL, data BLOB NOT NULL)')
|
|
135
|
+
conn.execute('CREATE TABLE IF NOT EXISTS Requirename (key BLOB NOT NULL, data BLOB NOT NULL)')
|
|
136
|
+
conn.execute('CREATE TABLE IF NOT EXISTS Dirnames (key BLOB NOT NULL, data BLOB NOT NULL)')
|
|
137
|
+
conn.execute('CREATE TABLE IF NOT EXISTS Sha1header (key BLOB NOT NULL, data BLOB NOT NULL)')
|
|
138
|
+
conn.execute('CREATE TABLE IF NOT EXISTS Sigmd5 (key BLOB NOT NULL, data BLOB NOT NULL)')
|
|
139
|
+
conn.commit()
|
|
140
|
+
conn.close()
|
|
141
|
+
" 2>/dev/null
|
|
142
|
+
fi
|
|
143
|
+
}
|
|
144
|
+
chmod -R 755 /var/lib/rpm 2>/dev/null
|
|
145
|
+
|
|
146
|
+
REPO_ARCH=$(uname -m)
|
|
147
|
+
|
|
148
|
+
rpm --import https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9 2>/dev/null || \
|
|
149
|
+
curl -fsSL https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9 -o /etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9 2>/dev/null || true
|
|
150
|
+
|
|
151
|
+
cat > /etc/dnf/dnf.conf << 'DNFCONF'
|
|
152
|
+
[main]
|
|
153
|
+
gpgcheck=1
|
|
154
|
+
installonly_limit=3
|
|
155
|
+
clean_requirements_on_remove=True
|
|
156
|
+
best=True
|
|
157
|
+
skip_if_unavailable=True
|
|
158
|
+
install_weak_deps=False
|
|
159
|
+
tsflags=nodocs
|
|
160
|
+
DNFCONF
|
|
161
|
+
|
|
162
|
+
cat > /etc/yum.repos.d/rocky-baseos.repo << REPOEOF
|
|
163
|
+
[baseos]
|
|
164
|
+
name=Rocky Linux 9 - BaseOS
|
|
165
|
+
baseurl=http://dl.rockylinux.org/pub/rocky/9/BaseOS/$REPO_ARCH/os/
|
|
166
|
+
gpgcheck=1
|
|
167
|
+
enabled=1
|
|
168
|
+
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
|
|
169
|
+
https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9
|
|
170
|
+
skip_if_unavailable=1
|
|
171
|
+
REPOEOF
|
|
172
|
+
|
|
173
|
+
cat > /etc/yum.repos.d/rocky-appstream.repo << REPOEOF2
|
|
174
|
+
[appstream]
|
|
175
|
+
name=Rocky Linux 9 - AppStream
|
|
176
|
+
baseurl=http://dl.rockylinux.org/pub/rocky/9/AppStream/$REPO_ARCH/os/
|
|
177
|
+
gpgcheck=1
|
|
178
|
+
enabled=1
|
|
179
|
+
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
|
|
180
|
+
https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9
|
|
181
|
+
skip_if_unavailable=1
|
|
182
|
+
REPOEOF2
|
|
183
|
+
|
|
184
|
+
cat > /etc/yum.repos.d/rocky-extras.repo << REPOEOF3
|
|
185
|
+
[extras]
|
|
186
|
+
name=Rocky Linux 9 - Extras
|
|
187
|
+
baseurl=http://dl.rockylinux.org/pub/rocky/9/extras/$REPO_ARCH/os/
|
|
188
|
+
gpgcheck=1
|
|
189
|
+
enabled=1
|
|
190
|
+
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
|
|
191
|
+
https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9
|
|
192
|
+
skip_if_unavailable=1
|
|
193
|
+
REPOEOF3
|
|
194
|
+
|
|
195
|
+
cat > /etc/yum.repos.d/rocky-crb.repo << REPOEOF4
|
|
196
|
+
[crb]
|
|
197
|
+
name=Rocky Linux 9 - CRB
|
|
198
|
+
baseurl=http://dl.rockylinux.org/pub/rocky/9/CRB/$REPO_ARCH/os/
|
|
199
|
+
gpgcheck=1
|
|
200
|
+
enabled=0
|
|
201
|
+
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
|
|
202
|
+
https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9
|
|
203
|
+
skip_if_unavailable=1
|
|
204
|
+
REPOEOF4
|
|
205
|
+
|
|
206
|
+
cat > /etc/yum.repos.d/epel.repo << REPOEOF5
|
|
207
|
+
[epel]
|
|
208
|
+
name=Extra Packages for Enterprise Linux 9
|
|
209
|
+
metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-9&arch=$REPO_ARCH
|
|
210
|
+
gpgcheck=1
|
|
211
|
+
enabled=1
|
|
212
|
+
gpgkey=https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9
|
|
213
|
+
skip_if_unavailable=1
|
|
214
|
+
REPOEOF5
|
|
215
|
+
|
|
216
|
+
rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9 2>/dev/null || \
|
|
217
|
+
curl -fsSL https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9 -o /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-9 2>/dev/null || true
|
|
218
|
+
|
|
219
|
+
dnf makecache --releasever=9 --quiet 2>/dev/null || dnf makecache --releasever=9 2>/dev/null || true
|
|
220
|
+
|
|
221
|
+
# Install sudo
|
|
222
|
+
if ! command -v sudo >/dev/null 2>&1; then
|
|
223
|
+
dnf install -y --releasever=9 --nogpgcheck sudo 2>/dev/null || \
|
|
224
|
+
dnf install -y --releasever=9 --nogpgcheck --disableplugin='*' sudo 2>/dev/null || true
|
|
225
|
+
fi
|
|
226
|
+
|
|
227
|
+
if command -v sudo >/dev/null 2>&1; then
|
|
228
|
+
mkdir -p /etc/sudoers.d
|
|
229
|
+
echo "$ADMIN_USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$ADMIN_USER
|
|
230
|
+
chmod 0440 /etc/sudoers.d/$ADMIN_USER
|
|
231
|
+
fi
|
|
232
|
+
|
|
233
|
+
cat > /home/$ADMIN_USER/.bash_profile 2>/dev/null << PROFILEEOF
|
|
234
|
+
if ! command -v sudo >/dev/null 2>&1; then
|
|
235
|
+
echo ""
|
|
236
|
+
echo "NOTE: sudo is not available. Use 'su -' to switch to root."
|
|
237
|
+
echo ""
|
|
238
|
+
fi
|
|
239
|
+
PROFILEEOF
|
|
240
|
+
chown $ADMIN_USER:$ADMIN_USER /home/$ADMIN_USER/.bash_profile 2>/dev/null || true
|
|
241
|
+
|
|
242
|
+
# Restart sshd
|
|
243
|
+
if command -v systemctl >/dev/null 2>&1; then
|
|
244
|
+
systemctl restart sshd 2>/dev/null || systemctl restart sshd.service 2>/dev/null
|
|
245
|
+
fi
|
|
246
|
+
SSHD_PID=$(cat /var/run/sshd.pid 2>/dev/null || pidof sshd 2>/dev/null | awk '{print $1}')
|
|
247
|
+
[ -n "$SSHD_PID" ] && kill -HUP "$SSHD_PID" 2>/dev/null
|
|
248
|
+
if ! pidof sshd >/dev/null 2>&1; then
|
|
249
|
+
/usr/sbin/sshd 2>/dev/null || sshd 2>/dev/null
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
# 6. Status report
|
|
253
|
+
DETECTED_IP=$(ip -4 addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d/ -f1 | head -1)
|
|
254
|
+
|
|
255
|
+
echo ""
|
|
256
|
+
echo "=============================================="
|
|
257
|
+
echo "Underpost: Ephemeral SSHD Setup Complete"
|
|
258
|
+
echo "=============================================="
|
|
259
|
+
echo "Root login: root / (password set: $([ -n "$ROOT_PASS" ] && echo 'yes' || echo 'no'))"
|
|
260
|
+
echo "Admin user: $ADMIN_USER / (password set: $([ -n "$ROOT_PASS" ] && echo 'yes' || echo 'no'))"
|
|
261
|
+
echo "SSH keys: $([ -n "$AUTHORIZED_KEYS" ] && echo 'configured' || echo 'NOT configured')"
|
|
262
|
+
echo "sshd status: $(pidof sshd >/dev/null 2>&1 && echo "running (pid $(pidof sshd))" || echo 'NOT running')"
|
|
263
|
+
echo "sudo: $(command -v sudo >/dev/null 2>&1 && echo 'installed' || echo 'NOT available (use su -)')"
|
|
264
|
+
echo "IP address: $DETECTED_IP"
|
|
265
|
+
echo "=============================================="
|
|
266
|
+
|
|
267
|
+
# Physical console display (printf with \r\n for proper line breaks on serial/physical consoles)
|
|
268
|
+
{
|
|
269
|
+
printf "\r\n"
|
|
270
|
+
printf "██╗░░░██╗███╗░░██╗██████╗░███████╗██████╗░██████╗░░█████╗░░██████╗████████╗\r\n"
|
|
271
|
+
printf "██║░░░██║████╗░██║██╔══██╗██╔════╝██╔══██╗██╔══██╗██╔══██╗██╔════╝╚══██╔══╝\r\n"
|
|
272
|
+
printf "██║░░░██║██╔██╗██║██║░░██║█████╗░░██████╔╝██████╔╝██║░░██║╚█████╗░░░░██║░░░\r\n"
|
|
273
|
+
printf "██║░░░██║██║╚████║██║░░██║██╔══╝░░██╔══██╗██╔═══╝░██║░░██║░╚═══██╗░░░██║░░░\r\n"
|
|
274
|
+
printf "╚██████╔╝██║░╚███║██████╔╝███████╗██║░░██║██║░░░░░╚█████╔╝██████╔╝░░░██║░░░\r\n"
|
|
275
|
+
printf "░╚═════╝░╚═╝░░╚══╝╚═════╝░╚══════╝╚═╝░░╚═╝╚═╝░░░░░░╚════╝░╚═════╝░░░░╚═╝░░░\r\n"
|
|
276
|
+
printf "==============================================\r\n"
|
|
277
|
+
printf " Underpost Ephemeral Commissioning Active\r\n"
|
|
278
|
+
printf "==============================================\r\n"
|
|
279
|
+
printf " SSH as: root@%s\r\n" "$DETECTED_IP"
|
|
280
|
+
printf " or: %s@%s\r\n" "$ADMIN_USER" "$DETECTED_IP"
|
|
281
|
+
printf " Key: %s\r\n" "$([ -n "$AUTHORIZED_KEYS" ] && echo 'pubkey auth enabled' || echo 'password only')"
|
|
282
|
+
printf " dnf: ready (BaseOS, AppStream, Extras, EPEL)\r\n"
|
|
283
|
+
printf "==============================================\r\n"
|
|
284
|
+
printf "\r\n"
|
|
285
|
+
} > /dev/console 2>/dev/null || true
|
|
286
|
+
|
|
287
|
+
# 7. Infinite wait loop - keep Anaconda live environment active
|
|
288
|
+
while true; do
|
|
289
|
+
sleep 60
|
|
290
|
+
if ! pidof sshd >/dev/null 2>&1; then
|
|
291
|
+
echo "$(date): sshd not running, restarting..." >> /tmp/ks-pre.log
|
|
292
|
+
/usr/sbin/sshd 2>/dev/null || sshd 2>/dev/null
|
|
293
|
+
fi
|
|
294
|
+
done
|