Setup
Installa immagine Debian 12
ssh root@xxx.xxx.xxx.xxxAggiorna e pkg base
# update base system
sudo apt update && sudo apt upgrade -y
# install essentials for Docker repository
sudo apt install ca-certificates curl gnupg lsb-release -yPuk user
Prerequisites: ~/.ssh.config in locale:
Host vps_root
User root
Host vps_puk
User puk
Host vps*
HostName xxx.xxx.xxx # IP server
IdentityFile /home/luca/.ssh/id_pukvpsCreate User
adduser --gecos "" puk # imposta una password temporanea
# oppure, se vuoi saltare le domande:
# adduser --disabled-password --gecos "" pukRoot privilege
usermod -aG sudo pukVerifica:
grep '^%sudo' /etc/sudoers # dovrebbe mostrare "%sudo ALL=(ALL:ALL) ALL"Docker
Se docker è installato, aggiungere l’utente al gruppo
sudo usermod -aG docker pukSsh-key
Server:
# crea la directory e imposta i permessi stretti
mkdir -p /home/puk/.ssh
chmod 700 /home/puk/.ssh
# copia la chiave pubblica (scegli uno dei due metodi)
## Metodo rapido con ssh-copy-id (dalla tua macchina locale, ancora loggato come luca):
ssh-copy-id -i ~/.ssh/id_pukvps.pub puk@xxx.xxx.xxx
## Oppure manualmente (se non hai ssh-copy-id):
cat <<'EOF' > /home/puk/.ssh/authorized_keys
# incolla qui tutto il contenuto di ~/.ssh/id_pukvps.pub
EOF
chmod 600 /home/puk/.ssh/authorized_keys
chown -R puk:puk /home/puk/.sshSecurity
Server: /etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication no # dopo aver verificato che l’accesso con chiave funziona!
PermitRootLogin prohibit-password # o "no"Caution
L’utente root non usa la chiave ssh così, bisogna aggiungerlo: da locale:
ssh-copy-id -i ~/.ssh/id_pukvps.pub root@xxx.xxx.xxxda VPS loggato come puk
sudo mkdir -p /root/.ssh
sudo chmod 700 /root/.ssh
sudo tee -a /root/.ssh/authorized_keys < ~/.ssh/authorized_keys
sudo chmod 600 /root/.ssh/authorized_keysReload deamon
systemctl restart sshdDocker Base
Docker engine GPG
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian bookworm stable" | \
sudo tee /etc/apt/sources.list.d/docker.list >/dev/nullDocker engine
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -yDocker no sudo
sudo usermod -aG docker $USER
# logout/login o `newgrp docker` per applicare il gruppoTest
docker run --rm hello-worldDocker Core stack
External network
docker network create proxy # reverse‑proxy / HTTP(S)
docker network create db # rete DB condivisaVengono restituiti degli hash
Base Dirs
sudo mkdir -p /srv/infra/letsencrypt
cd /srv/infra
nano db.envdb.env
MYSQL_ROOT_PASSWORD=SuperRootPW!
# le seguenti variabili non servono al core‑stack, ma possono essere utili
# MYSQL_DATABASE=
# MYSQL_USER=
# MYSQL_PASSWORD=Core Stack
- traefik
- mariadb
- phpmyadmin
- redis
nano /srv/infra/docker-compose.yml/srv/infra/docker-compose.yml
version: "3.9"
services:
traefik:
image: traefik:v2.11 # reverse‑proxy
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
command:
# static config
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.lets.acme.httpchallenge=true"
- "--certificatesresolvers.lets.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.lets.acme.email=dev@lpuk.it"
- "--certificatesresolvers.lets.acme.storage=/letsencrypt/acme.json"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
networks:
- proxy
mariadb:
image: mariadb:11
container_name: mariadb
restart: unless-stopped
env_file: ./db.env # root password here
volumes:
- mariadb_data:/var/lib/mysql
networks:
- db
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: pma
restart: unless-stopped
environment:
- PMA_HOST=mariadb
labels:
- traefik.enable=true
- traefik.http.routers.pma.rule=Host(`vpsma.lpuk.it`)
- traefik.http.routers.pma.entrypoints=websecure
- traefik.http.routers.pma.tls.certresolver=lets
networks:
- proxy
- db
redis:
image: redis:7-alpine
container_name: redis
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis_data:/data
networks:
- db
volumes:
mariadb_data:
redis_data:
networks:
proxy:
external: true
db:
external: trueErrori e appunti
Gateway Timeoutandando in https su il sottodominio di phpmyadmin non riuscivo ad accedere. Analizzandodocker inspect pma(e dandolo a chatGPT) il problema era che il container pma era avviato in modalitànetwork_mode: db. Dopo aver fermato e rimosso i container condocker compose down, rimuovere immagini e cache precedenti condocker image prune -facme.jsonricordare che il file in/srv/infra/letsencrypt/acme.jsondeve avere permessi 600 (chmod 600 acme.json)
Docker mini-stack
I mini stack stanno nella cartella /srv/[nome-app], con:
- cartella
srcdove risiede l’app - cartella
docker/phpdove abbiamo il Dockerfile - file
docker-compose.ymldel mini stack
Nell’esempio, abbiamo laravel-app come nome progetto, e sottodominio api.tuodominio.com. L’esempio utilizza laravel 10 e php 8.2, per modificare la versione php, nel Dockerfile :
-FROM php:8.2-fpm-alpine
+FROM php:8.4-fpm-alpineBase dir
cd /srv
mkdir -p laravel-app/{src,docker}Laravel init
# se hai già un repo remoto
git clone https://github.com/<tu-user>/<tu-repo>.git laravel-app/src
# oppure, se vuoi iniziare da zero:
# cd laravel-app/src && composer create-project laravel/laravel .Docker-compose mini-stack
version: "3.9"
services:
app:
build:
context: . # root della cartella mini‑stack
dockerfile: docker/php/Dockerfile
args:
uid: 1000 # UID del tuo utente puk
user: puk
container_name: laravel_app
restart: unless-stopped
working_dir: /var/www/html
volumes:
- ./src:/var/www/html # codice Laravel
env_file:
- ./src/.env # variabili dell’app
labels:
- traefik.enable=true
- traefik.http.routers.laravel-app.rule=Host(`api.tuodominio.com`)
- traefik.http.routers.laravel-app.entrypoints=websecure
- traefik.http.routers.laravel-app.tls.certresolver=lets
networks:
- proxy
- db
networks:
proxy:
external: true
db:
external: trueDockerfile
# PHP‑FPM 8.2 with Composer
FROM php:8.2-fpm-alpine
# System dependencies
RUN apk add --no-cache bash git unzip curl icu-dev libpng-dev \
libxml2-dev oniguruma-dev zlib-dev libzip-dev
# PHP extensions
RUN docker-php-ext-install pdo pdo_mysql mbstring intl exif pcntl bcmath gd
# Install Composer v2
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# Non‑root user (matches host UID/GID)
ARG user
ARG uid
RUN addgroup -g ${uid} ${user} && \
adduser -D -u ${uid} -G ${user} ${user}
USER ${user}
WORKDIR /var/www/html