underpost 3.2.80 → 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 (84) 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 +291 -1
  6. package/CLI-HELP.md +174 -23
  7. package/README.md +5 -2
  8. package/bin/build.js +7 -5
  9. package/bin/deploy.js +19 -17
  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/manifests/deployment/playwright/deployment.yaml +1 -1
  19. package/manifests/mongodb/kustomization.yaml +4 -1
  20. package/manifests/mongodb/statefulset.yaml +4 -0
  21. package/manifests/mongodb/storage-class.yaml +9 -2
  22. package/package.json +19 -19
  23. package/scripts/audit-selinux.sh +64 -0
  24. package/scripts/coverall-test.sh +24 -0
  25. package/scripts/gpu-diag.sh +0 -0
  26. package/scripts/ip-info.sh +0 -0
  27. package/scripts/k3s-node-setup.sh +18 -15
  28. package/scripts/kubeadm-node-setup.sh +12 -23
  29. package/scripts/link-local-underpost-cli.sh +0 -0
  30. package/scripts/lxd-vm-setup.sh +0 -0
  31. package/scripts/maas-nat-firewalld.sh +0 -0
  32. package/scripts/nat-iptables.sh +12 -4
  33. package/scripts/rhel-grpc-setup.sh +0 -0
  34. package/scripts/rocky-kickstart.sh +25 -9
  35. package/scripts/test-monitor.sh +4 -3
  36. package/src/cli/baremetal.js +1 -2
  37. package/src/cli/cloud-init.js +1 -1
  38. package/src/cli/cluster.js +786 -96
  39. package/src/cli/db.js +11 -4
  40. package/src/cli/deploy.js +1698 -177
  41. package/src/cli/docker-compose.js +19 -178
  42. package/src/cli/env.js +1 -1
  43. package/src/cli/image.js +15 -7
  44. package/src/cli/index.js +245 -44
  45. package/src/cli/ipfs.js +82 -11
  46. package/src/cli/lxd.js +1 -1
  47. package/src/cli/monitor.js +2 -2
  48. package/src/cli/release.js +57 -22
  49. package/src/cli/repository.js +12 -10
  50. package/src/cli/run.js +2195 -427
  51. package/src/cli/secrets.js +969 -0
  52. package/src/cli/ssh.js +206 -105
  53. package/src/cli/system.js +26 -13
  54. package/src/cli/test.js +1 -1
  55. package/src/cli/vultr.js +583 -0
  56. package/src/cli/wireguard.js +2125 -0
  57. package/src/client-builder/client-build.js +102 -13
  58. package/src/client-builder/ssr.js +27 -73
  59. package/src/db/mongo/MongoBootstrap.js +295 -54
  60. package/src/db/mongo/MongooseDB.js +51 -32
  61. package/src/index.js +25 -1
  62. package/src/projects/underpost/catalog-underpost.js +4 -1
  63. package/src/server/backup.js +1 -1
  64. package/src/server/conf.js +1216 -168
  65. package/src/server/cri.js +70 -0
  66. package/src/server/cron.js +249 -51
  67. package/src/server/dns.js +100 -6
  68. package/src/server/environment.js +98 -0
  69. package/src/server/forward-proxy.js +549 -0
  70. package/src/server/middlewares.js +56 -1
  71. package/src/server/process.js +0 -1
  72. package/src/server/selinux.js +185 -0
  73. package/src/server/systemd.js +205 -0
  74. package/src/server/underpost-compression.js +186 -0
  75. package/src/server/underpost-gateway.js +1083 -0
  76. package/src/server/underpost-ingress.js +380 -0
  77. package/test/cluster-instances.test.js +435 -0
  78. package/test/deploy-node-placement.test.js +45 -0
  79. package/test/instance-traffic-plan.test.js +710 -0
  80. package/test/selinux.test.js +71 -0
  81. package/test/sops-secret-store.test.js +612 -0
  82. package/test/underpost-gateway.test.js +510 -0
  83. package/test/underpost-ingress.test.js +305 -0
  84. 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.80}
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.80
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.80
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.80
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.80
101
+ image: underpost/underpost-engine:v3.3.0
102
102
  # resources:
103
103
  # requests:
104
104
  # memory: "124Ki"
