Skip to content

Latest commit

 

History

History
588 lines (437 loc) · 21.5 KB

File metadata and controls

588 lines (437 loc) · 21.5 KB

bootstrap-server.sh — guida d'uso

Setup base di un server Debian o Ubuntu appena installato: aggiornamento, utente amministratore, accesso SSH, Docker, Portainer, Git/GitHub, Claude Code, tmux e (opzionale) una cartella condivisa Samba.

Lo script è riprendibile: ogni passo completato viene registrato su disco. Se si interrompe (errore, rete caduta, Ctrl+C, SSH chiuso) basta rilanciarlo: salta quello che è già fatto e riparte dal passo interrotto con gli stessi parametri.


1. Requisiti

Requisito Dettaglio
Sistema Debian o Ubuntu (anche derivate con ID_LIKE=debian/ubuntu)
Privilegi root (sudo)
Utente di lavoro Un account non-root già esistente e con password impostata
Rete Accesso a Internet (repository apt, Docker Hub, GitHub)

Se l'utente non ha una password valida lo script si ferma. Impostala prima:

sudo passwd nomeutente

2. Avvio

# copia lo script sul server, poi:
chmod +x bootstrap-server.sh
sudo ./bootstrap-server.sh nomeutente

Se ometti il nome utente viene usato l'utente che ha lanciato sudo:

sudo ./bootstrap-server.sh

Vengono poste due domande: se vuoi la cartella condivisa Samba (in caso affermativo seguono nome, cartella, reti autorizzate e password) e se vuoi installare Claude Code. Tutte le domande arrivano all'inizio: da lì in poi l'installazione procede da sola. Senza un terminale interattivo (per esempio dentro uno script) entrambi vengono saltati e restano installabili dopo, con --samba e --claude-code.

Esecuzione in una sessione che non si interrompe

Su una connessione SSH instabile conviene lanciarlo dentro tmux o screen:

sudo apt-get install -y tmux
tmux new -s setup
sudo ./bootstrap-server.sh nomeutente
# se cade la connessione:  tmux attach -t setup

3. Comandi dello script

Comando Cosa fa
sudo ./bootstrap-server.sh [utente] Installazione o ripresa
sudo ./bootstrap-server.sh --status Mostra i passi completati e quando
sudo ./bootstrap-server.sh --portainer-token Mostra il token di setup di Portainer
sudo ./bootstrap-server.sh --samba [utente] Configura/aggiorna una condivisione Samba in seguito
sudo ./bootstrap-server.sh --claude-code Installa (o reinstalla) Claude Code in seguito
sudo ./bootstrap-server.sh --reset Azzera lo stato: al prossimo avvio riparte da zero
./bootstrap-server.sh --help Riassunto delle opzioni

Non è possibile eseguire due istanze contemporaneamente: la seconda si ferma con un messaggio (lock su /run/bootstrap-server.lock).


4. Cosa viene fatto, passo per passo

# Passo Contenuto
1 Aggiornamento del sistema apt-get update + full-upgrade, installa ca-certificates curl gnupg sudo openssh-server git tmux ncurses-term iproute2, pulizia pacchetti
2 Privilegi amministrativi Utente nel gruppo sudo + regola sudo senza password in /etc/sudoers.d/90-<utente>-nopasswd (validata con visudo -c)
3 Accesso SSH /etc/ssh/sshd_config.d/00-bootstrap.conf: PermitRootLogin no, PasswordAuthentication yes, PubkeyAuthentication yes. Ricarica ssh senza chiudere le sessioni aperte
4 Docker Engine Repository ufficiale Docker, docker-ce, docker-ce-cli, containerd.io, plugin buildx e compose
5 Portainer Portainer CE sulla 9443 oppure Portainer Agent sulla 9001 (vedi capitolo 6)
6 Git e GitHub git config di base, GitHub CLI (gh) opzionale, chiave SSH dedicata ~/.ssh/id_ed25519_github + voce in ~/.ssh/config
7 Claude Code Solo se richiesto: repository apt di Anthropic con verifica dell'impronta della chiave, pacchetto claude-code (vedi capitolo 8)
8 Permessi Utente nel gruppo docker (docker senza sudo), git config --system safe.directory '*', /opt scrivibile dall'utente (vedi capitolo 7)
9 tmux Crea ~/.tmux.conf con mouse, cronologia 50000 righe, numerazione da 1 (non tocca un file già esistente)
10 Samba Solo se richiesto: pacchetti, cartella, condivisione, utente Samba, regole UFW

Cosa non fa: non attiva UFW, non installa un reverse proxy, non richiede certificati TLS, non disabilita l'accesso SSH con password.


