Primo giorno: script che preparano il PC di chi arriva

configura.sh (token Gitea, git, chiave SSH, nomi dei server), verifica.sh
(verde/rosso per ogni accesso), progetti.sh (scarica i repository visibili),
e un CLAUDE.md che guida la persona senza chiederle mai un segreto in chat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Fabio
2026-09-29 17:17:15 +02:00
co-authored by Claude Opus 5.5
commit 5b028688ba
6 changed files with 454 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
# Istruzioni per Claude: preparare il PC di chi arriva
Chi apre questo repository è una persona **nuova in OTO**, spesso non
tecnica, al primo giorno. Il tuo compito: portarla da "ho solo le password
provvisorie" a "`./verifica.sh` è tutto verde e ho scaricato i miei
progetti". Parla semplice, un passo alla volta, e controlla ogni passo prima
di passare al successivo.
La spiegazione per le persone sta in
`https://servizi.oto-farm.com/nuovo-collaboratore.html`: non contraddirla.
## Regole che non si negoziano
1. **Mai un segreto in chat.** Token Gitea, chiave e segreto AWS, password,
chiavi private: non chiederli e, se la persona li incolla, dille di
rigenerarli (un token finito in chat va considerato esposto). I segreti
li chiede `configura.sh` nel terminale, con l'input nascosto.
2. **Gli script che chiedono qualcosa li lancia la persona**, in un suo
terminale, non tu: tu non puoi rispondere al posto suo a un prompt
nascosto. Tu lanci solo `./verifica.sh` e i comandi di sola lettura.
3. **Non creare accessi e non chiederli.** Utenti AWS, utenti Gitea, VPN,
chiavi sui server li crea un amministratore (con gli script di `_OTO_IT`).
Se manca qualcosa, dillo con precisione ("serve che l'amministratore ti
aggiunga al repository X") e vai avanti col resto.
4. **Un "accesso negato" di AWS non è un guasto**: è il ruolo della persona.
Lo dici e prosegui.
5. **Non copiare file da altri PC** e non proporlo: se a un progetto manca un
segreto, va messo su AWS SSM da un amministratore.
## L'ordine
1. **Programmi**: `./verifica.sh` dice cosa manca tra git, Docker, AWS CLI.
Guida l'installazione per il sistema della persona (Linux, macOS o
Windows con WSL).
2. **AWS**, nel browser: entrare nella console con la password provvisoria,
sceglierne una nuova, attivare l'MFA, poi *nome in alto a destra →
Security credentials → Create access key* (uso: CLI). Poi nel terminale
`aws configure`, con regione `eu-central-1`. Controllo:
`aws sts get-caller-identity` deve mostrare `nome.cognome`.
3. **Gitea**, nel browser: cambiare la password provvisoria, poi
*Impostazioni → Applicazioni → Genera token* con permesso di scrittura
sui repository.
4. **`./configura.sh`**, nel terminale della persona: salva il token Gitea,
configura git, genera la chiave SSH, scrive i nomi dei server in
`~/.ssh/config`.
5. **La chiave SSH pubblica**: `configura.sh` la stampa. La persona la manda
all'amministratore (si può mandare in chat: è la parte pubblica). Ribadisci
che il file **senza** `.pub` non esce dal PC.
6. **VPN**: importare il file ricevuto (Linux: *Impostazioni → Rete → VPN →
+ → Importa da file*).
7. **`./verifica.sh`**: tutto verde, o un elenco preciso di cosa manca e a chi
chiederlo.
8. **`./progetti.sh`**: scarica i progetti che la persona vede su Gitea.
Poi, in ogni progetto: `./start.sh` per i progetti con pannello,
`bin/local-init.sh` per Drupal e WordPress. Il resto lo spiega il
`CLAUDE.md` di quel progetto.
## Stato al 29/09/2026: cosa non è ancora pronto
Dillo alla persona, invece di farle scoprire un rosso inspiegabile:
- **le chiavi SSH personali non sono ancora installate sui server**: il
controllo SSH resterà rosso finché l'amministratore non aggiunge la sua;
- **alcuni progetti non hanno ancora tutti i segreti su SSM**: in locale
qualcosa può mancare;
- la produzione nuova non esiste ancora: in `~/.ssh/config` c'è quella vecchia.
+48
View File
@@ -0,0 +1,48 @@
# Primo giorno in OTO: preparare il PC
Questo repository serve una volta sola: prepara il tuo PC per lavorare sui
progetti OTO. Non contiene segreti. I segreti dei progetti li scaricano i
progetti stessi da AWS, con il tuo accesso personale.
La spiegazione completa (cosa sono i quattro accessi, chi li crea, cosa fai
quando qualcuno se ne va) è sul portale dei servizi, alla voce **Chi arriva →
Accessi e primo giorno**: `https://servizi.oto-farm.com/nuovo-collaboratore.html`.
## Prima di iniziare ti servono
Te li manda l'amministratore:
- la **password provvisoria di AWS** (utente `nome.cognome`);
- la **password provvisoria di Gitea**, con cui hai scaricato questo repository;
- il **file della VPN**, che arriva dal fornitore della VPN.
Sul PC ti servono installati **git**, **Docker**, la **AWS CLI** e
**Claude Code**.
## Come si usa
```bash
git clone https://git.oto-farm.com/admin/_OTO_IT_onboard.git
cd _OTO_IT_onboard
claude
```
e a Claude scrivi: **«configura la mia postazione»**. Ti guida passo per passo
e controlla ogni passo.
Se preferisci fare da solo:
```bash
./configura.sh # chiede quello che serve, una cosa per volta
./verifica.sh # dice verde o rosso per ogni accesso
./progetti.sh # scarica i progetti a cui hai accesso
```
Puoi rilanciarli quante volte vuoi: quello che è già a posto non viene
toccato.
## Una regola
**Token, password e chiavi private non si scrivono mai in chat, nemmeno a
Claude.** Quando serve un segreto, `configura.sh` lo chiede nel terminale senza
mostrarlo a schermo.
Executable
+53
View File
@@ -0,0 +1,53 @@
#!/bin/bash
#
# Valori e funzioni condivisi dagli script di questo repository.
# Qui non ci sono segreti: solo nomi di server e percorsi.
GITEA_URL="https://git.oto-farm.com"
GITEA_HOST="git.oto-farm.com"
AWS_REGIONE="eu-central-1"
# Dove stanno le cose della persona, sul suo PC. Gli script dei progetti
# leggono da qui: non cambiarli senza cambiare anche loro.
TOKEN_GITEA_FILE="$HOME/.config/oto/gitea.token"
CHIAVE_SSH="$HOME/.ssh/oto_ed25519"
CARTELLA_PROGETTI="${CARTELLA_PROGETTI:-$HOME/Work/workspace/oto}"
# I server, con i nomi che usano gli script dei progetti. Staging sta su rete
# privata: senza VPN non risponde. La produzione "vecchia" e' questa; quando
# arriva la nuova si cambia qui e si rilancia configura.sh.
STAGING_NOME="oto-staging"
STAGING_HOST="10.110.185.10"
PRODUZIONE_NOME="oto-produzione"
PRODUZIONE_HOST="vps-production.oto-farm.com"
UTENTE_SERVER="admin"
# Un parametro che ogni ruolo di sviluppo puo' leggere: serve a verifica.sh
# per sapere se l'accesso AWS arriva davvero alla cassaforte.
SSM_PROVA="/oto/_comune/MAILTRAP_SMTP_USER"
if [ -t 1 ] ; then
VERDE=$'\e[32m' ; ROSSO=$'\e[31m' ; GIALLO=$'\e[33m' ; GRASSETTO=$'\e[1m' ; FINE=$'\e[0m'
else
VERDE="" ; ROSSO="" ; GIALLO="" ; GRASSETTO="" ; FINE=""
fi
ok () { echo " ${VERDE}✔${FINE} $*" ; }
male () { echo " ${ROSSO}✘${FINE} $*" ; }
attento () { echo " ${GIALLO}!${FINE} $*" ; }
titolo () { echo ; echo "${GRASSETTO}$*${FINE}" ; }
c_e () { command -v "$1" > /dev/null 2>&1 ; }
token_gitea () {
[ -s "$TOKEN_GITEA_FILE" ] && tr -d '[:space:]' < "$TOKEN_GITEA_FILE"
}
# Stampa il nome utente Gitea del token, o niente se il token non vale.
utente_gitea () {
local token
token="$(token_gitea)" || return 1
[ -n "$token" ] || return 1
curl -s --max-time 10 -H "Authorization: token $token" "$GITEA_URL/api/v1/user" \
| sed -n 's/.*"login":"\([^"]*\)".*/\1/p'
}
Executable
+124
View File
@@ -0,0 +1,124 @@
#!/bin/bash
#
# PREPARA IL PC: token Gitea, git, chiave SSH, nomi dei server.
#
# ./configura.sh
#
# Si lancia nel proprio terminale (chiede il token Gitea con l'input
# nascosto). Si puo' rilanciare: quello che e' gia' a posto non viene toccato.
# Non crea accessi: quelli li crea un amministratore, qui si usano.
set -u
cd "$(dirname "$0")" || exit 1
. ./comune.sh
# --------------------------------------------------------------------------
titolo "1. AWS"
# --------------------------------------------------------------------------
if ! c_e aws ; then
male "AWS CLI non installata: installala e rilancia questo script."
elif IDENTITA="$(aws sts get-caller-identity --query Arn --output text 2> /dev/null)" ; then
ok "accesso AWS: ${IDENTITA##*/}"
else
attento "AWS non ancora configurato. Nel terminale:"
echo " aws configure (regione: $AWS_REGIONE)"
echo " con la chiave che crei dalla console AWS (Security credentials)."
fi
# --------------------------------------------------------------------------
titolo "2. Gitea"
# --------------------------------------------------------------------------
UTENTE="$(utente_gitea)"
if [ -n "$UTENTE" ] ; then
ok "token Gitea gia' salvato (utente $UTENTE)"
else
echo " Incolla il token Gitea (Impostazioni → Applicazioni → Genera token)."
echo " Non si vede mentre lo incolli, ed e' normale."
read -r -s -p " Token: " TOKEN ; echo
TOKEN="$(printf '%s' "$TOKEN" | tr -d '[:space:]')"
mkdir -p "$(dirname "$TOKEN_GITEA_FILE")"
chmod 700 "$(dirname "$TOKEN_GITEA_FILE")"
( umask 077 ; printf '%s\n' "$TOKEN" > "$TOKEN_GITEA_FILE" )
UTENTE="$(utente_gitea)"
if [ -n "$UTENTE" ] ; then
ok "token valido, salvato in $TOKEN_GITEA_FILE (utente $UTENTE)"
else
rm -f "$TOKEN_GITEA_FILE"
male "Gitea non accetta questo token: controlla di averlo copiato intero, o generane un altro."
fi
fi
# git: chi sei, e come si ricorda le credenziali. Il token vale anche come
# password per git: lo si scrive una volta in ~/.git-credentials.
if [ -n "$UTENTE" ] ; then
[ -n "$(git config --global user.name)" ] || git config --global user.name "$UTENTE"
if [ -z "$(git config --global user.email)" ] ; then
read -r -p " La tua email di lavoro (per i commit): " EMAIL
[ -n "$EMAIL" ] && git config --global user.email "$EMAIL"
fi
[ -n "$(git config --global credential.helper)" ] || git config --global credential.helper store
CREDENZIALI="$HOME/.git-credentials"
if ! grep -q "@$GITEA_HOST" "$CREDENZIALI" 2> /dev/null ; then
( umask 077 ; printf 'https://%s:%s@%s\n' "$UTENTE" "$(token_gitea)" "$GITEA_HOST" >> "$CREDENZIALI" )
fi
ok "git configurato ($(git config --global user.name) <$(git config --global user.email)>)"
fi
# --------------------------------------------------------------------------
titolo "3. Chiave SSH"
# --------------------------------------------------------------------------
if [ -f "$CHIAVE_SSH" ] ; then
ok "chiave gia' presente: $CHIAVE_SSH"
else
mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh"
COMMENTO="${UTENTE:-$(whoami)}@oto"
ssh-keygen -q -t ed25519 -f "$CHIAVE_SSH" -C "$COMMENTO" -N "" \
&& ok "chiave creata: $CHIAVE_SSH"
fi
if [ -f "$CHIAVE_SSH.pub" ] ; then
echo
echo " Manda all'amministratore QUESTA riga (e' la parte pubblica, si puo' mandare in chat):"
echo
echo " $(cat "$CHIAVE_SSH.pub")"
echo
echo " Il file $CHIAVE_SSH, senza .pub, non esce mai da questo PC."
fi
# --------------------------------------------------------------------------
titolo "4. Nomi dei server in ~/.ssh/config"
# --------------------------------------------------------------------------
# Un blocco fra due segni, riscritto intero a ogni giro: cosi' quando cambia
# un server basta rilanciare. Un nome gia' definito fuori dal blocco non si
# tocca (e' una configurazione tua).
CONFIG="$HOME/.ssh/config"
touch "$CONFIG" && chmod 600 "$CONFIG"
INIZIO="# >>> OTO (scritto da _OTO_IT_onboard/configura.sh) >>>"
FINE_BLOCCO="# <<< OTO <<<"
# Confronto esatto, non una regex: il segno contiene "/" e "(".
FUORI="$(awk -v i="$INIZIO" -v f="$FINE_BLOCCO" '$0 == i {dentro=1; next} $0 == f {dentro=0; next} !dentro' "$CONFIG")"
BLOCCO="$INIZIO"
for VOCE in "$STAGING_NOME $STAGING_HOST" "$PRODUZIONE_NOME $PRODUZIONE_HOST" ; do
set -- $VOCE
if printf '%s\n' "$FUORI" | grep -qE "^Host[[:space:]]+$1([[:space:]]|\$)" ; then
attento "$1 e' gia' definito in $CONFIG: lo lascio com'e'"
continue
fi
BLOCCO="$BLOCCO
Host $1
HostName $2
User $UTENTE_SERVER
IdentitiesOnly yes
IdentityFile $CHIAVE_SSH
"
done
BLOCCO="$BLOCCO$FINE_BLOCCO"
{ printf '%s\n' "$FUORI" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' ; echo ; printf '%s\n' "$BLOCCO" ; } > "$CONFIG.nuovo" \
&& mv "$CONFIG.nuovo" "$CONFIG" && chmod 600 "$CONFIG"
ok "ssh $STAGING_NOME e ssh $PRODUZIONE_NOME: configurati"
# --------------------------------------------------------------------------
titolo "Fatto"
# --------------------------------------------------------------------------
echo " Ora: importa il file della VPN, poi lancia ./verifica.sh"
Executable
+83
View File
@@ -0,0 +1,83 @@
#!/bin/bash
#
# SCARICA I PROGETTI A CUI HAI ACCESSO SU GITEA.
#
# ./progetti.sh # elenca e chiede quali scaricare
# ./progetti.sh nome1 nome2 # scarica questi
#
# Li mette in $CARTELLA_PROGETTI (di solito ~/Work/workspace/oto). Un progetto
# gia' scaricato non si tocca. Vedi solo i repository che l'amministratore ti
# ha dato: se ne manca uno, e' da chiedere a lui.
set -u
cd "$(dirname "$0")" || exit 1
. ./comune.sh
TOKEN="$(token_gitea)"
if [ -z "$TOKEN" ] || [ -z "$(utente_gitea)" ] ; then
male "token Gitea mancante o non valido: lancia prima ./configura.sh"
exit 1
fi
# Tutti i repository visibili, pagina per pagina.
ELENCO=""
PAGINA=1
while : ; do
BLOCCO="$(curl -s --max-time 15 -H "Authorization: token $TOKEN" \
"$GITEA_URL/api/v1/user/repos?limit=50&page=$PAGINA" \
| grep -o '"full_name":"[^"]*"' | sed 's/"full_name":"\(.*\)"/\1/')"
[ -z "$BLOCCO" ] && break
ELENCO="$ELENCO
$BLOCCO"
PAGINA=$((PAGINA + 1))
done
ELENCO="$(printf '%s\n' "$ELENCO" | grep -v '^$' | grep -v '/_OTO_IT_onboard$' | sort -u)"
if [ -z "$ELENCO" ] ; then
attento "non vedi ancora nessun progetto: chiedi all'amministratore di aggiungerti ai repository"
exit 0
fi
if [ "$#" -gt 0 ] ; then
SCELTI="$*"
else
titolo "Progetti che puoi scaricare"
printf '%s\n' "$ELENCO" | sed 's#.*/##' | nl -w3 -s'. '
echo
read -r -p "Numeri o nomi, separati da spazio (invio = nessuno, 'tutti' = tutti): " RISPOSTA
[ -z "$RISPOSTA" ] && exit 0
if [ "$RISPOSTA" = "tutti" ] ; then
SCELTI="$(printf '%s\n' "$ELENCO" | sed 's#.*/##')"
else
SCELTI=""
for R in $RISPOSTA ; do
case "$R" in
*[!0-9]*) SCELTI="$SCELTI $R" ;;
*) SCELTI="$SCELTI $(printf '%s\n' "$ELENCO" | sed -n "${R}p" | sed 's#.*/##')" ;;
esac
done
fi
fi
mkdir -p "$CARTELLA_PROGETTI"
titolo "Scarico in $CARTELLA_PROGETTI"
for NOME in $SCELTI ; do
COMPLETO="$(printf '%s\n' "$ELENCO" | grep -E "/$NOME\$" | head -n 1)"
if [ -z "$COMPLETO" ] ; then
male "$NOME: non lo vedi su Gitea"
continue
fi
if [ -d "$CARTELLA_PROGETTI/$NOME/.git" ] ; then
ok "$NOME: gia' scaricato"
continue
fi
if git clone -q "$GITEA_URL/$COMPLETO.git" "$CARTELLA_PROGETTI/$NOME" ; then
ok "$NOME"
else
male "$NOME: git clone non riuscito"
fi
done
echo
echo " In ogni progetto: ./start.sh (progetti con pannello) oppure bin/local-init.sh"
echo " (Drupal e WordPress). Apri claude nella cartella del progetto: ti spiega il resto."
Executable
+80
View File
@@ -0,0 +1,80 @@
#!/bin/bash
#
# DICE VERDE O ROSSO PER OGNI ACCESSO, e per ogni rosso cosa fare.
#
# ./verifica.sh
#
# Non modifica niente e non chiede niente: si puo' lanciare quando si vuole,
# anche da Claude. Esce 0 se e' tutto verde, 1 altrimenti.
set -u
cd "$(dirname "$0")" || exit 1
. ./comune.sh
ROSSI=0
rosso () { male "$@" ; ROSSI=$((ROSSI + 1)) ; }
titolo "Programmi"
for P in git docker aws curl ssh ; do
if c_e "$P" ; then ok "$P" ; else rosso "$P non installato" ; fi
done
if c_e docker ; then
if docker info > /dev/null 2>&1 ; then ok "Docker risponde"
else rosso "Docker installato ma non risponde (e' acceso? il tuo utente e' nel gruppo docker?)" ; fi
fi
if c_e claude ; then ok "Claude Code" ; else attento "Claude Code non installato (non obbligatorio, ma ti guida)" ; fi
titolo "AWS"
if c_e aws && IDENTITA="$(aws sts get-caller-identity --query Arn --output text 2> /dev/null)" ; then
ok "accesso: ${IDENTITA##*/}"
if aws ssm get-parameter --region "$AWS_REGIONE" --name "$SSM_PROVA" --query Parameter.Name --output text > /dev/null 2>&1 ; then
ok "legge i segreti comuni su SSM"
else
rosso "non legge SSM: all'amministratore serve darti il ruolo di sviluppo"
fi
else
rosso "AWS non configurato: aws configure (regione $AWS_REGIONE)"
fi
titolo "Gitea"
UTENTE="$(utente_gitea)"
if [ -n "$UTENTE" ] ; then
ok "token valido (utente $UTENTE)"
if grep -q "@$GITEA_HOST" "$HOME/.git-credentials" 2> /dev/null || [ -n "$(git config --global credential.helper)" ] ; then
ok "git sa come entrare su $GITEA_HOST"
else
rosso "git non ha le credenziali di Gitea: rilancia ./configura.sh"
fi
else
rosso "token Gitea mancante o non valido: rilancia ./configura.sh"
fi
titolo "Chiave SSH"
if [ -f "$CHIAVE_SSH" ] ; then ok "$CHIAVE_SSH" ; else rosso "chiave mancante: rilancia ./configura.sh" ; fi
titolo "VPN e server"
# La VPN si riconosce da una cosa sola: staging, che sta su rete privata,
# risponde sulla porta SSH.
if timeout 5 bash -c "exec 3<>/dev/tcp/$STAGING_HOST/22" 2> /dev/null ; then
ok "VPN attiva (staging raggiungibile)"
if ssh -o BatchMode=yes -o ConnectTimeout=8 "$STAGING_NOME" true 2> /dev/null ; then
ok "entri su staging ($STAGING_NOME)"
else
rosso "staging non accetta la tua chiave: l'amministratore deve ancora aggiungerla"
fi
else
rosso "staging non raggiungibile: la VPN e' accesa?"
fi
if ssh -o BatchMode=yes -o ConnectTimeout=8 "$PRODUZIONE_NOME" true 2> /dev/null ; then
ok "entri in produzione ($PRODUZIONE_NOME)"
else
attento "produzione: non entri (normale se non hai il ruolo di rilascio, o se la tua chiave non e' ancora stata aggiunta)"
fi
titolo "Risultato"
if [ "$ROSSI" = "0" ] ; then
ok "tutto a posto. Prossimo passo: ./progetti.sh"
exit 0
fi
male "$ROSSI cose da sistemare (sopra, in rosso)"
exit 1