@@ -14,7 +14,7 @@ spec:
14
14
  spec:
15
15
  containers:
16
16
  - name: playwright
17
- image: mcr.microsoft.com/playwright:v1.59.0-jammy
17
+ image: mcr.microsoft.com/playwright:v1.62.1-jammy
18
18
  command:
19
19
  - /bin/bash
20
20
  - -c
@@ -3,7 +3,10 @@
3
3
  apiVersion: kustomize.config.k8s.io/v1beta1
4
4
  kind: Kustomization
5
5
  resources:
6
- - pv-pvc.yaml
6
+ # pv-pvc.yaml is intentionally absent: the PersistentVolume set is one-per-replica, so it is
7
+ # generated from the effective replica count by MongoBootstrap.applyReplicaVolumes() and applied
8
+ # just before this kustomization. A static file can only describe a fixed number of members, and
9
+ # any --replicas above it leaves the surplus claims unbindable.
7
10
  - headless-service.yaml
8
11
  - statefulset.yaml
9
12
  # - backup-pv-pvc.yaml
@@ -105,6 +105,10 @@ spec:
105
105
  volumeClaimTemplates:
106
106
  - metadata:
107
107
  name: mongodb-storage
108
+ # Without this label `kubectl delete pvc -l app=mongodb` matches nothing, leaving stale
109
+ # claims bound to retained PVs across redeploys.
110
+ labels:
111
+ app: mongodb
108
112
  spec:
109
113
  accessModes: ['ReadWriteOnce']
110
114
  storageClassName: mongodb-storage-class
@@ -3,7 +3,14 @@ kind: StorageClass
3
3
  metadata:
4
4
  name: mongodb-storage-class
5
5
  annotations:
6
- storageclass.kubernetes.io/is-default-class: "false"
7
- provisioner: rancher.io/local-path
6
+ storageclass.kubernetes.io/is-default-class: 'false'
7
+ # Static class: the replica volumes are hostPath PVs generated one per member by
8
+ # MongoBootstrap.applyReplicaVolumes(), each pinned to one member via `claimRef`. It must NOT name a dynamic provisioner — with
9
+ # `rancher.io/local-path` the local-path controller also provisions for these PVCs, racing the
10
+ # static binder, so which volume a member ends up on is not deterministic. Two members landing
11
+ # on one directory is fatal: mongod dies on `WiredTiger.lock: fcntl: Resource temporarily
12
+ # unavailable`, since kind bind-mounts /data/mongodb from the host into every node.
13
+ provisioner: kubernetes.io/no-provisioner
8
14
  reclaimPolicy: Retain
15
+ # Static hostPath PVs carry no nodeAffinity, so binding can safely wait for the scheduler.
9
16
  volumeBindingMode: WaitForFirstConsumer
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.80",
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",
@@ -72,16 +72,16 @@
72
72
  "homepage": "https://github.com/underpostnet/pwa-microservices-template#readme",
