Server Lamp su Alma Linux, Rocky Linux, Oracle Linux 10

lamp rhel

Comandi di base e configurazione iniziale

Questa guida assume che Linux (AlmaLinux, RockyLinux, oppure Oracle Linux 10) sia disponibile come macchina remota (attraverso servizi come digital oceans, oppure aruba cloud) oppure che firi come macchina virtuale (VMware).

Nel caso di una macchina locale la modalità di rete utilizzata è NAT, con macchina host Windows 11.

La guida è compatibile anche se usi linux su Virtualbox, l’unica differenza è come fare i port forwarding

Port Forwarding

Recperare l’ip della macchina virtuale. Da dentro oracle linux eseguire il comando ip a. Nel mio caso l’ip della macchina è 192.168.86.128

Dalla interfaccia di WMware acedi alla voce di menu Edit / Virtual Network Editor

Clicca sul pulsante Change Settings

vmware change setings

Clicca sulla riga VMnet8 e poi su NAT settings

vmware nat setings

Cliccare sul tasto Add e impostare la regole seguendo come da immagine, modificando dove serve

vmware nat setings

L’immagine precedente imposta la reole per accedere alla macchina con ssh. Per accedere alla macchina posso usare il comando seguente, sostituendo il nome utente reale

ssh localhost@[nomeutente] -p 34522

Comandi di sistema essenziali

Ecco i comandi che userai di più nella gestione quotidiana

# Aggiornare il sistema
sudo dnf update -y

# Riavviare / spegnere
sudo reboot
sudo shutdown -h now

# Informazioni sul sistema
uname -a
cat /etc/os-release
hostnamectl

# Gestione servizi (systemd)
sudo systemctl start   [servizio]
sudo systemctl stop    [servizio]
sudo systemctl restart [servizio]
sudo systemctl enable  [servizio]   # avvio automatico al boot
sudo systemctl disable [servizio]
sudo systemctl status  [servizio]

# Monitoraggio processi e risorse
top
htop          # più leggibile, installa con: sudo dnf install htop -y
df -h         # spazio disco
free -h       # memoria RAM

Abilitare CRB, EPEL e REMI

Questi repository estendono i pacchetti disponibili su distribuzioni AlmaLinux/RockyLinux/Oracle Linux 10.

  • CRB (CodeReady Builder): contiene pacchetti di sviluppo e dipendenze che normalmente non sono incluse nel repo base. Molti pacchetti di EPEL e REMI lo richiedono.
  • EPEL (Extra Packages for Enterprise Linux): repository della community Fedora con centinaia di pacchetti non presenti nei repo ufficiali Red Hat/Oracle.
  • REMI: repository specializzato per versioni aggiornate di PHP, MySQL e software LAMP. Fondamentale per installare PHP 8.5.

Per Oracle Linux 10 puoi i seguenti comandi

# Command to install the EPEL repository configuration package:
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm

# abilitare crb
sudo /usr/bin/crb status
sudo /usr/bin/crb enable

# Command to install the Remi repository configuration package:
sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-10.rpm
sudo dnf update

Per AlmaLinux / RockyLinux 10 puoi usare i seguenti comandi

sudo dnf config-manager --set-enabled crb
sudo dnf install epel-release
sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-10.rpm
sudo dnf update

Disabilitare SELinux

SELinux (Security-Enhanced Linux) è un sistema di controllo degli accessi obligtorio. In produzione va gestito correttamente, ma su un server di sviluppo locale crea spesso problemi con Apache, PHP e la lettura delle cartelle condivise.

Esegui la seguente linea di codice e poi riavvia la macchina

sudo sed -i -e "s/^SELINUX=.*/SELINUX=disabled/" /etc/selinux/config

Impostare il timezone

Verifica che il tuo timezone sia corretto, e nel caso correggilo con i seguenti comandi

# Verificare
timedatectl
date

# Elencare i timezone disponibili (filtrando per Europa)
timedatectl list-timezones | grep Europe

# Impostare Roma
sudo timedatectl set-timezone Europe/Rome

Programmi aggiuntivi

Opzionalmente puoi installare i seuenti programmi aggiuntivi

sudo dnf install wget curl zip unzip nano tar rsync dos2unix

Dopo aver abilitato epel-release puoi installare anche i seguenti programmi

sudo dnf install htop

Gestione pachetti con DNF

# per vedere i programmi installati
sudo dnf list installed

# per vedere se un programma è installato
sudo dnf list installed | grep libreoffice

# per rimuovere un pacchetto e le sue dipendenze
sudo dnf remove libreoffice*

# pulizia dei pacchetti residui
sudo dnf autoremove
sudo dnf clean all

Macchina Oracle cloud “Always free”

Tutorial utile a questa pagina

Tenere attiva istanza Oracle con stress ng

Le risorse che non vengono utilizzate a sufficienza possono essere ritirate da Oracle. Vedere di più a questa pagina.

Per evitare ciò possiamo usare l’utility stress-ng e schedularla di notte di modo che la nostra istanza continui a funzionare nel tempo. Per prima cosa procediamo a installare l’utility

sudo dnf install stress-ng