5. Il riepilogo finale

A fine installazione lo script stampa:

  • indirizzo IP e comando di accesso SSH;
  • URL di Portainer e token di setup;
  • promemoria che /opt è scrivibile senza sudo;
  • chiave pubblica da incollare su GitHub;
  • versione di Claude Code e comandi per il primo accesso, se installato;
  • dati della condivisione Samba (percorsi Windows / macOS / Linux);
  • avvisi: rientrare in SSH per usare docker senza sudo, riavvio richiesto, ecc.

Tutto l'output è anche in /var/log/bootstrap-server.log (leggibile solo da root):

sudo less /var/log/bootstrap-server.log

6. Portainer e il token di setup

Perché serve

Dalle versioni 2.39.4 / 2.43 Portainer chiede un setup token per creare il primo amministratore: senza token la pagina iniziale non si completa. Serve a impedire che qualcun altro, raggiungendo il server prima di te, si prenda l'istanza appena avviata. Documentazione: https://docs.portainer.io/faqs/installing/setup-token

Normalmente Portainer genera il token da solo e lo scrive nei log. Questo script fa una cosa diversa e più comoda: lo genera lui e lo passa al container con --setup-token. Conseguenze utili:

  • il token è noto prima ancora che il container parta e viene stampato a video;
  • resta lo stesso anche dopo un riavvio del container: se scadono i 5 minuti non devi rileggere niente, riavvii e riusi lo stesso token;
  • viene salvato in /var/lib/bootstrap-server/portainer-setup-token (solo root).

Dove trovarlo

sudo ./bootstrap-server.sh --portainer-token

Oppure direttamente:

sudo cat /var/lib/bootstrap-server/portainer-setup-token

Se il container è stato creato prima di questa versione dello script (token generato da Portainer), leggilo dai log:

docker logs portainer 2>&1 | grep setup_token

Come si usa

  1. Apri https://IP-DEL-SERVER:9443 (certificato autofirmato: il browser avvisa, è normale).
  2. Nella pagina iniziale incolla il token, poi crea nome utente e password dell'amministratore.
  3. Hai 5 minuti dall'avvio del container. Se scadono:
docker restart portainer
# poi riusa lo stesso token

Il token è monouso: dopo la creazione dell'amministratore non serve più.

Modalità di Portainer

PORTAINER_MODE Effetto
server (predefinito) Portainer CE completo, porta 9443 (HTTPS), volume portainer_data
agent Solo l'agente, porta 9001: il server va aggiunto da un Portainer centrale
none Portainer non viene installato

In modalità agent il token non c'entra: l'agente non ha interfaccia.

Opzioni del token

# predefinito: token casuale generato dallo script
sudo PORTAINER_SETUP_TOKEN=auto ./bootstrap-server.sh utente

# token scelto da te (min 8 caratteri: lettere, numeri, . _ -)
sudo PORTAINER_SETUP_TOKEN=IlMioToken-2026 ./bootstrap-server.sh utente

# nessun token (solo su rete fidata: chi raggiunge la 9443 può prendersi l'istanza)
sudo PORTAINER_SETUP_TOKEN=none ./bootstrap-server.sh utente

Sulle versioni di Portainer che non conoscono l'opzione lo script se ne accorge da solo (interroga l'immagine) e non passa nulla.

Comandi utili

docker ps --filter name=portainer      # stato
docker logs -f portainer               # log in tempo reale
docker restart portainer               # riavvio (il token resta lo stesso)

# aggiornamento all'ultima versione (dati e utenti restano nel volume)
docker pull portainer/portainer-ce:lts
docker rm -f portainer
sudo rm /var/lib/bootstrap-server/portainer.done
sudo ./bootstrap-server.sh

Il segnalibro portainer.done va cancellato: senza, lo script considera il passo già fatto e non ricrea il container.

Attenzione: le porte pubblicate da Docker scavalcano UFW. Portainer sulla 9443 resta raggiungibile anche con il firewall attivo. Su un server esposto a Internet proteggilo con il firewall del provider, con una VPN, oppure pubblicalo solo in locale e mettici davanti un reverse proxy:

sudo PORTAINER_BIND=127.0.0.1 ./bootstrap-server.sh utente

7. La cartella /opt per le tue applicazioni

/opt è il posto giusto dove tenere gli stack Docker e le applicazioni installate a mano. Di serie appartiene però solo a root, quindi dall'utente:

$ mkdir /opt/miostack
mkdir: cannot create directory '/opt/miostack': Permission denied

