kastell 2.2.3 → 2.2.5
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/.claude-plugin/marketplace.json +18 -18
- package/.claude-plugin/plugin.json +45 -39
- package/CHANGELOG.md +1294 -1266
- package/LICENSE +201 -201
- package/NOTICE +5 -5
- package/README.md +1 -1
- package/README.tr.md +1 -1
- package/bin/kastell +2 -2
- package/bin/kastell-mcp +5 -5
- package/dist/adapters/coolify.js +92 -92
- package/dist/adapters/dokploy.js +99 -99
- package/dist/core/audit/formatters/badge.js +20 -20
- package/dist/core/completions.js +631 -631
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +25 -31
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/serverExplain.d.ts.map +1 -1
- package/dist/mcp/tools/serverExplain.js.map +1 -1
- package/dist/mcp/tools/serverFleet.d.ts.map +1 -1
- package/dist/mcp/tools/serverFleet.js.map +1 -1
- package/dist/mcp/tools/serverInfo.d.ts +1 -1
- package/dist/mcp/tools/serverInfo.js +1 -1
- package/dist/mcp/tools/serverPlugin.d.ts.map +1 -1
- package/dist/mcp/tools/serverPlugin.js.map +1 -1
- package/dist/mcp-bundle.mjs +101015 -0
- package/dist/utils/cloudInit.js +58 -58
- package/dist/utils/version.d.ts.map +1 -1
- package/dist/utils/version.js +19 -4
- package/dist/utils/version.js.map +1 -1
- package/kastell-plugin/.claude-plugin/plugin.json +20 -20
- package/kastell-plugin/.mcp.json +15 -8
- package/kastell-plugin/README.md +113 -113
- package/kastell-plugin/agents/kastell-auditor.md +77 -77
- package/kastell-plugin/agents/scripts/bucket_mapper.sh +101 -101
- package/kastell-plugin/agents/scripts/trend_report.sh +91 -91
- package/kastell-plugin/hooks/destroy-block.cjs +31 -31
- package/kastell-plugin/hooks/hooks.json +57 -57
- package/kastell-plugin/hooks/pre-commit-audit-guard.cjs +75 -75
- package/kastell-plugin/hooks/session-audit.cjs +86 -86
- package/kastell-plugin/hooks/session-log.cjs +56 -56
- package/kastell-plugin/hooks/stop-quality-check.cjs +72 -72
- package/kastell-plugin/skills/kastell-careful/SKILL.md +64 -64
- package/kastell-plugin/skills/kastell-ops/SKILL.md +139 -139
- package/kastell-plugin/skills/kastell-ops/references/commands.md +45 -45
- package/kastell-plugin/skills/kastell-ops/references/mcp-tools.md +50 -50
- package/kastell-plugin/skills/kastell-ops/references/patterns.md +145 -145
- package/kastell-plugin/skills/kastell-ops/references/pitfalls.md +136 -136
- package/kastell-plugin/skills/kastell-ops/scripts/check_coverage.sh +101 -101
- package/kastell-plugin/skills/kastell-ops/scripts/fleet_report.sh +73 -73
- package/kastell-plugin/skills/kastell-ops/scripts/parse_audit.sh +76 -76
- package/kastell-plugin/skills/kastell-research/SKILL.md +90 -90
- package/kastell-plugin/skills/kastell-scaffold/SKILL.md +104 -104
- package/kastell-plugin/skills/kastell-scaffold/references/template-audit-check.md +150 -150
- package/kastell-plugin/skills/kastell-scaffold/references/template-command.md +80 -80
- package/kastell-plugin/skills/kastell-scaffold/references/template-mcp-tool.md +72 -72
- package/kastell-plugin/skills/kastell-scaffold/references/template-provider.md +67 -67
- package/kastell-plugin/skills/kastell-scaffold/scripts/scaffold.sh +180 -180
- package/kastell-plugin/skills/kastell-scaffold/templates/check-test.ts.tpl +27 -27
- package/kastell-plugin/skills/kastell-scaffold/templates/check.ts.tpl +50 -50
- package/kastell-plugin/skills/kastell-scaffold/templates/command-core.ts.tpl +18 -18
- package/kastell-plugin/skills/kastell-scaffold/templates/command-test.ts.tpl +17 -17
- package/kastell-plugin/skills/kastell-scaffold/templates/command.ts.tpl +25 -25
- package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool-test.ts.tpl +30 -30
- package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool.ts.tpl +29 -29
- package/kastell-plugin/skills/kastell-scaffold/templates/provider-test.ts.tpl +34 -34
- package/kastell-plugin/skills/kastell-scaffold/templates/provider.ts.tpl +32 -32
- package/package.json +125 -122
- package/dist/commands/interactive.d.ts +0 -11
- package/dist/commands/interactive.d.ts.map +0 -1
- package/dist/commands/interactive.js +0 -1079
- package/dist/commands/interactive.js.map +0 -1
- package/dist/core/lock.d.ts +0 -66
- package/dist/core/lock.d.ts.map +0 -1
- package/dist/core/lock.js +0 -556
- package/dist/core/lock.js.map +0 -1
package/dist/adapters/coolify.js
CHANGED
|
@@ -10,98 +10,98 @@ export class CoolifyAdapter {
|
|
|
10
10
|
platformPorts = [80, 443, COOLIFY_PORT, 6001, 6002];
|
|
11
11
|
getCloudInit(serverName, sshPublicKey) {
|
|
12
12
|
const safeName = serverName.replace(/[^a-z0-9-]/g, "");
|
|
13
|
-
return `#!/bin/bash
|
|
14
|
-
set +e
|
|
15
|
-
export DEBIAN_FRONTEND=noninteractive
|
|
16
|
-
touch /var/log/kastell-install.log
|
|
17
|
-
chmod 600 /var/log/kastell-install.log
|
|
18
|
-
exec > >(tee /var/log/kastell-install.log) 2>&1
|
|
19
|
-
|
|
20
|
-
echo "=================================="
|
|
21
|
-
echo "Kastell Auto-Installer"
|
|
22
|
-
echo "Server: ${safeName}"
|
|
23
|
-
echo "=================================="
|
|
24
|
-
|
|
25
|
-
# Wait for network connectivity (DO cloud-init may start before network is ready)
|
|
26
|
-
echo "Waiting for network connectivity..."
|
|
27
|
-
MAX_ATTEMPTS=30
|
|
28
|
-
ATTEMPTS=0
|
|
29
|
-
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
|
|
30
|
-
if curl -s --max-time 5 https://cdn.coollabs.io > /dev/null 2>&1; then
|
|
31
|
-
echo "Network is ready!"
|
|
32
|
-
break
|
|
33
|
-
fi
|
|
34
|
-
ATTEMPTS=$((ATTEMPTS + 1))
|
|
35
|
-
echo "Network not ready (attempt $ATTEMPTS/$MAX_ATTEMPTS)..."
|
|
36
|
-
sleep 2
|
|
37
|
-
done
|
|
38
|
-
|
|
39
|
-
# Disable needrestart to prevent interactive prompts during Docker/package installation
|
|
40
|
-
echo "Disabling needrestart..."
|
|
41
|
-
if dpkg -l needrestart > /dev/null 2>&1; then
|
|
42
|
-
apt-get remove -y needrestart || true
|
|
43
|
-
fi
|
|
44
|
-
export NEEDRESTART_MODE=a
|
|
45
|
-
export NEEDRESTART_SUSPEND=1
|
|
46
|
-
|
|
47
|
-
# Update system
|
|
48
|
-
echo "Updating system packages..."
|
|
49
|
-
apt-get update -y
|
|
50
|
-
|
|
51
|
-
# Configure firewall BEFORE installer (prevents SSH lockout if installer hangs)
|
|
52
|
-
echo "Configuring firewall..."
|
|
53
|
-
if command -v ufw &> /dev/null; then
|
|
54
|
-
ufw allow 22/tcp
|
|
55
|
-
ufw allow 80/tcp
|
|
56
|
-
ufw allow 443/tcp
|
|
57
|
-
ufw allow 8000/tcp
|
|
58
|
-
ufw allow 6001/tcp
|
|
59
|
-
ufw allow 6002/tcp
|
|
60
|
-
echo "y" | ufw enable || true
|
|
61
|
-
else
|
|
62
|
-
iptables -A INPUT -p tcp --dport 8000 -j ACCEPT
|
|
63
|
-
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
|
|
64
|
-
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
|
|
65
|
-
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
|
|
66
|
-
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
67
|
-
mkdir -p /etc/iptables
|
|
68
|
-
iptables-save > /etc/iptables/rules.v4 || true
|
|
69
|
-
apt-get install -y iptables-persistent || true
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
# Switch from socket activation to traditional SSH service (prevents Ubuntu 24.04 ssh.socket bugs)
|
|
73
|
-
echo "Switching to traditional SSH service..."
|
|
74
|
-
systemctl disable --now ssh.socket 2>/dev/null || true
|
|
75
|
-
systemctl enable --now ssh.service 2>/dev/null || true
|
|
76
|
-
|
|
77
|
-
# Install Coolify
|
|
78
|
-
echo "Installing Coolify..."
|
|
79
|
-
curl -fsSL https://cdn.coollabs.io/coolify/install.sh -o /tmp/coolify-install.sh && head -c2 /tmp/coolify-install.sh | grep -q "#!" && [ "$(wc -c < /tmp/coolify-install.sh)" -gt 100 ] && env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a NEEDRESTART_SUSPEND=1 bash /tmp/coolify-install.sh && rm -f /tmp/coolify-install.sh
|
|
80
|
-
|
|
81
|
-
# Ensure SSH remains accessible after Coolify installation
|
|
82
|
-
echo "Ensuring SSH service is active..."
|
|
83
|
-
if ! ss -tlnp | grep -q ':22 '; then
|
|
84
|
-
systemctl restart ssh.service 2>/dev/null || systemctl restart sshd.service 2>/dev/null || true
|
|
85
|
-
sleep 2
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
|
-
# Re-inject SSH public key (Coolify installer may overwrite authorized_keys)
|
|
89
|
-
${sshPublicKey ? `echo "Re-injecting SSH public key..."
|
|
90
|
-
mkdir -p /root/.ssh
|
|
91
|
-
chmod 700 /root/.ssh
|
|
92
|
-
grep -qF '${sshPublicKey.trim().replace(/'/g, "'\\''")}' /root/.ssh/authorized_keys 2>/dev/null || echo '${sshPublicKey.trim().replace(/'/g, "'\\''")}' >> /root/.ssh/authorized_keys
|
|
93
|
-
chmod 600 /root/.ssh/authorized_keys` : "# No SSH public key provided — skipping re-injection"}
|
|
94
|
-
|
|
95
|
-
# Wait for services
|
|
96
|
-
echo "Waiting for Coolify services to start..."
|
|
97
|
-
sleep 30
|
|
98
|
-
|
|
99
|
-
echo "=================================="
|
|
100
|
-
echo "Coolify installation completed!"
|
|
101
|
-
echo "=================================="
|
|
102
|
-
echo ""
|
|
103
|
-
echo "Please wait 3-5 more minutes for Coolify to fully initialize."
|
|
104
|
-
echo "Then access your instance at: http://YOUR_SERVER_IP:8000"
|
|
13
|
+
return `#!/bin/bash
|
|
14
|
+
set +e
|
|
15
|
+
export DEBIAN_FRONTEND=noninteractive
|
|
16
|
+
touch /var/log/kastell-install.log
|
|
17
|
+
chmod 600 /var/log/kastell-install.log
|
|
18
|
+
exec > >(tee /var/log/kastell-install.log) 2>&1
|
|
19
|
+
|
|
20
|
+
echo "=================================="
|
|
21
|
+
echo "Kastell Auto-Installer"
|
|
22
|
+
echo "Server: ${safeName}"
|
|
23
|
+
echo "=================================="
|
|
24
|
+
|
|
25
|
+
# Wait for network connectivity (DO cloud-init may start before network is ready)
|
|
26
|
+
echo "Waiting for network connectivity..."
|
|
27
|
+
MAX_ATTEMPTS=30
|
|
28
|
+
ATTEMPTS=0
|
|
29
|
+
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
|
|
30
|
+
if curl -s --max-time 5 https://cdn.coollabs.io > /dev/null 2>&1; then
|
|
31
|
+
echo "Network is ready!"
|
|
32
|
+
break
|
|
33
|
+
fi
|
|
34
|
+
ATTEMPTS=$((ATTEMPTS + 1))
|
|
35
|
+
echo "Network not ready (attempt $ATTEMPTS/$MAX_ATTEMPTS)..."
|
|
36
|
+
sleep 2
|
|
37
|
+
done
|
|
38
|
+
|
|
39
|
+
# Disable needrestart to prevent interactive prompts during Docker/package installation
|
|
40
|
+
echo "Disabling needrestart..."
|
|
41
|
+
if dpkg -l needrestart > /dev/null 2>&1; then
|
|
42
|
+
apt-get remove -y needrestart || true
|
|
43
|
+
fi
|
|
44
|
+
export NEEDRESTART_MODE=a
|
|
45
|
+
export NEEDRESTART_SUSPEND=1
|
|
46
|
+
|
|
47
|
+
# Update system
|
|
48
|
+
echo "Updating system packages..."
|
|
49
|
+
apt-get update -y
|
|
50
|
+
|
|
51
|
+
# Configure firewall BEFORE installer (prevents SSH lockout if installer hangs)
|
|
52
|
+
echo "Configuring firewall..."
|
|
53
|
+
if command -v ufw &> /dev/null; then
|
|
54
|
+
ufw allow 22/tcp
|
|
55
|
+
ufw allow 80/tcp
|
|
56
|
+
ufw allow 443/tcp
|
|
57
|
+
ufw allow 8000/tcp
|
|
58
|
+
ufw allow 6001/tcp
|
|
59
|
+
ufw allow 6002/tcp
|
|
60
|
+
echo "y" | ufw enable || true
|
|
61
|
+
else
|
|
62
|
+
iptables -A INPUT -p tcp --dport 8000 -j ACCEPT
|
|
63
|
+
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
|
|
64
|
+
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
|
|
65
|
+
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
|
|
66
|
+
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
67
|
+
mkdir -p /etc/iptables
|
|
68
|
+
iptables-save > /etc/iptables/rules.v4 || true
|
|
69
|
+
apt-get install -y iptables-persistent || true
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# Switch from socket activation to traditional SSH service (prevents Ubuntu 24.04 ssh.socket bugs)
|
|
73
|
+
echo "Switching to traditional SSH service..."
|
|
74
|
+
systemctl disable --now ssh.socket 2>/dev/null || true
|
|
75
|
+
systemctl enable --now ssh.service 2>/dev/null || true
|
|
76
|
+
|
|
77
|
+
# Install Coolify
|
|
78
|
+
echo "Installing Coolify..."
|
|
79
|
+
curl -fsSL https://cdn.coollabs.io/coolify/install.sh -o /tmp/coolify-install.sh && head -c2 /tmp/coolify-install.sh | grep -q "#!" && [ "$(wc -c < /tmp/coolify-install.sh)" -gt 100 ] && env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a NEEDRESTART_SUSPEND=1 bash /tmp/coolify-install.sh && rm -f /tmp/coolify-install.sh
|
|
80
|
+
|
|
81
|
+
# Ensure SSH remains accessible after Coolify installation
|
|
82
|
+
echo "Ensuring SSH service is active..."
|
|
83
|
+
if ! ss -tlnp | grep -q ':22 '; then
|
|
84
|
+
systemctl restart ssh.service 2>/dev/null || systemctl restart sshd.service 2>/dev/null || true
|
|
85
|
+
sleep 2
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Re-inject SSH public key (Coolify installer may overwrite authorized_keys)
|
|
89
|
+
${sshPublicKey ? `echo "Re-injecting SSH public key..."
|
|
90
|
+
mkdir -p /root/.ssh
|
|
91
|
+
chmod 700 /root/.ssh
|
|
92
|
+
grep -qF '${sshPublicKey.trim().replace(/'/g, "'\\''")}' /root/.ssh/authorized_keys 2>/dev/null || echo '${sshPublicKey.trim().replace(/'/g, "'\\''")}' >> /root/.ssh/authorized_keys
|
|
93
|
+
chmod 600 /root/.ssh/authorized_keys` : "# No SSH public key provided — skipping re-injection"}
|
|
94
|
+
|
|
95
|
+
# Wait for services
|
|
96
|
+
echo "Waiting for Coolify services to start..."
|
|
97
|
+
sleep 30
|
|
98
|
+
|
|
99
|
+
echo "=================================="
|
|
100
|
+
echo "Coolify installation completed!"
|
|
101
|
+
echo "=================================="
|
|
102
|
+
echo ""
|
|
103
|
+
echo "Please wait 3-5 more minutes for Coolify to fully initialize."
|
|
104
|
+
echo "Then access your instance at: http://YOUR_SERVER_IP:8000"
|
|
105
105
|
`;
|
|
106
106
|
}
|
|
107
107
|
async healthCheck(ip, domain) {
|
package/dist/adapters/dokploy.js
CHANGED
|
@@ -10,105 +10,105 @@ export class DokployAdapter {
|
|
|
10
10
|
platformPorts = [80, 443, DOKPLOY_PORT];
|
|
11
11
|
getCloudInit(serverName, sshPublicKey) {
|
|
12
12
|
const safeName = serverName.replace(/[^a-z0-9-]/g, "");
|
|
13
|
-
return `#!/bin/bash
|
|
14
|
-
set +e
|
|
15
|
-
export DEBIAN_FRONTEND=noninteractive
|
|
16
|
-
touch /var/log/kastell-install.log
|
|
17
|
-
chmod 600 /var/log/kastell-install.log
|
|
18
|
-
exec > >(tee /var/log/kastell-install.log) 2>&1
|
|
19
|
-
|
|
20
|
-
echo "=================================="
|
|
21
|
-
echo "Kastell Auto-Installer"
|
|
22
|
-
echo "Server: ${safeName}"
|
|
23
|
-
echo "Platform: Dokploy"
|
|
24
|
-
echo "=================================="
|
|
25
|
-
|
|
26
|
-
# Wait for network connectivity
|
|
27
|
-
echo "Waiting for network connectivity..."
|
|
28
|
-
MAX_ATTEMPTS=30
|
|
29
|
-
ATTEMPTS=0
|
|
30
|
-
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
|
|
31
|
-
if curl -s --max-time 5 https://dokploy.com > /dev/null 2>&1; then
|
|
32
|
-
echo "Network is ready!"
|
|
33
|
-
break
|
|
34
|
-
fi
|
|
35
|
-
ATTEMPTS=$((ATTEMPTS + 1))
|
|
36
|
-
echo "Network not ready (attempt $ATTEMPTS/$MAX_ATTEMPTS)..."
|
|
37
|
-
sleep 2
|
|
38
|
-
done
|
|
39
|
-
|
|
40
|
-
# Disable needrestart to prevent interactive prompts during Docker/package installation
|
|
41
|
-
echo "Disabling needrestart..."
|
|
42
|
-
if dpkg -l needrestart > /dev/null 2>&1; then
|
|
43
|
-
apt-get remove -y needrestart || true
|
|
44
|
-
fi
|
|
45
|
-
export NEEDRESTART_MODE=a
|
|
46
|
-
export NEEDRESTART_SUSPEND=1
|
|
47
|
-
|
|
48
|
-
# Update system
|
|
49
|
-
echo "Updating system packages..."
|
|
50
|
-
apt-get update -y
|
|
51
|
-
|
|
52
|
-
# Configure firewall BEFORE installer (prevents SSH lockout if installer hangs)
|
|
53
|
-
echo "Configuring firewall..."
|
|
54
|
-
if command -v ufw &> /dev/null; then
|
|
55
|
-
ufw allow 22/tcp
|
|
56
|
-
ufw allow 80/tcp
|
|
57
|
-
ufw allow 443/tcp
|
|
58
|
-
ufw allow 3000/tcp
|
|
59
|
-
ufw allow 2377/tcp
|
|
60
|
-
ufw allow 7946/tcp
|
|
61
|
-
ufw allow 7946/udp
|
|
62
|
-
ufw allow 4789/udp
|
|
63
|
-
echo "y" | ufw enable || true
|
|
64
|
-
else
|
|
65
|
-
iptables -A INPUT -p tcp --dport 3000 -j ACCEPT
|
|
66
|
-
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
|
|
67
|
-
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
|
|
68
|
-
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
|
|
69
|
-
iptables -A INPUT -p tcp --dport 2377 -j ACCEPT
|
|
70
|
-
iptables -A INPUT -p tcp --dport 7946 -j ACCEPT
|
|
71
|
-
iptables -A INPUT -p udp --dport 7946 -j ACCEPT
|
|
72
|
-
iptables -A INPUT -p udp --dport 4789 -j ACCEPT
|
|
73
|
-
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
74
|
-
mkdir -p /etc/iptables
|
|
75
|
-
iptables-save > /etc/iptables/rules.v4 || true
|
|
76
|
-
apt-get install -y iptables-persistent || true
|
|
77
|
-
fi
|
|
78
|
-
|
|
79
|
-
# Switch from socket activation to traditional SSH service (prevents Ubuntu 24.04 ssh.socket bugs)
|
|
80
|
-
echo "Switching to traditional SSH service..."
|
|
81
|
-
systemctl disable --now ssh.socket 2>/dev/null || true
|
|
82
|
-
systemctl enable --now ssh.service 2>/dev/null || true
|
|
83
|
-
|
|
84
|
-
# Install Dokploy
|
|
85
|
-
echo "Installing Dokploy..."
|
|
86
|
-
curl -sSL https://dokploy.com/install.sh -o /tmp/dokploy-install.sh && head -c2 /tmp/dokploy-install.sh | grep -q "#!" && [ "$(wc -c < /tmp/dokploy-install.sh)" -gt 100 ] && env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a NEEDRESTART_SUSPEND=1 sh /tmp/dokploy-install.sh && rm -f /tmp/dokploy-install.sh
|
|
87
|
-
|
|
88
|
-
# Ensure SSH remains accessible after installation
|
|
89
|
-
echo "Ensuring SSH service is active..."
|
|
90
|
-
if ! ss -tlnp | grep -q ':22 '; then
|
|
91
|
-
systemctl restart ssh.service 2>/dev/null || systemctl restart sshd.service 2>/dev/null || true
|
|
92
|
-
sleep 2
|
|
93
|
-
fi
|
|
94
|
-
|
|
95
|
-
# Re-inject SSH public key (platform installer may overwrite authorized_keys)
|
|
96
|
-
${sshPublicKey ? `echo "Re-injecting SSH public key..."
|
|
97
|
-
mkdir -p /root/.ssh
|
|
98
|
-
chmod 700 /root/.ssh
|
|
99
|
-
grep -qF '${sshPublicKey.trim().replace(/'/g, "'\\''")}' /root/.ssh/authorized_keys 2>/dev/null || echo '${sshPublicKey.trim().replace(/'/g, "'\\''")}' >> /root/.ssh/authorized_keys
|
|
100
|
-
chmod 600 /root/.ssh/authorized_keys` : "# No SSH public key provided — skipping re-injection"}
|
|
101
|
-
|
|
102
|
-
# Wait for services
|
|
103
|
-
echo "Waiting for Dokploy services to start..."
|
|
104
|
-
sleep 30
|
|
105
|
-
|
|
106
|
-
echo "=================================="
|
|
107
|
-
echo "Dokploy installation completed!"
|
|
108
|
-
echo "=================================="
|
|
109
|
-
echo ""
|
|
110
|
-
echo "Please wait 3-5 more minutes for Dokploy to fully initialize."
|
|
111
|
-
echo "Then access your instance at: http://YOUR_SERVER_IP:3000"
|
|
13
|
+
return `#!/bin/bash
|
|
14
|
+
set +e
|
|
15
|
+
export DEBIAN_FRONTEND=noninteractive
|
|
16
|
+
touch /var/log/kastell-install.log
|
|
17
|
+
chmod 600 /var/log/kastell-install.log
|
|
18
|
+
exec > >(tee /var/log/kastell-install.log) 2>&1
|
|
19
|
+
|
|
20
|
+
echo "=================================="
|
|
21
|
+
echo "Kastell Auto-Installer"
|
|
22
|
+
echo "Server: ${safeName}"
|
|
23
|
+
echo "Platform: Dokploy"
|
|
24
|
+
echo "=================================="
|
|
25
|
+
|
|
26
|
+
# Wait for network connectivity
|
|
27
|
+
echo "Waiting for network connectivity..."
|
|
28
|
+
MAX_ATTEMPTS=30
|
|
29
|
+
ATTEMPTS=0
|
|
30
|
+
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
|
|
31
|
+
if curl -s --max-time 5 https://dokploy.com > /dev/null 2>&1; then
|
|
32
|
+
echo "Network is ready!"
|
|
33
|
+
break
|
|
34
|
+
fi
|
|
35
|
+
ATTEMPTS=$((ATTEMPTS + 1))
|
|
36
|
+
echo "Network not ready (attempt $ATTEMPTS/$MAX_ATTEMPTS)..."
|
|
37
|
+
sleep 2
|
|
38
|
+
done
|
|
39
|
+
|
|
40
|
+
# Disable needrestart to prevent interactive prompts during Docker/package installation
|
|
41
|
+
echo "Disabling needrestart..."
|
|
42
|
+
if dpkg -l needrestart > /dev/null 2>&1; then
|
|
43
|
+
apt-get remove -y needrestart || true
|
|
44
|
+
fi
|
|
45
|
+
export NEEDRESTART_MODE=a
|
|
46
|
+
export NEEDRESTART_SUSPEND=1
|
|
47
|
+
|
|
48
|
+
# Update system
|
|
49
|
+
echo "Updating system packages..."
|
|
50
|
+
apt-get update -y
|
|
51
|
+
|
|
52
|
+
# Configure firewall BEFORE installer (prevents SSH lockout if installer hangs)
|
|
53
|
+
echo "Configuring firewall..."
|
|
54
|
+
if command -v ufw &> /dev/null; then
|
|
55
|
+
ufw allow 22/tcp
|
|
56
|
+
ufw allow 80/tcp
|
|
57
|
+
ufw allow 443/tcp
|
|
58
|
+
ufw allow 3000/tcp
|
|
59
|
+
ufw allow 2377/tcp
|
|
60
|
+
ufw allow 7946/tcp
|
|
61
|
+
ufw allow 7946/udp
|
|
62
|
+
ufw allow 4789/udp
|
|
63
|
+
echo "y" | ufw enable || true
|
|
64
|
+
else
|
|
65
|
+
iptables -A INPUT -p tcp --dport 3000 -j ACCEPT
|
|
66
|
+
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
|
|
67
|
+
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
|
|
68
|
+
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
|
|
69
|
+
iptables -A INPUT -p tcp --dport 2377 -j ACCEPT
|
|
70
|
+
iptables -A INPUT -p tcp --dport 7946 -j ACCEPT
|
|
71
|
+
iptables -A INPUT -p udp --dport 7946 -j ACCEPT
|
|
72
|
+
iptables -A INPUT -p udp --dport 4789 -j ACCEPT
|
|
73
|
+
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
74
|
+
mkdir -p /etc/iptables
|
|
75
|
+
iptables-save > /etc/iptables/rules.v4 || true
|
|
76
|
+
apt-get install -y iptables-persistent || true
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Switch from socket activation to traditional SSH service (prevents Ubuntu 24.04 ssh.socket bugs)
|
|
80
|
+
echo "Switching to traditional SSH service..."
|
|
81
|
+
systemctl disable --now ssh.socket 2>/dev/null || true
|
|
82
|
+
systemctl enable --now ssh.service 2>/dev/null || true
|
|
83
|
+
|
|
84
|
+
# Install Dokploy
|
|
85
|
+
echo "Installing Dokploy..."
|
|
86
|
+
curl -sSL https://dokploy.com/install.sh -o /tmp/dokploy-install.sh && head -c2 /tmp/dokploy-install.sh | grep -q "#!" && [ "$(wc -c < /tmp/dokploy-install.sh)" -gt 100 ] && env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a NEEDRESTART_SUSPEND=1 sh /tmp/dokploy-install.sh && rm -f /tmp/dokploy-install.sh
|
|
87
|
+
|
|
88
|
+
# Ensure SSH remains accessible after installation
|
|
89
|
+
echo "Ensuring SSH service is active..."
|
|
90
|
+
if ! ss -tlnp | grep -q ':22 '; then
|
|
91
|
+
systemctl restart ssh.service 2>/dev/null || systemctl restart sshd.service 2>/dev/null || true
|
|
92
|
+
sleep 2
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# Re-inject SSH public key (platform installer may overwrite authorized_keys)
|
|
96
|
+
${sshPublicKey ? `echo "Re-injecting SSH public key..."
|
|
97
|
+
mkdir -p /root/.ssh
|
|
98
|
+
chmod 700 /root/.ssh
|
|
99
|
+
grep -qF '${sshPublicKey.trim().replace(/'/g, "'\\''")}' /root/.ssh/authorized_keys 2>/dev/null || echo '${sshPublicKey.trim().replace(/'/g, "'\\''")}' >> /root/.ssh/authorized_keys
|
|
100
|
+
chmod 600 /root/.ssh/authorized_keys` : "# No SSH public key provided — skipping re-injection"}
|
|
101
|
+
|
|
102
|
+
# Wait for services
|
|
103
|
+
echo "Waiting for Dokploy services to start..."
|
|
104
|
+
sleep 30
|
|
105
|
+
|
|
106
|
+
echo "=================================="
|
|
107
|
+
echo "Dokploy installation completed!"
|
|
108
|
+
echo "=================================="
|
|
109
|
+
echo ""
|
|
110
|
+
echo "Please wait 3-5 more minutes for Dokploy to fully initialize."
|
|
111
|
+
echo "Then access your instance at: http://YOUR_SERVER_IP:3000"
|
|
112
112
|
`;
|
|
113
113
|
}
|
|
114
114
|
async healthCheck(ip, domain) {
|
|
@@ -21,26 +21,26 @@ export function formatBadge(result) {
|
|
|
21
21
|
const labelWidth = 62;
|
|
22
22
|
const valueWidth = 48;
|
|
23
23
|
const totalWidth = labelWidth + valueWidth;
|
|
24
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="20" role="img" aria-label="security: ${value}">
|
|
25
|
-
<title>security: ${value}</title>
|
|
26
|
-
<linearGradient id="s" x2="0" y2="100%">
|
|
27
|
-
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
|
28
|
-
<stop offset="1" stop-opacity=".1"/>
|
|
29
|
-
</linearGradient>
|
|
30
|
-
<clipPath id="r">
|
|
31
|
-
<rect width="${totalWidth}" height="20" rx="3" fill="#fff"/>
|
|
32
|
-
</clipPath>
|
|
33
|
-
<g clip-path="url(#r)">
|
|
34
|
-
<rect width="${labelWidth}" height="20" fill="#555"/>
|
|
35
|
-
<rect x="${labelWidth}" width="${valueWidth}" height="20" fill="${color}"/>
|
|
36
|
-
<rect width="${totalWidth}" height="20" fill="url(#s)"/>
|
|
37
|
-
</g>
|
|
38
|
-
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
|
|
39
|
-
<text aria-hidden="true" x="${labelWidth * 5}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="${(labelWidth - 10) * 10}">security</text>
|
|
40
|
-
<text x="${labelWidth * 5}" y="140" transform="scale(.1)" fill="#fff" textLength="${(labelWidth - 10) * 10}">security</text>
|
|
41
|
-
<text aria-hidden="true" x="${(labelWidth + valueWidth / 2) * 10}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="${(valueWidth - 10) * 10}">${value}</text>
|
|
42
|
-
<text x="${(labelWidth + valueWidth / 2) * 10}" y="140" transform="scale(.1)" fill="#fff" textLength="${(valueWidth - 10) * 10}">${value}</text>
|
|
43
|
-
</g>
|
|
24
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${totalWidth}" height="20" role="img" aria-label="security: ${value}">
|
|
25
|
+
<title>security: ${value}</title>
|
|
26
|
+
<linearGradient id="s" x2="0" y2="100%">
|
|
27
|
+
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
|
28
|
+
<stop offset="1" stop-opacity=".1"/>
|
|
29
|
+
</linearGradient>
|
|
30
|
+
<clipPath id="r">
|
|
31
|
+
<rect width="${totalWidth}" height="20" rx="3" fill="#fff"/>
|
|
32
|
+
</clipPath>
|
|
33
|
+
<g clip-path="url(#r)">
|
|
34
|
+
<rect width="${labelWidth}" height="20" fill="#555"/>
|
|
35
|
+
<rect x="${labelWidth}" width="${valueWidth}" height="20" fill="${color}"/>
|
|
36
|
+
<rect width="${totalWidth}" height="20" fill="url(#s)"/>
|
|
37
|
+
</g>
|
|
38
|
+
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
|
|
39
|
+
<text aria-hidden="true" x="${labelWidth * 5}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="${(labelWidth - 10) * 10}">security</text>
|
|
40
|
+
<text x="${labelWidth * 5}" y="140" transform="scale(.1)" fill="#fff" textLength="${(labelWidth - 10) * 10}">security</text>
|
|
41
|
+
<text aria-hidden="true" x="${(labelWidth + valueWidth / 2) * 10}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="${(valueWidth - 10) * 10}">${value}</text>
|
|
42
|
+
<text x="${(labelWidth + valueWidth / 2) * 10}" y="140" transform="scale(.1)" fill="#fff" textLength="${(valueWidth - 10) * 10}">${value}</text>
|
|
43
|
+
</g>
|
|
44
44
|
</svg>`;
|
|
45
45
|
}
|
|
46
46
|
//# sourceMappingURL=badge.js.map
|