Dopodichè il comando che esegue è il seguente

stress-ng -c `grep -c ^processor /proc/cpuinfo` -t 5000 -l 22

dove

  1. -c grep -c ^processor /proc/cpuinfo recupera il numero di CPU
  2. -t 5000 è il numero di secondi impiegato dal job, poco meno di 1h e mezza
  3. -l 22 indica la percentuale stress

Per far girare questo applicativo ogni giorno aggiungere ils eguente comando a cronjob

sudo crontab -e

# strees ng per macchine oracle
00 05 * * * stress-ng -c `grep -c ^processor /proc/cpuinfo` -t 5000 -l 22

Aprire porte 80 e 443 per macchina oracle linux

Se usi una macchina virtuale “always free” creata su oracle linux assicurati di avere le porte 443 e 80 apert. Per fare ciò segui questi screenshot.

  1. Entra dentro la sezione “Networking” della macchina. Nella sezione “Attached VNICs” clicca sul link che porta alla tua subnet

subnet oracle

  1. Vai nel tab “Security” e infine clicca sulla riga relativa alla security list

oracle security list

  1. Naviga nel tab “Security rules” e infine aggiungi le regole per le porte 80 e 443 se non esistono

oracle security list oracle open http port

Aggiungere Swap

Se con il comando free -h oppure swapon --show lo spazio di swap è 0 ti consiglio di impostare lo spazio di swap. Per fare ciò crea prima il file di swap e imposta i permessi corretti.

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile

Dopodichè formatta il file come swap, e attiva lo swap

sudo mkswap /swapfile
sudo swapon /swapfile

Verifica che vi sia 2GB eseguendo il comando free -h. Per rendere lo swap permanente aggiungi la seguente voce in /etc/fstab

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Ora settiamo quanto il kernel deve usare lo swap, impostando lo swappiness

# Imposta subito (senza riavvio)
sudo sysctl vm.swappiness=10

# Rendi permanente
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Verifica con il seguente comando, dovrebbe restituire 10

cat /proc/sys/vm/swappiness

Firewall (firewalld)

Oracle Linux 10 usa firewalld come frontend per iptables. Il concetto base è quello delle zone: ogni interfaccia di rete viene assegnata a una zona con regole specifiche. La zona di default è public

Comandi base

# Stato del firewall
sudo systemctl status firewalld
sudo firewall-cmd --state

# Avviare e abilitare al boot
sudo systemctl enable --now firewalld

# Vedere tutte le regole attive
sudo firewall-cmd --list-all

# Vedere le zone disponibili
sudo firewall-cmd --get-zones
sudo firewall-cmd --get-active-zones

Abilitare servizi http e https

# Aggiungere http e https (permanente)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

# Ricaricare per applicare le modifiche permanenti
sudo firewall-cmd --reload

# Verificare
sudo firewall-cmd --list-services

Abilitare RDP

sudo firewall-cmd --permanent --add-port=3389/tcp    
sudo firewall-cmd --reload

Aprire porte singole

# Aprire la porta 3389 (TCP)
sudo firewall-cmd --permanent --add-port=3389/tcp

# Aprire una porta custom, es. 8080
sudo firewall-cmd --permanent --add-port=8080/tcp

# Aprire un range di porte
sudo firewall-cmd --permanent --add-port=8080-8090/tcp

# Ricaricare
sudo firewall-cmd --reload

# Verificare le porte aperte
sudo firewall-cmd --list-ports

Rimuovere regole

# Rimuovere un servizio
sudo firewall-cmd --permanent --remove-service=http

# Rimuovere una porta
sudo firewall-cmd --permanent --remove-port=3389/tcp

# Ricaricare
sudo firewall-cmd --reload

Gestione pacchetti con DNF

DNF è il package manager di Oracle Linux 10 (successore di YUM). Gestisce l’installazione, aggiornamento e rimozione di software.

Di seguito una serie di comandi base

# Aggiornare tutti i pacchetti
sudo dnf update -y

# Installare un pacchetto
sudo dnf install [nome-pacchetto] -y

# Installare più pacchetti
sudo dnf install wget curl git vim -y

# Rimuovere un pacchetto
sudo dnf remove [nome-pacchetto] -y

# Cercare un pacchetto
sudo dnf search [termine]

# Informazioni su un pacchetto
sudo dnf info [nome-pacchetto]

# Elencare i pacchetti installati
sudo dnf list installed
sudo dnf list installed | grep php

# Pulire la cache
sudo dnf clean all

# Vedere la cronologia delle operazioni
sudo dnf history

# Annullare l'ultima operazione
sudo dnf history undo last

# Elencare i gruppi disponibili
sudo dnf group list

# Installare un gruppo di pacchetti
sudo dnf group install 'Development Tools' -y

SSH con autenticazione a chiave

Macchina remota cloud

L’autenticazione con chiave SSH è più sicura della password. Generi una coppia di chiavi sul tuo PC, copi la chiave pubblica sul server, e da quel momento ti connetti senza digitare la password.

Installa ssh sul server

sudo dnf install openssh-server
sudo systemctl enable --now sshd

# per verificare ssh 
sudo systemctl status sshd

