Perché SSH è fondamentale per le agenzie WordPress
L’accesso SSH (Secure Shell) rappresenta lo strumento più potente per la gestione professionale di siti WordPress client. Mentre il pannello di controllo e l’interfaccia web sono sufficienti per operazioni basilari, SSH consente di eseguire operazioni complesse, automazioni e interventi di emergenza con velocità ed efficienza impossibili da raggiungere altrimenti.
Per un’agenzia che gestisce decine o centinaia di siti WordPress, padroneggiare SSH non è opzionale: è una competenza core che distingue un team tecnico professionale da uno amatoriale. Secondo i dati del WordPress Security Report 2025, le agenzie che utilizzano SSH per manutenzione e deployment riducono del 73% i tempi di risoluzione degli incidenti critici rispetto a chi si affida esclusivamente a FTP o pannelli web.
SSH permette di:
- Eseguire comandi WP-CLI per operazioni batch su database e contenuti
- Gestire file e permessi con precisione chirurgica
- Monitorare risorse server in tempo reale
- Automatizzare backup, deployment e aggiornamenti
- Risolvere emergenze quando il sito è irraggiungibile via web
- Eseguire operazioni di debug avanzato
Nelle prossime sezioni analizzeremo configurazione, operazioni quotidiane e workflow avanzati che ogni agenzia WordPress dovrebbe implementare.
Configurazione iniziale dell’accesso SSH
Generazione e gestione delle chiavi SSH
La prima regola per l’accesso SSH professionale: mai utilizzare password. Le chiavi SSH basate su crittografia asimmetrica offrono sicurezza superiore e workflow più efficienti. Ecco il processo corretto per generare una coppia di chiavi:
ssh-keygen -t ed25519 -C "agenzia@agencypilot.it" -f ~/.ssh/client_nomeazienda
Il parametro -t ed25519 specifica l’algoritmo EdDSA, che nel 2026 rappresenta lo standard consigliato per nuove chiavi grazie alla combinazione di sicurezza elevata e prestazioni superiori rispetto a RSA. Per sistemi legacy che non supportano Ed25519, utilizzare RSA con chiavi da 4096 bit:
ssh-keygen -t rsa -b 4096 -C "agenzia@agencypilot.it" -f ~/.ssh/client_legacy
Best practice per la gestione delle chiavi:
- Creare chiavi separate per ogni client o progetto importante
- Utilizzare passphrase robuste per proteggere le chiavi private
- Implementare ssh-agent per evitare di digitare passphrase ripetutamente
- Conservare backup crittografati delle chiavi in vault aziendale
- Rotare le chiavi ogni 12-18 mesi
- Documentare quali chiavi hanno accesso a quali server
Configurazione del file SSH config
Il file ~/.ssh/config trasforma SSH da strumento basico a sistema di gestione efficiente. Configurarlo correttamente elimina la necessità di ricordare hostname, username, porte e percorsi chiavi per ogni server:
Host cliente-produzione
HostName 203.0.113.45
User wp_deploy
Port 22022
IdentityFile ~/.ssh/cliente_prod
ServerAliveInterval 60
ServerAliveCountMax 3
Host cliente-staging
HostName staging.cliente.it
User deploy
Port 22
IdentityFile ~/.ssh/cliente_staging
ForwardAgent yes
Host *.agencypilot-managed
User agency_admin
IdentityFile ~/.ssh/agencypilot_master
StrictHostKeyChecking yes
UserKnownHostsFile ~/.ssh/known_hosts_clients
Con questa configurazione, connettersi diventa semplice come digitare ssh cliente-produzione. I parametri ServerAliveInterval e ServerAliveCountMax prevengono disconnessioni indesiderate durante operazioni lunghe.
Caricare la chiave pubblica sul server
Dopo aver generato la coppia di chiavi, è necessario installare la chiave pubblica sul server target. Il metodo più semplice quando si ha ancora accesso via password:
ssh-copy-id -i ~/.ssh/client_nomeazienda.pub -p 22022 utente@server.cliente.it
Se ssh-copy-id non è disponibile o si preferisce un controllo manuale, il processo manuale è:
cat ~/.ssh/client_nomeazienda.pub | ssh utente@server.it "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
Per ambienti ad alta sicurezza dove ogni agenzia ha un utente dedicato, richiedere al sistemista del cliente di aggiungere manualmente la chiave pubblica è la prassi corretta.
Operazioni WordPress essenziali via SSH
WP-CLI: il coltellino svizzero per WordPress
WP-CLI è lo strumento command-line ufficiale per WordPress e rappresenta la ragione principale per cui SSH è indispensabile. Permette di eseguire praticamente qualsiasi operazione WordPress senza toccare il browser.
Verificare l’installazione e versione di WP-CLI:
wp --info
Se WP-CLI non è installato, su server con accesso root o sudo:
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
Operazioni WP-CLI che ogni agenzia deve padroneggiare:
- Aggiornamenti controllati:
wp core update --version=6.8.2per specificare versione esatta - Gestione plugin batch:
wp plugin update --all --exclude=plugin-problematico - Operazioni database:
wp db optimizeewp db repair - Search-replace sicuro:
wp search-replace 'vecchiodomain.it' 'nuovodominio.it' --dry-run - Gestione utenti:
wp user create tecnico tecnico@agenzia.it --role=administrator - Cache management:
wp cache flushper object cache ewp transient delete --all - Verifica integrità:
wp core verify-checksumsewp plugin verify-checksums --all
Gestione file e permessi corretti
I permessi file errati sono tra le prime cause di problemi di sicurezza e malfunzionamenti. La configurazione corretta per WordPress è:
find /percorso/installazione/wordpress -type d -exec chmod 755 {} \;
find /percorso/installazione/wordpress -type f -exec chmod 644 {} \;
Il file wp-config.php deve avere permessi più restrittivi:
chmod 600 wp-config.php
Per verificare la proprietà corretta dei file (assumendo che l’utente web sia www-data):
sudo chown -R www-data:www-data /var/www/cliente.it/public_html
Un pattern comune per agenzie è avere file di proprietà dell’utente di deploy ma gruppo www-data, permettendo al web server di leggere ma non modificare:
sudo chown -R deploy:www-data /var/www/cliente.it
find /var/www/cliente.it -type d -exec chmod 750 {} \;
find /var/www/cliente.it -type f -exec chmod 640 {} \;
chmod 770 /var/www/cliente.it/wp-content/uploads
Monitoraggio risorse e troubleshooting
Durante incidenti o performance degradate, SSH permette diagnosi immediate:
Verificare carico server e processi:
top -u www-data
Identificare processi PHP problematici:
ps aux | grep php | grep -v grep | sort -k3 -r | head -10
Monitorare log di errore in tempo reale:
tail -f /var/log/nginx/error.log
tail -f /var/www/cliente.it/wp-content/debug.log
Verificare spazio disco:
df -h
du -sh /var/www/cliente.it/wp-content/uploads/*
Controllare connessioni database attive:
mysqladmin -u root -p processlist | grep wordpress_db
Automazioni e script per workflow agenzia
Script di backup automatizzato
Un sistema di backup solido è non negoziabile. Ecco uno script bash che ogni agenzia dovrebbe personalizzare e schedulare via cron:
#!/bin/bash
# backup-wordpress.sh
SITE_PATH="/var/www/cliente.it"
BACKUP_PATH="/backups/cliente.it"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="cliente_wp"
DB_USER="backup_user"
DB_PASS="password_sicura"
# Backup database
wp db export ${BACKUP_PATH}/db_${DATE}.sql --path=${SITE_PATH}
# Backup file
tar -czf ${BACKUP_PATH}/files_${DATE}.tar.gz -C ${SITE_PATH} .
# Rimuovi backup più vecchi di 30 giorni
find ${BACKUP_PATH} -name "*.sql" -mtime +30 -delete
find ${BACKUP_PATH} -name "*.tar.gz" -mtime +30 -delete
# Upload su storage remoto (esempio con rclone)
rclone sync ${BACKUP_PATH} remote:cliente-backups/
echo "Backup completato: ${DATE}"
Schedulare via crontab per esecuzione notturna:
0 3 * * * /home/deploy/scripts/backup-wordpress.sh >> /var/log/backup-cliente.log 2>&1
Deploy automatizzato con Git
Il deployment manuale via FTP è obsoleto e pericoloso. Un workflow Git-based professionale prevede:
#!/bin/bash
# deploy-production.sh
set -e # Exit on error
SITE_PATH="/var/www/cliente.it"
GIT_REPO="git@github.com:agenzia/cliente-wordpress.git"
BRANCH="production"
cd ${SITE_PATH}
# Backup pre-deploy
wp db export backup-pre-deploy-$(date +%Y%m%d_%H%M%S).sql
# Git pull
git fetch origin
git checkout ${BRANCH}
git pull origin ${BRANCH}
# Composer dependencies
composer install --no-dev --optimize-autoloader
# WP operations
wp core update-db
wp cache flush
# Restart PHP-FPM se necessario
sudo systemctl reload php8.3-fpm
echo "Deploy completato: $(date)"
Health check automatizzati
Script per verificare lo stato di salute di tutti i siti client:
#!/bin/bash
# health-check-all-sites.sh
SITES=(
"cliente1.it:/var/www/cliente1.it"
"cliente2.it:/var/www/cliente2.it"
"cliente3.it:/var/www/cliente3.it"
)
for site in "${SITES[@]}"; do
DOMAIN=$(echo $site | cut -d: -f1)
PATH=$(echo $site | cut -d: -f2)
echo "Checking ${DOMAIN}..."
# Core integrity
wp core verify-checksums --path=${PATH} || echo "⚠️ Checksum failed for ${DOMAIN}"
# Plugin updates available
UPDATES=$(wp plugin list --update=available --format=count --path=${PATH})
echo " ${UPDATES} plugin updates available"
# Database status
wp db check --path=${PATH} || echo "⚠️ Database issue for ${DOMAIN}"
echo "---"
done
Sicurezza SSH per ambienti production
Hardening configurazione SSH server
Per server sotto controllo dell’agenzia, implementare queste configurazioni in /etc/ssh/sshd_config:
# Disable root login
PermitRootLogin no
# Disable password authentication
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
# Use custom port (security through obscurity + riduce bot scanning)
Port 22022
# Limit users
AllowUsers deploy agency_admin
# Modern crypto only
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
# Connection limits
MaxAuthTries 3
MaxSessions 5
ClientAliveInterval 300
ClientAliveCountMax 2
Dopo modifiche, verificare sintassi e riavviare:
sudo sshd -t
sudo systemctl restart sshd
Fail2ban per protezione brute-force
Fail2ban monitora log e banna IP che mostrano comportamenti sospetti. Configurazione per SSH in /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = 22022
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
Verificare ban attivi:
sudo fail2ban-client status sshd
Audit e logging accessi
Implementare logging centralizzato degli accessi SSH per compliance e sicurezza:
# In /etc/ssh/sshd_config
LogLevel VERBOSE
# Inviare log a servizio centralizzato
# Con rsyslog in /etc/rsyslog.d/ssh-audit.conf
if $programname == 'sshd' then @logs.agencypilot.it:514
Analizzare log accessi:
grep 'Accepted publickey' /var/log/auth.log | tail -20
grep 'Failed password' /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr
SSH per team: gestione accessi multipli
Struttura utenti per agenzie
Per team con più tecnici, creare una gerarchia utenti chiara:
- agency_admin: accesso completo con sudo, solo per senior e emergenze
- developer: accesso file e WP-CLI, no sudo, per sviluppatori
- deploy: utente automatico per CI/CD, permessi limitati a deployment
- backup: utente read-only per sistemi di backup
Creare utente developer con accesso limitato:
sudo useradd -m -s /bin/bash -G www-data developer
sudo mkdir -p /home/developer/.ssh
sudo touch /home/developer/.ssh/authorized_keys
sudo chmod 700 /home/developer/.ssh
sudo chmod 600 /home/developer/.ssh/authorized_keys
Jump host e bastioni SSH
Per agenzie che gestiscono molti server, implementare un jump host centralizzato aumenta sicurezza e tracciabilità:
# Sul client, in ~/.ssh/config
Host bastion
HostName bastion.agencypilot.it
User agenzia
IdentityFile ~/.ssh/agency_master
Host cliente-*.prod
ProxyJump bastion
User deploy
IdentityFile ~/.ssh/deploy_key
Connettersi a server produzione attraverso bastion diventa trasparente:
ssh cliente-ecommerce.prod
Tutti gli accessi passano attraverso bastion dove vengono loggati e auditati.
Rotazione chiavi e revoca accessi
Quando un collaboratore lascia il team o una chiave viene compromessa:
- Rimuovere la chiave pubblica da
~/.ssh/authorized_keyssu tutti i server - Verificare rimozione con
grep "email@collaboratore.it" ~/.ssh/authorized_keys - Controllare log per identificare ultimo accesso:
last -i username - Per sicurezza massima, rigenerare tutte le chiavi host e aggiornarle su team
Documentare la procedura di offboarding includendo revoca accessi SSH come step obbligatorio.
Troubleshooting problemi SSH comuni
Errori di connessione e diagnostica
Quando SSH non si connette, diagnosticare con verbose output:
ssh -vvv utente@server.it
Problemi comuni e soluzioni:
- Permission denied (publickey): verificare che chiave privata corrisponda a pubblica su server, controllare permessi file chiave (deve essere 600)
- Connection timeout: verificare firewall, porta corretta, che il servizio SSH sia attivo con
systemctl status sshd - Host key verification failed: fingerprint server cambiato, rimuovere vecchia entry con
ssh-keygen -R hostname - Too many authentication failures: troppi tentativi con chiavi diverse, specificare chiave esatta con
ssh -i ~/.ssh/chiave_specifica
Performance e connessioni lente
Se SSH è lento, possibili cause:
- DNS lookup lenti: disabilitare DNS reverse lookup server-side aggiungendo
UseDNS noin sshd_config - GSSAPI authentication: disabilitare client-side con
GSSAPIAuthentication noin ssh_config - Network issues: testare latenza con
pingemtr
Abilitare compressione per connessioni con banda limitata:
ssh -C utente@server.it
Recupero accesso quando tutto va storto
In scenari estremi dove SSH non funziona più:
- Accedere via console seriale/VNC fornita dal provider hosting
- Verificare servizio SSH:
systemctl status sshde riavviare se necessario - Controllare configurazione:
sshd -tper verificare errori sintassi - Verificare firewall:
iptables -L -noufw status - Come ultima risorsa, riabilitare temporaneamente password authentication per ripristinare accesso chiavi
Tool e risorse avanzate
Software per gestione SSH multi-server
Per agenzie con decine di server, tool specializzati migliorano produttività:
- Ansible: automazione e orchestrazione via SSH, ideale per operazioni batch su molti server
- tmux/screen: multiplexer terminale per sessioni persistenti durante operazioni lunghe
- parallel-ssh (pssh): eseguire comandi SSH su più host contemporaneamente
- ssh-audit: tool open source per audit configurazione SSH e identificare debolezze crittografiche
Esempio utilizzo parallel-ssh per controllare versione PHP su tutti i server:
parallel-ssh -h hosts.txt -i "php -v | head -1"
Integrazione SSH in workflow CI/CD
Esempio GitHub Actions per deploy automatico via SSH:
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: deploy
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/cliente.it
git pull origin main
composer install --no-dev
wp cache flush
FAQ
È sicuro dare accesso SSH ai clienti?
Dipende dal livello tecnico del cliente e dall’architettura del server. Per clienti non tecnici, sconsigliato: preferire interfacce gestite come AgencyPilot o pannelli custom. Se necessario, creare un utente dedicato con permessi limitati (no sudo, solo cartella WordPress specifica) e forzare SSH con chiavi, mai password. Implementare logging rigoroso di tutte le azioni. In alternativa, offrire accesso SSH su richiesta temporaneo (chiave valida 24-48h) per esigenze specifiche.
Quale porta SSH utilizzare: 22 standard o custom?
La best practice moderna è utilizzare una porta custom (es. 22022, 2222) combinata con altri meccanismi di sicurezza. Cambiare porta riduce drasticamente scanning automatici da bot (oltre il 90% secondo analisi fail2ban), ma non offre vera sicurezza contro attacchi mirati. Deve essere parte di una strategia difensiva che include: autenticazione solo con chiavi, fail2ban attivo, utenti limitati, e firewall correttamente configurato. Per server ad alta visibilità, considerare port knocking o VPN come layer aggiuntivo.
Come gestire backup delle chiavi SSH per disaster recovery?
Implementare una procedura rigorosa: conservare backup crittografati delle chiavi private in password manager aziendale (1Password, Bitwarden) o vault dedicato (HashiCorp Vault). Ogni chiave deve essere documentata con: server/servizi a cui dà accesso, data creazione, passphrase (se stored separatamente), responsabile. Per chiavi critiche, implementare schema M-of-N dove sono necessarie chiavi di più persone (usando ssh-agent forwarding con bastion multi-firma). Testare recovery procedure trimestralmente. Mai commitare chiavi private in repository Git.
WP-CLI via SSH è più veloce dell’interfaccia admin WordPress?
Sì, drasticamente. WP-CLI bypassa l’overhead HTTP, rendering interfaccia, e limiti PHP execution time imposti da web server. Operazioni batch come aggiornamenti plugin multipli o search-replace database sono 10-50x più veloci. Esempio concreto: aggiornare 50 plugin via admin richiede 5-10 minuti con numerosi timeout risk; via WP-CLI con wp plugin update --all richiede 30-60 secondi. Inoltre WP-CLI permette automazione impossibile via GUI e output parseable per integrazione con script. Per agenzie, WP-CLI è essenziale per scalare operazioni su molti siti.
Come configurare accesso SSH per ambienti di staging e produzione separati?
Utilizzare chiavi SSH separate per staging e produzione per minimizzare rischio di operazioni su ambiente sbagliato. Nel file ~/.ssh/config creare entry distinte con naming convention chiaro (es. cliente-prod vs cliente-staging). Utilizzare colori prompt diversi nel file .bashrc per visual feedback: rosso per produzione, verde per staging. Per team, implementare bastion host separati o almeno utenti diversi. Nei workflow CI/CD, utilizzare secret/variabili ambiente separate per ogni ambiente. Considerare require sudo per operazioni critiche su produzione, mentre staging più permissivo per facilitare testing.