From 55cacb0ff4240b6c5a5d99210a1c8e53e5a0bcb9 Mon Sep 17 00:00:00 2001 From: zenaku Date: Sun, 30 Aug 2026 13:11:52 +0000 Subject: [PATCH] universal zero-downtime migration from legacy WireGuard/Go stack to operator-docker --- readme.md | 385 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 385 insertions(+) create mode 100644 readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..8b10bff --- /dev/null +++ b/readme.md @@ -0,0 +1,385 @@ +# 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. \ No newline at end of file