Genera la coppia di chiavi in locale, sul tuo PC

# Sul tuo computer locale (Windows PowerShell / macOS / Linux)
ssh-keygen -t ed25519 -C 'mio-server-oracle'

# Ti chiede dove salvare (default: ~/.ssh/id_ed25519)
# e una passphrase opzionale (consigliata)

# Verrà creata:
#   ~/.ssh/id_ed25519       (chiave privata - non condividere mai!)
#   ~/.ssh/id_ed25519.pub   (chiave pubblica - questa va sul server)

Copiare la chiave pubblica sul server

# Metodo 1: ssh-copy-id (Linux/macOS)
ssh-copy-id -i ~/.ssh/id_ed25519.pub utente@ip-server

# Metodo 2: manuale (se ssh-copy-id non è disponibile)
# Sul server, crea la cartella .ssh e il file authorized_keys
mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
# Incolla il contenuto del file id_ed25519.pub
chmod 600 ~/.ssh/authorized_keys

Configura SSH sul server

sudo nano /etc/ssh/sshd_config

# Valori consigliati:
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no    # disabilita login con password
PermitRootLogin no           # blocca login diretto come root

# Riavviare il servizio
sudo systemctl restart sshd

# Aprire la porta SSH nel firewall (se non già aperta)
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload

Crea il file config SSH locale (sul tuo PC). Il file ~/.ssh/config ti permette di definire alias e impostazioni per ogni server, evitando di digitare ogni volta ip, utente e chiave.

nano ~/.ssh/config
Host oracle-dev
    HostName 192.168.1.100
    User mario
    IdentityFile ~/.ssh/id_ed25519
    Port 22

Host oracle-prod
    HostName 10.0.0.50
    User deploy
    IdentityFile ~/.ssh/id_ed25519_prod

Modifica le permission del file creato

sudo chmod 600  ~/.ssh/config
sudo chown $USER:$USER ~/.ssh/config

Con questo file puoi connetterti semplicemente con ssh oracle-dev

Macchina locale VMWare

Con VMware in modalità NAT e il port forwarding configurato, non ti connetti direttamente all’IP della VM ma all’IP dell’host Windows sulla porta mappata.

Nel mio caso specifico ho fatto port forwarding della porta 34522 dell’host, sulla porta 22 del guest. Quindi per colelgarmi alla machina posso fare come segue

# Da PowerShell o terminale Windows
ssh mario@127.0.0.1 -p 34522

# Oppure, se ti connetti da un altro PC sulla stessa rete
ssh mario@192.168.86.128 -p 34522

Se vuoi semplificare il comando, aggiungi una voce al file `~/.ssh/config` sul tuo PC Windows (`C:\Users\mario\.ssh\config`):

Host oracle-dev
    HostName 127.0.0.1
    User mario
    Port 34522

Da quel momento ti basta:

ssh oracle-dev

Git con GitHub e Bitbucket

Installazione e configurazione base

sudo dnf install git

# Configurazione globale
git config --global user.name 'NomeCognome'
git config --global user.email 'nome@esempio.it'

# Verificare
git config --list

Se la cartella ~/.ssh non esiste creala ora

sudo mkdir ~/.ssh && sudo chown -R $USER:$USER ~/.ssh

Autenticazione con chiave SSH: Sia GitHub che Bitbucket supportano l’autenticazione tramite chiave SSH. Il processo è lo stesso per entrambi.

# Generare una chiave dedicata per GitHub
ssh-keygen -t ed25519 -C 'mario@esempio.it' -f ~/.ssh/id_github

# Generare una chiave dedicata per Bitbucket
ssh-keygen -t ed25519 -C 'mario@esempio.it' -f ~/.ssh/id_bitbucket

# Aggiungere le chiavi all'agente SSH
eval '$(ssh-agent -s)'
# oppure
eval "$(ssh-agent)"
# comandi per aggiungere chiavi
ssh-add ~/.ssh/id_github
ssh-add ~/.ssh/id_bitbucket

# per verificare le chiavi caricate 
ssh-add -l

Per visualizzare le chiavi pubbliche da copiare su GitHub/Bitbucket

cat ~/.ssh/id_github.pub
cat ~/.ssh/id_bitbucket.pub

Copia il contenuto di ogni .pub nelle rispettive impostazioni SSH del tuo account:

  • GitHub → Settings → SSH Keys
  • Bitbucket → Personal settings → SSH keys

File config SSH per Git

# nano ~/.ssh/config

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_github

Host bitbucket.org
    HostName bitbucket.org
    User git
    IdentityFile ~/.ssh/id_bitbucket

Testa la connessione con

ssh -T git@github.com
ssh -T git@bitbucket.org

Cartelle condivise (VMware Shared Folders e Samba)

VMWare cartella condivisa

Come prima cosa impostare la cartella da condividere con VMware

Cartella shre vmware

Supponiamo di mondare la cartella condivisa d. Crea la cartella dentro /mnt

sudo mkdir -p /mnt/d
sudo chown $USER:$USER /mnt/d

Per montare la cartella host sulla cartella /mnt/d di linux lanciare il seguente comando da terminale