73
73
  "dependencies": {
74
74
  "@fortawesome/fontawesome-free": "^7.3.1",
75
- "@fullcalendar/rrule": "^7.0.1",
75
+ "@fullcalendar/rrule": "^7.0.2",
76
76
  "@grpc/grpc-js": "^1.14.4",
77
77
  "@grpc/proto-loader": "^0.8.1",
78
78
  "@neodrag/vanilla": "^2.3.1",
79
79
  "adm-zip": "^0.6.0",
80
- "ag-grid-community": "^36.0.1",
81
- "axios": "^1.18.1",
82
- "bumpp": "^11.1.0",
80
+ "ag-grid-community": "^36.1.0",
81
+ "bumpp": "^12.2.1",
82
+ "axios": "^1.19.0",
83
83
  "chai": "^6.2.2",
84
- "clipboardy": "^5.3.1",
84
+ "clipboardy": "^5.3.2",
85
85
  "cloudinary": "^2.10.0",
86
86
  "colors": "^1.4.0",
87
87
  "commander": "^15.0.0",
@@ -89,32 +89,32 @@
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",
99
- "express-rate-limit": "^8.6.0",
99
+ "express-rate-limit": "^8.6.2",
100
100
  "express-slow-down": "^3.1.0",
101
101
  "fast-json-stable-stringify": "^2.1.0",
102
- "favicons": "^7.3.0",
103
- "fs-extra": "^11.3.6",
104
- "fullcalendar": "^7.0.1",
102
+ "favicons": "^7.3.1",
103
+ "fs-extra": "^11.4.0",
104
+ "fullcalendar": "^7.0.2",
105
105
  "helmet": "^8.3.0",
106
106
  "html-minifier-terser": "^7.2.0",
107
107
  "http-proxy-middleware": "^4.2.0",
108
108
  "ignore-walk": "^9.0.0",
109
- "iovalkey": "^0.3.3",
109
+ "iovalkey": "^0.4.0",
110
110
  "json-colorizer": "^3.0.1",
111
111
  "jsonwebtoken": "^9.0.3",
112
112
  "mariadb": "^3.5.3",
113
- "marked": "^18.0.6",
114
- "mocha": "^11.7.6",
115
- "mongoose": "^9.7.4",
113
+ "marked": "^18.0.9",
114
+ "mongoose": "^9.9.2",
115
+ "mocha": "^11.8.0",
116
116
  "morgan": "^1.11.0",
117
- "nodemailer": "^9.0.3",
117
+ "nodemailer": "^9.0.5",
118
118
  "nodemon": "^3.0.1",
119
119
  "peer": "^1.0.2",
120
120
  "peerjs": "^1.5.5",
@@ -129,9 +129,9 @@
129
129
  "swagger-autogen": "^2.23.7",
130
130
  "swagger-ui-express": "^5.0.0",
131
131
  "typedoc": "^0.28.20",
132
- "typescript": "^6.0.3",
132
+ "typescript": "6.0.3",
133
133
  "validator": "^13.15.35",
134
- "vanilla-jsoneditor": "^3.12.0",
134
+ "vanilla-jsoneditor": "^3.13.0",
135
135
  "winston": "^3.19.0",
136
136
  "workbox-background-sync": "^7.4.1",
137
137
  "workbox-cacheable-response": "^7.4.1",
@@ -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
@@ -32,16 +32,24 @@ sudo firewall-cmd --permanent --zone=public --add-service=ssh
32
32
  sudo firewall-cmd --permanent --zone=public --add-service=http
33
33
  sudo firewall-cmd --permanent --zone=public --add-service=https
34
34
 
35
+ # QUIC / HTTP3. The `https` service above covers TCP 443 only, so without this
36
+ # an HTTP/3 gateway advertises `Alt-Svc: h3=":443"` and every client that acts
37
+ # on it silently fails over UDP while HTTP/2 keeps working.
38
+ sudo firewall-cmd --permanent --zone=public --add-port=443/udp
39
+ sudo firewall-cmd --permanent --zone=public --add-port=80/udp
40
+
35
41
  echo "[INFO] Opening Kubernetes control plane ports..."
36
42
 
37
43
  # Kubernetes API Server
38
44
  sudo firewall-cmd --permanent --zone=public --add-port=6443/tcp
45
+ sudo firewall-cmd --permanent --zone=public --add-port=6443/udp
39
46
 
40
47
  # etcd
41
48
  sudo firewall-cmd --permanent --zone=public --add-port=2379-2380/tcp
42
49
 
43
50
  # kubelet API
44
51
  sudo firewall-cmd --permanent --zone=public --add-port=10250/tcp
52
+ sudo firewall-cmd --permanent --zone=public --add-port=10250/udp
45
53
 
46
54
  # kube-scheduler
47
55
  sudo firewall-cmd --permanent --zone=public --add-port=10259/tcp
@@ -98,10 +106,10 @@ sudo firewall-cmd --reload
98
106
  echo
99
107
  echo "[INFO] Sysctl status:"
100
108
  sudo sysctl \
101
- net.ipv4.ip_forward \
102
- net.ipv6.conf.all.forwarding \
103
- net.bridge.bridge-nf-call-iptables \
104
- net.bridge.bridge-nf-call-ip6tables
109
+ net.ipv4.ip_forward \
110
+ net.ipv6.conf.all.forwarding \
111
+ net.bridge.bridge-nf-call-iptables \
112
+ net.bridge.bridge-nf-call-ip6tables
105
113
 
106
114
  echo
107
115
  echo "[INFO] Firewall status:"
File without changes