underpost 3.2.90 → 3.3.0

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.
Files changed (71) hide show
  1. package/.github/workflows/ghpkg.ci.yml +7 -1
  2. package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -16
  3. package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
  4. package/.github/workflows/release.cd.yml +1 -9
  5. package/CHANGELOG.md +110 -1
  6. package/CLI-HELP.md +139 -9
  7. package/README.md +5 -2
  8. package/bin/build.js +7 -5
  9. package/bin/deploy.js +1 -1
  10. package/deploy/lib/logging.sh +96 -0
  11. package/deploy/pwa-microservices-template/deploy.sh +72 -0
  12. package/deploy/release/deploy.sh +62 -0
  13. package/docker-compose.yml +1 -1
  14. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +5 -1
  15. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  16. package/manifests/cronjobs/dd-cron/dd-cron-vultr.yaml +52 -0
  17. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  18. package/package.json +5 -5
  19. package/scripts/audit-selinux.sh +64 -0
  20. package/scripts/coverall-test.sh +24 -0
  21. package/scripts/gpu-diag.sh +0 -0
  22. package/scripts/ip-info.sh +0 -0
  23. package/scripts/k3s-node-setup.sh +18 -15
  24. package/scripts/kubeadm-node-setup.sh +12 -23
  25. package/scripts/link-local-underpost-cli.sh +0 -0
  26. package/scripts/lxd-vm-setup.sh +0 -0
  27. package/scripts/maas-nat-firewalld.sh +0 -0
  28. package/scripts/nat-iptables.sh +2 -0
  29. package/scripts/rhel-grpc-setup.sh +0 -0
  30. package/scripts/rocky-kickstart.sh +25 -9
  31. package/scripts/test-monitor.sh +1 -1
  32. package/src/cli/baremetal.js +1 -2
  33. package/src/cli/cloud-init.js +1 -1
  34. package/src/cli/cluster.js +73 -68
  35. package/src/cli/db.js +9 -2
  36. package/src/cli/deploy.js +21 -5
  37. package/src/cli/docker-compose.js +1 -1
  38. package/src/cli/env.js +1 -1
  39. package/src/cli/image.js +0 -1
  40. package/src/cli/index.js +121 -9
  41. package/src/cli/lxd.js +1 -1
  42. package/src/cli/monitor.js +1 -1
  43. package/src/cli/release.js +57 -22
  44. package/src/cli/repository.js +11 -9
  45. package/src/cli/run.js +36 -9
  46. package/src/cli/ssh.js +198 -77
  47. package/src/cli/system.js +26 -13
  48. package/src/cli/test.js +1 -1
  49. package/src/cli/vultr.js +583 -0
  50. package/src/cli/wireguard.js +2125 -0
  51. package/src/client-builder/client-build.js +20 -14
  52. package/src/db/mongo/MongooseDB.js +4 -0
  53. package/src/index.js +25 -1
  54. package/src/projects/underpost/catalog-underpost.js +4 -1
  55. package/src/server/backup.js +1 -1
  56. package/src/server/conf.js +18 -108
  57. package/src/server/cron.js +249 -51
  58. package/src/server/dns.js +100 -6
  59. package/src/server/environment.js +98 -0
  60. package/src/server/forward-proxy.js +549 -0
  61. package/src/server/middlewares.js +56 -1
  62. package/src/server/process.js +0 -1
  63. package/src/server/selinux.js +185 -0
  64. package/src/server/systemd.js +205 -0
  65. package/src/server/underpost-compression.js +186 -0
  66. package/src/server/underpost-gateway.js +20 -10
  67. package/src/server/underpost-ingress.js +18 -2
  68. package/test/selinux.test.js +71 -0
  69. package/test/underpost-gateway.test.js +41 -0
  70. package/test/underpost-ingress.test.js +52 -0
  71. package/test/wireguard-edge.test.js +1177 -0