sudo vmhgfs-fuse .host:/ /mnt/d/ -o allow_other -o uid=1000

Oppure puoi montare tutto dentro la cartella /mnt

sudo vmhgfs-fuse .host:/ /mnt/ -o allow_other -o uid=1000

Per scoprire le cartelle condivise `.host:/` dentro usare

vmware-hgfsclient

Per montare all’avvio della macchina

# Use shared folders between VMWare guest and host
.host:/    /mnt/d/    fuse.vmhgfs-fuse    defaults,allow_other,uid=1000     0    0

Samba - condivisione cartelle con Windows

Samba permette di esporre cartelle Linux come share di rete accessibili da Windows. L’utente Samba avrà lo stesso nome dell’utente Linux (mario), con una password Samba separata.

Dato che uso NAT sulla macchiana virtuale devo fare il port forwarding di una porta della macchina windows sulla macchina linux

esempio 34545 -> 445

Procedo con l’installazione di samba

# Installare Samba
sudo dnf install samba samba-client

# Abilitare e avviare
sudo systemctl enable --now smb nmb

# Aprire il firewall
sudo firewall-cmd --permanent --add-service=samba
sudo firewall-cmd --reload

Configura la share nel file smb.conf:

# sudo nano /etc/samba/smb.conf
[home-mario]
    comment = Home di Mario
    path = /home/mario
    valid users = mario
    read only = no
    browsable = yes
    create mask = 0664
    directory mask = 0775
    force user = mario
    force group = mario

Ora aggiungo la password all’utente samba

sudo smbpasswd -a mario

# Riavviare Samba
sudo systemctl restart smb

Da Windows, apri Esplora File e digita nella barra degli indirizzi \\ip-del-server. Dato però che ho mappato la porta 34545 (host) sulla macchina 445 (linux) posso attaccare una directory di rete teporanea a windows specificando la porta di connessione.

net use T: \\127.0.0.1\home-mario   /TCPPORT:34545 /user:mario

# per togliere la cartella di rete
NET USE T: /DELETE

Inserisci come credenziali mario e la password impostata con smbpasswd. Poiché mario è proprietario della propria home, avrà già pieno accesso in lettura e scrittura senza bisogno di modificare permessi.

Stack LAMP

Apache

Installiamo Apache (httpd) e lo configuriamo per supportare WordPress, Laravel e phpMyAdmin.

Procediamo con l’installazione

# Installazione
sudo dnf install httpd httpd-tools mod_ssl

# Abilitare e avviare
sudo systemctl enable --now httpd

Se la macchina è remota agiungiamo le seguenti regole al firewall

# lancia i seguenti comandi per aprire il firewall
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Per comodità decido di settare una variabile che riassume la porta utilizza dal web server apache

export APACHE_PORT=80
echo "export APACHE_PORT=80" >> ~/.bashrc

Se stai usando la macchina locale con NAT di seguito considero di aver fatto il port forwarding dalla porta 34580 (host) alla 34580 (guest). Quindi il web server apache risponderà all’indirizzo http://localhost:34580. Apporta le seguenti modifiche

export APACHE_PORT=34580

sudo nano /etc/httpd/conf/httpd.conf

# Assicurati che ci sia la seguente riga:
Listen 34580
    
# lancia i seguenti comandi per aprire il firewall
sudo firewall-cmd --zone=public --permanent --add-port=34580/tcp 
sudo firewall-cmd --reload

La root di Apache sarà /var/www. Quando accedi a localhost la root è /var/www/html

Modifica il file di configurazione principale:

sudo nano /etc/httpd/conf/httpd.conf

# Cerca la riga #ServerName www.example.com:80 e sostituiscila con:
ServerName localhost

# assicurati che ci sia "AllowOverride All" 
<Directory "/var/www/html">
 ....
 AllowOverride All

Aggiungi il virtualhost per la cartella /var/www/html che risponde all’indirizzo ip della macchina. Sostituisci $APACHE_PORT con la porta corretta.

sudo nano /etc/httpd/conf.d/000-default.conf

<VirtualHost *:$APACHE_PORT>
	ServerName ......
	DocumentRoot /var/www/html
  
	<Directory "/var/www/html">
		Options -Indexes +FollowSymLinks
		AllowOverride All
		Require all granted
	</Directory>
  
	ErrorLog /var/log/httpd/error.log
	CustomLog /var/log/httpd/access.log combined
</VirtualHost>

Disabilita il conf welcome.conf

sudo mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.old

Riavvia Apache e controlla lo status

sudo systemctl restart httpd
sudo systemctl status httpd

Per ogni sito crea un file di configurazione separato in /etc/httpd/conf.d/:

sudo nano /etc/httpd/conf.d/miosito.conf

<VirtualHost *:$APACHE_PORT>
    ServerName miosito.local
    DocumentRoot /var/www/miosito

    <Directory /var/www/miosito>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    ErrorLog /var/log/httpd/miosito-error.log
    CustomLog /var/log/httpd/miosito-access.log combined
</VirtualHost>

Se sono in locale per comodità posso aggiungere il mio utente locale al gruppo apache