Lo script risolve la cosa nel passo Permessi: assegna /opt al gruppo dell'utente e gli mette il bit setgid.

# quello che fa lo script:
chgrp <gruppo-utente> /opt
chmod 2775 /opt

Risultato:

drwxrwsr-x  root  mario  /opt
  • l'utente crea cartelle e file in /opt senza sudo;
  • il setgid (la s) fa ereditare il gruppo a tutto quello che viene creato dentro: comodo se in futuro aggiungi altri utenti allo stesso gruppo;
  • il contenuto già presente non viene toccato: le cartelle installate da root (per esempio da un pacchetto .deb) restano di root e protette.

Verifica:

ls -ld /opt
mkdir /opt/prova && rmdir /opt/prova

Se il server è già installato

Il passo "Permessi" risulta già completato, quindi va rifatto esplicitamente:

sudo rm /var/lib/bootstrap-server/permissions.done
sudo ./bootstrap-server.sh

Oppure, se preferisci farlo a mano subito:

sudo chgrp "$(id -gn)" /opt
sudo chmod 2775 /opt

Lasciare /opt a root

sudo OPT_WRITABLE=no ./bootstrap-server.sh utente

Per tornare alla situazione originale di Debian/Ubuntu:

sudo chown root:root /opt
sudo chmod 755 /opt

Nota: se il gruppo principale dell'utente non è personale (non ha cioè lo stesso nome dell'utente), scriveranno in /opt tutti i membri di quel gruppo. Lo script te lo segnala durante l'installazione.


8. Claude Code

Claude Code è l'assistente di Anthropic da riga di comando. Lo script chiede all'avvio se installarlo e, se rispondi di no, puoi installarlo in qualsiasi momento in seguito.

Come viene installato

Dal repository apt ufficiale di Anthropic, con lo stesso metodo usato per Docker e GitHub CLI: chiave di firma in /etc/apt/keyrings/, repository in /etc/apt/sources.list.d/, pacchetto claude-code.

Prima di aggiungere il repository lo script verifica l'impronta della chiave contro quella pubblicata da Anthropic:

31DDDE24DDFAB679F42D7BD2BAA929FF1A7ECACE

Se non corrisponde, la chiave viene cancellata, il repository non viene aggiunto e l'installazione si ferma con un errore. È una difesa contro una chiave sostituita lungo il percorso.

L'installazione è di sistema (/usr/bin/claude): vale per tutti gli utenti. Architetture supportate: amd64 e arm64; su altre lo script avvisa e salta.

Installarlo in un secondo momento

sudo ./bootstrap-server.sh --claude-code

Funziona anche se al primo giro avevi risposto di no: forza il passo, lo rifà e mostra il riepilogo.

Primo utilizzo

claude                 # avvia la sessione; il primo avvio chiede di accedere
claude --version       # versione installata
claude doctor          # diagnostica di installazione e impostazioni

Serve un account con piano Pro, Max, Team, Enterprise oppure Console: il piano gratuito di Claude.ai non include Claude Code. In alternativa si può usare un provider terzo (Amazon Bedrock, Google Cloud, Microsoft Foundry).

Documentazione: https://code.claude.com/docs/en/setup

Aggiornamenti

L'installazione da repository apt non si aggiorna da sola: segue il normale aggiornamento di sistema.

sudo apt update && sudo apt upgrade claude-code

Canale di rilascio

CLAUDE_CODE_CHANNEL Effetto
stable (predefinito) Versione di circa una settimana fa, senza le release con regressioni gravi
latest Ogni versione appena esce
sudo CLAUDE_CODE_CHANNEL=latest ./bootstrap-server.sh --claude-code

Per cambiare canale su un server già configurato, rilancia il comando qui sopra: il file del repository viene riscritto con il nuovo canale.

Non installarlo mai (nessuna domanda)

sudo CLAUDE_CODE_INSTALL=no ./bootstrap-server.sh utente

Disinstallare

sudo apt remove claude-code
sudo rm /etc/apt/sources.list.d/claude-code.list /etc/apt/keyrings/claude-code.asc

9. Variabili di configurazione

Si passano davanti al comando. Vengono salvate in /var/lib/bootstrap-server/config e riusate automaticamente alla ripresa (le password non vengono mai salvate).

Priorità: variabile passata ora → valore salvato → valore predefinito.

Generali

