machineconfig 6.82__py3-none-any.whl → 8.51__py3-none-any.whl
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.
- machineconfig/cluster/remote/cloud_manager.py +1 -1
- machineconfig/cluster/remote/run_cluster.py +1 -1
- machineconfig/cluster/remote/run_remote.py +1 -1
- machineconfig/cluster/sessions_managers/utils/maker.py +29 -15
- machineconfig/cluster/sessions_managers/wt_local.py +17 -222
- machineconfig/cluster/sessions_managers/wt_local_manager.py +56 -194
- machineconfig/cluster/sessions_managers/wt_remote_manager.py +42 -198
- machineconfig/cluster/sessions_managers/wt_utils/manager_persistence.py +52 -0
- machineconfig/cluster/sessions_managers/wt_utils/monitoring_helpers.py +50 -0
- machineconfig/cluster/sessions_managers/wt_utils/status_reporting.py +76 -0
- machineconfig/cluster/sessions_managers/wt_utils/wt_helpers.py +199 -0
- machineconfig/cluster/sessions_managers/zellij_local.py +1 -1
- machineconfig/cluster/sessions_managers/zellij_local_manager.py +4 -2
- machineconfig/cluster/sessions_managers/zellij_remote_manager.py +3 -2
- machineconfig/cluster/sessions_managers/zellij_utils/process_monitor.py +2 -2
- machineconfig/jobs/installer/checks/check_installations.py +133 -0
- machineconfig/jobs/installer/checks/install_utils.py +132 -0
- machineconfig/jobs/installer/checks/report_utils.py +39 -0
- machineconfig/jobs/installer/checks/vt_utils.py +89 -0
- machineconfig/jobs/installer/installer_data.json +1500 -310
- machineconfig/jobs/installer/linux_scripts/docker.sh +6 -9
- machineconfig/jobs/installer/linux_scripts/q.sh +10 -7
- machineconfig/jobs/installer/linux_scripts/redis.sh +1 -0
- machineconfig/jobs/installer/package_groups.py +62 -91
- machineconfig/jobs/installer/powershell_scripts/install_fonts.ps1 +129 -34
- machineconfig/jobs/installer/{custom → python_scripts}/boxes.py +2 -3
- machineconfig/jobs/installer/{custom_dev → python_scripts}/brave.py +5 -3
- machineconfig/jobs/installer/python_scripts/cloudflare_warp_cli.py +23 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/code.py +14 -9
- machineconfig/jobs/installer/{custom_dev → python_scripts}/dubdb_adbc.py +1 -1
- machineconfig/jobs/installer/python_scripts/hx.py +214 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/nerdfont.py +2 -2
- machineconfig/jobs/installer/{custom_dev → python_scripts}/nerfont_windows_helper.py +32 -26
- machineconfig/jobs/installer/python_scripts/sysabc.py +145 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/wezterm.py +2 -19
- machineconfig/jobs/installer/{custom_dev → python_scripts}/winget.py +10 -14
- machineconfig/jobs/installer/python_scripts/yazi.py +139 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nfs +0 -1
- machineconfig/jobs/scripts/powershell_scripts/cmatrix.ps1 +52 -0
- machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +13 -0
- machineconfig/jobs/scripts/powershell_scripts/obs.ps1 +4 -0
- machineconfig/jobs/scripts_dynamic/a.py +428 -0
- machineconfig/logger.py +1 -2
- machineconfig/profile/create_helper.py +56 -18
- machineconfig/profile/create_links.py +79 -21
- machineconfig/profile/create_links_export.py +87 -36
- machineconfig/profile/create_shell_profile.py +92 -127
- machineconfig/profile/mapper_data.toml +45 -0
- machineconfig/profile/mapper_dotfiles.toml +249 -0
- machineconfig/scripts/__init__.py +0 -4
- machineconfig/scripts/linux/wrap_mcfg +46 -0
- machineconfig/scripts/nu/wrap_mcfg.nu +69 -0
- machineconfig/scripts/python/agents.py +85 -165
- machineconfig/scripts/python/ai/initai.py +4 -2
- machineconfig/scripts/python/ai/scripts/__init__.py +1 -0
- machineconfig/scripts/python/ai/scripts/command_runner.ps1 +33 -0
- machineconfig/scripts/python/ai/{command_runner → scripts}/command_runner.sh +1 -1
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.ps1 +2 -0
- machineconfig/scripts/python/ai/scripts/lint_and_type_check.sh +8 -6
- machineconfig/scripts/python/ai/solutions/claude/claude.py +1 -1
- machineconfig/scripts/python/ai/solutions/cline/cline.py +1 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Thinking-Beast-Mode.chatmode.md → agents/Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/Ultimate-Transparent-Thinking-Beast-Mode.chatmode.md → agents/Ultimate-Transparent-Thinking-Beast-Mode.agent.md} +0 -1
- machineconfig/scripts/python/ai/solutions/copilot/{chatmodes/deepResearch.chatmode.md → agents/deepResearch.agent.md} +2 -2
- machineconfig/scripts/python/ai/solutions/copilot/github_copilot.py +6 -6
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/dev.instructions.md +33 -0
- machineconfig/scripts/python/ai/solutions/copilot/instructions/python/watch_exec.prompt.md +20 -0
- machineconfig/scripts/python/ai/solutions/crush/crush.py +1 -1
- machineconfig/scripts/python/ai/solutions/cursor/cursors.py +1 -1
- machineconfig/scripts/python/ai/solutions/gemini/gemini.py +1 -1
- machineconfig/scripts/python/ai/solutions/gemini/settings.json +3 -0
- machineconfig/scripts/python/ai/{generate_files.py → utils/generate_files.py} +2 -2
- machineconfig/scripts/python/ai/{solutions → utils}/generic.py +2 -15
- machineconfig/scripts/python/ai/{vscode_tasks.py → utils/vscode_tasks.py} +13 -5
- machineconfig/scripts/python/cloud.py +58 -11
- machineconfig/scripts/python/croshell.py +10 -162
- machineconfig/scripts/python/devops.py +73 -36
- machineconfig/scripts/python/devops_navigator.py +16 -6
- machineconfig/scripts/python/fire_jobs.py +8 -222
- machineconfig/scripts/python/ftpx.py +7 -200
- machineconfig/scripts/python/graph/cli_graph.json +8743 -0
- machineconfig/scripts/python/{env_manager → helper_env}/path_manager_tui.py +2 -2
- machineconfig/scripts/python/helpers/helper_env/env_manager_tui.py +204 -0
- machineconfig/scripts/python/helpers/helper_env/path_manager_tui.py +228 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_crush.json +1 -1
- machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_crush.py +39 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/fire_cursor_agents.py +3 -4
- machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_gemini.py +55 -0
- machineconfig/scripts/python/helpers/helpers_agents/agentic_frameworks/fire_qwen.py +30 -0
- machineconfig/scripts/python/helpers/helpers_agents/agents_impl.py +168 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_launch.py +38 -16
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_helper_types.py +11 -14
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aichat/config.yaml +5 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/aider/.aider.conf.yml +2 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/copilot/config.yml +1 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/crush/crush.json +10 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/configs/gemini/settings.json +12 -0
- machineconfig/scripts/python/helpers/helpers_agents/privacy/privacy.py +109 -0
- machineconfig/scripts/python/helpers/helpers_agents/templates/prompt.txt +10 -0
- machineconfig/scripts/python/helpers/helpers_agents/templates/template.sh +34 -0
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_copy.py +32 -25
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_mount.py +29 -22
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_sync.py +9 -8
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers2.py +1 -1
- machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/crosh.py +3 -3
- machineconfig/scripts/python/helpers/helpers_croshell/croshell_impl.py +225 -0
- machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/scheduler.py +4 -4
- machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/start_slidev.py +12 -12
- machineconfig/scripts/python/helpers/helpers_devops/backup_config.py +149 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_backup_retrieve.py +262 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_config.py +98 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_config_dotfile.py +274 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_data.py +67 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_nw.py +201 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_repos.py +274 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_self.py +197 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_share_file.py +151 -0
- machineconfig/scripts/python/helpers/helpers_devops/cli_share_server.py +125 -0
- machineconfig/scripts/python/{helpers_devops/cli_terminal.py → helpers/helpers_devops/cli_share_terminal.py} +26 -22
- machineconfig/scripts/python/helpers/helpers_devops/cli_ssh.py +167 -0
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_status.py +17 -23
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/devops_update_repos.py +1 -1
- machineconfig/scripts/python/{interactive.py → helpers/helpers_devops/interactive.py} +78 -71
- machineconfig/scripts/python/helpers/helpers_devops/run_script.py +197 -0
- machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.ps1 +41 -0
- machineconfig/scripts/python/helpers/helpers_devops/themes/choose_starship_theme.sh +48 -0
- machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_wezterm_theme.py +4 -4
- machineconfig/scripts/python/{helpers_fire/helpers4.py → helpers/helpers_fire_command/file_wrangler.py} +57 -20
- machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_args_helper.py +1 -0
- machineconfig/scripts/python/helpers/helpers_fire_command/fire_jobs_impl.py +233 -0
- machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/fire_jobs_route_helper.py +26 -16
- machineconfig/scripts/python/helpers/helpers_msearch/__init__.py +5 -0
- machineconfig/scripts/python/helpers/helpers_msearch/msearch_impl.py +248 -0
- machineconfig/scripts/{linux → python/helpers/helpers_msearch/scripts_linux}/fzfg +6 -5
- machineconfig/scripts/python/helpers/helpers_msearch/scripts_linux/search_with_context.sh +48 -0
- machineconfig/scripts/python/helpers/helpers_msearch/scripts_windows/fzfg.ps1 +59 -0
- machineconfig/scripts/python/helpers/helpers_navigator/__init__.py +20 -0
- machineconfig/scripts/python/helpers/helpers_navigator/cli_graph_loader.py +234 -0
- machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/command_builder.py +61 -13
- machineconfig/scripts/python/helpers/helpers_navigator/command_detail.py +153 -0
- machineconfig/scripts/python/helpers/helpers_navigator/command_tree.py +45 -0
- machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/data_models.py +18 -11
- machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/main_app.py +5 -5
- machineconfig/scripts/python/helpers/helpers_network/address.py +174 -0
- machineconfig/scripts/python/helpers/helpers_network/address_switch.py +78 -0
- machineconfig/scripts/python/helpers/helpers_network/ftpx_impl.py +276 -0
- machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nfs.py +2 -2
- machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_ssh.py +3 -3
- machineconfig/scripts/python/helpers/helpers_network/ssh_add_identity.py +73 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh_add_ssh_key.py +175 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh_debug_linux.py +319 -0
- machineconfig/scripts/python/helpers/helpers_network/ssh_debug_windows.py +275 -0
- machineconfig/scripts/python/{nw → helpers/helpers_network}/wifi_conn.py +1 -53
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action.py +3 -3
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/action_helper.py +3 -3
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/clone.py +0 -1
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/cloud_repo_sync.py +159 -48
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/grource.py +4 -3
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/record.py +33 -12
- machineconfig/scripts/python/helpers/helpers_repos/repo_analyzer_1.py +160 -0
- machineconfig/scripts/python/{helpers_repos/count_lines.py → helpers/helpers_repos/repo_analyzer_2.py} +156 -191
- machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/update.py +0 -6
- machineconfig/scripts/python/helpers/helpers_search/ast_search.py +74 -0
- machineconfig/scripts/python/helpers/helpers_search/qr_code.py +166 -0
- machineconfig/scripts/python/helpers/helpers_search/repo_rag.py +325 -0
- machineconfig/scripts/python/helpers/helpers_search/script_help.py +81 -0
- machineconfig/scripts/python/helpers/helpers_search/symantic_search.py +25 -0
- machineconfig/scripts/python/helpers/helpers_sessions/__init__.py +0 -0
- machineconfig/scripts/python/helpers/helpers_sessions/sessions_impl.py +186 -0
- machineconfig/scripts/python/{helpers_sessions → helpers/helpers_sessions}/sessions_multiprocess.py +20 -14
- machineconfig/scripts/python/helpers/helpers_terminal/__init__.py +0 -0
- machineconfig/scripts/python/helpers/helpers_terminal/terminal_impl.py +96 -0
- machineconfig/scripts/python/helpers/helpers_utils/download.py +150 -0
- machineconfig/scripts/python/helpers/helpers_utils/pdf.py +96 -0
- machineconfig/scripts/python/helpers/helpers_utils/python.py +210 -0
- machineconfig/scripts/python/helpers/helpers_utils/specs.py +246 -0
- machineconfig/scripts/python/mcfg_entry.py +143 -0
- machineconfig/scripts/python/msearch.py +26 -0
- machineconfig/scripts/python/sessions.py +69 -135
- machineconfig/scripts/python/terminal.py +58 -0
- machineconfig/scripts/python/utils.py +115 -38
- machineconfig/scripts/windows/wrap_mcfg.ps1 +63 -0
- machineconfig/settings/atuin/config.toml +294 -0
- machineconfig/settings/atuin/themes/catppuccin-mocha-mauve.toml +12 -0
- machineconfig/settings/broot/conf.toml +1 -1
- machineconfig/settings/helix/config.toml +16 -0
- machineconfig/settings/helix/languages.toml +13 -4
- machineconfig/settings/helix/yazi-picker.sh +12 -0
- machineconfig/settings/lf/linux/exe/lfcd.sh +1 -0
- machineconfig/settings/lf/linux/exe/previewer.sh +3 -2
- machineconfig/settings/lf/windows/lfcd.ps1 +1 -1
- machineconfig/settings/lf/windows/lfrc +14 -16
- machineconfig/settings/linters/.ruff.toml +2 -1
- machineconfig/settings/marimo/marimo.toml +1 -1
- machineconfig/settings/marimo/snippets/globalize.py +34 -0
- machineconfig/settings/mprocs/windows/mprocs.yaml +2 -2
- machineconfig/settings/shells/bash/init.sh +47 -12
- machineconfig/settings/shells/ipy/profiles/default/startup/playext.py +1 -1
- machineconfig/settings/shells/nushell/config.nu +25 -33
- machineconfig/settings/shells/nushell/env.nu +21 -8
- machineconfig/settings/shells/nushell/init.nu +138 -0
- machineconfig/settings/shells/pwsh/init.ps1 +111 -17
- machineconfig/settings/shells/pwsh/search_pwsh_history.ps1 +99 -0
- machineconfig/settings/shells/starship/starship.toml +16 -0
- machineconfig/settings/shells/wezterm/wezterm.lua +6 -1
- machineconfig/settings/shells/wt/settings.json +27 -18
- machineconfig/settings/shells/zsh/init.sh +42 -23
- machineconfig/settings/television/cable_unix/alias.toml +8 -0
- machineconfig/settings/television/cable_unix/aws-buckets.toml +14 -0
- machineconfig/settings/television/cable_unix/aws-instances.toml +13 -0
- machineconfig/settings/television/cable_unix/bash-history.toml +8 -0
- machineconfig/settings/television/cable_unix/channels.toml +19 -0
- machineconfig/settings/television/cable_unix/dirs.toml +13 -0
- machineconfig/settings/television/cable_unix/distrobox-list.toml +42 -0
- machineconfig/settings/television/cable_unix/docker-images.toml +13 -0
- machineconfig/settings/television/cable_unix/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_unix/env.toml +17 -0
- machineconfig/settings/television/cable_unix/files.toml +11 -0
- machineconfig/settings/television/cable_unix/fish-history.toml +8 -0
- machineconfig/settings/television/cable_unix/git-branch.toml +11 -0
- machineconfig/settings/television/cable_unix/git-diff.toml +10 -0
- machineconfig/settings/television/cable_unix/git-log.toml +12 -0
- machineconfig/settings/television/cable_unix/git-reflog.toml +12 -0
- machineconfig/settings/television/cable_unix/git-repos.toml +16 -0
- machineconfig/settings/television/cable_unix/guix.toml +20 -0
- machineconfig/settings/television/cable_unix/just-recipes.toml +18 -0
- machineconfig/settings/television/cable_unix/k8s-deployments.toml +36 -0
- machineconfig/settings/television/cable_unix/k8s-pods.toml +50 -0
- machineconfig/settings/television/cable_unix/k8s-services.toml +36 -0
- machineconfig/settings/television/cable_unix/man-pages.toml +24 -0
- machineconfig/settings/television/cable_unix/nu-history.toml +7 -0
- machineconfig/settings/television/cable_unix/procs.toml +20 -0
- machineconfig/settings/television/cable_unix/text.toml +17 -0
- machineconfig/settings/television/cable_unix/tldr.toml +18 -0
- machineconfig/settings/television/cable_unix/zsh-history.toml +9 -0
- machineconfig/settings/television/cable_windows/alias.toml +7 -0
- machineconfig/settings/television/cable_windows/dirs.toml +13 -0
- machineconfig/settings/television/cable_windows/docker-images.toml +13 -0
- machineconfig/settings/television/cable_windows/dotfiles.toml +11 -0
- machineconfig/settings/television/cable_windows/env.toml +17 -0
- machineconfig/settings/television/cable_windows/files.toml +14 -0
- machineconfig/settings/television/cable_windows/git-branch.toml +11 -0
- machineconfig/settings/television/cable_windows/git-diff.toml +10 -0
- machineconfig/settings/television/cable_windows/git-log.toml +11 -0
- machineconfig/settings/television/cable_windows/git-reflog.toml +11 -0
- machineconfig/settings/television/cable_windows/git-repos.toml +15 -0
- machineconfig/settings/television/cable_windows/nu-history.toml +7 -0
- machineconfig/settings/television/cable_windows/pwsh-history.toml +6 -0
- machineconfig/settings/television/cable_windows/text.toml +17 -0
- machineconfig/settings/tv/config.toml +234 -0
- machineconfig/settings/tv/themes/catppuccin-mocha-sky.toml +22 -0
- machineconfig/settings/wsl/.wslconfig +5 -30
- machineconfig/settings/wt/__init__.py +0 -0
- machineconfig/settings/yazi/init.lua +61 -0
- machineconfig/settings/yazi/keymap_linux.toml +94 -0
- machineconfig/settings/yazi/keymap_windows.toml +78 -0
- machineconfig/settings/yazi/shell/yazi_cd.ps1 +33 -0
- machineconfig/settings/yazi/shell/yazi_cd.sh +8 -0
- machineconfig/settings/yazi/theme.toml +4 -0
- machineconfig/settings/yazi/yazi_linux.toml +94 -0
- machineconfig/settings/yazi/yazi_windows.toml +58 -0
- machineconfig/settings/zellij/layouts/st.kdl +40 -9
- machineconfig/settings/zellij/layouts/st2.kdl +1 -1
- machineconfig/setup_linux/__init__.py +2 -2
- machineconfig/setup_linux/apps_desktop.sh +8 -27
- machineconfig/setup_linux/web_shortcuts/interactive.sh +27 -12
- machineconfig/setup_linux/web_shortcuts/live_from_github.sh +34 -0
- machineconfig/setup_mac/__init__.py +1 -4
- machineconfig/setup_mac/apps_gui.sh +248 -0
- machineconfig/setup_windows/__init__.py +2 -5
- machineconfig/setup_windows/uv.ps1 +8 -1
- machineconfig/setup_windows/web_shortcuts/interactive.ps1 +28 -12
- machineconfig/setup_windows/web_shortcuts/live_from_github.ps1 +31 -0
- machineconfig/setup_windows/web_shortcuts/quick_init.ps1 +17 -0
- machineconfig/type_hinting/sql/__init__.py +1 -0
- machineconfig/type_hinting/sql/base.py +216 -0
- machineconfig/type_hinting/sql/core_schema.py +64 -0
- machineconfig/type_hinting/sql/core_schema_typeddict.py +41 -0
- machineconfig/type_hinting/sql/typeddict_codegen.py +222 -0
- machineconfig/type_hinting/typedict/__init__.py +1 -0
- machineconfig/type_hinting/typedict/ast_utils.py +130 -0
- machineconfig/type_hinting/typedict/generator_helpers.py +319 -0
- machineconfig/type_hinting/typedict/generators.py +231 -0
- machineconfig/type_hinting/typedict/polars_schema.py +24 -0
- machineconfig/type_hinting/typedict/polars_schema_typeddict.py +63 -0
- machineconfig/utils/accessories.py +31 -4
- machineconfig/utils/code.py +163 -51
- machineconfig/utils/files/ascii_art.py +11 -15
- machineconfig/utils/files/headers.py +6 -7
- machineconfig/utils/files/read.py +8 -1
- machineconfig/utils/installer_utils/github_release_bulk.py +95 -138
- machineconfig/utils/installer_utils/github_release_scraper.py +99 -0
- machineconfig/utils/installer_utils/install_from_url.py +183 -0
- machineconfig/utils/installer_utils/installer_class.py +53 -102
- machineconfig/utils/installer_utils/installer_cli.py +161 -0
- machineconfig/utils/installer_utils/installer_helper.py +129 -0
- machineconfig/utils/installer_utils/{installer_abc.py → installer_locator_utils.py} +42 -91
- machineconfig/utils/{installer.py → installer_utils/installer_runner.py} +20 -65
- machineconfig/utils/io.py +94 -9
- machineconfig/utils/links.py +56 -38
- machineconfig/utils/meta.py +38 -21
- machineconfig/utils/options.py +81 -23
- machineconfig/utils/options_utils/__init__.py +0 -0
- machineconfig/utils/options_utils/options_tv_linux.py +211 -0
- machineconfig/utils/options_utils/options_tv_windows.py +88 -0
- machineconfig/utils/options_utils/tv_options.py +37 -0
- machineconfig/utils/path_extended.py +52 -102
- machineconfig/utils/path_helper.py +76 -23
- machineconfig/utils/procs.py +1 -1
- machineconfig/utils/scheduler.py +26 -53
- machineconfig/utils/scheduling.py +0 -2
- machineconfig/utils/schemas/fire_agents/fire_agents_input.py +1 -1
- machineconfig/utils/schemas/layouts/layout_types.py +1 -1
- machineconfig/utils/source_of_truth.py +6 -1
- machineconfig/utils/ssh.py +216 -419
- machineconfig/utils/ssh_utils/abc.py +5 -0
- machineconfig/utils/ssh_utils/copy_from_here.py +116 -0
- machineconfig/utils/ssh_utils/copy_to_here.py +303 -0
- machineconfig/utils/ssh_utils/utils.py +158 -0
- machineconfig/utils/ssh_utils/wsl.py +147 -0
- machineconfig/utils/ssh_utils/wsl_helper.py +217 -0
- machineconfig/utils/terminal.py +1 -0
- machineconfig/utils/upgrade_packages.py +107 -35
- machineconfig/utils/ve.py +12 -4
- machineconfig-8.51.dist-info/METADATA +140 -0
- machineconfig-8.51.dist-info/RECORD +543 -0
- {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/entry_points.txt +4 -1
- machineconfig/jobs/installer/check_installations.py +0 -248
- machineconfig/jobs/installer/custom/hx.py +0 -140
- machineconfig/jobs/installer/linux_scripts/pgsql.sh +0 -41
- machineconfig/jobs/installer/linux_scripts/timescaledb.sh +0 -71
- machineconfig/jobs/installer/powershell_scripts/archive_pygraphviz.ps1 +0 -12
- machineconfig/jobs/installer/powershell_scripts/openssh-server_add_key.ps1 +0 -7
- machineconfig/jobs/installer/powershell_scripts/openssh-server_copy-ssh-id.ps1 +0 -14
- machineconfig/profile/backup.toml +0 -49
- machineconfig/profile/mapper.toml +0 -256
- machineconfig/scripts/linux/fzf2g +0 -21
- machineconfig/scripts/linux/fzfag +0 -17
- machineconfig/scripts/linux/fzffg +0 -25
- machineconfig/scripts/linux/fzfrga +0 -21
- machineconfig/scripts/linux/mcfgs +0 -38
- machineconfig/scripts/linux/other/share_smb +0 -1
- machineconfig/scripts/linux/other/switch_ip +0 -20
- machineconfig/scripts/linux/skrg +0 -4
- machineconfig/scripts/linux/warp-cli.sh +0 -122
- machineconfig/scripts/linux/z_ls +0 -104
- machineconfig/scripts/python/ai/command_runner/prompt.txt +0 -9
- machineconfig/scripts/python/helpers_devops/cli_config.py +0 -120
- machineconfig/scripts/python/helpers_devops/cli_config_dotfile.py +0 -77
- machineconfig/scripts/python/helpers_devops/cli_data.py +0 -25
- machineconfig/scripts/python/helpers_devops/cli_nw.py +0 -73
- machineconfig/scripts/python/helpers_devops/cli_repos.py +0 -181
- machineconfig/scripts/python/helpers_devops/cli_self.py +0 -122
- machineconfig/scripts/python/helpers_devops/cli_share_server.py +0 -104
- machineconfig/scripts/python/helpers_devops/cli_utils.py +0 -221
- machineconfig/scripts/python/helpers_devops/devops_backup_retrieve.py +0 -80
- machineconfig/scripts/python/helpers_devops/themes/choose_starship_theme.bash +0 -3
- machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_crush.py +0 -37
- machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_gemini.py +0 -44
- machineconfig/scripts/python/helpers_fire/agentic_frameworks/fire_qwen.py +0 -43
- machineconfig/scripts/python/helpers_fire/prompt.txt +0 -2
- machineconfig/scripts/python/helpers_fire/template.sh +0 -15
- machineconfig/scripts/python/helpers_navigator/__init__.py +0 -20
- machineconfig/scripts/python/helpers_navigator/command_detail.py +0 -44
- machineconfig/scripts/python/helpers_navigator/command_tree.py +0 -588
- machineconfig/scripts/python/helpers_repos/count_lines_frontend.py +0 -17
- machineconfig/scripts/python/helpers_repos/entrypoint.py +0 -76
- machineconfig/scripts/python/helpers_repos/secure_repo.py +0 -15
- machineconfig/scripts/python/mcfg.py +0 -48
- machineconfig/scripts/python/nw/add_ssh_key.py +0 -148
- machineconfig/scripts/python/nw/devops_add_identity.py +0 -82
- machineconfig/scripts/python/nw/devops_add_ssh_key.py +0 -134
- machineconfig/scripts/python/nw/ssh_debug_linux.py +0 -391
- machineconfig/scripts/python/nw/ssh_debug_windows.py +0 -338
- machineconfig/scripts/python/nw/wsl_windows_transfer.py +0 -66
- machineconfig/scripts/windows/fzfb.ps1 +0 -3
- machineconfig/scripts/windows/fzfg.ps1 +0 -2
- machineconfig/scripts/windows/fzfrga.bat +0 -20
- machineconfig/scripts/windows/mcfgs.ps1 +0 -17
- machineconfig/scripts/windows/mounts/mount_ssh.ps1 +0 -13
- machineconfig/settings/lf/linux/exe/fzf_nano.sh +0 -16
- machineconfig/settings/lf/windows/fzf_edit.ps1 +0 -6
- machineconfig/settings/lf/windows/tst.ps1 +0 -1
- machineconfig/settings/yazi/yazi.toml +0 -4
- machineconfig/setup_linux/apps.sh +0 -66
- machineconfig/setup_linux/others/cli_installation.sh +0 -137
- machineconfig/setup_linux/others/mint_keyboard_shortcuts.sh +0 -30
- machineconfig/setup_linux/ssh/openssh_all.sh +0 -25
- machineconfig/setup_linux/ssh/openssh_wsl.sh +0 -38
- machineconfig/setup_mac/apps.sh +0 -73
- machineconfig/setup_mac/ssh/openssh_setup.sh +0 -114
- machineconfig/setup_windows/apps.ps1 +0 -62
- machineconfig/setup_windows/others/obs.ps1 +0 -4
- machineconfig/setup_windows/ssh/add-sshkey.ps1 +0 -29
- machineconfig/setup_windows/ssh/add_identity.ps1 +0 -11
- machineconfig/setup_windows/ssh/openssh-server.ps1 +0 -37
- machineconfig/utils/installer_utils/installer.py +0 -225
- machineconfig/utils/tst.py +0 -20
- machineconfig-6.82.dist-info/METADATA +0 -82
- machineconfig-6.82.dist-info/RECORD +0 -441
- machineconfig/jobs/installer/{custom_dev → checks}/__init__.py +0 -0
- machineconfig/jobs/installer/linux_scripts/{warp-cli.sh → cloudflare_warp_cli.sh} +0 -0
- machineconfig/{scripts/python/helpers_cloud → jobs/installer/python_scripts}/__init__.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/alacritty.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/bypass_paywall.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/cursor.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/espanso.py +0 -0
- machineconfig/jobs/installer/{custom → python_scripts}/gh.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/goes.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/lvim.py +0 -0
- machineconfig/jobs/installer/{custom_dev → python_scripts}/redis.py +0 -0
- machineconfig/{setup_linux/others → jobs/scripts/bash_scripts}/android.sh +0 -0
- machineconfig/jobs/{installer/linux_scripts → scripts/bash_scripts}/lid.sh +0 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_drive +0 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_nw_drive +0 -0
- machineconfig/{scripts/python/nw → jobs/scripts/bash_scripts}/mount_smb +0 -0
- machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_cloud.sh +0 -0
- machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/share_nfs +0 -0
- machineconfig/{scripts/linux/other → jobs/scripts/bash_scripts}/start_docker +0 -0
- machineconfig/{scripts → jobs/scripts/powershell_scripts}/Restore-ThunderbirdProfile.ps1 +0 -0
- machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/docker.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nfs.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_nw.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/mount_smb.ps1 +0 -0
- machineconfig/{setup_windows/others → jobs/scripts/powershell_scripts}/power_options.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_cloud.cmd +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/share_smb.ps1 +0 -0
- machineconfig/{scripts/windows/mounts → jobs/scripts/powershell_scripts}/unlock_bitlocker.ps1 +0 -0
- machineconfig/scripts/python/{helpers_croshell → ai/utils}/__init__.py +0 -0
- machineconfig/scripts/python/ai/{solutions/_shared.py → utils/shared.py} +0 -0
- machineconfig/scripts/python/{helpers_devops → graph}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_devops/themes → helpers}/__init__.py +0 -0
- machineconfig/scripts/python/{env_manager → helpers/helper_env}/__init__.py +0 -0
- machineconfig/scripts/python/{env_manager → helpers/helper_env}/path_manager_backend.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/agentic_frameworks/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_help_search.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents}/fire_agents_load_balancer.py +0 -0
- machineconfig/scripts/python/{helpers_fire → helpers/helpers_agents/templates}/template.ps1 +0 -0
- machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_cloud}/__init__.py +0 -0
- machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/cloud_helpers.py +1 -1
- /machineconfig/scripts/python/{helpers_cloud → helpers/helpers_cloud}/helpers5.py +0 -0
- /machineconfig/scripts/python/{helpers_sessions → helpers/helpers_croshell}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/pomodoro.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer.py +0 -0
- /machineconfig/scripts/python/{helpers_croshell → helpers/helpers_croshell}/viewer_template.py +0 -0
- /machineconfig/scripts/python/{nw → helpers/helpers_devops}/__init__.py +0 -0
- /machineconfig/{setup_windows/wt_and_pwsh → scripts/python/helpers/helpers_devops/themes}/__init__.py +0 -0
- /machineconfig/scripts/python/{helpers_devops → helpers/helpers_devops}/themes/choose_pwsh_theme.ps1 +0 -0
- /machineconfig/scripts/python/{helpers_devops/themes/choose_starship_theme.ps1 → helpers/helpers_fire_command/__init__.py} +0 -0
- /machineconfig/scripts/python/{helpers_fire_command → helpers/helpers_fire_command}/cloud_manager.py +0 -0
- /machineconfig/scripts/python/{helpers_fire_command/fire_jobs_streamlit_helper.py → helpers/helpers_fire_command/f.py} +0 -0
- /machineconfig/{settings/shells/pwsh/profile.ps1 → scripts/python/helpers/helpers_fire_command/fire_jobs_streamlit_helper.py} +0 -0
- /machineconfig/scripts/python/{helpers_navigator → helpers/helpers_navigator}/search_bar.py +0 -0
- /machineconfig/{settings/yazi/keymap.toml → scripts/python/helpers/helpers_network/__init__.py} +0 -0
- /machineconfig/scripts/python/{nw → helpers/helpers_network}/mount_nw_drive.py +0 -0
- /machineconfig/scripts/python/{nw → helpers/helpers_network}/onetimeshare.py +0 -0
- /machineconfig/scripts/python/{helpers_repos → helpers/helpers_repos}/sync.py +0 -0
- /machineconfig/{setup_windows/wt_and_pwsh → settings/wt}/set_wt_settings.py +0 -0
- {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/WHEEL +0 -0
- {machineconfig-6.82.dist-info → machineconfig-8.51.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""SSH"""
|
|
2
|
+
|
|
3
|
+
from platform import system
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
from rich.panel import Panel
|
|
7
|
+
from rich import box
|
|
8
|
+
from typing import Optional, Annotated
|
|
9
|
+
import typer
|
|
10
|
+
import subprocess
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
console = Console()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _add_ssh_key_windows(path_to_key: Path) -> None:
|
|
17
|
+
"""Add SSH key on Windows using Python with proper UTF-8 encoding.
|
|
18
|
+
This replaces the PowerShell script that was writing UTF-16LE encoded files which openssh server cannot read.
|
|
19
|
+
"""
|
|
20
|
+
sshd_dir = Path("C:/ProgramData/ssh")
|
|
21
|
+
admin_auth_keys = sshd_dir / "administrators_authorized_keys"
|
|
22
|
+
sshd_config = sshd_dir / "sshd_config"
|
|
23
|
+
key_content = path_to_key.read_text(encoding="utf-8").strip()
|
|
24
|
+
if admin_auth_keys.exists():
|
|
25
|
+
existing = admin_auth_keys.read_text(encoding="utf-8")
|
|
26
|
+
if not existing.endswith("\n"):
|
|
27
|
+
existing += "\n"
|
|
28
|
+
admin_auth_keys.write_text(existing + key_content + "\n", encoding="utf-8")
|
|
29
|
+
else:
|
|
30
|
+
admin_auth_keys.write_text(key_content + "\n", encoding="utf-8")
|
|
31
|
+
icacls_cmd = f'icacls "{admin_auth_keys}" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"'
|
|
32
|
+
subprocess.run(icacls_cmd, shell=True, check=True)
|
|
33
|
+
if sshd_config.exists():
|
|
34
|
+
config_text = sshd_config.read_text(encoding="utf-8")
|
|
35
|
+
config_text = config_text.replace("#PubkeyAuthentication", "PubkeyAuthentication")
|
|
36
|
+
sshd_config.write_text(config_text, encoding="utf-8")
|
|
37
|
+
subprocess.run("Restart-Service sshd -Force", shell=True, check=True)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_add_ssh_key_script(path_to_key: Path, verbose: bool = True) -> tuple[str, str]:
|
|
41
|
+
"""Returns (program_script, status_message) tuple. For Windows, program_script is empty because we handle it in Python."""
|
|
42
|
+
os_name = system()
|
|
43
|
+
if os_name == "Linux" or os_name == "Darwin":
|
|
44
|
+
authorized_keys = Path.home().joinpath(".ssh/authorized_keys")
|
|
45
|
+
os_icon, os_label = "🐧", "Linux/macOS"
|
|
46
|
+
elif os_name == "Windows":
|
|
47
|
+
authorized_keys = Path("C:/ProgramData/ssh/administrators_authorized_keys")
|
|
48
|
+
os_icon, os_label = "🪟", "Windows"
|
|
49
|
+
else:
|
|
50
|
+
raise NotImplementedError("Only Linux, macOS and Windows are supported")
|
|
51
|
+
|
|
52
|
+
status_lines: list[str] = [f"{os_icon} {os_label} │ Auth file: {authorized_keys}"]
|
|
53
|
+
program = ""
|
|
54
|
+
|
|
55
|
+
if authorized_keys.exists():
|
|
56
|
+
keys_text = authorized_keys.read_text(encoding="utf-8").split("\n")
|
|
57
|
+
key_count = len([k for k in keys_text if k.strip()])
|
|
58
|
+
status_lines.append(f"🔑 Existing keys: {key_count}")
|
|
59
|
+
if path_to_key.read_text(encoding="utf-8") in authorized_keys.read_text(encoding="utf-8"):
|
|
60
|
+
status_lines.append(f"⚠️ Key [yellow]{path_to_key.name}[/yellow] already authorized, skipping")
|
|
61
|
+
else:
|
|
62
|
+
status_lines.append(f"➕ Adding: [green]{path_to_key.name}[/green]")
|
|
63
|
+
if os_name == "Linux" or os_name == "Darwin":
|
|
64
|
+
program = f"cat {path_to_key} >> ~/.ssh/authorized_keys"
|
|
65
|
+
elif os_name == "Windows":
|
|
66
|
+
_add_ssh_key_windows(path_to_key)
|
|
67
|
+
else:
|
|
68
|
+
raise NotImplementedError
|
|
69
|
+
else:
|
|
70
|
+
status_lines.append(f"📝 Creating auth file with: [green]{path_to_key.name}[/green]")
|
|
71
|
+
if os_name == "Linux" or os_name == "Darwin":
|
|
72
|
+
program = f"cat {path_to_key} > ~/.ssh/authorized_keys"
|
|
73
|
+
else:
|
|
74
|
+
_add_ssh_key_windows(path_to_key)
|
|
75
|
+
|
|
76
|
+
if os_name == "Linux" or os_name == "Darwin":
|
|
77
|
+
program += """
|
|
78
|
+
sudo chmod 700 ~/.ssh
|
|
79
|
+
sudo chmod 644 ~/.ssh/authorized_keys
|
|
80
|
+
sudo chmod 644 ~/.ssh/*.pub
|
|
81
|
+
sudo service ssh --full-restart
|
|
82
|
+
# from superuser.com/questions/215504/permissions-on-private-key-in-ssh-folder
|
|
83
|
+
"""
|
|
84
|
+
return program, "\n".join(status_lines)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
Common pitfalls:
|
|
89
|
+
🚫 Wrong line endings (LF/CRLF) in config files
|
|
90
|
+
🌐 Network port conflicts (try 2222 -> 2223) between WSL and Windows
|
|
91
|
+
sudo service ssh restart
|
|
92
|
+
sudo service ssh status
|
|
93
|
+
sudo nano /etc/ssh/sshd_config
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def main(pub_path: Annotated[Optional[str], typer.Argument(help="Path to the public key file")] = None,
|
|
98
|
+
pub_choose: Annotated[bool, typer.Option("--choose", "-c", help="Choose from available public keys in ~/.ssh")] = False,
|
|
99
|
+
pub_val: Annotated[bool, typer.Option("--paste", "-p", help="Paste the public key content manually")] = False,
|
|
100
|
+
from_github: Annotated[Optional[str], typer.Option("--from-github", "-g", help="Fetch public keys from a GitHub username")] = None
|
|
101
|
+
) -> None:
|
|
102
|
+
info_lines: list[str] = []
|
|
103
|
+
program = ""
|
|
104
|
+
status_msg = ""
|
|
105
|
+
|
|
106
|
+
if pub_path:
|
|
107
|
+
key_path = Path(pub_path).expanduser().absolute()
|
|
108
|
+
key_path.parent.mkdir(parents=True, exist_ok=True)
|
|
109
|
+
if not key_path.exists():
|
|
110
|
+
console.print(Panel(f"❌ Key path does not exist: {key_path}", title="[bold red]Error[/bold red]", border_style="red"))
|
|
111
|
+
raise typer.Exit(code=1)
|
|
112
|
+
info_lines.append(f"📄 Source: Local file │ {key_path}")
|
|
113
|
+
program, status_msg = get_add_ssh_key_script(key_path)
|
|
114
|
+
|
|
115
|
+
elif pub_choose:
|
|
116
|
+
pub_keys = list(Path.home().joinpath(".ssh").glob("*.pub"))
|
|
117
|
+
if not pub_keys:
|
|
118
|
+
console.print(Panel("⚠️ No public keys found in ~/.ssh", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
|
|
119
|
+
return
|
|
120
|
+
info_lines.append(f"📄 Source: Local ~/.ssh │ Found {len(pub_keys)} key(s)")
|
|
121
|
+
programs: list[str] = []
|
|
122
|
+
statuses: list[str] = []
|
|
123
|
+
for key in pub_keys:
|
|
124
|
+
p, s = get_add_ssh_key_script(key)
|
|
125
|
+
programs.append(p)
|
|
126
|
+
statuses.append(s)
|
|
127
|
+
program = "\n\n\n".join(programs)
|
|
128
|
+
status_msg = "\n".join(statuses)
|
|
129
|
+
|
|
130
|
+
elif pub_val:
|
|
131
|
+
key_filename = input("📝 File name (default: my_pasted_key.pub): ") or "my_pasted_key.pub"
|
|
132
|
+
key_path = Path.home().joinpath(f".ssh/{key_filename}")
|
|
133
|
+
key_path.parent.mkdir(parents=True, exist_ok=True)
|
|
134
|
+
key_path.write_text(input("🔑 Paste the public key here: "), encoding="utf-8")
|
|
135
|
+
info_lines.append(f"📄 Source: Pasted │ Saved to {key_path}")
|
|
136
|
+
program, status_msg = get_add_ssh_key_script(key_path)
|
|
137
|
+
|
|
138
|
+
elif from_github:
|
|
139
|
+
import requests
|
|
140
|
+
response = requests.get(f"https://api.github.com/users/{from_github}/keys")
|
|
141
|
+
if response.status_code != 200:
|
|
142
|
+
console.print(Panel(f"❌ GitHub API error for user '{from_github}' │ Status: {response.status_code}", title="[bold red]Error[/bold red]", border_style="red"))
|
|
143
|
+
raise typer.Exit(code=1)
|
|
144
|
+
keys = response.json()
|
|
145
|
+
if not keys:
|
|
146
|
+
console.print(Panel(f"⚠️ No public keys found for GitHub user: {from_github}", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
|
|
147
|
+
return
|
|
148
|
+
key_path = Path.home().joinpath(f".ssh/{from_github}_github_keys.pub")
|
|
149
|
+
key_path.parent.mkdir(parents=True, exist_ok=True)
|
|
150
|
+
key_path.write_text("\n".join([key["key"] for key in keys]), encoding="utf-8")
|
|
151
|
+
info_lines.append(f"📄 Source: GitHub @{from_github} │ {len(keys)} key(s) → {key_path}")
|
|
152
|
+
program, status_msg = get_add_ssh_key_script(key_path)
|
|
153
|
+
|
|
154
|
+
else:
|
|
155
|
+
console.print(Panel("❌ No key source specified. Use --help for options.", title="[bold red]Error[/bold red]", border_style="red"))
|
|
156
|
+
raise typer.Exit(code=1)
|
|
157
|
+
|
|
158
|
+
combined_info = "\n".join(info_lines + [""] + status_msg.split("\n"))
|
|
159
|
+
console.print(Panel(combined_info, title="[bold blue]🔑 SSH Key Authorization[/bold blue]", border_style="blue"))
|
|
160
|
+
|
|
161
|
+
if program.strip():
|
|
162
|
+
from machineconfig.utils.code import run_shell_script
|
|
163
|
+
run_shell_script(script=program, display_script=True, clean_env=False)
|
|
164
|
+
|
|
165
|
+
import machineconfig.scripts.python.helpers.helpers_network.address as helper
|
|
166
|
+
res = helper.select_lan_ipv4(prefer_vpn=False)
|
|
167
|
+
if res is None:
|
|
168
|
+
console.print(Panel("❌ Could not determine local LAN IPv4 address", title="[bold red]Error[/bold red]", border_style="red"))
|
|
169
|
+
raise typer.Exit(code=1)
|
|
170
|
+
|
|
171
|
+
console.print(Panel(f"✅ Complete │ This machine accessible at: [green]{res}[/green]", title="[bold green]SSH Key Authorization[/bold green]", border_style="green", box=box.DOUBLE_EDGE))
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
if __name__ == "__main__":
|
|
175
|
+
pass
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
from platform import system
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
from rich.panel import Panel
|
|
7
|
+
from rich.table import Table
|
|
8
|
+
from rich import box
|
|
9
|
+
import subprocess
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
console = Console()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _run(cmd: list[str]) -> tuple[bool, str]:
|
|
18
|
+
try:
|
|
19
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=False)
|
|
20
|
+
return result.returncode == 0, result.stdout.strip()
|
|
21
|
+
except FileNotFoundError:
|
|
22
|
+
return False, ""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _check_sshd_installed() -> tuple[bool, str]:
|
|
26
|
+
sshd_paths = ["/usr/sbin/sshd", "/usr/bin/sshd", "/sbin/sshd"]
|
|
27
|
+
for path in sshd_paths:
|
|
28
|
+
if Path(path).exists():
|
|
29
|
+
return True, path
|
|
30
|
+
ok, which_out = _run(["which", "sshd"])
|
|
31
|
+
if ok and which_out:
|
|
32
|
+
return True, which_out
|
|
33
|
+
return False, ""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _detect_package_manager() -> tuple[str, str]:
|
|
37
|
+
if Path("/usr/bin/apt").exists() or Path("/usr/bin/apt-get").exists():
|
|
38
|
+
return "apt", "sudo apt update && sudo apt install -y openssh-server"
|
|
39
|
+
if Path("/usr/bin/dnf").exists():
|
|
40
|
+
return "dnf", "sudo dnf install -y openssh-server"
|
|
41
|
+
if Path("/usr/bin/yum").exists():
|
|
42
|
+
return "yum", "sudo yum install -y openssh-server"
|
|
43
|
+
if Path("/usr/bin/pacman").exists():
|
|
44
|
+
return "pacman", "sudo pacman -S --noconfirm openssh"
|
|
45
|
+
if Path("/usr/bin/zypper").exists():
|
|
46
|
+
return "zypper", "sudo zypper install -y openssh"
|
|
47
|
+
return "unknown", "# Install openssh-server using your package manager"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
|
|
51
|
+
if system() != "Linux":
|
|
52
|
+
raise NotImplementedError("ssh_debug_linux is only supported on Linux")
|
|
53
|
+
|
|
54
|
+
results: dict[str, dict[str, str | bool]] = {}
|
|
55
|
+
issues: list[tuple[str, str, str]] = []
|
|
56
|
+
current_user = os.environ.get("USER", os.environ.get("USERNAME", "unknown"))
|
|
57
|
+
ssh_port = "22"
|
|
58
|
+
ip_addresses: list[str] = []
|
|
59
|
+
|
|
60
|
+
ok, hostname = _run(["hostname"])
|
|
61
|
+
hostname = hostname if ok else "unknown"
|
|
62
|
+
|
|
63
|
+
install_info: list[str] = []
|
|
64
|
+
sshd_installed, sshd_path = _check_sshd_installed()
|
|
65
|
+
_pkg_manager, install_cmd = _detect_package_manager()
|
|
66
|
+
if not sshd_installed:
|
|
67
|
+
results["installation"] = {"status": "error", "message": "OpenSSH Server not installed"}
|
|
68
|
+
issues.append(("sshd not installed", "Cannot accept incoming SSH connections", install_cmd))
|
|
69
|
+
install_info.append("❌ OpenSSH Server: [red]NOT INSTALLED[/red]")
|
|
70
|
+
install_info.append(f" [dim]Install with: {install_cmd}[/dim]")
|
|
71
|
+
else:
|
|
72
|
+
results["installation"] = {"status": "ok", "message": f"sshd found at {sshd_path}"}
|
|
73
|
+
install_info.append(f"✅ OpenSSH Server: installed at [cyan]{sshd_path}[/cyan]")
|
|
74
|
+
console.print(Panel("\n".join(install_info), title="[bold]Installation[/bold]", border_style="blue"))
|
|
75
|
+
|
|
76
|
+
ssh_dir = Path.home().joinpath(".ssh")
|
|
77
|
+
authorized_keys = ssh_dir.joinpath("authorized_keys")
|
|
78
|
+
home_dir = Path.home()
|
|
79
|
+
|
|
80
|
+
perm_info: list[str] = []
|
|
81
|
+
home_stat = os.stat(home_dir)
|
|
82
|
+
home_perms = oct(home_stat.st_mode)[-3:]
|
|
83
|
+
if home_perms[2] in ["7", "6", "3", "2"]:
|
|
84
|
+
results["home_directory"] = {"status": "error", "message": f"Home world-writable: {home_perms}"}
|
|
85
|
+
issues.append((f"Home dir perms {home_perms}", "sshd refuses login if home is world-writable", f"chmod 755 {home_dir}"))
|
|
86
|
+
perm_info.append(f"❌ Home directory: [red]{home_perms}[/red] (world-writable)")
|
|
87
|
+
perm_info.append(" [dim]sshd will refuse key auth if home is writable by others[/dim]")
|
|
88
|
+
else:
|
|
89
|
+
perm_info.append(f"✅ Home directory: {home_perms}")
|
|
90
|
+
|
|
91
|
+
if not ssh_dir.exists():
|
|
92
|
+
results["ssh_directory"] = {"status": "error", "message": "~/.ssh missing"}
|
|
93
|
+
issues.append(("~/.ssh missing", "No place for authorized_keys", "mkdir -p ~/.ssh && chmod 700 ~/.ssh"))
|
|
94
|
+
perm_info.append("❌ ~/.ssh: [red]does not exist[/red]")
|
|
95
|
+
else:
|
|
96
|
+
ssh_perms = oct(os.stat(ssh_dir).st_mode)[-3:]
|
|
97
|
+
if ssh_perms != "700":
|
|
98
|
+
results["ssh_directory"] = {"status": "error", "message": f"~/.ssh perms {ssh_perms}"}
|
|
99
|
+
issues.append((f"~/.ssh perms {ssh_perms}", "sshd requires 700 on ~/.ssh", "chmod 700 ~/.ssh"))
|
|
100
|
+
perm_info.append(f"❌ ~/.ssh: [red]{ssh_perms}[/red] (must be 700)")
|
|
101
|
+
else:
|
|
102
|
+
perm_info.append(f"✅ ~/.ssh: {ssh_perms}")
|
|
103
|
+
|
|
104
|
+
if not authorized_keys.exists():
|
|
105
|
+
results["authorized_keys"] = {"status": "error", "message": "authorized_keys missing"}
|
|
106
|
+
issues.append(("authorized_keys missing", "No keys = no login", "Add public key: cat id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"))
|
|
107
|
+
perm_info.append("❌ authorized_keys: [red]does not exist[/red]")
|
|
108
|
+
perm_info.append(" [dim]No authorized keys = cannot login with SSH key[/dim]")
|
|
109
|
+
else:
|
|
110
|
+
ak_perms = oct(os.stat(authorized_keys).st_mode)[-3:]
|
|
111
|
+
try:
|
|
112
|
+
keys = [line for line in authorized_keys.read_text(encoding="utf-8").split("\n") if line.strip()]
|
|
113
|
+
key_count = len(keys)
|
|
114
|
+
except Exception:
|
|
115
|
+
key_count = 0
|
|
116
|
+
if ak_perms not in ["600", "644"]:
|
|
117
|
+
results["authorized_keys"] = {"status": "error", "message": f"authorized_keys perms {ak_perms}"}
|
|
118
|
+
issues.append((f"authorized_keys perms {ak_perms}", "sshd requires 600 or 644", "chmod 600 ~/.ssh/authorized_keys"))
|
|
119
|
+
perm_info.append(f"❌ authorized_keys: [red]{ak_perms}[/red] ({key_count} key(s)) - must be 600/644")
|
|
120
|
+
else:
|
|
121
|
+
results["authorized_keys"] = {"status": "ok", "message": f"{key_count} key(s)"}
|
|
122
|
+
perm_info.append(f"✅ authorized_keys: {ak_perms} ([green]{key_count} key(s)[/green])")
|
|
123
|
+
|
|
124
|
+
console.print(Panel("\n".join(perm_info), title="[bold]Permissions[/bold]", border_style="blue"))
|
|
125
|
+
|
|
126
|
+
svc_info: list[str] = []
|
|
127
|
+
ssh_ok, _ = _run(["systemctl", "is-active", "ssh"])
|
|
128
|
+
sshd_ok, _ = _run(["systemctl", "is-active", "sshd"])
|
|
129
|
+
if ssh_ok or sshd_ok:
|
|
130
|
+
svc_name = "ssh" if ssh_ok else "sshd"
|
|
131
|
+
results["ssh_service"] = {"status": "ok", "message": f"{svc_name} running"}
|
|
132
|
+
svc_info.append(f"✅ Service: [green]{svc_name} running[/green]")
|
|
133
|
+
else:
|
|
134
|
+
results["ssh_service"] = {"status": "error", "message": "sshd not running"}
|
|
135
|
+
issues.append(("sshd not running", "No SSH daemon = no connections", "sudo systemctl start ssh && sudo systemctl enable ssh"))
|
|
136
|
+
svc_info.append("❌ Service: [red]not running[/red]")
|
|
137
|
+
|
|
138
|
+
console.print(Panel("\n".join(svc_info), title="[bold]Service[/bold]", border_style="blue"))
|
|
139
|
+
|
|
140
|
+
net_info: list[str] = []
|
|
141
|
+
ok, ip_out = _run(["ip", "addr", "show"])
|
|
142
|
+
if ok:
|
|
143
|
+
ip_addresses = re.findall(r'inet\s+(\d+\.\d+\.\d+\.\d+)/\d+.*scope\s+global', ip_out)
|
|
144
|
+
if ip_addresses:
|
|
145
|
+
net_info.append(f"🌐 IP: [cyan]{', '.join(ip_addresses)}[/cyan]")
|
|
146
|
+
|
|
147
|
+
sshd_config_paths = [Path("/etc/ssh/sshd_config"), Path("/etc/sshd_config")]
|
|
148
|
+
sshd_config: Path | None = None
|
|
149
|
+
for p in sshd_config_paths:
|
|
150
|
+
if p.exists():
|
|
151
|
+
sshd_config = p
|
|
152
|
+
break
|
|
153
|
+
|
|
154
|
+
if sshd_config:
|
|
155
|
+
try:
|
|
156
|
+
config_text = sshd_config.read_text(encoding="utf-8")
|
|
157
|
+
port_lines = [line for line in config_text.split("\n") if line.strip().startswith("Port") and not line.strip().startswith("#")]
|
|
158
|
+
if port_lines:
|
|
159
|
+
ssh_port = port_lines[0].split()[1]
|
|
160
|
+
net_info.append(f"🔌 Port: [cyan]{ssh_port}[/cyan]")
|
|
161
|
+
|
|
162
|
+
pubkey_lines = [line for line in config_text.split("\n") if "PubkeyAuthentication" in line and not line.strip().startswith("#")]
|
|
163
|
+
if pubkey_lines and "no" in pubkey_lines[-1].lower():
|
|
164
|
+
results["pubkey_auth"] = {"status": "error", "message": "PubkeyAuthentication disabled"}
|
|
165
|
+
issues.append(("PubkeyAuthentication disabled", "Key-based login won't work", f"Edit {sshd_config}: set PubkeyAuthentication yes, then sudo systemctl restart ssh"))
|
|
166
|
+
net_info.append("❌ PubkeyAuthentication: [red]disabled[/red]")
|
|
167
|
+
else:
|
|
168
|
+
net_info.append("✅ PubkeyAuthentication: enabled")
|
|
169
|
+
|
|
170
|
+
password_lines = [line for line in config_text.split("\n") if "PasswordAuthentication" in line and not line.strip().startswith("#")]
|
|
171
|
+
if password_lines:
|
|
172
|
+
password_enabled = "yes" in password_lines[-1].lower()
|
|
173
|
+
if password_enabled:
|
|
174
|
+
results["password_auth"] = {"status": "ok", "message": "PasswordAuthentication enabled"}
|
|
175
|
+
net_info.append("✅ PasswordAuthentication: [green]enabled[/green]")
|
|
176
|
+
else:
|
|
177
|
+
results["password_auth"] = {"status": "info", "message": "PasswordAuthentication disabled"}
|
|
178
|
+
net_info.append("ℹ️ PasswordAuthentication: [yellow]disabled[/yellow] (key-only)")
|
|
179
|
+
else:
|
|
180
|
+
results["password_auth"] = {"status": "ok", "message": "PasswordAuthentication enabled (default)"}
|
|
181
|
+
net_info.append("✅ PasswordAuthentication: [green]enabled[/green] (default)")
|
|
182
|
+
|
|
183
|
+
permit_root = [line for line in config_text.split("\n") if "PermitRootLogin" in line and not line.strip().startswith("#")]
|
|
184
|
+
if permit_root:
|
|
185
|
+
val = permit_root[-1].split()[-1].lower()
|
|
186
|
+
net_info.append(f"ℹ️ PermitRootLogin: {val}")
|
|
187
|
+
except Exception:
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
ok, ss_out = _run(["ss", "-tlnp"])
|
|
191
|
+
if ok:
|
|
192
|
+
listening = [line for line in ss_out.split("\n") if f":{ssh_port}" in line]
|
|
193
|
+
if not listening:
|
|
194
|
+
results["ssh_listening"] = {"status": "error", "message": f"Not listening on {ssh_port}"}
|
|
195
|
+
issues.append((f"Not listening on port {ssh_port}", "No connections possible", "sudo systemctl restart ssh"))
|
|
196
|
+
net_info.append(f"❌ Listening: [red]NOT on port {ssh_port}[/red]")
|
|
197
|
+
elif all("127.0.0.1" in line or "[::1]" in line for line in listening):
|
|
198
|
+
results["ssh_listening"] = {"status": "error", "message": "Localhost only"}
|
|
199
|
+
issues.append(("SSH bound to localhost", "Only local connections", f"Edit {sshd_config}: remove/comment ListenAddress 127.0.0.1"))
|
|
200
|
+
net_info.append("❌ Listening: [red]localhost only[/red]")
|
|
201
|
+
else:
|
|
202
|
+
results["ssh_listening"] = {"status": "ok", "message": f"Listening on {ssh_port}"}
|
|
203
|
+
net_info.append(f"✅ Listening: 0.0.0.0:{ssh_port}")
|
|
204
|
+
|
|
205
|
+
fw_checked = False
|
|
206
|
+
ok, ufw_out = _run(["ufw", "status"])
|
|
207
|
+
if ok and "Status: active" in ufw_out:
|
|
208
|
+
fw_checked = True
|
|
209
|
+
if f"{ssh_port}/tcp" in ufw_out.lower() or "ssh" in ufw_out.lower() or f" {ssh_port} " in ufw_out:
|
|
210
|
+
results["firewall"] = {"status": "ok", "message": "UFW allows SSH"}
|
|
211
|
+
net_info.append("✅ Firewall (UFW): allows SSH")
|
|
212
|
+
else:
|
|
213
|
+
results["firewall"] = {"status": "error", "message": "UFW blocking SSH"}
|
|
214
|
+
issues.append(("UFW blocking SSH", "Incoming connections dropped", f"sudo ufw allow {ssh_port}/tcp"))
|
|
215
|
+
net_info.append("❌ Firewall (UFW): [red]blocking SSH[/red]")
|
|
216
|
+
net_info.append(" [dim]Active firewall without SSH rule = blocked[/dim]")
|
|
217
|
+
|
|
218
|
+
if not fw_checked:
|
|
219
|
+
ok, fwd_out = _run(["firewall-cmd", "--state"])
|
|
220
|
+
if ok and "running" in fwd_out.lower():
|
|
221
|
+
fw_checked = True
|
|
222
|
+
ok2, svc_out = _run(["firewall-cmd", "--list-services"])
|
|
223
|
+
if ok2 and "ssh" in svc_out.lower():
|
|
224
|
+
results["firewall"] = {"status": "ok", "message": "firewalld allows SSH"}
|
|
225
|
+
net_info.append("✅ Firewall (firewalld): allows SSH")
|
|
226
|
+
else:
|
|
227
|
+
results["firewall"] = {"status": "error", "message": "firewalld blocking SSH"}
|
|
228
|
+
issues.append(("firewalld blocking SSH", "Incoming connections dropped", "sudo firewall-cmd --permanent --add-service=ssh && sudo firewall-cmd --reload"))
|
|
229
|
+
net_info.append("❌ Firewall (firewalld): [red]blocking SSH[/red]")
|
|
230
|
+
|
|
231
|
+
if not fw_checked:
|
|
232
|
+
ok, ipt_out = _run(["iptables", "-L", "INPUT", "-n"])
|
|
233
|
+
if ok and ipt_out:
|
|
234
|
+
has_drop_policy = "policy DROP" in ipt_out or "policy REJECT" in ipt_out
|
|
235
|
+
has_ssh_allow = f"dpt:{ssh_port}" in ipt_out or "dpt:ssh" in ipt_out
|
|
236
|
+
if has_drop_policy and not has_ssh_allow:
|
|
237
|
+
results["firewall"] = {"status": "error", "message": "iptables blocking SSH"}
|
|
238
|
+
issues.append(("iptables blocking SSH", "DROP/REJECT policy without SSH allow", f"sudo iptables -I INPUT -p tcp --dport {ssh_port} -j ACCEPT"))
|
|
239
|
+
net_info.append("❌ Firewall (iptables): [red]DROP policy, no SSH rule[/red]")
|
|
240
|
+
fw_checked = True
|
|
241
|
+
elif has_drop_policy and has_ssh_allow:
|
|
242
|
+
results["firewall"] = {"status": "ok", "message": "iptables allows SSH"}
|
|
243
|
+
net_info.append("✅ Firewall (iptables): allows SSH")
|
|
244
|
+
fw_checked = True
|
|
245
|
+
|
|
246
|
+
if not fw_checked:
|
|
247
|
+
net_info.append("ℹ️ Firewall: none detected / not active")
|
|
248
|
+
|
|
249
|
+
console.print(Panel("\n".join(net_info), title="[bold]Network & Firewall[/bold]", border_style="blue"))
|
|
250
|
+
|
|
251
|
+
other_info: list[str] = []
|
|
252
|
+
hosts_deny = Path("/etc/hosts.deny")
|
|
253
|
+
if hosts_deny.exists():
|
|
254
|
+
try:
|
|
255
|
+
content = hosts_deny.read_text(encoding="utf-8")
|
|
256
|
+
active = [line for line in content.splitlines() if line.strip() and not line.strip().startswith("#")]
|
|
257
|
+
joined = " ".join(active).lower()
|
|
258
|
+
if "sshd" in joined or "all" in joined:
|
|
259
|
+
results["hosts_deny"] = {"status": "error", "message": "hosts.deny blocking"}
|
|
260
|
+
issues.append(("hosts.deny blocking SSH", "TCP wrappers deny before firewall", "Edit /etc/hosts.deny to remove sshd/ALL entries"))
|
|
261
|
+
other_info.append("❌ /etc/hosts.deny: [red]may block SSH[/red]")
|
|
262
|
+
else:
|
|
263
|
+
other_info.append("✅ /etc/hosts.deny: OK")
|
|
264
|
+
except Exception:
|
|
265
|
+
pass
|
|
266
|
+
|
|
267
|
+
ok, se_out = _run(["getenforce"])
|
|
268
|
+
if ok and se_out:
|
|
269
|
+
if se_out == "Enforcing":
|
|
270
|
+
other_info.append("ℹ️ SELinux: Enforcing (run [cyan]restorecon -Rv ~/.ssh[/cyan] if issues)")
|
|
271
|
+
else:
|
|
272
|
+
other_info.append(f"ℹ️ SELinux: {se_out}")
|
|
273
|
+
|
|
274
|
+
log_files = [Path("/var/log/auth.log"), Path("/var/log/secure")]
|
|
275
|
+
for lf in log_files:
|
|
276
|
+
if lf.exists():
|
|
277
|
+
ok, tail = _run(["tail", "-n", "20", str(lf)])
|
|
278
|
+
if ok:
|
|
279
|
+
errors = [line for line in tail.split("\n") if any(k in line.lower() for k in ["error", "failed", "refused", "denied"]) and "ssh" in line.lower()]
|
|
280
|
+
if errors:
|
|
281
|
+
other_info.append(f"⚠️ Recent SSH errors in {lf.name}: {len(errors)}")
|
|
282
|
+
else:
|
|
283
|
+
other_info.append(f"✅ {lf.name}: no recent SSH errors")
|
|
284
|
+
break
|
|
285
|
+
|
|
286
|
+
if other_info:
|
|
287
|
+
console.print(Panel("\n".join(other_info), title="[bold]Additional[/bold]", border_style="blue"))
|
|
288
|
+
|
|
289
|
+
if issues:
|
|
290
|
+
fix_table = Table(title="Issues & Fixes", box=box.ROUNDED, show_lines=True, title_style="bold red")
|
|
291
|
+
fix_table.add_column("Issue", style="yellow", width=25)
|
|
292
|
+
fix_table.add_column("Impact", style="white", width=35)
|
|
293
|
+
fix_table.add_column("Fix Command", style="green", width=55)
|
|
294
|
+
for issue, impact, fix in issues:
|
|
295
|
+
fix_table.add_row(issue, impact, fix)
|
|
296
|
+
console.print(fix_table)
|
|
297
|
+
|
|
298
|
+
fix_script_path = Path("/tmp/ssh_fix.sh")
|
|
299
|
+
script_lines = ["#!/bin/bash", "set -e", "", "# SSH Fix Script - Generated by ssh_debug_linux", f"# {len(issues)} issue(s) to fix", ""]
|
|
300
|
+
for issue, _impact, fix in issues:
|
|
301
|
+
script_lines.append(f"# Fix: {issue}")
|
|
302
|
+
script_lines.append(fix)
|
|
303
|
+
script_lines.append("")
|
|
304
|
+
script_lines.append("echo 'All fixes applied. Re-run ssh_debug_linux to verify.'")
|
|
305
|
+
fix_script_path.write_text("\n".join(script_lines), encoding="utf-8")
|
|
306
|
+
fix_script_path.chmod(0o755)
|
|
307
|
+
|
|
308
|
+
console.print(Panel(f"[bold yellow]⚠️ {len(issues)} issue(s) found[/bold yellow]\n\nFix script generated: [cyan]{fix_script_path}[/cyan]\nRun: [green]sudo bash {fix_script_path}[/green]", title="[bold]Summary[/bold]", border_style="yellow"))
|
|
309
|
+
else:
|
|
310
|
+
conn_info = f"👤 {current_user} 🖥️ {hostname} 🔌 :{ssh_port}"
|
|
311
|
+
if ip_addresses:
|
|
312
|
+
conn_info += f"\n\n[bold]Connect:[/bold] ssh {current_user}@{ip_addresses[0]}"
|
|
313
|
+
console.print(Panel(f"[bold green]✅ All checks passed[/bold green]\n\n{conn_info}", title="[bold]Ready[/bold]", border_style="green"))
|
|
314
|
+
|
|
315
|
+
return results
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
if __name__ == "__main__":
|
|
319
|
+
ssh_debug_linux()
|