Wordpress sincronizzato tra locale e hosting: missione impossibile?
Wordpress è il CMS più amato e odiato dagli sviluppatori di siti web. Se utilizzarlo è quasi semplice, lo sviluppo di siti complessi può essere come aprire il Vaso di Pandora. Tutto questo viene amplificato nel momento si utilizza un hosting condiviso e, specialmente, al momento del deploy finale o quando va ripreso in mano per fare le modifiche.
Le problematiche
I problemi con Wordpress sono fondamentalmente 2: il database e la gestione del tema.
Nel primo caso il problema è che quasi qualsiasi cosa venga fatta tramite la pagina di amministrazione del CMS viene registrata a database, in particolar modo i permalink come link assoluti comprensivi di dominio. Questo è un vero problema nel momento del passaggio da locale a remoto o viceversa, ma c’è una via relativamente semplice.
Nel secondo caso il problema è che nel momento del passaggio all’hosting si perde ogni storico di un eventuale versionamento. Ovviamente si perde anche nel momento del download in locale o quanto meno è particolarmente difficoltosa la sincronizzazione, specie quando si lavora in più persone sullo stesso sito.
L’approccio
Fino a questo momento facevamo il grosso del lavoro direttamente in una cartella di sviluppo sull’hosting, modificando i file del tema direttamente via FTP. Se si è sicuri che ci lavora una sola persona si può sviluppare solo in locale e mettere online a lavoro ultimato, ma nel momento in cui si lavora in team e/o vanno fatte modifiche successive l’unica via “semplice” è quella. Puoi immaginare la quantità di santi interpellati nel momento di un copia incolla errato o di un file caricato in due persone per sbaglio.
Da questa pena immonda la necessità di trovare una soluzione. Visto che abbiamo un server nostro con gitlab installato (ma la cosa è replicabile anche con le versioni managed e direi anche con github), sarebbe stato bello trovare un modo di usare la sua CI/CD per fare un deploy automatico delle modifiche del tema, magari al push. Ed ecco la soluzione: un workflow basato su ftp, docker e i runner di gitlab che lavori con la cartella themes di wordpress (per avere sincronizzati sia il tema base che eventuali temi child).
La configurazione lato hosting condiviso
Lo spazio hosting
La configurazione lato hosting è abbastanza banale. Si installa Wordpress nella cartella di destinazione come di consueto e si tengono a disposizione le credenziali FTP. Nel caso di hosting multisito è utile creare un utente FTP dedicato con la root direttamente alla cartella dove risiede l’installazione di Wordpress. Prendiamo nota di questi dati, ci serviranno successivamente.
Il database
Molti database di hosting condivisi hanno firewall che bloccano l’accesso dall’esterno. In questo caso basta tenere in whitelist l’ip con cui siamo visibili online, può essere utile avere un ip statico o una vpn con un exit node fisso, come una vps esterna. Prendiamo nota di indirizzo del database, username, password e nome database. È importante che l’indirizzo sia quello pubblico e non quello interno all’hosting, ad esempio su OVH quello che finisce per ovh.net e non privatesql
Creazione del repository remoto
Creiamo su Gitlab un repository remoto con un nome adeguato. Andiamo nella sezione Impostazioni->CI/CD->Variabili e aggiungiamo le variabili FTP_HOST con l’indirizzo dell’host FTP, FTP_USER con il relativo nome utente, FTP_PASSWORD con la relativa password e FTP_ROOTDIR con il nome della cartella di installazione di wordpress sull’hosting.
Inoltre va creata una chiave ssh, su Linux con il consueto ssh-keygen
, la parte privata va copiata nella variabile SSH_PRIVATE_KEY come file, la chiave pubblica nelle Deploy key dei progetti utilizzati come submodules e/o nelle chiavi ssh dell’utente stesso.
La prima configurazione in locale
Dato che collegheremo l’installazione locale direttamente al db, è sufficiente scaricare via ftp i file dell’installazione nella cartella del nostro server web locale. Bisognerà fare però alcuni aggiustamenti al sistema
Innanzitutto, se non l’avete mai creato sulla vostra macchina o non ne aveete a disposizione, va creato un certificato SSL. Dato che la nostra macchina non ha un dominio suo, va creato un cosiddetto certificato self-signed, tramite il comando
openssl req -newkey rsa:4096 -x509 -sha512 -days 365 -nodes -out certificate.crt -keyout privatekey.crt
Ai fini della configurazione è utile rinominare i file in modo che abbiano estensione .crt. Mettiamoli in una cartella, ad esempio /etc/apache/ssl/
.
A questo punto va modificato il file hosts, sotto Linux il famigerato file /etc/hosts
in modo che il dominio remoto punti al nostro localhost. Nel caso di Linux è sufficiente aggiungere la riga
127.0.0.1 dominio.it www.dominio.it
Ultima configurazione necessaria: va creato un Virtualhost che resti in ascolto sulla porta 443, rimanga in attesa del dominio del nostro sito, prenda il certificato SSL dove l’abbiamo salvato e rimandi alla cartella sul nostro computer.
Ad esempio, sotto Linux con Apache web server è sufficiente creare un file, ad esempio worpress.conf, all’interno della cartella /etc/apache/sites-available con un virtualhost simile al seguente
<VirtualHost *:443>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
ServerName dominio.it
ServerAlias www.dominio.it
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/www_dominio/
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
SSLEngine on
SSLCertificateFile /etc/ssl/localhost_cert/certificate.crt
SSLCertificateKeyFile /etc/ssl/localhost_cert/privatekey.crt
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
e aggiornare la configurazione di Apache con i seguenti comandi
sudo a2ensite wordpress.conf
sudo systemctl reload apache2.service
A questo punto basta controllare che in wp-config.php ci siano le variabili adeguate per l’acccesso al database e se ci colleghiamo al sito dominio.it vedremo il sito in locale con i contenuti sul database remoto. Non ci resta che versionare il tema e abilitare la CI/CD.
Versionamento del tema.
Per prima cosa inizializziamo il repository locale con
git init
e aggiungiamo il repository remoto come origin con il comando
git remote add git@servergit:gruppo_o_utente/repository origin
Accertiamoci di essere sul branch main, versioniamo i file e carichiamoli sul server
git fetch
git checkout main
git add .
git commit -m "Initial commit"
git push
Abilitiamo la CI/CD
Per abilitare la CI/CD è necessario avere un runner abilitato per il repository. Nel caso di Gitlab.com basta utilizzare un runner di quelli disponibili, per Gitlab self-hosted è necessario aggiungere un runner di tipo docker. Il file .gitlab-ci.yml da aggiungere al repository è il seguente
image: alpine
before_script:
- echo "Preparing run..."
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- touch ~/.ssh/known_hosts
- chmod 600 ~/.ssh/known_hosts
- apk add -qU openssh
- apk add git
- ssh-keyscan -H -p 22 server.gitlab.remoto | tee -a ~/.ssh/known_hosts
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
- git submodule sync --recursive
- git submodule update --init --recursive
- apk add lftp
build-main:
only:
- main
script:
- ls -altr .
- lftp -e "open $FTP_HOST; user $FTP_USERNAME $FTP_PASSWORD; mirror -X .* -X .*/ -X cypress/ -X package.json -X package-lock.json -X cypress.config.js --only-newer --parallel --reverse --verbose --delete ./ /$FTP_ROOT_DIR/wp-content/themes/; bye"
In caso di più runner attivi configurare quello prescelto con una tag abbastanza descrittiva e aggiungere alla build dello yaml le righe
tags:
- tagPrescelta
D’ora in poi ad ogni push il runner si clonerà il progetto, scaricherà eventuali submodule e caricherà sullo spazio ftp i file più recenti.
Configurazione per modifiche successive
Se abbiamo necessità di lavorare successivamente al sito è sufficiente seguire i seguenti passi
- Scaricare i file via ftp
- Controllare che il nostro indirizzo ip sia in whitelist
- Eseguire le eventuali riconfigurazioni per quanto riguarda Virtualhost e file hosts
- Rimuovere la cartella themes dell’installazione in locale
- clonare il repository remoto dando come cartelle di destinazione themes con il comando
git clone repository_remoto themes
La procedura è piuttosto lunga, ma in questo modo è possibile lavorare in locale versionando e sincronizzando il sito stesso con la versione online. L’unica cosa che va passata via FTP saranno gli uploads fatti tramite l’amministrazione di Wordpress ed eventuali plugin installati.
A te è mai successo di dover effettuare procedure simili? Hai usato altri sistemi? Fammelo sapere, sono curioso di provarli ed eventualmente portarli su questo blog