@@ -0,0 +1,72 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ source "$SCRIPT_DIR/../lib/logging.sh"
6
+
7
+ # Runs in the workflow's rockylinux:9 container against the checked-out
8
+ # workspace instead of over SSH, so the repository root is this script's
9
+ # grandparent rather than a fixed remote path.
10
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
11
+
12
+ main() {
13
+ echo "Starting github pages deploy"
14
+
15
+ cd "$REPO_ROOT"
16
+
17
+ run_quiet \
18
+ "Install required packages" \
19
+ "Target pod:" \
20
+ 14 \
21
+ dnf install -y sudo tar gzip bzip2 git
22
+
23
+ run_quiet \
24
+ "Install curl" \
25
+ "Target pod:" \
26
+ 14 \
27
+ dnf install -y curl --allowerasing
28
+
29
+ run_quiet \
30
+ "Add Node.js repository" \
31
+ "Target pod:" \
32
+ 14 \
33
+ bash -c "curl -fsSL https://rpm.nodesource.com/setup_24.x | bash -"
34
+
35
+ run_quiet \
36
+ "Install Node.js" \
37
+ "Target pod:" \
38
+ 14 \
39
+ dnf install nodejs -y
40
+
41
+ run_quiet \
42
+ "Install dependencies" \
43
+ "Target pod:" \
44
+ 14 \
45
+ npm install
46
+
47
+ run_quiet \
48
+ "Build dd-github-pages configuration" \
49
+ "Target pod:" \
50
+ 14 \
51
+ node bin new --default-conf --conf-workflow-id dd-github-pages
52
+
53
+ run_quiet \
54
+ "Create dd-github-pages deployment" \
55
+ "Target pod:" \
56
+ 14 \
57
+ node bin new --deploy-id dd-github-pages
58
+
59
+ run_quiet \
60
+ "Load dd-github-pages production environment" \
61
+ "Target pod:" \
62
+ 14 \
63
+ node bin env dd-github-pages production
64
+
65
+ run_quiet \
66
+ "Build dd-github-pages client" \
67
+ "Target pod:" \
68
+ 14 \
69
+ env NODE_ENV=production node bin client dd-github-pages '' underpostnet.github.io /pwa-microservices-template-ghpkg
70
+ }
71
+
72
+ main "$@"
@@ -0,0 +1,62 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ source "$SCRIPT_DIR/../lib/logging.sh"
6
+
7
+ ENGINE_ROOT=/home/dd/engine
8
+
9
+ main() {
10
+ echo "Starting remote release deploy"
11
+
12
+ run_quiet \
13
+ "Pull repository" \
14
+ "Target pod:" \
15
+ 14 \
16
+ sudo -n -- /bin/bash -lc \
17
+ "cd $ENGINE_ROOT && node bin run pull"
18
+
19
+ run_quiet \
20
+ "Install dependencies" \
21
+ "Target pod:" \
22
+ 14 \
23
+ sudo -n -- /bin/bash -lc \
24
+ "cd $ENGINE_ROOT && npm install"
25
+
26
+ run_quiet \
27
+ "Sync secrets" \
28
+ "Target pod:" \
29
+ 14 \
30
+ sudo -n -- /bin/bash -lc \
31
+ "cd $ENGINE_ROOT && node bin run secret"
32
+
33
+ run_quiet \
34
+ "Install underpost CLI" \
35
+ "Target pod:" \
36
+ 14 \
37
+ sudo -n -- /bin/bash -lc \
38
+ "cd $ENGINE_ROOT && npm install -g underpost"
39
+
40
+ run_quiet \
41
+ "Resync secrets" \
42
+ "Target pod:" \
43
+ 14 \
44
+ sudo -n -- /bin/bash -lc \
45
+ "cd $ENGINE_ROOT && node bin run secret"
46
+
47
+ run_quiet \
48
+ "Configure git" \
49
+ "Target pod:" \
50
+ 14 \
51
+ sudo -n -- /bin/bash -lc \
52
+ "cd $ENGINE_ROOT && node bin run --dev git-conf"
53
+
54
+ run_quiet \
55
+ "Build and publish docker images" \
56
+ "Target pod:" \
57
+ 14 \
58
+ sudo -n -- /bin/bash -lc \
59
+ "cd $ENGINE_ROOT && node bin run docker-image"
60
+ }
61
+
62
+ main "$@"
@@ -81,7 +81,7 @@ services:
81
81
  # (dd-default-development-blue). Connection targets use Docker service