sudo usermod -aG apache $USER

# riavvia macchina
sudo reboot

# controlla gruppi utente corrente
groups

D’ora in poi posso aggiornare i permessi della cartella /var/www nel seguente modo (di modo che posso modificare i files con il mio utente locale)

# Imposta permessi corretti
sudo chown -R apache:apache /var/www
sudo find /var/www -type d -exec chmod 775 {} \;
sudo find /var/www -type f -exec chmod 664 {} \;

Come utility creo uno script per aggiornare i permessi della cartella corrente, di modo che possa modificare senza problemi i files e cartelle con il mio utente locale

sudo nano /usr/local/bin/aggiorna_permessi_web.sh

#!/bin/bash

# Define user and group variables
WEB_USER="apache"
WEB_GROUP="apache"

# Script to update permissions recursively from current directory
# Usage: ./update_permissions.sh

# Check if running as root or with sudo
# if [ "$EUID" -ne 0 ]; then
#   echo "Please run as root or with sudo"
#   exit 1
# fi

# Set ownership recursively
echo "Updating ownership to $WEB_USER:$WEB_GROUP..."
sudo chown $WEB_USER:$WEB_GROUP -R .

# Set directory permissions (775)
echo "Setting directory permissions to 775..."
sudo find . -type d -exec chmod 775 {} \;

# Set file permissions (664)
echo "Setting file permissions to 664..."
sudo find . -type f -exec chmod 664 {} \;

echo "Permissions updated successfully!"

Rendi eseguibile lo script con

sudo chmod +x /usr/local/bin/aggiorna_permessi_web.sh

Per vedere i log di apache

# Log di errore principale
sudo tail -f /var/log/httpd/error_log

# Log accessi
sudo tail -f /var/log/httpd/access_log

# Log dei virtual host specifici
sudo tail -f /var/log/httpd/miosito-error.log

# Testare la configurazione senza riavviare
sudo apachectl configtest

# Ricaricare la configurazione
sudo systemctl reload httpd

PHP 8.5

Usiamo il repository REMI per installare PHP 8.5

sudo dnf module reset php

# per vedere i moduli php
sudo dnf module list php

# abilita il modulo per php8.5
sudo dnf module enable php:remi-8.5

Installiamo php

sudo dnf install php php-cli php-fpm php-mysqlnd php-zip php-devel php-gd php-mcrypt php-mbstring php-curl php-xml php-pear php-bcmath php-json php-opcache php-intl php-soap php-xmlrpc php-gettext php-ldap php-imap php-odbc php-pdo php-common php-process php-imagick php-xdebug

Per verificare la versione

php -v

Aumenta i limiti di PHP per compatibilità con WordPress e upload di file grandi:

# Trovare il percorso del php.ini
php --ini

# Di solito si trova in /etc/php.ini
sudo nano /etc/php.ini

# Modificare questi valori:
max_execution_time = 300
max_input_time = 300
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 512M
date.timezone = Europe/Rome

Configuriamo XDebug

# Trovare il file di configurazione xdebug
php --ini | grep xdebug

# modifica il file xdebug.ini
sudo nano /etc/php.d/15-xdebug.ini

# contenuto da aggiungere
xdebug.mode = develop,debug
xdebug.start_with_request = trigger
xdebug.client_host = localhost
xdebug.client_port = 9003

Riavviamo apache e controlliamo che sia caricato il modulo xdebug

# Riavviare Apache
sudo systemctl restart httpd php-fpm

# Verificare che Xdebug sia caricato
php -m | grep xdebug

Per debuggare con vscode

  1. Installa l’estensione PHP Debug su VS Code
  2. Crea il launch.json in VS Code: Nella cartella del tuo progetto, VS Code crea automaticamente .vscode/launch.json quando premi F5 → scegli PHP. Il contenuto sarà:
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003
        }
    ]
}

Come debug aggiungiamo il file info.php alla cartella /var/www/html

echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php
sudo chown apache:apache /var/www/html/info.php

Verifica lo stato navigando su http://[server_ip]:[apache_porta]

MariaDB

Creiamo il file /etc/yum.repos.d/MariaDB.repo e aggiungiamo ils eguente contenuto

sudo nano /etc/yum.repos.d/MariaDB.repo

[mariadb]
name = MariaDB
baseurl = https://mirror1.hs-esslingen.de/pub/Mirrors/mariadb/yum/12.2/rhel/$releasever/$basearch
gpgkey = https://mirror1.hs-esslingen.de/pub/Mirrors/mariadb/yum/RPM-GPG-KEY-MariaDB
gpgcheck = 1

Installa mariadb con il seguente comando

sudo dnf install MariaDB-server MariaDB-client

In aggiunta prosegui con i seguenti comandi

# Abilitare e avviare
sudo systemctl enable --now mariadb

# Verificare la versione
mariadb --version

# Wizard di configurazione sicurezza (imposta password root, rimuove utenti anonimi, ecc.)
sudo mariadb-secure-installation

# Rispondere così:
# Enter current password for root: [invio - vuota di default]
# Switch to unix_socket auth: N
# Change root password: Y  → inserisci una password sicura
# Remove anonymous users: Y
# Disallow root login remotely: Y
# Remove test database: Y
# Reload privilege tables: Y

