@@ -18,13 +18,13 @@ interface SshKeyPair {
1818
1919type PresetId =
2020 | "install3xui"
21+ | "sshKey"
2122 | "ipReputation"
2223 | "bbr"
2324 | "benchmark"
2425 | "region"
2526 | "hardenSsh"
26- | "ufw"
27- | "sshKey" ;
27+ | "ufw" ;
2828
2929interface PresetItem {
3030 id : PresetId ;
@@ -36,6 +36,13 @@ interface PresetItem {
3636}
3737
3838const presets : PresetItem [ ] = [
39+ {
40+ id : "sshKey" ,
41+ name : "Copy SSH public key" ,
42+ description : "Adds a selected ~/.ssh public key to authorized_keys on the server." ,
43+ command : "" ,
44+ recommended : true ,
45+ } ,
3946 {
4047 id : "install3xui" ,
4148 name : "Install 3x-ui panel" ,
@@ -79,9 +86,9 @@ const presets: PresetItem[] = [
7986 {
8087 id : "hardenSsh" ,
8188 name : "Harden SSH" ,
82- description : "Disables password auth, enables public key auth, and restarts SSH." ,
89+ description : "Requires an authorized key, disables password auth, and restarts SSH." ,
8390 command :
84- "for file in /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf; do [ -f \"$file\" ] || continue; sed -i -E 's/^[#[:space:]]*PasswordAuthentication[[:space:]]+.*/PasswordAuthentication no/' \"$file\"; sed -i -E 's/^[#[:space:]]*PubkeyAuthentication[[:space:]]+.*/PubkeyAuthentication yes/' \"$file\"; sed -i -E 's/^[#[:space:]]*KbdInteractiveAuthentication[[:space:]]+.*/KbdInteractiveAuthentication no/' \"$file\"; done; printf 'PasswordAuthentication no\\nPubkeyAuthentication yes\\nKbdInteractiveAuthentication no\\n' > /etc/ssh/sshd_config.d/99-nodenet-hardening.conf && sshd -t && systemctl restart ssh" ,
91+ "test -s ~/.ssh/authorized_keys || { echo 'No SSH public key found in ~/.ssh/authorized_keys. Run Copy SSH public key first.' >&2; exit 1; }; for file in /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf; do [ -f \"$file\" ] || continue; sed -i -E 's/^[#[:space:]]*PasswordAuthentication[[:space:]]+.*/PasswordAuthentication no/' \"$file\"; sed -i -E 's/^[#[:space:]]*PubkeyAuthentication[[:space:]]+.*/PubkeyAuthentication yes/' \"$file\"; sed -i -E 's/^[#[:space:]]*KbdInteractiveAuthentication[[:space:]]+.*/KbdInteractiveAuthentication no/' \"$file\"; done; printf 'PasswordAuthentication no\\nPubkeyAuthentication yes\\nKbdInteractiveAuthentication no\\n' > /etc/ssh/sshd_config.d/99-nodenet-hardening.conf && sshd -t && ( systemctl restart ssh || systemctl restart sshd) " ,
8592 recommended : true ,
8693 } ,
8794 {
@@ -92,13 +99,6 @@ const presets: PresetItem[] = [
9299 recommended : true ,
93100 outputWindow : true ,
94101 } ,
95- {
96- id : "sshKey" ,
97- name : "Copy SSH public key" ,
98- description : "Adds a selected ~/.ssh public key to authorized_keys on the server." ,
99- command : "" ,
100- recommended : true ,
101- } ,
102102] ;
103103
104104export default function SetupPresets ( { server, onPanelInfoSaved, onServerUpdated, onDone } : SetupPresetsProps ) {
@@ -147,7 +147,7 @@ export default function SetupPresets({ server, onPanelInfoSaved, onServerUpdated
147147 setNewKeyName ( `nodenet_${ server . id } _ed25519` ) ;
148148 } , [ server . id ] ) ;
149149
150- const runPreset = async ( preset : PresetItem ) => {
150+ const runPreset = async ( preset : PresetItem , rethrow = false ) => {
151151 setError ( "" ) ;
152152 setMessage ( "" ) ;
153153 setRunning ( preset . id ) ;
@@ -175,7 +175,11 @@ export default function SetupPresets({ server, onPanelInfoSaved, onServerUpdated
175175 setShowPanelCredentialPrompt ( true ) ;
176176 }
177177 } catch ( err ) {
178- setError ( err instanceof Error ? err . message : String ( err ) ) ;
178+ const error = err instanceof Error ? err : new Error ( String ( err ) ) ;
179+ setError ( error . message ) ;
180+ if ( rethrow ) {
181+ throw error ;
182+ }
179183 } finally {
180184 setRunning ( null ) ;
181185 }
@@ -188,7 +192,7 @@ export default function SetupPresets({ server, onPanelInfoSaved, onServerUpdated
188192 try {
189193 for ( const preset of presets ) {
190194 if ( selected [ preset . id ] ) {
191- await runPreset ( preset ) ;
195+ await runPreset ( preset , true ) ;
192196 }
193197 }
194198 if ( selected . install3xui ) {
@@ -207,16 +211,18 @@ export default function SetupPresets({ server, onPanelInfoSaved, onServerUpdated
207211 throw new Error ( "Your management IP is required before configuring UFW." ) ;
208212 }
209213 const ip = shellQuote ( managementIp . trim ( ) ) ;
214+ const sshPort = Math . max ( 1 , Math . min ( 65535 , Math . round ( server . sshPort || 22 ) ) ) ;
210215 return [
211216 "if ! command -v ufw >/dev/null 2>&1; then apt-get update && apt-get install -y ufw; fi" ,
212- `ufw allow from ${ ip } to any port 22` ,
213- "ufw delete allow 22/tcp || true" ,
217+ `ufw allow from ${ ip } to any port ${ sshPort } ` ,
218+ `ufw delete allow ${ sshPort } /tcp || true` ,
219+ sshPort === 22 ? "" : "ufw delete allow 22/tcp || true" ,
214220 "ufw allow 65333/tcp" ,
215221 "ufw allow 443/tcp" ,
216222 "yes | ufw enable" ,
217223 "ufw reload" ,
218224 "ufw status verbose" ,
219- ] . join ( " && " ) ;
225+ ] . filter ( Boolean ) . join ( " && " ) ;
220226 }
221227
222228 if ( preset . id === "sshKey" ) {
0 commit comments