Variabile Valori Predefinito Note
GIT_NAME testo vuoto git config --global user.name
GIT_EMAIL testo vuoto git config --global user.email
INSTALL_GH_CLI yes / no yes Installa la GitHub CLI (gh)
GIT_SAFE_DIRECTORY_ALL yes / no yes Evita l'errore "dubious ownership" tra utente e sudo
OPT_WRITABLE yes / no yes Rende /opt scrivibile dall'utente senza sudo (capitolo 7)
CLAUDE_CODE_INSTALL ask / yes / no ask Installa Claude Code (senza terminale interattivo: no)
CLAUDE_CODE_CHANNEL stable / latest stable Canale di rilascio del pacchetto claude-code

Portainer

Variabile Valori Predefinito
PORTAINER_MODE server / agent / none server
PORTAINER_BIND indirizzo su cui pubblicare 0.0.0.0
PORTAINER_EDGE_PORT yes / no no (se yes pubblica anche la 8000 per gli Edge Agent)
PORTAINER_SETUP_TOKEN auto / none / valore auto
PORTAINER_IMAGE immagine portainer/portainer-ce:lts
PORTAINER_AGENT_IMAGE immagine portainer/agent:lts

Samba

Variabile Valori Predefinito
SAMBA_ENABLE ask / yes / no ask (senza terminale interattivo: no)
SAMBA_SHARE_NAME nome condivisa
SAMBA_PATH percorso assoluto /srv/samba/<nome>
SAMBA_HOSTS_ALLOW reti separate da spazio, oppure all reti private rilevate
SAMBA_PASSWORD min 8 caratteri — (chiesta a terminale, mai salvata su disco)

Esempio completo, senza nessuna domanda

sudo GIT_NAME="Mario Rossi" GIT_EMAIL="mario@example.com" \
     PORTAINER_MODE=server PORTAINER_BIND=127.0.0.1 \
     SAMBA_ENABLE=yes SAMBA_SHARE_NAME=dati \
     SAMBA_HOSTS_ALLOW="192.168.1.0/24" SAMBA_PASSWORD='PasswordLunga1' \
     ./bootstrap-server.sh mario

10. File e cartelle create