82
82
  # discovery instead of hardcoded localhost.
83
83
  app:
84
- image: ${APP_IMAGE:-underpost/underpost-engine}:${APP_TAG:-v3.2.90}
84
+ image: ${APP_IMAGE:-underpost/underpost-engine}:${APP_TAG:-v3.3.0}
85
85
  container_name: dd-app
86
86
  # The start command is supplied by the generated override docker/compose.app.yml
87
87
  # (see `underpost docker-compose --generate --deploy-id <id>`), keeping this
@@ -14,6 +14,10 @@ spec:
14
14
  failedJobsHistoryLimit: 1
15
15
  suspend: false
16
16
  jobTemplate:
17
+ metadata:
18
+ labels:
19
+ app: dd-cron-backup
20
+ managed-by: underpost
17
21
  spec:
18
22
  template:
19
23
  metadata:
@@ -23,7 +27,7 @@ spec:
23
27
  spec:
24
28
  containers:
25
29
  - name: dd-cron-backup
26
- image: underpost/underpost-engine:v3.2.90
30
+ image: underpost/underpost-engine:v3.3.0
27
31
  command:
28
32
  - /bin/sh
29
33
  - -c
@@ -23,7 +23,7 @@ spec:
23
23
  spec:
24
24
  containers:
25
25
  - name: dd-cron-dns
26
- image: underpost/underpost-engine:v3.2.90
26
+ image: underpost/underpost-engine:v3.3.0
27
27
  command:
28
28
  - /bin/sh
29
29
  - -c
@@ -0,0 +1,52 @@
1
+ apiVersion: batch/v1
2
+ kind: CronJob
3
+ metadata:
4
+ name: dd-cron-vultr
5
+ namespace: default
6
+ labels:
7
+ app: dd-cron-vultr
8
+ managed-by: underpost
9
+ spec:
10
+ schedule: "*/30 * * * *"
11
+ concurrencyPolicy: Forbid
12
+ startingDeadlineSeconds: 200
13
+ successfulJobsHistoryLimit: 3
14
+ failedJobsHistoryLimit: 1
15
+ suspend: false
16
+ jobTemplate:
17
+ metadata:
18
+ labels:
19
+ app: dd-cron-vultr
20
+ managed-by: underpost
21
+ spec:
22
+ template:
23
+ metadata:
24
+ labels:
25
+ app: dd-cron-vultr
26
+ managed-by: underpost
27
+ spec:
28
+ containers:
29
+ - name: dd-cron-vultr
30
+ image: underpost/underpost-engine:v3.3.0
31
+ command:
32
+ - /bin/sh
33
+ - -c
34
+ - >
35
+ cd /home/dd/engine &&
36
+ node bin env dd-cron production &&
37
+ node bin cron dd-cron vultr --git --kubeadm
38
+ volumeMounts:
39
+ - mountPath: /home/dd/engine
40
+ name: underpost-cron-container-volume
41
+ - mountPath: /usr/lib/node_modules/underpost
42
+ name: underpost-share-env
43
+ volumes:
44
+ - hostPath:
45
+ path: /home/dd/engine
46
+ type: Directory
47
+ name: underpost-cron-container-volume
48
+ - hostPath:
49
+ path: /root/.nvm/versions/node/v24.15.0/lib/node_modules/underpost
50
+ type: DirectoryOrCreate
51
+ name: underpost-share-env
52
+ restartPolicy: OnFailure
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-default-development-blue
20
- image: underpost/underpost-engine:v3.2.90
20
+ image: underpost/underpost-engine:v3.3.0
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -98,7 +98,7 @@ spec:
98
98
  spec:
99
99
  containers:
100
100
  - name: dd-default-development-green