Per gestire il database ti riporto alcune query di utilità generale

# Accedere a MariaDB
mariadb -u root -p

-- Creare un database e un utente
CREATE DATABASE miosito CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mario'@'localhost' IDENTIFIED BY 'password-sicura';
GRANT ALL PRIVILEGES ON miosito.* TO 'mario'@'localhost';
FLUSH PRIVILEGES;
EXIT;

phpMyAdmin

Scarichiamo l’ultima versione di phpMyAdmin e rendiamo il sito disponibile sotto http://localhost:[PORTA]/pma.

Procediamo con l’installazione

# mi spoto nella cartella /var/www/html
cd /var/www/html

# Scaricare l'ultima versione (controlla la versione corrente su phpmyadmin.net)
sudo wget https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.tar.gz

# Estrarre
sudo tar -xzf phpMyAdmin-latest-all-languages.tar.gz
sudo mv phpMyAdmin-*-all-languages pma

# pulizia 
sudo rm phpMyAdmin-latest-all-languages.tar.gz

# Creare la cartella temporanea
sudo mkdir -p /var/www/html/pma/tmp

# Permessi
sudo chown -R apache:apache /var/www/html/pma
sudo find /var/www/html/pma -type d -exec chmod 775 {} \;
sudo find /var/www/html/pma -type f -exec chmod 664 {} \;

Modifichiamo il file di configurazione di phpmyadmin

# Generare una stringa casuale per blowfish_secret (es. con openssl):
openssl rand -hex 16

# Copiare il file di config di esempio
sudo cp /var/www/html/pma/config.sample.inc.php /var/www/html/pma/config.inc.php

sudo nano /var/www/html/pma/config.inc.php

# Impostare nel file:
$cfg['blowfish_secret'] = 'stringa-generata-da-openssl-qui';
$cfg['TempDir'] = '/var/www/html/pma/tmp';

# per eseguire il login automatico (AMBIENTE LOCALE) aggiungere o modificare i seguenti parametri
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = 'password di root';
$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['AllowNoPassword'] = true;

Wordpress

Per una configurazione veloce di wordpress seguire questi passaggi. Supponiamo di voler creare il sito web www.miosito.wp avente come cartella root /var/www/www.miosito.wp. Inoltre suppongo sia già stato configurato correttamento il puntamento DNS. Per prima cosa scarichiamo wordpress e creiamo la cartella del sito.

Cominciamo a creare il database miositowp e il relativo utente utentesito identificato da password password

mariadb -u root -p
CREATE DATABASE miositowp DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE USER 'utentesito'@'%' IDENTIFIED BY 'password';
GRANT ALL ON miositowp.* TO 'utentesito'@'%';
FLUSH PRIVILEGES;
EXIT;

Scarichiamo wordpress e creiamo la cartella per il nuovo sito

cd /var/www
sudo wget https://wordpress.org/latest.tar.gz
sudo tar xzf latest.tar.gz
sudo mv wordpress www.miosito.wp
sudo rm latest.tar.gz

Da dentro la cartella del sito appena creato apri in modifica il file config di wordpress

cd /var/www/www.miosito.wp
sudo cp wp-config-sample.php wp-config.php
sudo nano wp-config.php

modifica le seguenti costanti

define( 'DB_NAME', 'nomedb' );
define( 'DB_USER', 'utentedb' );
define( 'DB_PASSWORD', 'passwordutente' );

Visitando questo sito aggiungi queste informazioni casuali sostituendo le costanti presenti

define( 'AUTH_KEY',         '' );
define( 'SECURE_AUTH_KEY',  '' );
define( 'LOGGED_IN_KEY',    '' );
define( 'NONCE_KEY',        '' );
define( 'AUTH_SALT',        '' );
define( 'SECURE_AUTH_SALT', '' );
define( 'LOGGED_IN_SALT',   '' );
define( 'NONCE_SALT',       '' );

Infine per comodità, dopo la costante WP_DEBUG aggiungi le seguenti costanti

define( 'WP_POST_REVISIONS', 5 );
define( 'WP_AUTO_UPDATE_CORE', false );
define( 'ALLOW_UNFILTERED_UPLOADS', true );

Crea ora il file per il sito

sudo tee /etc/httpd/conf.d/www.miosito.wp.conf > /dev/null <<EOF
<VirtualHost *:$APACHE_PORT>
    ServerName www.miosito.wp
    DocumentRoot /var/www/www.miosito.wp
    
    <Directory /var/www/www.miosito.wp>
        DirectoryIndex index.php index.html
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    ErrorLog /var/log/httpd/miosito.local_error.log
    CustomLog /var/log/httpd/miosito.local_access.log combined
</VirtualHost>
EOF

Aggiorna i permessi per la cartella root del sito

sudo chown -R apache:apache /var/www/www.miosito.wp
sudo find /var/www/www.miosito.wp -type d -exec chmod 775 {} \;
sudo find /var/www/www.miosito.wp -type f -exec chmod 664 {} \;

Controlla che non ci siano errori e riavvia apache

