From 030d4ec94c450a7f3c7a543dc1eddceb1dc24593 Mon Sep 17 00:00:00 2001 From: "oscar.garcia" Date: Wed, 21 Jan 2026 23:02:03 -0500 Subject: [PATCH] Update Inicial --- README.md | 0 README.md.txt | 75 ++++++++++++++++++++++++++ scripts/01-New-SshConfigLink.ps1 | 76 ++++++++++++++++++++++++++ scripts/02-Backup-PwshSshSetup.ps1 | 60 +++++++++++++++++++++ scripts/03-Restore-PwshSshSetup.ps1 | 83 +++++++++++++++++++++++++++++ 5 files changed, 294 insertions(+) create mode 100644 README.md create mode 100644 README.md.txt create mode 100644 scripts/01-New-SshConfigLink.ps1 create mode 100644 scripts/02-Backup-PwshSshSetup.ps1 create mode 100644 scripts/03-Restore-PwshSshSetup.ps1 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/README.md.txt b/README.md.txt new file mode 100644 index 0000000..241ad67 --- /dev/null +++ b/README.md.txt @@ -0,0 +1,75 @@ +# PowerShell (Sapian) — SSH tipo Linux + Backup/Restore + +Este repositorio contiene los scripts para dejar PowerShell en Windows listo para trabajar como en Ubuntu: + +✅ Autosugerencias de comandos (tipo fish) +✅ Búsqueda en historial con `Ctrl+R` (fzf) +✅ Conexiones SSH rápidas usando tu `ssh_config` existente +✅ Backup y restore del entorno (incluye llaves si aplica) + +--- + +## Estructura del repo + +PowerShell/ +│ README.md +└─ scripts/ +│ 01-New-SshConfigLink.ps1 +│ 02-Backup-PwshSshSetup.ps1 +│ 03-Restore-PwshSshSetup.ps1 + + +--- + +## IMPORTANTE: ubicación real del ssh_config + +El archivo con los servidores **NO está dentro de este repo**. + +Se mantiene en esta ruta (NO se mueve): + +C:\Users\ofgar\Workspace\revelation\ssh_config + + +--- + +## ¿Qué hace cada script? + +### `01-New-SshConfigLink.ps1` +Crea el enlace para que Windows use tu ssh_config actual: + +C:\Users\ofgar.ssh\config --> C:\Users\ofgar\Workspace\revelation\ssh_config + + +Opcional: también puede reparar permisos de `id_rsa` si da error de permisos. + +--- + +### `02-Backup-PwshSshSetup.ps1` +Genera un backup del entorno: + +- Perfil de PowerShell +- Historial de comandos (PSReadLine) +- Copia del `ssh_config` (desde su ruta actual) +- Opcional: llaves SSH (`id_rsa`, `id_rsa.pub`, `known_hosts`) + +--- + +### `03-Restore-PwshSshSetup.ps1` +Restaura todo en un equipo nuevo: + +- Instala módulos necesarios +- Restaura perfil PowerShell +- Restaura historial (opcional) +- Restaura llaves + repara permisos (opcional) +- Vuelve a crear el enlace de `~\.ssh\config` + +--- + +## Instalación base (una sola vez) + +Abrir PowerShell y ejecutar: + +```powershell +Install-Module PSReadLine -Scope CurrentUser -Force +winget install fzf +Install-Module PSFzf -Scope CurrentUser -Force \ No newline at end of file diff --git a/scripts/01-New-SshConfigLink.ps1 b/scripts/01-New-SshConfigLink.ps1 new file mode 100644 index 0000000..6397aa0 --- /dev/null +++ b/scripts/01-New-SshConfigLink.ps1 @@ -0,0 +1,76 @@ +<# +Crea el link: C:\Users\ofgar\.ssh\config -> (ruta actual de ssh_config) +Opcional: repara permisos de la llave id_rsa (ACL) para evitar "permissions too open". +#> + +param( + [string]$RepoConfig = "C:\Users\ofgar\Workspace\revelation\ssh_config", + [switch]$FixKeyPermissions +) + +$ErrorActionPreference = "Stop" + +$userSshDir = Join-Path $env:USERPROFILE ".ssh" +$userConfig = Join-Path $userSshDir "config" +$timestamp = Get-Date -Format "yyyyMMdd_HHmmss" + +function Backup-File([string]$Path) { + if (Test-Path -LiteralPath $Path) { + $bak = "$Path.bak.$timestamp" + Copy-Item -LiteralPath $Path -Destination $bak -Force + } +} + +function Repair-PrivateKeyAcl([string]$KeyPath) { + if (-not (Test-Path -LiteralPath $KeyPath)) { return } + icacls $KeyPath /inheritance:r | Out-Null + icacls $KeyPath /grant:r "$($env:USERNAME):F" | Out-Null +} + +# Validar origen +if (-not (Test-Path -LiteralPath $RepoConfig)) { + throw "No existe el ssh_config en: $RepoConfig" +} + +# Asegurar .ssh +New-Item -ItemType Directory -Force -Path $userSshDir | Out-Null + +# Si existe config, manejarlo +if (Test-Path -LiteralPath $userConfig) { + $item = Get-Item -LiteralPath $userConfig -Force + $isLink = $null -ne $item.LinkType + + if ($isLink) { + try { + if ($item.Target -eq $RepoConfig) { + Write-Host "OK: ya está enlazado -> $RepoConfig" + } else { + Remove-Item -LiteralPath $userConfig -Force + } + } catch { + Remove-Item -LiteralPath $userConfig -Force + } + } else { + Backup-File $userConfig + Remove-Item -LiteralPath $userConfig -Force + } +} + +# Crear symlink (o fallback a copia) +if (-not (Test-Path -LiteralPath $userConfig)) { + try { + New-Item -ItemType SymbolicLink -Path $userConfig -Target $RepoConfig -Force | Out-Null + Write-Host "OK: config -> $RepoConfig" + } catch { + Write-Warning "No se pudo crear symlink. Se hará copia (NO queda sincronizado con el archivo original)." + Copy-Item -LiteralPath $RepoConfig -Destination $userConfig -Force + Write-Host "OK: config copiado desde $RepoConfig" + } +} + +# Reparar permisos de llave si se pide +if ($FixKeyPermissions) { + $key = Join-Path $userSshDir "id_rsa" + Repair-PrivateKeyAcl $key + Write-Host "OK: permisos ajustados para id_rsa" +} \ No newline at end of file diff --git a/scripts/02-Backup-PwshSshSetup.ps1 b/scripts/02-Backup-PwshSshSetup.ps1 new file mode 100644 index 0000000..cc0da2b --- /dev/null +++ b/scripts/02-Backup-PwshSshSetup.ps1 @@ -0,0 +1,60 @@ +<# +Backup del entorno PowerShell + SSH. +Incluye: perfil, historial PSReadLine, ssh_config (ruta actual) y opcional llaves. +#> + +param( + [string]$RepoConfig = "C:\Users\ofgar\Workspace\revelation\ssh_config", + [string]$BackupRoot = (Join-Path $env:USERPROFILE "Documents\pwsh_ssh_backup"), + [switch]$IncludeKeys +) + +$ErrorActionPreference = "Stop" + +$ts = Get-Date -Format "yyyyMMdd_HHmmss" +$dst = Join-Path $BackupRoot $ts + +New-Item -ItemType Directory -Force -Path $dst | Out-Null + +function SafeCopy([string]$src, [string]$name) { + if (Test-Path -LiteralPath $src) { + Copy-Item -LiteralPath $src -Destination (Join-Path $dst $name) -Force + Write-Host "OK: $name" + } else { + Write-Warning "No existe: $src" + } +} + +# 1) Perfil PowerShell +SafeCopy $PROFILE "Microsoft.PowerShell_profile.ps1" + +# 2) Historial PSReadLine +$hist = (Get-PSReadLineOption).HistorySavePath +SafeCopy $hist "ConsoleHost_history.txt" + +# 3) ssh_config (ruta actual) +SafeCopy $RepoConfig "ssh_config" + +# 4) Inventario de módulos +Get-InstalledModule | Select Name, Version | Sort Name | + Out-File (Join-Path $dst "pwsh_modules.txt") -Encoding UTF8 +Write-Host "OK: pwsh_modules.txt" + +# 5) Opcional: llaves y archivos SSH +if ($IncludeKeys) { + $sshDir = Join-Path $env:USERPROFILE ".ssh" + SafeCopy (Join-Path $sshDir "id_rsa") "id_rsa" + SafeCopy (Join-Path $sshDir "id_rsa.pub") "id_rsa.pub" + SafeCopy (Join-Path $sshDir "known_hosts") "known_hosts" + SafeCopy (Join-Path $sshDir "config") "config_current" +} + +# 6) Info general +$info = Join-Path $dst "env_info.txt" +"PowerShell: $($PSVersionTable.PSVersion)" | Out-File $info -Encoding UTF8 +"PROFILE: $PROFILE" | Add-Content $info +"PSReadLineHistory: $hist" | Add-Content $info +"RepoConfig: $RepoConfig" | Add-Content $info + +Write-Host "" +Write-Host "Backup creado en: $dst" \ No newline at end of file diff --git a/scripts/03-Restore-PwshSshSetup.ps1 b/scripts/03-Restore-PwshSshSetup.ps1 new file mode 100644 index 0000000..deacb4d --- /dev/null +++ b/scripts/03-Restore-PwshSshSetup.ps1 @@ -0,0 +1,83 @@ +<# +Restaura el entorno desde un backup: +- Perfil +- Historial (opcional) +- Llaves (opcional) + permisos id_rsa +- Re-crea el link ~/.ssh/config -> ssh_config (ruta actual) +#> + +param( + [Parameter(Mandatory=$true)] + [string]$BackupPath, + + [string]$RepoConfig = "C:\Users\ofgar\Workspace\revelation\ssh_config", + + [switch]$RestoreHistory, + [switch]$RestoreKeys +) + +$ErrorActionPreference = "Stop" + +function Repair-PrivateKeyAcl([string]$KeyPath) { + if (-not (Test-Path -LiteralPath $KeyPath)) { return } + icacls $KeyPath /inheritance:r | Out-Null + icacls $KeyPath /grant:r "$($env:USERNAME):F" | Out-Null +} + +# 1) Asegurar módulos +Install-Module PSReadLine -Scope CurrentUser -Force +Install-Module PSFzf -Scope CurrentUser -Force + +# 2) Perfil +$profileSrc = Join-Path $BackupPath "Microsoft.PowerShell_profile.ps1" +if (Test-Path -LiteralPath $profileSrc) { + New-Item -ItemType Directory -Force -Path (Split-Path -Parent $PROFILE) | Out-Null + Copy-Item -LiteralPath $profileSrc -Destination $PROFILE -Force + Write-Host "OK: Perfil restaurado" +} else { + Write-Warning "No se encontró perfil en el backup" +} + +# 3) Historial (opcional) +if ($RestoreHistory) { + $histDst = (Get-PSReadLineOption).HistorySavePath + $histSrc = Join-Path $BackupPath "ConsoleHost_history.txt" + if (Test-Path -LiteralPath $histSrc) { + New-Item -ItemType Directory -Force -Path (Split-Path -Parent $histDst) | Out-Null + Copy-Item -LiteralPath $histSrc -Destination $histDst -Force + Write-Host "OK: Historial restaurado" + } else { + Write-Warning "No se encontró historial en el backup" + } +} + +# 4) Llaves (opcional) +if ($RestoreKeys) { + $sshDir = Join-Path $env:USERPROFILE ".ssh" + New-Item -ItemType Directory -Force -Path $sshDir | Out-Null + + foreach ($f in @("id_rsa","id_rsa.pub","known_hosts")) { + $src = Join-Path $BackupPath $f + $dst = Join-Path $sshDir $f + if (Test-Path -LiteralPath $src) { + Copy-Item -LiteralPath $src -Destination $dst -Force + Write-Host "OK: restaurado $f" + } else { + Write-Warning "No existe en backup: $f" + } + } + + Repair-PrivateKeyAcl (Join-Path $sshDir "id_rsa") + Write-Host "OK: permisos ajustados id_rsa" +} + +# 5) Re-crear link de config (usa script del mismo folder) +$scriptLink = Join-Path $PSScriptRoot "New-SshConfigLink.ps1" +if (-not (Test-Path -LiteralPath $scriptLink)) { + throw "Falta New-SshConfigLink.ps1 en: $PSScriptRoot" +} + +& $scriptLink -RepoConfig $RepoConfig + +Write-Host "" +Write-Host "Restauración lista. Abre PowerShell nuevo y prueba: ssh / Ctrl+R" \ No newline at end of file