Percorso Contenuto
/var/lib/bootstrap-server/ Stato dell'installazione (permessi 700)
/var/lib/bootstrap-server/config Parametri salvati (600)
/var/lib/bootstrap-server/portainer-setup-token Token di setup di Portainer (600)
/var/lib/bootstrap-server/<passo>.done Segnalibro di ogni passo completato
/var/log/bootstrap-server.log Log completo (600)
/etc/sudoers.d/90-<utente>-nopasswd sudo senza password
/etc/ssh/sshd_config.d/00-bootstrap.conf Impostazioni SSH
/etc/apt/sources.list.d/docker.list Repository Docker
/etc/apt/sources.list.d/github-cli.list Repository GitHub CLI
/etc/apt/sources.list.d/claude-code.list Repository Claude Code
/etc/apt/keyrings/claude-code.asc Chiave di firma di Claude Code (impronta verificata)
~/.ssh/id_ed25519_github[.pub] Chiave SSH per GitHub
~/.ssh/config Voce Host github.com
~/.tmux.conf Configurazione tmux
/etc/samba/shares.d/<nome>.conf Una condivisione per file
/etc/samba/bootstrap-shares.conf Indice delle condivisioni, incluso in smb.conf
/srv/samba/<nome> Cartella condivisa (se non ne indichi un'altra)
/opt Non creata, ma resa scrivibile dall'utente: gruppo dell'utente, permessi 2775

11. Verifiche dopo l'installazione

# accesso SSH con password (da un altro computer)
ssh utente@IP-DEL-SERVER

# root senza password, dall'utente
sudo -i

# Docker senza sudo  (prima esci e rientra in SSH: il gruppo è nuovo)
docker run --rm hello-world
docker compose version

# Portainer
docker ps --filter name=portainer
sudo ./bootstrap-server.sh --portainer-token

# /opt scrivibile senza sudo
ls -ld /opt                    # atteso: drwxrwsr-x root <tuogruppo>
mkdir /opt/prova && rmdir /opt/prova

# Claude Code (se installato)
claude --version
claude doctor

# GitHub: incolla prima la chiave su https://github.com/settings/keys
cat ~/.ssh/id_ed25519_github.pub
ssh -T git@github.com          # risposta attesa: "Hi <utente>! You've successfully authenticated"
gh auth login                  # in alternativa, con la GitHub CLI

# Samba
testparm -s                    # configurazione valida?
smbclient -L localhost -U utente

Accesso alla cartella condivisa:

  • Windows: \\IP-DEL-SERVER\nomecondivisione
  • macOS / Linux: smb://IP-DEL-SERVER/nomecondivisione
  • Utente: il tuo utente Linux, con la password Samba (è separata da quella di sistema). Per cambiarla: sudo smbpasswd utente

12. Ripresa e ripetizione

sudo ./bootstrap-server.sh --status     # cosa è già stato fatto
sudo ./bootstrap-server.sh              # riprende da dove si era fermato

Per rifare un solo passo, cancella il suo segnalibro e rilancia:

sudo rm /var/lib/bootstrap-server/portainer.done
sudo ./bootstrap-server.sh

Nomi dei segnalibri: system_update, admin_user, ssh_access, docker, portainer, git_github, claude_code, permissions, tmux, samba.

Per ricreare Portainer da zero (per esempio per cambiare token o porta):

docker rm -f portainer
sudo rm /var/lib/bootstrap-server/portainer.done
sudo ./bootstrap-server.sh

Il volume portainer_data non viene toccato: utenti e ambienti restano. Se elimini anche il volume (docker volume rm portainer_data) riparti da un'istanza vuota e servirà di nuovo il token.

Per ricominciare tutto da capo (non disinstalla nulla, azzera solo lo stato):

sudo ./bootstrap-server.sh --reset

13. Problemi frequenti

Sintomo Causa e soluzione
Portainer: "Your Portainer instance timed out" Passati i 5 minuti: docker restart portainer, poi riusa lo stesso token
La pagina di Portainer chiede un token che non hai sudo ./bootstrap-server.sh --portainer-token; se vuoto, docker logs portainer 2>&1 | grep setup_token
Il token non viene accettato È monouso e legato all'avvio corrente: riavvia il container e riprova
docker: permission denied Il gruppo docker vale dalla sessione successiva: esci e rientra in SSH (oppure newgrp docker)
mkdir: /opt/...: Permission denied Passo "Permessi" non ancora eseguito con questa versione: sudo rm /var/lib/bootstrap-server/permissions.done e rilancia lo script (capitolo 7)
Permission denied dentro una cartella di /opt creata da root Solo /opt è condiviso, non il suo contenuto preesistente: sudo chown -R utente:gruppo /opt/quella-cartella
SSH chiede una chiave e rifiuta la password Un file in /etc/ssh/sshd_config.d/ con numero più alto, o un blocco Match, sovrascrive l'impostazione: sudo sshd -T | grep passwordauthentication
L'utente non ha password sudo passwd utente, poi rilancia lo script
Lo script si ferma su apt/dpkg Rilancialo: ripara dpkg e riprende. Se persiste: sudo dpkg --configure -a
"Un'altra esecuzione è già in corso" C'è davvero un'altra istanza, oppure una sessione morta: sudo rm /run/bootstrap-server.lock
Samba non raggiungibile Rete non autorizzata: sudo ./bootstrap-server.sh --samba e indica la rete giusta (es. 192.168.1.0/24)
Password Samba dimenticata sudo smbpasswd utente
claude: command not found Non installato (o hai risposto di no): sudo ./bootstrap-server.sh --claude-code
"Chiave di Claude Code non attendibile" L'impronta scaricata non è quella pubblicata da Anthropic: non installare, controlla la rete (proxy che intercetta HTTPS) e riprova
NO_PUBKEY BAA929FF1A7ECACE durante apt update Il file della chiave è mancante o corrotto: sudo ./bootstrap-server.sh --claude-code lo riscarica e lo verifica
Claude Code chiede un abbonamento Serve un piano Pro, Max, Team, Enterprise o Console: il piano gratuito di Claude.ai non lo include
Portainer raggiungibile nonostante UFW Le porte Docker scavalcano UFW: usa PORTAINER_BIND=127.0.0.1 + reverse proxy, o il firewall del provider

14. Note di sicurezza

  • Il login SSH diretto di root è disabilitato; si entra con l'utente e poi sudo -i.
  • sudo senza password è comodo ma significa che chi ottiene la sessione dell'utente è root: la password dell'utente va scelta lunga e, meglio ancora, passa all'accesso con chiave SSH.
  • Il token di setup e il log contengono informazioni sensibili: entrambi sono leggibili solo da root.
  • Portainer ha accesso a /var/run/docker.sock: chi entra in Portainer controlla il server. Non esporlo su Internet senza una protezione davanti.
  • /opt diventa scrivibile dall'utente: è una comodità, non una porta aperta (nessun altro account ci guadagna accesso), ma ricorda che i file che metti lì sono modificabili senza sudo. Se /opt deve restare solo di root usa OPT_WRITABLE=no.
  • L'accesso a Internet della porta 9443 (e 445 per Samba) va valutato caso per caso: lo script non attiva UFW al posto tuo.