diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..daae5b8 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,199 @@ +# Migration: gratalouparchitecte.ch from 199 to 208 + +Migration from nginx-proxy (199.241.137.4) to Traefik (208.87.129.133) + +**Date:** 2025-12-10 +**Domain:** gratalouparchitecte.ch +**Table Prefix:** wp_42604_ + +## Source (199.241.137.4) + +- Containers: `ch_grataloup_wp`, `ch_grataloup_wp_db` +- Database: `ch_grataloup_wp_db_name` +- WordPress files: `/home/g/Documents/workspace/wordpress_sites/ch_grataloup/wordpress_files` +- Setup: nginx-proxy + letsencrypt companion, MySQL 5.7, bind mounts + +## Target (208.87.129.133) + +- Containers: `php-wp-ch_grataloup_wp`, `php-wp-ch_grataloup_wp_db`, etc. +- Database: `php-wp-ch_grataloup-db_name` +- Setup: Traefik, MariaDB 11, Docker volumes +- Deployment: Drone CI from Gitea + +--- + +## Migration Steps + +### 1. Project Setup + +```bash +# Copy template from hair_select project +cp -r php-wp-ch_hair_select php-wp-ch_grataloup +cd php-wp-ch_grataloup + +# Clean up +rm -rf .git MIGRATION.md + +# Initialize git +git init +git add -A +git commit -m "Initial commit from template" +``` + +### 2. Generate Secure Credentials + +```bash +# Generate .env.prod with secure passwords and WordPress salts +./generate-env-secrets.sh php-wp-ch_grataloup gratalouparchitecte.ch wp_42604_ +``` + +This script: +- Generates random passwords using `openssl rand -base64 32` +- Fetches WordPress salts from https://api.wordpress.org/secret-key/1.1/salt/ +- Updates .env.prod with all required values + +### 3. Hydrate Vault + +```bash +# Run from project directory +vault-new-project --env_file .env.prod --name php-wp-ch_grataloup --inventory_hostname sn48 +``` + +### 4. Create Gitea Repository + +1. Create repo at https://gitea.sn48.zivili.ch: `php-wp-ch_grataloup` +2. Add remote: + ```bash + git remote add origin ssh://git@gitea.sn48.zivili.ch:222/gbili/php-wp-ch_grataloup.git + ``` + +### 5. Activate in Drone + +1. Go to https://drone.sn48.zivili.ch +2. Find `php-wp-ch_grataloup` repository +3. Click "Activate" to enable builds + +### 6. Push to Trigger Deployment + +```bash +git push -u origin master +``` + +Wait for Drone to deploy containers on 208. + +### 7. Export Data from Source (199) + +```bash +# Export database (44MB) +ssh g@199.241.137.4 "docker exec ch_grataloup_wp_db sh -c 'mysqldump -u root -p\$MYSQL_ROOT_PASSWORD ch_grataloup_wp_db_name' > /tmp/grataloup_db.sql" + +# Export wp-content via docker (5.3GB) - avoids permission issues with Wordfence +# Note: tar may exit with code 1 due to "file changed as we read it" - this is normal +ssh g@199.241.137.4 "docker exec ch_grataloup_wp tar -czf /tmp/wp_content.tar.gz -C /var/www/html wp-content" +ssh g@199.241.137.4 "docker cp ch_grataloup_wp:/tmp/wp_content.tar.gz /tmp/grataloup_wp_content.tar.gz" +``` + +### 8. Transfer to Target (208) + +```bash +# Large transfer (5.3GB wp-content) - expect significant time +scp g@199.241.137.4:/tmp/grataloup_db.sql g@199.241.137.4:/tmp/grataloup_wp_content.tar.gz g@208.87.129.133:/tmp/ +``` + +### 9. Import Data on Target (208) + +```bash +# Copy SQL into container and import +ssh g@208.87.129.133 "docker cp /tmp/grataloup_db.sql php-wp-ch_grataloup_wp_db:/tmp/grataloup_db.sql && docker exec php-wp-ch_grataloup_wp_db sh -c 'mariadb -u root -p\"\$MYSQL_ROOT_PASSWORD\" \"\$MYSQL_DATABASE\" < /tmp/grataloup_db.sql'" + +# Extract wp-content to volume (5.3GB extraction takes several minutes) +ssh g@208.87.129.133 "docker run --rm -v php-wp-ch_grataloup_wp-data:/data -v /tmp:/backup alpine sh -c 'cd /data && tar -xzf /backup/grataloup_wp_content.tar.gz --strip-components=1'" +``` + +### 10. Update DNS + +Update A record for `gratalouparchitecte.ch` to point to `208.87.129.133` + +Verify: +```bash +dig gratalouparchitecte.ch +short +# Should return: 208.87.129.133 +``` + +### 11. Restart Container for SSL + +```bash +ssh g@208.87.129.133 "docker restart php-wp-ch_grataloup_wp" +``` + +Verify SSL certificate: +```bash +echo | openssl s_client -connect gratalouparchitecte.ch:443 -servername gratalouparchitecte.ch 2>/dev/null | openssl x509 -noout -issuer -subject -dates +``` + +### 12. Verify Site + +```bash +# Test internally (before DNS propagates) +ssh g@208.87.129.133 "curl -sL -H 'Host: gratalouparchitecte.ch' http://localhost | head -50" + +# Test externally +curl -sI https://gratalouparchitecte.ch +``` + +### 13. Decommission Old Containers + +```bash +ssh g@199.241.137.4 "docker stop ch_grataloup_wp ch_grataloup_wp_db && docker rm ch_grataloup_wp ch_grataloup_wp_db" +``` + +--- + +## Key Differences: 199 vs 208 + +| Aspect | 199 (Source) | 208 (Target) | +|--------|--------------|--------------| +| Reverse proxy | nginx-proxy + letsencrypt companion | Traefik | +| Database | MySQL 5.7 | MariaDB 11 | +| DB command | `mysql` | `mariadb` | +| Volume type | Bind mounts (entire /var/www/html) | Docker volumes (wp-content only) | +| SSL config | LETSENCRYPT_HOST env var | Traefik labels (certresolver) | +| Deployment | Manual docker-compose | Drone CI | + +--- + +## Troubleshooting + +### Database import fails with "Access denied" +The `-i` flag with `docker exec` doesn't pass stdin properly when piping from outside. Solution: Copy SQL file into container first, then import from inside. + +### wp-content export permission denied +Wordfence creates files with restricted permissions. Use `docker exec` to tar from inside the container, then `docker cp` to extract. + +### tar exits with code 1 "file changed as we read it" +This is a warning, not a fatal error. The archive is created successfully. Run `docker cp` separately after tar completes. Verify archive integrity with: +```bash +gzip -t /tmp/grataloup_wp_content.tar.gz +tar -tzf /tmp/grataloup_wp_content.tar.gz | head -20 +``` + +### SSL shows self-signed cert +Deploy AFTER DNS points to new server. If deployed before, restart the container after DNS propagates: +```bash +docker restart php-wp-ch_grataloup_wp +``` + +### Site redirects to /wp-admin/install.php +TABLE_PREFIX mismatch. Check source database tables: +```bash +docker exec mariadb -u root -p -e 'SHOW TABLES;' +``` +Update TABLE_PREFIX in .env.prod, re-run vault-new-project, redeploy. + +--- + +## Data Sizes + +- Database dump: 44MB +- wp-content archive: 5.3GB (large architect portfolio with images) +- Theme: Divi child theme (Grataloup v.0.0.1)