operator-migration/readme.md

385 lines
No EOL
11 KiB
Markdown

# migration-guide
[🇺🇸English](#english) · [🇪🇸Español](#español)
---
# English
Zero-downtime migration from the legacy WireGuard + Go API stack to operator-docker. Existing VPN clients reconnect automatically — no new configuration required on their end.
---
## How it works
```text
Before migration
Legacy stack (sp-env-wireguard-ipv6)
├── wireguard (linuxserver/wireguard)
├── wireguard-api (Go)
└── nginx-certbot
After migration
operator-docker
├── wireguard (same identity — same public key)
├── operator-api (FastAPI)
├── marzban
├── hysteria2
└── mysql
```
The server's WireGuard identity (private key → public key) is preserved.
All peers are migrated via the new API. Clients reconnect without any config change.
---
## Prerequisites
- Legacy stack running (`docker ps` shows `wireguard`)
- Domain with DNS pointing to this server
- One subdomain per service (`api`, `legacy`, `cdn`, `news` or similar)
- SSH key authorized by Simplified Privacy (generated in step 00)
- Port 80/TCP reachable externally (required by Let's Encrypt)
---
## Migration steps
| Script | Run as | Description |
| :----- | :----- | :---------- |
| `00-migrate-root.sh` | root | Backup, shutdown legacy, clean system |
| `01-migrate-user.sh` | user | Clone repo, install operator-docker |
| `02-migrate-peers.sh` | user | Inject identity, migrate peers |
---
## Usage
Scripts can be run from any directory:
```bash
sudo bash ~/migration/00-migrate-root.sh
bash ~/migration/01-migrate-user.sh
bash ~/migration/02-migrate-peers.sh
```
---
## Step 00 — Backup and cleanup
Run as root:
```bash
sudo bash 00-migrate-root.sh
```
What it does:
| Action | Detail |
| :----- | :----- |
| Detects legacy WireGuard container | By image or name |
| Backs up private key and public key | Saved to `~/.wg-migration/` |
| Backs up all peers | From `wg showconf wg0` |
| Backs up Nginx configs and SSL certs | Full `/etc/nginx` and `/etc/letsencrypt` |
| Backs up UFW rules | Snapshot only |
| Generates SSH key | For repo access |
| Shuts down legacy stack | `docker compose down` |
| Cleans Nginx | Removes all sites for fresh install |
| Verifies port 51820 is free | Fails if still in use |
At the end, the script prints the SSH public key. Send it to Simplified Privacy before running `01`.
---
## Step 01 — Install operator-docker
Once Simplified Privacy authorizes the SSH key, run as your Linux user:
```bash
bash 01-migrate-user.sh
```
What it does:
| Action | Detail |
| :----- | :----- |
| Validates backups exist | Fails early if `00` was not run |
| Cleans any failed previous install | Detects corrupt `.env`, incomplete repo |
| Clones private repo | Via SSH |
| Runs `install.sh` in migration mode | WireGuard is NOT started yet |
| Creates `wg0.conf` placeholder | `02` will inject the real private key |
| Restores external Nginx configs | e.g. mail server vhosts |
> `MIGRATION_MODE=1` tells the installer to skip starting WireGuard. The `02` script starts it after injecting the legacy identity.
---
## Step 02 — Migrate identity and peers
```bash
bash 02-migrate-peers.sh
```
What it does:
| Action | Detail |
| :----- | :----- |
| Stops legacy WireGuard | Via `docker compose stop` in legacy dir |
| Injects legacy private key | Into `wg0.conf` and server keyfiles |
| Starts new WireGuard | With the legacy identity |
| Verifies public key matches | Fails and rolls back if it doesn't |
| Verifies API is responding | `GET /wireguard/peers` must return 200 |
| Migrates all peers | `POST /wireguard/peers` for each peer |
| Destroys private key from disk | `shred` or `rm` |
---
## Rollback
Each script has automatic rollback on failure:
- `00` — No rollback needed (legacy stays running until `02`)
- `01` — Removes `operator-docker`, restores Nginx and certs, restarts legacy
- `02` — Stops new WireGuard, restores `wg0.conf`, restarts legacy
Manual rollback if needed:
```bash
# Restore SSL certificates
sudo cp -r ~/.wg-migration/letsencrypt/. /etc/letsencrypt/
# Restore Nginx
sudo cp -r ~/.wg-migration/nginx/sites-available/. /etc/nginx/sites-available/
sudo cp -r ~/.wg-migration/nginx/sites-enabled/. /etc/nginx/sites-enabled/
sudo systemctl restart nginx
# Remove operator-docker
rm -rf ~/operator-docker
# Restart legacy stack
LEGACY_DIR=$(cat ~/.wg-migration/legacy_compose_dir)
cd "$LEGACY_DIR" && docker compose up -d
```
WireGuard identity and peers are never modified in the legacy stack — they remain intact.
---
## Backup location
All backups are stored in `~/.wg-migration/`:
| File | Content |
| :--- | :------ |
| `private_key` | WireGuard private key (deleted after `02`) |
| `public_key` | WireGuard public key |
| `wg0-legacy.conf` | Full peer list |
| `wg0-legacy.conf.original` | Unmodified copy |
| `legacy.env` | Legacy stack `.env` |
| `legacy_compose_dir` | Path to legacy stack |
| `nginx/` | Nginx sites and config |
| `letsencrypt/` | SSL certificates |
| `ufw-snapshot.txt` | UFW rules |
| `network_info` | IPv4/IPv6 detection result |
| `ssh_pubkey` | SSH public key for repo access |
| `migration.log` | Full log of all steps |
---
## Notes
- Existing VPN clients reconnect automatically after `02` completes — no config changes needed.
- The private key is destroyed from disk after successful peer migration.
- If port 80 is blocked externally, SSL certificate issuance will fail at step 01. Contact your VPS provider or use DNS challenge manually.
- IPv6 is detected and enabled automatically.
---
# Español
Migración sin tiempo de inactividad desde el stack legacy WireGuard + Go API hacia operator-docker. Los clientes VPN existentes se reconectan automáticamente — no requieren ningún cambio de configuración.
---
## Cómo funciona
```text
Antes de la migración
Stack legacy (sp-env-wireguard-ipv6)
├── wireguard (linuxserver/wireguard)
├── wireguard-api (Go)
└── nginx-certbot
Después de la migración
operator-docker
├── wireguard (misma identidad — misma clave pública)
├── operator-api (FastAPI)
├── marzban
├── hysteria2
└── mysql
```
La identidad WireGuard del servidor (clave privada → clave pública) se preserva.
Todos los peers se migran vía la nueva API. Los clientes se reconectan sin cambios.
---
## Requisitos
- Stack legacy corriendo (`docker ps` muestra `wireguard`)
- Dominio con DNS apuntando a este servidor
- Un subdominio por servicio (`api`, `legacy`, `cdn`, `news` o similar)
- SSH key autorizada por Simplified Privacy (generada en el paso 00)
- Puerto 80/TCP accesible externamente (requerido por Let's Encrypt)
---
## Pasos de migración
| Script | Ejecutar como | Descripción |
| :----- | :------------ | :---------- |
| `00-migrate-root.sh` | root | Backup, apaga legacy, limpia sistema |
| `01-migrate-user.sh` | usuario | Clona repo, instala operator-docker |
| `02-migrate-peers.sh` | usuario | Inyecta identidad, migra peers |
---
## Uso
Los scripts se pueden ejecutar desde cualquier directorio:
```bash
sudo bash ~/migration/00-migrate-root.sh
bash ~/migration/01-migrate-user.sh
bash ~/migration/02-migrate-peers.sh
```
---
## Paso 00 — Backup y limpieza
Ejecutar como root:
```bash
sudo bash 00-migrate-root.sh
```
Acciones:
| Acción | Detalle |
| :----- | :------ |
| Detecta el contenedor WireGuard legacy | Por imagen o nombre |
| Respalda clave privada y pública | Guardadas en `~/.wg-migration/` |
| Respalda todos los peers | Desde `wg showconf wg0` |
| Respalda Nginx y certificados SSL | `/etc/nginx` y `/etc/letsencrypt` completos |
| Respalda reglas UFW | Solo snapshot |
| Genera SSH key | Para acceso al repo |
| Apaga el stack legacy | `docker compose down` |
| Limpia Nginx | Elimina todos los sites para instalación limpia |
| Verifica que el puerto 51820 esté libre | Falla si sigue en uso |
Al finalizar, el script muestra la clave SSH pública. Envíala a Simplified Privacy antes de ejecutar el `01`.
---
## Paso 01 — Instalar operator-docker
Una vez que Simplified Privacy autorice la SSH key, ejecutar como usuario Linux:
```bash
bash 01-migrate-user.sh
```
Acciones:
| Acción | Detalle |
| :----- | :------ |
| Valida que existan los backups | Falla si no se ejecutó el `00` |
| Limpia instalación anterior fallida | Detecta `.env` corrupto, repo incompleto |
| Clona el repo privado | Vía SSH |
| Ejecuta `install.sh` en modo migración | WireGuard NO se inicia todavía |
| Crea placeholder de `wg0.conf` | El `02` inyectará la clave privada real |
| Restaura configs Nginx externos | Por ejemplo, vhosts del servidor de correo |
> `MIGRATION_MODE=1` indica al instalador que omita el inicio de WireGuard. El script `02` lo inicia después de inyectar la identidad legacy.
---
## Paso 02 — Migrar identidad y peers
```bash
bash 02-migrate-peers.sh
```
Acciones:
| Acción | Detalle |
| :----- | :------ |
| Detiene WireGuard legacy | Vía `docker compose stop` en el directorio legacy |
| Inyecta la clave privada legacy | En `wg0.conf` y keyfiles del servidor |
| Inicia el nuevo WireGuard | Con la identidad legacy |
| Verifica que la clave pública coincida | Falla y hace rollback si no coincide |
| Verifica que la API responda | `GET /wireguard/peers` debe devolver 200 |
| Migra todos los peers | `POST /wireguard/peers` por cada peer |
| Destruye la clave privada del disco | `shred` o `rm` |
---
## Rollback
Cada script tiene rollback automático en caso de fallo:
- `00` — Sin rollback necesario (el legacy sigue corriendo hasta el `02`)
- `01` — Elimina `operator-docker`, restaura Nginx y certs, reinicia legacy
- `02` — Detiene el nuevo WireGuard, restaura `wg0.conf`, reinicia legacy
Rollback manual si es necesario:
```bash
# Restaurar certificados SSL
sudo cp -r ~/.wg-migration/letsencrypt/. /etc/letsencrypt/
# Restaurar Nginx
sudo cp -r ~/.wg-migration/nginx/sites-available/. /etc/nginx/sites-available/
sudo cp -r ~/.wg-migration/nginx/sites-enabled/. /etc/nginx/sites-enabled/
sudo systemctl restart nginx
# Eliminar operator-docker
rm -rf ~/operator-docker
# Reiniciar stack legacy
LEGACY_DIR=$(cat ~/.wg-migration/legacy_compose_dir)
cd "$LEGACY_DIR" && docker compose up -d
```
La identidad WireGuard y los peers nunca se modifican en el stack legacy — permanecen intactos.
---
## Ubicación del backup
Todos los backups se almacenan en `~/.wg-migration/`:
| Archivo | Contenido |
| :------ | :-------- |
| `private_key` | Clave privada WireGuard (eliminada tras el `02`) |
| `public_key` | Clave pública WireGuard |
| `wg0-legacy.conf` | Lista completa de peers |
| `wg0-legacy.conf.original` | Copia sin modificar |
| `legacy.env` | `.env` del stack legacy |
| `legacy_compose_dir` | Ruta al stack legacy |
| `nginx/` | Sites y configuración de Nginx |
| `letsencrypt/` | Certificados SSL |
| `ufw-snapshot.txt` | Reglas UFW |
| `network_info` | Resultado de detección IPv4/IPv6 |
| `ssh_pubkey` | Clave SSH pública para acceso al repo |
| `migration.log` | Log completo de todos los pasos |
---
## Notas
- Los clientes VPN existentes se reconectan automáticamente al finalizar el `02` — no requieren cambios de configuración.
- La clave privada se destruye del disco tras la migración exitosa de peers.
- Si el puerto 80 está bloqueado externamente, la emisión de certificados SSL fallará en el paso 01. Contacta a tu proveedor VPS o usa DNS challenge manualmente.
- IPv6 se detecta y habilita automáticamente.