CHIFACOSA — Da piattaforma centralizzata a software installabile

0

Il problema reale

Tre anni fa ho lanciato myBand.it — una piattaforma per musicisti, una sorta di Linktree evoluto. Ha funzionato. I musicisti erano soddisfatti. Poi è arrivata la domanda inevitabile: “Posso installare questo sul mio dominio?”

Era la domanda giusta. Una piattaforma centralizzata sul mio server è comoda per me, ma fragile per loro. Io controllo i dati, i backup, la continuità del servizio. Se chiudo domani, loro rimangono con niente. Se cambio i termini di servizio, non hanno scelta.

I musicisti volevano proprietà dei dati. Autonomia. Indipendenza.

Non potevo dargli myBand.it. Dovevo dargli qualcosa che potessero installare sul loro hosting, controllare completamente, spostare dove vogliono.

Così è nata CHIFACOSA.

Cosa significa renderlo installabile?

Non basta copiare il codice. Il vero problema è: come faccio in modo che lo stesso codice funzioni su tre ambienti completamente diversi?

  • Docker (per chi è tecnico, vuole il meglio)
  • WSL + Apache locale (per chi sviluppa su Windows come me)
  • Aruba Hosting Basic (hosting condiviso vecchio stile, niente SSH, solo FTP)

Questi ambienti hanno esigenze opposte:

  • Docker: variabili d’ambiente, container networking, storage volumes
  • WSL: permessi file Windows, path locali, single machine
  • Aruba: zero comandi shell, solo interfacce web, accesso limitato al filesystem

La sfida architetturale: Un unico codebase che capisce automaticamente dove gira e si configura di conseguenza.

Il primo bug: il database non era agnostico

Quando ho copiato il codice di myBand, il file schema.sql conteneva:

CREATE DATABASE myband;
USE myband;

Semplice? No. Chi installa CHIFACOSA su Aruba non può eseguire comandi SQL arbitrari — ha solo phpMyAdmin con una GUI. E il nome del database sarà user_chifacosa123, non myband.

Questo era il momento decisivo: o accettavo che il software fosse hardcoded a myBand (e quindi non realmente installabile), o ricostruivo tutto partendo da una premessa diversa.

Ho scelto la seconda strada.

La soluzione: configurazione stratificata

L’idea è semplice: il codice non deve sapere dov’è. Deve solo chiedere le credenziali al suo ambiente.

Ho implementato una gerarchia di configurazione:

Livello 1: Variabili d’ambiente (Docker, server moderni)

# docker-compose.yml
environment:
  DB_HOST: mysql
  DB_NAME: chifacosa
  DB_USER: chifacosa_user
  DB_PASS: secure_password
  SITE_NAME: CHI FA COSA
  ADMIN_EMAIL: admin@chifacosa.it

Il codice PHP legge queste variabili:

$db_host = getenv('DB_HOST') ?: 'localhost';
$db_name = getenv('DB_NAME') ?: 'chifacosa';

Livello 2: File config locale (Aruba, hosting condiviso)

Su Aruba le variabili d’ambiente non funzionano (non c’è modo di impostarle). Allora il codice controlla se esiste un file config.local.php:

if (file_exists(__DIR__ . '/../../config.local.php')) {
    require __DIR__ . '/../../config.local.php';
    $db_host = $LOCAL_DB_HOST ?? getenv('DB_HOST') ?: 'localhost';
}

L’utente di Aruba crea semplicemente:

<?php
// config.local.php (mai committato su GitHub)
$LOCAL_DB_HOST = '192.168.x.x';
$LOCAL_DB_NAME = 'user_chifacosa';
$LOCAL_DB_USER = 'user_chifacosa';
$LOCAL_DB_PASS = 'password_dal_pannello_aruba';

Questo significa: Il codice funziona ovunque. Su Docker legge le variabili d’ambiente. Su Aruba legge il file locale. Su WSL legge i defaults, ma puoi anche aggiungere un file locale se vuoi.

Il wizard: automazione intelligente

Non posso chiedere all’utente di importare manualmente schema.sql con phpMyAdmin. Troppo complicato. Allora ho creato install.php — una pagina che:

  1. Controlla se il database è già stato inizializzato
  2. Se no, guida l’utente passo per passo
  3. Su Aruba (dove non posso eseguire SQL), fornisce il file SQL pre-generato da importare via phpMyAdmin
  4. Su Docker, esegue direttamente lo schema
  5. Una volta completato, chiede nome del sito, email admin, password
  6. Blocca il wizard — non può essere rilancato
function check_installation_complete() {
    try {
        $stmt = $pdo->query("SELECT COUNT(*) FROM users");
        if ($stmt->fetchColumn() === 0) {
            header('Location: /install.php');
            exit;
        }
    } catch (Exception $e) {
        // Database non inizializzato
        header('Location: /install.php');
        exit;
    }
}

Ogni pagina chiama questa funzione. Se zero utenti nel database, ti reindirizza automaticamente all’installer. È semplice, elegante, e funziona su tutti e tre gli ambienti.

Il costo di questa portabilità

Non è gratis. Ho dovuto:

  • Niente path assoluti: Tutto relativo a costanti definite al boot
  • PDO con prepared statements: Non optional — SQL injection è un rischio reale quando il software viene installato su hosting di bassa qualità
  • Schema SQL puro, no migration tool: Laravel Migrations o Doctrine sarebbero troppi per hosting condiviso. Uso schema.sql puro + note di upgrade nel README
  • Gestione dei permessi file: Su WSL, cambiare proprietario a www-data rende i file illeggibili da Esplora File. Soluzione: mantenere proprietario gianluca, usare ACL o gestire permessi via PHP

Il flusso di deploy: tre realtà diverse

Docker

git clone https://github.com/posillipo/chifacosa.git
docker-compose up
# Accesso a http://localhost, install.php auto-configura tutto

Aruba

  1. Crea database via pannello di controllo
  2. Importa schema.sql via phpMyAdmin
  3. Carica file via FTP
  4. Crea config.local.php con credenziali
  5. Visita https://tuodominio.it/install.php

Lo stesso codice. Due install path diversi. Zero modifiche.

Perché è importante

CHIFACOSA è uno strumento di liberazione. Non per i developer — per i creativi, i musicisti, i professionisti che non vogliono dipendere da una SaaS.

Ma questo è possibile solo se il software è realmente autonomo. Se richiede SSH, comandi shell, variabili d’ambiente custom — allora non è per persone normali. È per persone che sanno come amministrare un server.

Io voglio che CHIFACOSA sia per persone normali.

Tutto il tecnicismo che vedrai negli articoli seguenti serve a un unico scopo: nascondi la complessità dietro a un’interfaccia semplice che funziona dovunque.

Nel prossimo articolo: Come ho strutturato la directory, il pattern MVC minimalista senza framework, e come il database schema comunica con il frontend tramite API REST semplici.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *