@@ -238,6 +238,7 @@ def start_pixiecore(
238238class Options :
239239 flake : str
240240 netboot_image_flake : str
241+ skip_firewall : bool
241242 dhcp_interface : str
242243 dhcp_server_ip : ipaddress .IPv4Address
243244 dhcp_subnet : int
@@ -247,6 +248,45 @@ class Options:
247248 nixos_anywhere_args : list [str ]
248249
249250
251+ @contextmanager
252+ def open_firewall (options : Options ) -> Iterator [None ]:
253+ if options .skip_firewall :
254+ yield
255+ return
256+
257+ ports = [
258+ [p ]
259+ for p in [f"tcp/{ options .pixiecore_http_port } " , "67/udp" , "69/udp" , "4011/udp" ]
260+ ]
261+ if shutil .which ("nixos-firewall-tool" ) is not None :
262+ command_prefix = ["nixos-firewall-tool" , "open" ]
263+ ports = [p [0 ].split ("/" ) for p in ports ]
264+ reset_command = ["nixos-firewall-tool" , "reset" ]
265+ elif shutil .which ("ufw" ) is not None :
266+ command_prefix = ["ufw" , "allow" ]
267+ reset_command = ["ufw" , "reload" ]
268+ elif shutil .which ("firewall-cmd" ) is not None :
269+ command_prefix = ["firewall-cmd" , "--add-port" ]
270+ reset_command = ["firewall-cmd" , "--reload" ]
271+ else :
272+ print (
273+ f"No firewall tool found. Please make sure that the following ports are open: 67/udp, 69/udp, 4011/udp, and { options .pixiecore_http_port } /tcp" ,
274+ file = sys .stderr ,
275+ )
276+ yield
277+ return
278+
279+ try :
280+ for port in ports :
281+ subprocess .run ([* command_prefix , * port ], check = True )
282+ yield
283+ finally :
284+ if subprocess .run (reset_command , check = True ).returncode != 0 :
285+ print (
286+ "failed to reset firewall rules, see above for details" , file = sys .stderr
287+ )
288+
289+
250290def die (msg : str ) -> NoReturn :
251291 print (msg , file = sys .stderr )
252292 sys .exit (1 )
@@ -287,6 +327,11 @@ def parse_args(args: list[str]) -> Options:
287327 help = "Whether to wait for user confirmation before tearing down the network setup once the installation completed" ,
288328 action = "store_true" ,
289329 )
330+ parser .add_argument (
331+ "--skip-firewall" ,
332+ help = "Skip opening firewall ports" ,
333+ action = "store_true" ,
334+ )
290335
291336 parsed , unknown_args = parser .parse_known_args (args )
292337 try :
@@ -318,6 +363,7 @@ def parse_args(args: list[str]) -> Options:
318363
319364 return Options (
320365 flake = parsed .flake ,
366+ skip_firewall = parsed .skip_firewall ,
321367 netboot_image_flake = parsed .netboot_image_flake ,
322368 dhcp_server_ip = dhcp_server_ip ,
323369 dhcp_subnet = dhcp_subnet .prefixlen ,
@@ -464,6 +510,7 @@ def run_nixos_anywhere(options: Options) -> None:
464510 f"{ options .dhcp_server_ip } /{ options .dhcp_subnet } " ,
465511 ),
466512 ssh_private_key () as ssh_key ,
513+ open_firewall (options ),
467514 start_pixiecore (
468515 options .dhcp_server_ip ,
469516 options .pixiecore_http_port ,
0 commit comments