101
- image: underpost/underpost-engine:v3.2.90
101
+ image: underpost/underpost-engine:v3.3.0
102
102
  # resources:
103
103
  # requests:
104
104
  # memory: "124Ki"
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "3.2.90",
5
+ "version": "3.3.0",
6
6
  "description": "Underpost Platform — end-to-end CI/CD and application-delivery toolchain CLI. Covers bare metal, Kubernetes, K3s, kubeadm, LXD, container/image orchestration, secrets, databases, cron jobs, monitoring, SSH, runners, PWA + Workbox delivery, and release orchestration. Extensible via downstream CLIs.",
7
7
  "scripts": {
8
8
  "start": "node --max-old-space-size=8192 src/server",
@@ -78,7 +78,7 @@
78
78
  "@neodrag/vanilla": "^2.3.1",
79
79
  "adm-zip": "^0.6.0",
80
80
  "ag-grid-community": "^36.1.0",
81
- "bumpp": "^12.2.0",
81
+ "bumpp": "^12.2.1",
82
82
  "axios": "^1.19.0",
83
83
  "chai": "^6.2.2",
84
84
  "clipboardy": "^5.3.2",
@@ -89,10 +89,10 @@
89
89
  "cookie-parser": "^1.4.7",
90
90
  "cors": "^2.8.6",
91
91
  "d3": "^7.9.0",
92
- "dexie": "^4.4.4",
92
+ "dexie": "^4.4.5",
93
93
  "dotenv": "^17.4.2",
94
94
  "easymde": "^2.21.0",
95
- "esbuild": "^0.28.1",
95
+ "esbuild": "^0.28.2",
96
96
  "escape-string-regexp": "^5.0.0",
97
97
  "express": "^5.2.1",
98
98
  "express-fileupload": "^1.4.3",
@@ -111,7 +111,7 @@
111
111
  "jsonwebtoken": "^9.0.3",
112
112
  "mariadb": "^3.5.3",
113
113
  "marked": "^18.0.9",
114
- "mongoose": "^9.9.1",
114
+ "mongoose": "^9.9.2",
115
115
  "mocha": "^11.8.0",
116
116
  "morgan": "^1.11.0",
117
117
  "nodemailer": "^9.0.5",
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SINCE="recent"
5
+ FAIL_ON_AVC="1"
6
+
7
+ while [ "$#" -gt 0 ]; do
8
+ case "$1" in
9
+ --since)
10
+ [ "$#" -ge 2 ] || { echo "--since requires an ausearch time value" >&2; exit 2; }
11
+ SINCE="$2"
12
+ shift 2
13
+ ;;
14
+ --no-fail)
15
+ FAIL_ON_AVC="0"
16
+ shift
17
+ ;;
18
+ -h|--help)
19
+ echo "Usage: $0 [--since recent|today|boot|TIME] [--no-fail]"
20
+ exit 0
21
+ ;;
22
+ *)
23
+ echo "Unknown option: $1" >&2
24
+ exit 2
25
+ ;;
26
+ esac
27
+ done
28
+
29
+ command -v getenforce >/dev/null 2>&1 || {
30
+ echo "SELinux userspace is unavailable. Install policycoreutils." >&2
31
+ exit 2
32
+ }
33
+ command -v ausearch >/dev/null 2>&1 || {
34
+ echo "ausearch is unavailable. Install audit and start auditd." >&2
35
+ exit 2
36
+ }
37
+
38
+ MODE="$(getenforce)"
39
+ echo "SELinux mode: $MODE"
40
+ [ "$MODE" = "Enforcing" ] || echo "WARNING: expected Enforcing mode" >&2
41
+ command -v sestatus >/dev/null 2>&1 && sestatus
42
+
43
+ AUDIT=(ausearch)
44
+ [ "$(id -u)" -eq 0 ] || AUDIT=(sudo ausearch)
45
+ RAW_FILE="$(mktemp /tmp/underpost-selinux-avc.XXXXXX)"
46
+ trap 'rm -f "$RAW_FILE"' EXIT
47
+
48
+ "${AUDIT[@]}" -m AVC,USER_AVC,SELINUX_ERR -ts "$SINCE" --raw > "$RAW_FILE" 2>/dev/null || true
49
+ if ! grep -q '^type=' "$RAW_FILE"; then
50
+ echo "No SELinux AVC denials found since: $SINCE"
51
+ [ "$MODE" = "Enforcing" ]
52
+ exit
53
+ fi
54
+
55
+ echo "SELinux AVC denials found since: $SINCE" >&2
56
+ "${AUDIT[@]}" -m AVC,USER_AVC,SELINUX_ERR -ts "$SINCE" -i || true
57
+ if command -v sealert >/dev/null 2>&1; then
58
+ echo "sealert analysis:"
59
+ sealert -a "$RAW_FILE" || true
60
+ else
61
+ echo "Install setroubleshoot-server for sealert analysis." >&2
62
+ fi
63
+
64
+ [ "$FAIL_ON_AVC" = "0" ] || exit 1
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env bash
2
+ set -u -o pipefail
3
+
4
+ EXCLUDES=(
5
+ --exclude="test/cyberia-instance-conf-defaults.test.js"
6
+ --exclude="test/cyberia-load.test.js"
7
+ --exclude="test/object-layer-item-id.test.js"
8
+ --exclude="test/api.test.js"
9
+ --exclude="test/crypto.test.js"
10
+ --exclude="test/shape-generator.test.js"
11
+ )
12
+
13
+ TESTS=(
14
+ test/cluster-instances.test.js
15
+ test/deploy-monitor.test.js
16
+ test/deploy-node-placement.test.js
17
+ test/instance-traffic-plan.test.js
18
+ test/sops-secret-store.test.js
19
+ test/underpost-gateway.test.js
20
+ test/underpost-ingress.test.js
21
+ test/wireguard-edge.test.js
22
+ )
23
+
24
+ c8 "${EXCLUDES[@]}" mocha "${TESTS[@]}"
File without changes
File without changes
@@ -49,22 +49,25 @@ if [ -z "$(ls -A "$ENGINE_ROOT")" ]; then
49
49
  fi