sudo apachectl configtest
sudo systemctl restart httpd
sudo systemctl status httpd

Supponiamo di creare ora uno script che gestisce la creazione di istanze wordpress sotto la cartella /var/www/html. In questo specifico caso non ho bisogno di creare un file virtualhost. La porta utilizzata è quella locale di apache overo la 34580. All’inizio dello script ci sono una serie di variabili da modificare secondo il tuo specifico caso

sudo nano /usr/local/bin/wp-manager.sh
#!/bin/bash
# wp-manager.sh - Gestione istanze WordPress
#
# Uso:
#   wp-manager.sh create <nome> <db_name>
#   wp-manager.sh delete <nome> <db_name>
#   wp-manager.sh list

WEB_ROOT="/var/www/html"
APACHE_PORT="34580"
DB_ROOT_PASSWORD="root"
URL_PREFIX="http://localhost"

create_wp() {
    SITE=$1
    DB_NAME=$2

    if [ -z "$SITE" ] || [ -z "$DB_NAME" ]; then
        echo "Uso: wp-manager.sh create <nome> <db_name>"
        exit 1
    fi

    SITE_DIR="$WEB_ROOT/$SITE"

    if [ -d "$SITE_DIR" ]; then
        echo "Errore: la cartella $SITE_DIR esiste già."
        exit 1
    fi

    echo ">>> Creazione database..."
    sudo mariadb -u root -p"$DB_ROOT_PASSWORD" -e "
        DROP DATABASE IF EXISTS $DB_NAME;
        CREATE DATABASE IF NOT EXISTS $DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    "

    echo ">>> Download WordPress..."
    cd /var/www/html
  
    if [ -f "latest.tar.gz" ]; then
        read -p "Il file latest.tar.gz esiste già. Vuoi riscaricarlo? [s/N] " risposta
        if [ "$risposta" = "s" ] || [ "$risposta" = "S" ]; then
            sudo rm -f latest.tar.gz
            sudo wget -q https://wordpress.org/latest.tar.gz
        fi
    else
        sudo wget -q https://wordpress.org/latest.tar.gz
    fi
    sudo tar -xzf latest.tar.gz
    sudo mv wordpress "$SITE"
    

    echo ">>> Configurazione wp-config.php..."
    sudo cp "$SITE/wp-config-sample.php" "$SITE/wp-config.php"
    sudo sed -i "s/database_name_here/$DB_NAME/"     "$SITE/wp-config.php"
    sudo sed -i "s/username_here/root/"              "$SITE/wp-config.php"
    sudo sed -i "s/password_here/$DB_ROOT_PASSWORD/" "$SITE/wp-config.php"

    # sostituzioni chiavi salt
    # Scarica le nuove chiavi
    NEW_KEYS=$(curl -s https://api.wordpress.org/secret-key/1.1/salt)

    # Individua la prima e l'ultima riga del blocco da sostituire nel file
    FIRST_LINE=$(grep -n "define( 'AUTH_KEY'" $SITE/wp-config.php | head -1 | cut -d: -f1)
    LAST_LINE=$(grep -n "define( 'NONCE_SALT'" $SITE/wp-config.php | head -1 | cut -d: -f1)

    # Sostituisce il blocco con le nuove chiavi usando sed
    sudo sed -i "${FIRST_LINE},${LAST_LINE}d" $SITE/wp-config.php
    sudo sed -i "$((FIRST_LINE - 1))r /dev/stdin" $SITE/wp-config.php <<< "$NEW_KEYS"


    # === 2) Inserimento delle costanti dopo define( 'WP_DEBUG', false ); ===
    EXTRA_DEFINES="define( 'WP_POST_REVISIONS', 5 );\ndefine( 'WP_AUTO_UPDATE_CORE', false );\ndefine( 'ALLOW_UNFILTERED_UPLOADS', true );"
    sudo sed -i "/define( 'WP_DEBUG', false );/a ${EXTRA_DEFINES}" $SITE/wp-config.php


    echo ">>> Permessi..."
    sudo chown -R apache:apache "$SITE"
    sudo chmod -R 775 "$SITE"
    sudo find "$SITE" -type d -exec chmod g+s {} \;

    # echo ">>> Ricarica Apache..."
    # sudo systemctl reload httpd

    echo ""
    echo "=== WordPress installato! ==="
    echo "  Cartella : $SITE_DIR"
    echo "  Database : $DB_NAME"
    if [ "$APACHE_PORT" = "80" ]; then
        echo "  URL      : $URL_PREFIX/$SITE"
    else
        echo "  URL      : $URL_PREFIX:$APACHE_PORT/$SITE"
    fi
}

delete_wp() {
    SITE=$1
    DB_NAME=$2

    if [ -z "$SITE" ] || [ -z "$DB_NAME" ]; then
        echo "Uso: wp-manager.sh delete <nomecartellasito> <nomedb>"
        exit 1
    fi

    SITE_DIR="$WEB_ROOT/$SITE"

    read -p "Sei sicuro di voler eliminare '$SITE'? (s/N): " CONFIRM
    if [[ "$CONFIRM" != "s" && "$CONFIRM" != "S" ]]; then
        echo "Operazione annullata."
        exit 0
    fi

    echo ">>> Rimozione cartella..."
    sudo rm -rf "$SITE_DIR"

    echo ">>> Rimozione database..."
    sudo mariadb -u root -p"$DB_ROOT_PASSWORD" -e "
        DROP DATABASE IF EXISTS $DB_NAME;
    "

}

list_wp() {
    echo "=== Istanze WordPress in $WEB_ROOT ==="
    echo ""
    FOUND=0
    for DIR in "$WEB_ROOT"/*/; do
        if [ -f "${DIR}wp-config.php" ]; then
            FOUND=1
            NAME=$(basename "$DIR")
            DB=$(grep "DB_NAME" "${DIR}wp-config.php" | grep -o "'[^']*'" | sed -n '2p' | tr -d "'")
            echo "  [$NAME]"
            echo "    Cartella : $DIR"
            echo "    Database : $DB"
            if [ "$APACHE_PORT" = "80" ]; then
                echo "    URL      : $URL_PREFIX/$NAME"
            else
                echo "    URL      : $URL_PREFIX:$APACHE_PORT/$NAME"
            fi
            echo ""
        fi
    done
    if [ $FOUND -eq 0 ]; then
        echo "  Nessuna istanza trovata."
    fi
}

case "$1" in
    create) create_wp "$2" "$3" ;;
    delete) delete_wp "$2" "$3" ;;
    list)   list_wp ;;
    *)
        echo "Uso:"
        echo "  wp-manager.sh create <nome> <db_name>"
        echo "  wp-manager.sh delete <nome> <db_name>"
        echo "  wp-manager.sh list"
        ;;
esac

Per rendere eseguibile lo script

sudo chmod +x /usr/local/bin/wp-manager.sh

Esempi d’uso dello script

# creo una nuova istanza con nome cartella "miosito" e nome database "miosito_db"
wp-manager.sh create miosito miosito_db

# elenco le istanze disponbili
wp-manager.sh list

# cancello l'istanza con nome cartella "miosito" e nome database "miosito_db"
wp-manager.sh delete miosito miosito_db

Dopo create, apri il browser su http://localhost:34580/miosito per completare l’installazione di WordPress.

Certificati SSL/TLS per i siti Apache

Usiamo Certbot con Let’s Encrypt per i siti raggiungibili da internet. Let’s Encrypt fornisce certificati gratuiti e riconosciuti da tutti i browser.

# Installare Certbot
sudo dnf install certbot python3-certbot-apache -y

# Ottenere e installare il certificato (modifica automaticamente il virtual host)
sudo certbot --apache -d miosito.com -d www.miosito.com

# Certbot chiederà:
# - indirizzo email per notifiche di scadenza
# - accettazione termini di servizio
# - se redirigere HTTP → HTTPS automaticamente (consigliato: sì)

Il certificato viene rinnovato automaticamente. Puoi testare il rinnovo con:

sudo certbot renew --dry-run

Per Elencare i certificati Let’s Encrypt gestiti da Certbot

sudo certbot certificates

Per rimuovere un certificato Let’s Encrypt:

# Revocare e cancellare il certificato
sudo certbot delete --cert-name miosito.com

# In alternativa, solo revocare (mantiene i file)
sudo certbot revoke --cert-path /etc/letsencrypt/live/miosito.com/fullchain.pem

# Dopo la cancellazione, rimuovere il virtual host HTTPS se non più necessario
sudo rm /etc/httpd/conf.d/miosito-ssl.conf
sudo systemctl reload httpd

Basic Auth Apache

Crea il file delle password

# Crea la directory per i file di auth (fuori dal webroot)
sudo mkdir -p /etc/httpd/auth

# Crea il primo utente (-c crea il file, usalo solo la prima volta)
sudo htpasswd -c /etc/httpd/auth/pma.htpasswd nomeutente

# Per aggiungere altri utenti (senza -c, altrimenti sovrascrive)
sudo htpasswd /etc/httpd/auth/pma.htpasswd altrouser

Poi modifica il file conf ssl di apache, aggiungendo la direttiva <Location>

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName ....
    DocumentRoot ....

    <Directory ....>
        ....
    </Directory>

    # Basic Auth tramite Location (ha precedenza su .htaccess)
    <Location "/">
        AuthType Basic
        AuthName "Area Riservata"
        AuthUserFile /etc/httpd/auth/pma.htpasswd
        Require valid-user
    </Location>

    ErrorLog ....
    CustomLog ....

    SSLCertificateFile ....
    SSLCertificateKeyFile ....
    Include ....
</VirtualHost>
</IfModule>

Il file conf relativo alla porta :80 non serve modificarlo perché fa già redirect a HTTPS.

Aggiusta i permessi sul file htpasswd

sudo chown root:apache /etc/httpd/auth/pma.htpasswd
sudo chmod 640 /etc/httpd/auth/pma.htpasswd

Verifica la configurazione e riavvia Apache

# Controlla che non ci siano errori di sintassi
sudo apachectl configtest

# Riavvia Apache
sudo systemctl restart httpd