You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6.0 KiB

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

# 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

# Generate .env.prod with secure passwords and WordPress salts
./generate-env-secrets.sh php-wp-ch_grataloup gratalouparchitecte.ch wp_42604_

This script:

3. Hydrate Vault

# 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:
    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

git push -u origin master

Wait for Drone to deploy containers on 208.

7. Export Data from Source (199)

# 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)

# 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)

# 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:

dig gratalouparchitecte.ch +short
# Should return: 208.87.129.133

11. Restart Container for SSL

ssh g@208.87.129.133 "docker restart php-wp-ch_grataloup_wp"

Verify SSL certificate:

echo | openssl s_client -connect gratalouparchitecte.ch:443 -servername gratalouparchitecte.ch 2>/dev/null | openssl x509 -noout -issuer -subject -dates

12. Verify Site

# 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

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:

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:

docker restart php-wp-ch_grataloup_wp

Site redirects to /wp-admin/install.php

TABLE_PREFIX mismatch. Check source database tables:

docker exec <db_container> mariadb -u root -p<pass> <db_name> -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)