50
50
 
51
51
  # ---------------------------------------------------------------------------
52
- # NVM and Node.js required for `node bin ...` entrypoints
52
+ # System-wide Node.js is required by service units under SELinux.
53
53
  # ---------------------------------------------------------------------------
54
- echo "Installing NVM and Node.js v24.15.0..."
55
-
56
- curl -o- https://cdn.jsdelivr.net/gh/nvm-sh/nvm@v0.40.1/install.sh | bash
57
-
58
- export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
59
- # shellcheck disable=SC1090
60
- [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
54
+ if command -v dnf >/dev/null 2>&1; then
55
+ sudo dnf install -y policycoreutils policycoreutils-python-utils selinux-policy-targeted audit
56
+ fi
61
57
 
62
- nvm install 24.15.0
63
- nvm use 24.15.0
64
- nvm alias default 24.15.0
65
- ln -sf "$(command -v node)" /usr/local/bin/node
66
- ln -sf "$(command -v npm)" /usr/local/bin/npm
67
- ln -sf "$(command -v npx)" /usr/local/bin/npx
58
+ if ! command -v node >/dev/null 2>&1 || ! node --version 2>/dev/null | grep -q '^v24'; then
59
+ echo "Installing system-wide Node.js 24..."
60
+ if command -v dnf >/dev/null 2>&1; then
61
+ curl -fsSL https://rpm.nodesource.com/setup_24.x | sudo bash -
62
+ sudo dnf install -y nodejs
63
+ elif command -v apt-get >/dev/null 2>&1; then
64
+ curl -fsSL https://deb.nodesource.com/setup_24.x | sudo bash -
65
+ sudo apt-get install -y nodejs
66
+ else
67
+ echo "ERROR: a supported system package manager is required for Node.js 24" >&2
68
+ exit 1
69
+ fi
70
+ fi
68
71
 
69
72
  echo "
70
73
  ██╗░░░██╗███╗░░██╗██████╗░███████╗██████╗░██████╗░░█████╗░░██████╗████████╗
@@ -116,7 +119,7 @@ if [ "$ROLE" = "control" ]; then
116
119
  curl -sfL https://get.k3s.io | \
117
120
  K3S_URL="https://${CONTROL_IP}:6443" \
118
121
  K3S_TOKEN="${K3S_TOKEN}" \
119
- sh -s - agent
122
+ sh -s - agent $(if command -v selinuxenabled >/dev/null 2>&1 && selinuxenabled; then printf '%s' '--selinux'; fi)
120
123
 
121
124
  echo ""
122
125
  echo "K3s worker joined https://${CONTROL_IP}:6443 successfully."
@@ -5,8 +5,8 @@ set -euo pipefail
5
5
  # Underpost Kubeadm Node Setup (bare-metal physical node)
6
6
  #
7
7
  # Mirrors scripts/k3s-node-setup.sh but for kubeadm on real hardware: it runs on
8
- # the freshly deployed OS (disk-installed Rocky) after first boot, installs NVM +
9
- # Node.js, ensures the engine source is present, and drives the cluster bring-up
8
+ # the freshly deployed OS (disk-installed Rocky) after first boot, installs
9
+ # system-wide Node.js, ensures the engine source is present, and drives the cluster bring-up
10
10
  # through the local engine entrypoint `node bin cluster` (src/cli/cluster.js) —
11
11
  # reusing its kubeadm + Contour + host-init logic instead of reimplementing it.
12
12
  #
@@ -146,33 +146,22 @@ if [ "$JOIN_ONLY" = "1" ]; then
146
146
  fi
147
147
 
148
148
  # ---------------------------------------------------------------------------
149
- # 0. Base prerequisites — a minimal @core Rocky install lacks tar/xz/git, which
150
- # NVM needs to extract Node.js and the engine clone needs. Install them first.
149
+ # 0. Base prerequisites.
151
150
  # ---------------------------------------------------------------------------
152
- log "Installing base prerequisites (tar, xz, gzip, git, curl)..."
153
- sudo dnf install -y tar xz gzip bzip2 git curl ca-certificates which findutils 2>/dev/null \
154
- || dnf install -y tar xz gzip bzip2 git curl ca-certificates which findutils
151
+ log "Installing base prerequisites..."
152
+ sudo dnf install -y tar xz gzip bzip2 git curl ca-certificates which findutils policycoreutils policycoreutils-python-utils selinux-policy-targeted audit 2>/dev/null \
153
+ || dnf install -y tar xz gzip bzip2 git curl ca-certificates which findutils policycoreutils policycoreutils-python-utils selinux-policy-targeted audit
155
154
 
156
155
  # ---------------------------------------------------------------------------
157
- # 1. NVM and Node.js required for the `node bin ...` entrypoints. Idempotent so
158
- # a retried run does not reinstall Node from scratch.
156
+ # 1. System-wide Node.js. Home-directory runtimes cannot be used by hardened
157
+ # systemd services under SELinux.
159
158
  # ---------------------------------------------------------------------------
160
159
  if command -v node >/dev/null 2>&1 && node --version 2>/dev/null | grep -q '^v24'; then
161
- log "Node.js $(node --version) already installed; skipping NVM setup"
160
+ log "Node.js $(node --version) already installed"
162
161
  else
163
- log "Installing NVM and Node.js v24.15.0..."
164
- curl -o- https://cdn.jsdelivr.net/gh/nvm-sh/nvm@v0.40.1/install.sh | bash
165
-
166
- export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
167
- # shellcheck disable=SC1090
168
- [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
169
-
170
- nvm install 24.15.0
171
- nvm use 24.15.0
172
- nvm alias default 24.15.0
173
- ln -sf "$(command -v node)" /usr/local/bin/node
174
- ln -sf "$(command -v npm)" /usr/local/bin/npm
175
- ln -sf "$(command -v npx)" /usr/local/bin/npx
162
+ log "Installing system-wide Node.js 24..."
163
+ curl -fsSL https://rpm.nodesource.com/setup_24.x | sudo bash -
164
+ sudo dnf install -y nodejs
176
165
  fi
177
166
 
178
167
  echo "
File without changes
File without changes
File without changes
@@ -42,12 +42,14 @@ echo "[INFO] Opening Kubernetes control plane ports..."
42
42
 
43
43
  # Kubernetes API Server
44
44
  sudo firewall-cmd --permanent --zone=public --add-port=6443/tcp
45
+ sudo firewall-cmd --permanent --zone=public --add-port=6443/udp
45
46
 
46
47
  # etcd
47
48
  sudo firewall-cmd --permanent --zone=public --add-port=2379-2380/tcp
48
49
 
49
50
  # kubelet API
50
51
  sudo firewall-cmd --permanent --zone=public --add-port=10250/tcp
52
+ sudo firewall-cmd --permanent --zone=public --add-port=10250/udp
51
53
 
52
54
  # kube-scheduler
53
55
  sudo firewall-cmd --permanent --zone=public --add-port=10259/tcp
File without changes
@@ -168,7 +168,7 @@ PermitEmptyPasswords no
168
168
  PasswordAuthentication ${SSHD_PASSWORD_AUTH}
169
169
  ChallengeResponseAuthentication ${SSHD_KBD_INTERACTIVE}
170
170
  KbdInteractiveAuthentication ${SSHD_KBD_INTERACTIVE}
171
- UsePAM no
171
+ UsePAM yes
172
172
  X11Forwarding no
173
173
  PrintMotd no
174
174
  TCPKeepAlive yes
@@ -585,7 +585,7 @@ fi
585
585
  post_status "installing" "\"detail\":\"installing packages\",\"disk\":\"\$REAL_DISK\""
586
586
 
587
587
  ilog "Installing base packages with dnf --installroot ..."
588
- PKGS="@core kernel grub2-tools openssh-server NetworkManager chrony dracut-config-generic rocky-release"
588
+ PKGS="@core kernel grub2-tools openssh-server NetworkManager chrony dracut-config-generic rocky-release policycoreutils policycoreutils-python-utils selinux-policy-targeted audit sudo"
589
589
  if [ "\$FW" = "uefi" ]; then
590
590
  PKGS="\$PKGS grub2-efi-x64 shim-x64 efibootmgr"
591
591
  else
@@ -622,15 +622,10 @@ ilog "Configuring installed system (hostname, network, ssh, users) ..."
622
622
  echo "\${TARGET_HOSTNAME:-rocky9}" > "\$TARGET_MNT/etc/hostname"
623
623
 
624
624
  chroot "\$TARGET_MNT" /bin/bash -s << CHROOTEOF >> "\$KS_LOG" 2>&1
625
- set +e
625
+ set -e
626
626
  systemctl enable sshd NetworkManager chronyd 2>/dev/null
627
627
 
628
- # SELinux -> permissive in the DEPLOYED OS. Critical: with SELinux enforcing on
629
- # first boot, files written from this installer chroot (authorized_keys, home
630
- # dirs) carry the wrong security context, so sshd drops sessions ("Connection
631
- # reset by peer") and PAM can block console logins. Permissive ignores contexts
632
- # (no relabel reboot needed) and matches what kubeadm/cluster.js expect.
633
- sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config 2>/dev/null || true
628
+ sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config
634
629
 
635
630
  # Ensure sshd host keys exist so sshd actually starts on first boot.
636
631
  ssh-keygen -A 2>/dev/null || true
@@ -708,11 +703,19 @@ fi
708
703
  # Key-only SSH on the installed system.
709
704
  mkdir -p /etc/ssh/sshd_config.d
710
705
  cat > /etc/ssh/sshd_config.d/00-underpost.conf <<SSHDEOF
706
+ Port ${SSH_PORT}
711
707
  PermitRootLogin prohibit-password
712
708
  PubkeyAuthentication yes
713
709
  PasswordAuthentication no
710
+ KbdInteractiveAuthentication no
711
+ UsePAM yes
714
712
  SSHDEOF
715
713
 
714
+ if [ "${SSH_PORT}" != "22" ]; then
715
+ semanage port -a -t ssh_port_t -p tcp "${SSH_PORT}" 2>/dev/null || \
716
+ semanage port -m -t ssh_port_t -p tcp "${SSH_PORT}"
717
+ fi
718
+
716
719
  # Create the admin login accounts. create_user <name> writes the authorized key,
717
720
  # wheel membership and passwordless sudo. Passwords are applied after the chroot.
718
721
  create_user() {
@@ -738,11 +741,24 @@ chmod 600 /root/.ssh/authorized_keys
738
741
  create_user "\${ADMIN_USER}"
739
742
  create_user "\${DEPLOY_USER}"
740
743
 
744
+ restorecon -RF /etc/ssh /etc/sudoers.d /root/.ssh /home 2>/dev/null
745
+ touch /.autorelabel
746
+
741
747
  # Build initramfs for the installed kernel.
742
748
  KVER=\\\$(ls /lib/modules | head -1)
743
749
  [ -n "\\\$KVER" ] && dracut -f /boot/initramfs-\\\$KVER.img "\\\$KVER"
744
750
  CHROOTEOF
745
751
 
752
+ CHROOT_RC=\$?
753
+ if [ "\$CHROOT_RC" -ne 0 ]; then
754
+ ilog "FATAL: installed-system configuration failed (rc=\$CHROOT_RC)"
755
+ post_status "failed" "\"detail\":\"installed-system configuration rc=\$CHROOT_RC\""
756
+ for d in dev proc sys run; do umount -l "\$TARGET_MNT/\$d" 2>/dev/null; done
757
+ umount -R "\$TARGET_MNT" 2>/dev/null || true
758
+ rm -f "\$INSTALL_LOCK"
759
+ exit 1
760
+ fi
761
+
746
762
  # Set console passwords AFTER the chroot heredoc, from decoded installer vars.
747
763
  # Primary path: pipe 'user:password' into 'chroot chpasswd' (keeps password
748
764
  # characters out of any heredoc). Fallback: hash with openssl and apply via
@@ -24,7 +24,7 @@ MODE=runtime # runtime | instance
24
24
  ENV=development # development | production
25
25
  DEPLOY_ID=dd-test # deploy id (instance mode: parent of conf.instances.json)
26
26
  INSTANCE_IDS= # instance mode: csv of ids (default: all in conf.instances.json)
27
- IMAGE=underpost/wp:v3.2.90 # runtime mode image (instance mode reads image from conf)
27
+ IMAGE=underpost/wp:v3.3.0 # runtime mode image (instance mode reads image from conf)
28
28
  VERSIONS=green # csv of blue/green versions
29
29
  REPLICAS=1 # replicas per deployment
30
30
  NAMESPACE=default # k8s namespace
@@ -5,9 +5,8 @@
5
5
  */
6
6
 
7
7
  import { fileURLToPath } from 'url';
8
- import { getNpmRootPath, getUnderpostRootPath } from '../server/conf.js';
8
+ import { getNpmRootPath } from '../server/environment.js';
9
9
  import { pbcopy, shellExec } from '../server/process.js';
10
- import dotenv from 'dotenv';
11
10
  import { loggerFactory, loggerMiddleware } from '../server/logger.js';
12
11
  import fs from 'fs-extra';
13
12
  import path from 'path';
@@ -8,7 +8,7 @@
8
8
  import { shellExec } from '../server/process.js';
9
9
  import fs from 'fs-extra';
10
10
  import { loggerFactory } from '../server/logger.js';
11
- import { getNpmRootPath } from '../server/conf.js';
11
+ import { getNpmRootPath } from '../server/environment.js';
12
12
  import Underpost from '../index.js';
13
13
 
14
14
  const logger = loggerFactory(import.meta);