@@ -35,7 +35,6 @@ class InstallationInfo:
3535
3636
3737def get_installation_info () -> InstallationInfo :
38- # Check system installation but handle permission errors gracefully
3938 try :
4039 if MARKER_SYSTEM .exists ():
4140 try :
@@ -136,28 +135,32 @@ def create_directories(server_dir: pl.Path) -> None:
136135 (server_dir / "jobs" ).mkdir (parents = True , exist_ok = True )
137136
138137
139- def create_server_user () -> bool :
138+ def create_server_user (sup_groups : list [str ] | None = None ) -> bool :
139+ user_exists = False
140140 try :
141141 pwd .getpwnam (SERVER_USER )
142- return False
142+ user_exists = True
143143 except KeyError :
144144 subprocess .run (["useradd" , "--system" , "--create-home" , "--shell" , "/bin/bash" , SERVER_USER ], check = True )
145- return True
145+
146+ if sup_groups :
147+ for grp in sup_groups :
148+ subprocess .run (["usermod" , "-aG" , grp , SERVER_USER ], check = True )
149+ print (f"Added supplementary groups: { ', ' .join (sup_groups )} to user { SERVER_USER } ." )
150+
151+ return not user_exists
146152
147153
148154def setup_shared_screen_dir () -> bool :
149- """Create a shared screen socket directory that all users can access."""
150155 screen_dir = pl .Path ("/tmp/screen_nexus" )
151156 if not screen_dir .exists ():
152157 screen_dir .mkdir (parents = True , exist_ok = True )
153- # Mode 1777 = sticky bit + rwxrwxrwx (world-writable with sticky bit)
154158 os .chmod (screen_dir , 0o1777 )
155159 return True
156160 return False
157161
158162
159163def setup_passwordless_nexus_attach () -> bool :
160- """Set up passwordless sudo access to attach to nexus screen sessions."""
161164 sudoers_file = pl .Path ("/etc/sudoers.d/nexus_attach" )
162165 content = "ALL ALL=(nexus) NOPASSWD: /usr/bin/screen -r *\n "
163166
@@ -174,10 +177,10 @@ def set_system_permissions() -> None:
174177 subprocess .run (["chmod" , "-R" , "770" , str (SYSTEM_SERVER_DIR )], check = True )
175178
176179
177- def setup_systemd_server () -> tuple [bool , str | None ]:
180+ def setup_systemd_server (sup_groups : list [ str ] | None = None ) -> tuple [bool , str | None ]:
178181 from nexus .server .installation import systemd
179182
180- server_content = systemd .get_service_file_content ()
183+ server_content = systemd .get_service_file_content (sup_groups )
181184 dest_server = SYSTEMD_DIR / SYSTEMD_SERVICE_FILENAME
182185 dest_server .write_text (server_content )
183186 return True , None
@@ -200,8 +203,8 @@ def manage_systemd_server(action: str) -> bool:
200203 return False
201204
202205
203- def install_system_server () -> None :
204- server_ok , server_error = setup_systemd_server ()
206+ def install_system_server (sup_groups : list [ str ] | None = None ) -> None :
207+ server_ok , server_error = setup_systemd_server (sup_groups )
205208 if not server_ok :
206209 sys .exit (server_error )
207210 print (f"Installed server file to: { SYSTEMD_DIR / SYSTEMD_SERVICE_FILENAME } " )
@@ -315,7 +318,6 @@ def remove_installation_files(keep_config: bool) -> None:
315318
316319
317320def check_running_processes () -> list [int ]:
318- """Check if there are any processes running as the nexus user."""
319321 try :
320322 result = subprocess .run (["pgrep" , "-u" , SERVER_USER ], capture_output = True , text = True )
321323 if result .returncode == 0 :
@@ -326,7 +328,6 @@ def check_running_processes() -> list[int]:
326328
327329
328330def terminate_user_processes (yes_flag : bool = False ) -> bool :
329- """Terminate all processes running as the nexus user."""
330331 pids = check_running_processes ()
331332 if not pids :
332333 return True
@@ -340,14 +341,10 @@ def terminate_user_processes(yes_flag: bool = False) -> bool:
340341 return False
341342
342343 try :
343- # First try SIGTERM
344344 subprocess .run (["pkill" , "-TERM" , "-u" , SERVER_USER ], check = False )
345- # Wait a moment
346345 time .sleep (1 )
347- # Check if any processes are still running
348346 remaining_pids = check_running_processes ()
349347 if remaining_pids :
350- # If yes flag is set or user agreed, use SIGKILL
351348 if yes_flag or input ("Some processes are still running. Use force kill? [y/N]: " ).strip ().lower () == "y" :
352349 subprocess .run (["pkill" , "-KILL" , "-u" , SERVER_USER ], check = False )
353350 time .sleep (0.5 )
@@ -401,11 +398,19 @@ def check_installation_prerequisites(force: bool = False) -> None:
401398 sys .exit (f"Nexus server is already installed in system mode (version { info .version } )." )
402399
403400
404- def prepare_system_environment () -> None :
401+ def prompt_for_supplementary_groups () -> list [str ]:
402+ groups_input = input (
403+ "Enter supplementary groups to add to the nexus user (comma-separated, or leave empty for none): "
404+ ).strip ()
405+ if groups_input :
406+ return [grp .strip () for grp in groups_input .split ("," ) if grp .strip ()]
407+ return []
408+
409+ def prepare_system_environment (sup_groups : list [str ] | None = None ) -> None :
405410 create_directories (SYSTEM_SERVER_DIR )
406411 print (f"Created system directory: { SYSTEM_SERVER_DIR } " )
407412
408- if create_server_user ():
413+ if create_server_user (sup_groups ):
409414 print (f"Created { SERVER_USER } system user." )
410415 else :
411416 print (f"User '{ SERVER_USER } ' already exists." )
@@ -436,7 +441,12 @@ def install_system(
436441 check_installation_prerequisites (force )
437442
438443 print ("Installing Nexus server in system mode..." )
439- prepare_system_environment ()
444+
445+ sup_groups = []
446+ if interactive :
447+ sup_groups = prompt_for_supplementary_groups ()
448+
449+ prepare_system_environment (sup_groups )
440450
441451 _config = setup_config (SYSTEM_SERVER_DIR , interactive , config_file )
442452 create_persistent_directory (_config )
@@ -445,7 +455,11 @@ def install_system(
445455 set_system_permissions ()
446456 print ("Set proper directory permissions." )
447457
448- install_system_server ()
458+ server_ok , server_error = setup_systemd_server (sup_groups )
459+ if not server_ok :
460+ sys .exit (server_error )
461+ print (f"Installed server file to: { SYSTEMD_DIR / SYSTEMD_SERVICE_FILENAME } " )
462+
449463 server_started = False
450464 if start_server :
451465 server_started = start_system_server ()
@@ -469,7 +483,6 @@ def uninstall(keep_config: bool = False, force: bool = False, yes: bool = False)
469483 remove_system_components ()
470484 remove_installation_files (keep_config )
471485
472- # Check and terminate processes before removing user
473486 if not terminate_user_processes (yes_flag = yes ):
474487 print (f"\n Cannot remove { SERVER_USER } user while processes are still running." )
475488 print ("Please terminate these processes manually or run with --yes to force termination." )
@@ -658,4 +671,4 @@ def initialize_context(server_dir: pl.Path | None) -> context.NexusServerContext
658671 _logger = logger .create_logger (log_dir , name = "nexus_server" , log_level = _config .log_level )
659672 _db = db .create_connection (_logger , db_path = db_path )
660673
661- return context .NexusServerContext (db = _db , config = _config , logger = _logger )
674+ return context .NexusServerContext (db = _db , config = _config , logger = _logger )
0 commit comments