Distribuzione

In questa pagina

Distribuzione

site/ è un semplice sito statico - ospitalo ovunque vengano serviti file statici. bxSites deploy lo invia lì direttamente, con un solo comando: S3 (e qualsiasi servizio compatibile con S3 - DigitalOcean Spaces, Cloudflare R2, Backblaze B2, MinIO), Azure Blob Storage, Google Cloud Storage, Firebase Hosting, FTP, SFTP, rsync via SSH, Netlify, Vercel, Cloudflare Pages, una directory locale, oppure GitHub Pages.

Il comando deploy

Ogni target tranne i due più semplici (local/github-pages, che funzionano soltanto con dei flag - vedi Riferimento CLI) viene configurato tramite un file deployments/<nome>.json nella radice del progetto - un file per ogni target di deploy che usi realmente, ciascuno indicando quale target è, oltre ai campi propri di quel target:

bxSites deploy --entry=production
{ "target": "s3", "bucket": "my-docs-site", "accessKeyIdEnvVar": "AWS_ACCESS_KEY_ID", "secretAccessKeyEnvVar": "AWS_SECRET_ACCESS_KEY" }

I segreti provengono sempre da una variabile d'ambiente, mai da un valore letterale in deployments/*.json. Ogni campo che termina in EnvVar indica il nome della variabile d'ambiente che contiene il segreto vero e proprio (una chiave d'accesso, una password, un token API) - risolta dal vivo al momento del deploy, quindi deployments/*.json di per sé è sempre sicuro da mettere sotto controllo di versione. Un campo che è invece un percorso verso un file di credenziali che già gestisci tu stesso (una chiave privata SSH, una chiave JSON di service account GCP scaricata) è la sola eccezione - un campo semplice, dato che è il file stesso a dover restare fuori dal controllo di versione, non il suo percorso. In locale, quelle variabili d'ambiente possono provenire anche da un file .env (BoxLang ne carica uno automaticamente e getSystemSetting() - quello che ogni target usa per risolverle - lo controlla in modo trasparente) invece di esportarle a mano nella tua shell; in CI, impostale come veri segreti sul runner.

Distribuire su tutti i target contemporaneamente

Esegui bxSites deploy senza --entry né --target e ogni voce deployments/*.json viene distribuita a turno, a partire da un'unica build condivisa:

bxSites deploy

Il sito viene compilato una sola volta, indipendentemente da quante voci hai. Il fallimento di un target non ferma gli altri - ogni voce viene tentata, e il comando esce con un codice diverso da zero solo se almeno una di esse è fallita; il riepilogo riporta quante sono andate a buon fine (ad es. Deployed to 2/3 target(s) (1 failed)). Aggiungi --verbose (funziona anche con --entry/--target) per stampare una riga di avanzamento quando la build e ciascun target iniziano e finiscono, invece del solo riepilogo finale.

local

Copia il sito compilato in qualsiasi directory - un'unità condivisa, una cartella di staging, ovunque. È l'unico target che non necessita affatto di una voce in deployments/.

bxSites deploy --target=local --destination=/percorso/di/destinazione

github-pages

Lo stesso push che fa gh-deploy, raggiungibile anche da questo comando unificato - anch'esso non necessita di alcuna voce in deployments/:

bxSites deploy --target=github-pages [--branch=gh-pages] [--remote=origin] [--message="..."]

s3

Vero AWS S3, oppure qualsiasi servizio compatibile con S3 - imposta endpoint per qualsiasi cosa diversa da AWS stesso, e forcePathStyle: true per la maggior parte dei provider non-AWS.

{
  "target": "s3",
  "bucket": "my-docs-site",
  "region": "us-east-1",
  "prefix": "",
  "accessKeyIdEnvVar": "AWS_ACCESS_KEY_ID",
  "secretAccessKeyEnvVar": "AWS_SECRET_ACCESS_KEY"
}
{
  "target": "s3",
  "bucket": "my-docs-site",
  "endpoint": "https://nyc3.digitaloceanspaces.com",
  "forcePathStyle": true,
  "accessKeyIdEnvVar": "SPACES_KEY",
  "secretAccessKeyEnvVar": "SPACES_SECRET"
}

La stessa struttura (endpoint personalizzato + forcePathStyle: true) copre anche Cloudflare R2 (https://<accountid>.r2.cloudflarestorage.com), Backblaze B2, e MinIO/Wasabi.

azure

Azure Blob Storage, autenticato con un token SAS, una chiave d'account, o una connection string completa - esattamente uno dei tre.

{
  "target": "azure",
  "account": "mystorageaccount",
  "container": "site",
  "accountKeyEnvVar": "AZURE_STORAGE_KEY"
}

gcs

Google Cloud Storage, autenticato con una chiave JSON di service account scaricata (Google Cloud Console -> IAM & Admin -> Service Accounts -> Keys).

{
  "target": "gcs",
  "bucket": "my-docs-site",
  "serviceAccountKeyPath": "/path/to/service-account.json"
}

firebase

Firebase Hosting, che utilizza lo stesso tipo di chiave di service account di gcs.

{
  "target": "firebase",
  "siteId": "my-firebase-site",
  "serviceAccountKeyPath": "/path/to/service-account.json"
}

ftp / sftp

Carica l'intero sito su un server remoto via FTP o SFTP, preservandone la struttura delle cartelle. SFTP accetta una password oppure una chiave SSH.

{
  "target": "sftp",
  "host": "example.com",
  "username": "deploy",
  "remotePath": "/var/www/html",
  "key": "/home/me/.ssh/id_rsa"
}

rsync

Sincronizza il sito con un server remoto via SSH usando il vero binario rsync - più veloce di FTP/SFTP per una ricompilazione completa, dato che trasferisce solo ciò che è cambiato. Richiede rsync e ssh sulla macchina che esegue bxSites.

{
  "target": "rsync",
  "host": "example.com",
  "username": "deploy",
  "remotePath": "/var/www/html",
  "identityFile": "/home/me/.ssh/id_rsa"
}

netlify

{
  "target": "netlify",
  "siteId": "my-site-id-or-name.netlify.app",
  "authTokenEnvVar": "NETLIFY_AUTH_TOKEN"
}

vercel

{
  "target": "vercel",
  "projectId": "my-project",
  "authTokenEnvVar": "VERCEL_TOKEN"
}

cloudflare-pages

Cloudflare non dispone di un'API REST ufficialmente documentata per i deploy a caricamento diretto - solo della propria CLI wrangler. Questo target replica, per ingegneria inversa, lo stesso flusso di upload di Wrangler, e richiede un'implementazione dell'hash BLAKE3 nel classpath della JVM che la maggior parte delle installazioni Java predefinite non include - vedi Riferimento CLI e il codice sorgente stesso del target per il quadro completo e onesto sulle asperità di questo target.

{
  "target": "cloudflare-pages",
  "accountId": "your-account-id",
  "projectName": "my-project",
  "apiTokenEnvVar": "CLOUDFLARE_API_TOKEN"
}

Il comando package

Preferisci un semplice archivio rispetto a uno qualsiasi dei target qui sopra - allegare una build a una release GitHub, consegnarla a un host che accetta solo il caricamento di uno zip, oppure spedirla in un posto che nessuno dei target collegabili raggiunge? bxSites package compila il sito, poi lo comprime in un unico file la cui radice è il contenuto stesso del sito compilato (non una cartella site/ che lo racchiude):

bxSites package
bxSites package --output=dist/my-site.zip

--output ha come valore predefinito <projectRoot>/site.zip; un valore relativo viene risolto rispetto alla radice del progetto, e le sue cartelle padre vengono create automaticamente se non esistono già.

GitHub Actions (pubblicazione multi-versione)

Per la pubblicazione automatica a ogni push, invece di un bxSites deploy/gh-deploy eseguito manualmente, questo modulo include un workflow GitHub Actions già pronto all'uso (.github/workflows/pages.yml) che pubblica main e development come due versioni dello stesso sito su GitHub Pages, live in modo indipendente. Il resto di questa guida copre questo workflow, usato dalla documentazione di questo stesso repository.

Cosa fa

A ogni push su main o development che tocca docs/, bxsites.yaml, o il sorgente stesso del modulo (modifiche a tema/pipeline), il workflow:

  1. Installa BoxLang + bx-markdown
  2. Registra questo repository come modulo così che boxlang bxSites build si risolva
  3. Su qualsiasi branch diverso da main, punta baseURL a .../<nome-branch>/ solo per questo build (vedi sotto)
  4. Esegue boxlang bxSites build
  5. Invia site/ al branch gh-pages - main alla radice del sito, development a /development/ - senza toccare l'altra versione

È disponibile anche come trigger manuale (workflow_dispatch) dalla scheda Actions, per una ripubblicazione una tantum senza un nuovo commit.

Configurazione iniziale

GitHub Pages deve essere puntato sul branch gh-pages prima che il workflow possa pubblicare qualcosa - questa è un'impostazione del repository, non qualcosa che un file di workflow può attivare da solo. La prima esecuzione riuscita crea gh-pages per te, quindi fai questo dopo che il workflow è stato eseguito almeno una volta:

  1. Settings -> Pages
  2. Sotto Build and deployment -> Source, scegli Deploy from a branch
  3. Sotto Branch, scegli gh-pages e / (root)

Dopo di che, ogni push corrispondente compila e distribuisce automaticamente. L'URL pubblicato compare sotto Settings -> Pages una volta completato il primo deploy.

Pubblicare due versioni contemporaneamente

main pubblica sulla radice del sito (https://<user>.github.io/<repo>/) - trattala come la documentazione stabile/rilasciata. development pubblica su /development/ (https://<user>.github.io/<repo>/development/) - la documentazione più recente, non ancora rilasciata. Entrambe restano live simultaneamente: il job di ciascun branch effettua il push su gh-pages solo con keep_files: true e la propria destination_dir, quindi un deploy di development non sovrascrive mai il contenuto di main e viceversa.

Il bxsites.yaml proprio di main dovrebbe avere baseURL impostato sulla radice del sito (https://<user>.github.io/<repo>/); il workflow lo sovrascrive per ogni altro branch al momento del build, quindi il bxsites.yaml di development non ha bisogno di una propria voce baseURL perché tutto funzioni.

Per aggiungere un terzo branch (ad es. un'anteprima release/2.0), aggiungilo all'elenco on.push.branches e dagli un proprio passo di deploy con if: github.ref_name == '...' e destination_dir: release-2.0 (o simile) - lo schema è lo stesso di quello di development.

Usare questo per il tuo progetto

Copia .github/workflows/pages.yml nel tuo progetto (modifica la riga modules: se il tuo progetto necessita di qualcosa oltre a bx-markdown), attiva Pages come sopra, e i push su main/development pubblicheranno allo stesso modo. Se vuoi solo una singola versione pubblicata, elimina il branch che non ti serve da on.push.branches e il relativo passo di deploy.

Servire da un sotto-percorso di Pages di progetto

Un sito GitHub Pages di progetto (a differenza di un sito utente <user>.github.io) viene servito da https://<user>.github.io/<repo>/, non dalla radice del dominio. Imposta baseURL in bxsites.yaml su quell'URL completo così che ogni link interno, asset e voce di nav ottenga il prefisso /<repo>/ di cui ha bisogno - e così che venga generato anche un vero sitemap.xml:

baseURL: "https://<user>.github.io/<repo>/"
{ "baseURL": "https://<user>.github.io/<repo>/" }

Vedi Configurazione per il quadro completo di cosa fa baseURL. Un sito utente <user>.github.io, o qualsiasi dominio personalizzato mappato sulla radice del sito, può lasciare baseURL al suo valore predefinito (/).

Limitare chi può raggiungere il tuo sito

Qui non c'è alcun controllo degli accessi integrato - bx-sites produce sempre e soltanto un semplice site/ statico, e un file statico non ha alcun concetto di "chi sta chiedendo". Il robots: false di bxsites.json dice ai crawler ben educati di non indicizzare un build (utile per un deploy di staging/anteprima che non vuoi veder comparire nei risultati di ricerca), ma è una richiesta cortese, non un lucchetto - l'URL continua a funzionare per chiunque lo abbia. Se hai davvero bisogno di limitare l'accesso, questo deve avvenire davanti ai file statici, a qualunque host li stia servendo - alcune opzioni comuni, adatte a siti statici:

  • Cloudflare Pages/Access - metti il sito distribuito dietro una policy Cloudflare Access (lista email consentite, SSO, o un PIN monouso), senza bisogno di codice applicativo.
  • Netlify - protezione con password integrata, per sito o per singolo deploy, dalle sole impostazioni del sito.
  • Un piccolo reverse-proxy (qualsiasi host) - l'HTTP Basic Auth davanti ai file statici (una regola in stile .htpasswd, oppure una Cloudflare Worker/Netlify Edge Function di un solo file) basta per "tenere fuori i motori di ricerca e i visitatori a caso", anche se non è una vera identità per-utente come l'avrebbe un'app con login.

Nessuna di queste è una funzionalità di bx-sites - sono impostazioni a livello di host, che attivi ovunque finisca per essere servito site/.

Modifica questa pagina Scarica Markdown Ultimo aggiornamento Aug 28, 2026, 3:16:38 AM