Update Inicial

master
Oscar Garcia 4 months ago
commit 030d4ec94c

@ -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

@ -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"
}

@ -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"

@ -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"
Loading…
Cancel
Save