Terminal web local pour scripts SSH

Terminal web local pour scripts SSH

Notes

Se connecter sur le serveur Proxmox (ThinkCentre M700) via SSH

1
ssh tin@192.168.0.216 -p 55216 -i /home/yann/.ssh/m700-ed25519

Créer le fichier install-terminal.sh
Y copier le contenu ci-joint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/env bash
# Terminal web strictement local : ttyd + tmux derrière nginx (HTTPS, mot de passe, restriction au LAN)
# À lancer en root dans le conteneur Debian 13 dédié.
#
# Variables modifiables à l'appel, par exemple :
#   BIND_IP=192.168.0.206 WEB_USER=yannig bash install-terminal.sh
set -euo pipefail
# pct exec peut fournir un PATH réduit : on le fixe explicitement
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

FQDN="${FQDN:-terminal.home.arpa}"
LAN_CIDR="${LAN_CIDR:-192.168.0.0/24}"
BIND_IP="${BIND_IP:-$(hostname -I | awk '{print $1}')}"
TERM_USER="${TERM_USER:-termuser}"   # utilisateur Unix qui exécute le shell et les ssh
WEB_USER="${WEB_USER:-admin}"        # identifiant de l'authentification web
TTYD_PORT="${TTYD_PORT:-7681}"

[[ $EUID -eq 0 ]] || { echo "À lancer en root." >&2; exit 1; }
[[ -n "$BIND_IP" ]] || { echo "Impossible de déterminer BIND_IP." >&2; exit 1; }

if [[ -z "${WEB_PASS:-}" ]]; then
    read -rsp "Mot de passe web pour ${WEB_USER} : " WEB_PASS; echo
    read -rsp "Confirmer : " WEB_PASS2; echo
    [[ "$WEB_PASS" == "$WEB_PASS2" ]] || { echo "Les mots de passe diffèrent." >&2; exit 1; }
fi
[[ -n "$WEB_PASS" ]] || { echo "Mot de passe vide refusé." >&2; exit 1; }

echo "==> Paquets"
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq tmux nginx openssl openssh-client apache2-utils curl ca-certificates

echo "==> ttyd"
if apt-cache show ttyd >/dev/null 2>&1; then
    apt-get install -y -qq ttyd
else
    # ttyd absent des dépôts Debian 13 : binaire officiel (GitHub), vérifié par somme SHA256
    TTYD_VERSION="${TTYD_VERSION:-1.7.7}"
    case "$(uname -m)" in
        x86_64)  TTYD_ASSET="ttyd.x86_64" ;;
        aarch64) TTYD_ASSET="ttyd.aarch64" ;;
        *) echo "Architecture non gérée : $(uname -m)" >&2; exit 1 ;;
    esac
    TTYD_URL="https://github.com/tsl0922/ttyd/releases/download/${TTYD_VERSION}"
    tmpd="$(mktemp -d)"
    curl -fsSL -o "$tmpd/$TTYD_ASSET" "$TTYD_URL/$TTYD_ASSET"
    curl -fsSL -o "$tmpd/SHA256SUMS" "$TTYD_URL/SHA256SUMS"
    ( cd "$tmpd" && grep " ${TTYD_ASSET}\$" SHA256SUMS | sha256sum -c - )
    install -m 755 "$tmpd/$TTYD_ASSET" /usr/local/bin/ttyd
    rm -rf "$tmpd"
fi
TTYD_BIN="$(command -v ttyd || true)"
[[ -x "$TTYD_BIN" ]] || { echo "ttyd introuvable après installation." >&2; exit 1; }
echo "ttyd : $TTYD_BIN"

echo "==> Utilisateur ${TERM_USER}"
if ! id "$TERM_USER" &>/dev/null; then
    useradd -m -s /bin/bash "$TERM_USER"
fi
HOME_DIR="$(getent passwd "$TERM_USER" | cut -d: -f6)"
install -d -m 700 -o "$TERM_USER" -g "$TERM_USER" "$HOME_DIR/.ssh"
install -d -m 755 -o "$TERM_USER" -g "$TERM_USER" "$HOME_DIR/scripts"

if [[ ! -f "$HOME_DIR/.ssh/id_ed25519" ]]; then
    sudo_run() { runuser -u "$TERM_USER" -- "$@"; }
    sudo_run ssh-keygen -t ed25519 -N "" -C "terminal-web@${FQDN}" -f "$HOME_DIR/.ssh/id_ed25519" -q
fi

if [[ ! -f "$HOME_DIR/.tmux.conf" ]]; then
    cat > "$HOME_DIR/.tmux.conf" <<'EOF'
set -g history-limit 50000
set -g mouse on
set -g default-terminal "tmux-256color"
set -g status-style "bg=colour236,fg=colour250"
EOF
    chown "$TERM_USER:$TERM_USER" "$HOME_DIR/.tmux.conf"
fi

echo "==> Service ttyd (écoute sur loopback uniquement)"
cat > /etc/systemd/system/ttyd.service <<EOF
[Unit]
Description=ttyd - terminal web (tmux)
After=network.target

[Service]
User=${TERM_USER}
WorkingDirectory=${HOME_DIR}
ExecStart=${TTYD_BIN} -i lo -p ${TTYD_PORT} -W -O tmux new-session -A -s scripts
Restart=on-failure
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ReadWritePaths=${HOME_DIR}

[Install]
WantedBy=multi-user.target
EOF

echo "==> Certificat TLS"
if [[ ! -f /etc/ssl/certs/terminal.crt ]]; then
    openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -days 825 \
        -keyout /etc/ssl/private/terminal.key -out /etc/ssl/certs/terminal.crt \
        -subj "/CN=${FQDN}" \
        -addext "subjectAltName=DNS:${FQDN},IP:${BIND_IP}" 2>/dev/null
    chmod 600 /etc/ssl/private/terminal.key
fi

echo "==> Authentification web"
printf '%s' "$WEB_PASS" | htpasswd -iBc /etc/nginx/.htpasswd_terminal "$WEB_USER" >/dev/null
chown root:www-data /etc/nginx/.htpasswd_terminal
chmod 640 /etc/nginx/.htpasswd_terminal

echo "==> Vhost nginx"
rm -f /etc/nginx/sites-enabled/default
cat > /etc/nginx/sites-available/terminal <<EOF
server {
    listen ${BIND_IP}:443 ssl;
    server_name ${FQDN};

    ssl_certificate     /etc/ssl/certs/terminal.crt;
    ssl_certificate_key /etc/ssl/private/terminal.key;
    ssl_protocols       TLSv1.2 TLSv1.3;

    # Strictement local : réseau ${LAN_CIDR} ET mot de passe
    satisfy all;
    allow ${LAN_CIDR};
    deny  all;
    auth_basic "Terminal";
    auth_basic_user_file /etc/nginx/.htpasswd_terminal;

    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;

    location / {
        proxy_pass http://127.0.0.1:${TTYD_PORT};
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$host;
        proxy_read_timeout 1d;
    }
}
EOF
ln -sf /etc/nginx/sites-available/terminal /etc/nginx/sites-enabled/terminal
nginx -t

echo "==> Démarrage"
systemctl daemon-reload
systemctl enable --now ttyd
systemctl enable nginx
systemctl restart nginx

cat <<EOF

=====================================================================
Terminal prêt : https://${FQDN}/   (identifiant : ${WEB_USER})

1) Certificat à importer dans ton navigateur / système :
   /etc/ssl/certs/terminal.crt
   (depuis le nœud Proxmox : pct pull <ID> /etc/ssl/certs/terminal.crt ./terminal.crt)

2) Clé publique à ajouter dans authorized_keys des serveurs distants :
$(cat "$HOME_DIR/.ssh/id_ed25519.pub")

3) DNS : ${FQDN} doit pointer vers ${BIND_IP}
=====================================================================
EOF

Le rendre exécutable

1
chmod +x install-terminal.ssh

Le script install-terminal.sh est prêt.

LXC en ligne de commande, depuis le shell du nœud Proxmox

1
2
3
pveam update
pveam available --section system | grep debian-13
pveam download local debian-13-standard_13.6-1_amd64.tar.zst   # nom exact vu juste au-dessus

Pour ton usage, un conteneur LXC suffit largement : il est plus léger qu’une VM (environ 256 à 512 Mo de RAM, 4 Go de disque) et démarre en quelques secondes. Prends une VM seulement si tu veux l’isolation maximale, puisque cette machine contiendra tes clés SSH vers tous tes serveurs. Dans les deux cas, ce sera séparé de ton serveur public, ce qui était le but.

1
2
3
4
5
6
7
8
9
10
11
pct create 210 local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst \
  --hostname terminal \
  --unprivileged 1 \
  --cores 1 --memory 512 --swap 256 \
  --rootfs local-lvm:4 \
  --net0 name=eth0,bridge=vmbr0,ip=192.168.0.206/24,gw=192.168.0.254 \
  --nameserver 192.168.0.254 \
  --features nesting=1 \
  --onboot 1
pct start 210
pct enter 210

À adapter :

  • 210 : un ID libre
  • local-lvm : le nom de ton stockage (visible avec pvesm status, probablement lié à ton LVM tiny-vg)
  • 192.168.0.206 : une IP libre de ton /24, de préférence réservée en dehors de la plage DHCP
  • gw / nameserver : l’IP de ton routeur ou de ton DNS local 192.168.0.254

Si tu préfères l’interface web : Create CT, décoche « Privileged container », choisis le template Debian 13, 1 cœur, 512 Mo, 4 Go de disque, IP statique.

Une fois que le conteneur est démarré et qu’il a un accès réseau. Vérifie ces trois points avant de lancer le script :

1
2
3
pct status 210                                  # doit afficher : status: running
pct exec 210 -- ip -4 addr show eth0            # l'IP 192.168.0.206 doit apparaître
pct exec 210 -- apt-get update                  # doit réussir (le script a besoin d'Internet pour installer les paquets)

Si apt-get update échoue, vérifie la passerelle (gw) et le DNS (--nameserver) que tu as donnés à la création du conteneur.

1. En cas d’erreur - Libérer l’ID 210 et vérifier le template (sur le nœud Proxmox)

1
2
pct stop 210 2>/dev/null; pct destroy 210 --purge
pveam list local | grep debian-13

Si pveam list local n’affiche pas debian-13-standard_13.6-1_amd64.tar.zst, le nom du template est différent chez toi : recopie celui qui est affiché dans ta commande.

2. Créer et démarrer

Lance ta commande telle quelle avec les bons paramètres

1
2
3
4
5
6
7
8
9
10
11
pct create 210 local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst \
  --hostname terminal \
  --unprivileged 1 \
  --cores 1 --memory 512 --swap 256 \
  --rootfs local-lvm:4 \
  --net0 name=eth0,bridge=vmbr0,ip=192.168.0.206/24,gw=192.168.0.254 \
  --nameserver 192.168.0.254 \
  --features nesting=1 \
  --onboot 1
pct start 210
#pct enter 210

Résultat création

1
2
3
4
5
6
7
Detected container architecture: amd64
Creating SSH host key 'ssh_host_ed25519_key' - this may take some time ...
done: SHA256:uOzYgWwvC2/xTdhU+N1dGm4UU4fKHZXVC2tUO8M0fPQ root@terminal
Creating SSH host key 'ssh_host_rsa_key' - this may take some time ...
done: SHA256:31tn/rJPsYVOpuWJ1NQaNTa12P8eD8AMJjp3uz0oo84 root@terminal
Creating SSH host key 'ssh_host_ecdsa_key' - this may take some time ...
done: SHA256:JmQYlD8UuUcX4rxMYgSNmQp92saL6whte7yQJ8nQXds root@terminal

puis avant d’entrer dans le conteneur teste le réseau depuis le nœud :

1
2
3
pct exec 210 -- ping -c2 192.168.0.254
pct exec 210 -- ping -c2 1.1.1.1
pct exec 210 -- apt-get update

3. Lancer le script

Le fichier install-terminal.sh doit d’abord être copié sur le nœud (avec scp depuis ton poste, par exemple).

pct enter 210 ouvre le shell du conteneur, mais le script se pousse depuis le nœud. Ne fais donc pas pct enter avant, ou fais exit pour revenir au nœud, puis :

1
2
pct push 210 install-terminal.sh /root/install-terminal.sh
pct exec 210 -- env BIND_IP=192.168.0.206 WEB_USER=ton_login bash /root/install-terminal.sh

Le script te demande le mot de passe web, installe tout, puis affiche à la fin la clé publique à copier et le chemin du certificat.

Ce qu’il fait :

  • installe ttyd, tmux et nginx
  • crée l’utilisateur termuser avec une clé SSH ed25519 dédiée et un dossier ~/scripts
  • lance ttyd sur la boucle locale uniquement, avec ta session tmux persistante scripts
  • génère un certificat pour terminal.home.arpa
  • configure nginx en HTTPS, avec mot de passe et accès limité à 192.168.0.0/24

À la fin, le script affiche la clé publique à ajouter aux authorized_keys de tes serveurs et le chemin du certificat à importer dans ton navigateur.

1
2
3
4
5
6
7
8
9
10
11
12
=====================================================================
Terminal prêt : https://terminal.home.arpa/   (identifiant : tin)

1) Certificat à importer dans ton navigateur / système :
   /etc/ssl/certs/terminal.crt
   (depuis le nœud Proxmox : pct pull <ID> /etc/ssl/certs/terminal.crt ./terminal.crt)

2) Clé publique à ajouter dans authorized_keys des serveurs distants :
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBvZ/7YyRGE+7gCqRg/NqK5hXs60Cd++OTZAL64etxG8 terminal-web@terminal.home.arpa

3) DNS : terminal.home.arpa doit pointer vers 192.168.0.206
=====================================================================

Le script peut être relancé sans problème s’il s’arrête en cours de route : il ne régénère ni les clés ni le certificat s’ils existent déjà.

Cet avertissement perl: warning: Setting locale failed. est sans gravité. Le conteneur n’a pas la locale que ton shell lui transmet (probablement fr_FR.UTF-8), donc perl se rabat sur la locale par défaut. Ça n’affecte pas l’installation.

Pour le faire disparaître, depuis le nœud :

1
pct exec 210 -- bash -c 'apt-get install -y -qq locales && sed -i "s/^# *fr_FR.UTF-8/fr_FR.UTF-8/" /etc/locale.gen && locale-gen && update-locale LANG=fr_FR.UTF-8'

Si tu préfères ne pas installer de locale, LC_ALL=C devant tes commandes pct exec suffit à le masquer.

Maintenant que le script est allé au bout, il reste ces étapes :

  1. Récupérer le certificat et l’importer dans ton navigateur ou ton système :

    1
    
     pct pull 210 /etc/ssl/certs/terminal.crt ./terminal.crt
    
  2. DNS : fais pointer terminal.home.arpa vers 192.168.0.206. Pour un premier test, une ligne 192.168.0.206 terminal.home.arpa dans le /etc/hosts de ton poste suffit.
  3. Clé publique : ajoute celle qu’affiche le script (ou cat /home/termuser/.ssh/id_ed25519.pub dans le conteneur) aux authorized_keys de tes serveurs distants.
  4. Test : ouvre https://terminal.home.arpa/, connecte-toi avec tin et le mot de passe choisi, puis lance un ssh vers un de tes serveurs.

Si la page ne s’affiche pas, vérifie que les services tournent :

1
pct exec 210 -- systemctl status ttyd nginx --no-pager

Utiliser csv existant

deux scripts qui adaptent ton inventaire CSV au terminal web

Ton CSV se réutilise tel quel dans le conteneur, avec une différence : au lieu de tes ~20 clés, le terminal web utilise une seule clé dédiée (celle que le script d’installation a créée). Tes clés habituelles ne quittent donc pas ton poste. J’ai préparé deux scripts, testés sur un CSV d’exemple (la simulation et la génération de la config fonctionnent, mais je n’ai évidemment pas pu les essayer sur tes serveurs).

1. Sur ton poste : déposer la clé du terminal sur tes serveurs (deploy-key.sh)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/env bash
# À lancer sur TON POSTE (qui a déjà accès à tous les serveurs avec ses clés habituelles).
# Ajoute la clé publique du terminal web dans ~/.ssh/authorized_keys de chaque serveur du CSV.
#
# Par défaut : SIMULATION (n'écrit rien). Ajouter --apply pour exécuter.
#
# Usage :
#   PUB=./terminal.pub ./deploy-key.sh                 # simulation, tous les serveurs
#   PUB=./terminal.pub ./deploy-key.sh --apply cwwk proxtin   # seulement ces alias
#
# Variables :
#   CSV       chemin du CSV (défaut : ~/terminalweb.csv)
#   PUB       clé publique à déposer (obligatoire)
#   FROM_LAN  IP du conteneur (ex. 192.168.0.206) : limite la clé à cette IP,
#             uniquement pour les serveurs en 192.168.0.x
set -euo pipefail

CSV="${CSV:-$HOME/.ssh/terminalweb.csv}"
PUB="${PUB:-$HOME/.ssh/terminal.pub}"
FROM_LAN="${FROM_LAN:-192.168.0.206}"
APPLY=0
TARGETS=()

for a in "$@"; do
    case "$a" in
        --apply) APPLY=1 ;;
        *) TARGETS+=("$a") ;;
    esac
done

[[ -f "$CSV" ]] || { echo "CSV introuvable : $CSV" >&2; exit 1; }
[[ -f "$PUB" ]] || { echo "Clé publique introuvable : $PUB" >&2; exit 1; }

PUBLINE="$(head -n1 "$PUB")"
[[ "$PUBLINE" == ssh-ed25519\ * ]] || { echo "Format de clé inattendu dans $PUB" >&2; exit 1; }
KEYBODY="$(awk '{print $2}' <<<"$PUBLINE")"

want() {
    [[ ${#TARGETS[@]} -eq 0 ]] && return 0
    local t
    for t in "${TARGETS[@]}"; do [[ "$t" == "$1" ]] && return 0; done
    return 1
}

ok=0; ko=0; skip=0
while IFS=';' read -r name user host port key _local _dist _ping _opt ipv _rest; do
    [[ -n "${name// }" ]] || continue
    want "$name" || continue

    if [[ -z "$key" ]]; then
        echo "[$name] pas de clé dans le CSV : ignoré"
        skip=$((skip+1)); continue
    fi

    opts="no-agent-forwarding,no-X11-forwarding,no-port-forwarding"
    if [[ -n "$FROM_LAN" && "$host" == 192.168.0.* ]]; then
        opts="from=\"$FROM_LAN\",$opts"
    fi
    line="$opts $PUBLINE"

    remote="umask 077; mkdir -p ~/.ssh; touch ~/.ssh/authorized_keys; grep -qF -- '$KEYBODY' ~/.ssh/authorized_keys || echo '$line' >> ~/.ssh/authorized_keys"
    famopt=(); [[ "$ipv" == 4 ]] && famopt=(-4); [[ "$ipv" == 6 ]] && famopt=(-6)

    if [[ $APPLY -eq 0 ]]; then
        echo "[$name] (simulation) ssh ${famopt[*]} -p $port -i ~/.ssh/$key $user@$host"
        continue
    fi

    if ssh "${famopt[@]}" -p "$port" -i "$HOME/.ssh/$key" -o IdentitiesOnly=yes \
           -o BatchMode=yes -o ConnectTimeout=10 "$user@$host" "$remote"; then
        echo "[$name] OK"; ok=$((ok+1))
    else
        echo "[$name] ÉCHEC"; ko=$((ko+1))
    fi
done < <(tail -n +2 "$CSV" | tr -d '\r')

if [[ $APPLY -eq 1 ]]; then
    echo "Terminé : $ok OK, $ko échec(s), $skip ignoré(s)"
else
    echo "Simulation terminée. Relancer avec --apply pour déposer la clé."
fi

Il lit ton CSV et utilise les clés et ports habituels pour ajouter la clé publique du terminal dans authorized_keys. Par défaut c’est une simulation qui n’écrit rien.

1
2
3
4
5
pct pull 210 /home/termuser/.ssh/id_ed25519.pub ./terminal.pub     # sur le nœud Proxmox, puis copie-le sur ton poste

PUB=./terminal.pub CSV=~/terminalweb.csv ./deploy-key.sh            # simulation
PUB=./terminal.pub CSV=~/terminalweb.csv ./deploy-key.sh --apply cwwk   # un seul serveur pour tester
PUB=./terminal.pub CSV=~/terminalweb.csv ./deploy-key.sh --apply        # tous

La clé est déposée avec no-port-forwarding,no-agent-forwarding,no-X11-forwarding. Avec FROM_LAN=192.168.0.206 devant la commande, elle est en plus limitée à l’IP du conteneur, mais seulement pour les serveurs en 192.168.0.x : pour les VPS distants, la connexion arrive depuis ton IP publique, donc cette restriction ne s’y applique pas.

2. Dans le conteneur : générer ~/.ssh/config depuis le CSV (gen-ssh-config.sh)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/env bash
# À lancer dans le conteneur terminal, en tant que termuser.
# Génère ~/.ssh/config à partir du CSV des connexions :
#   Alias;User;IPouDomain;Port_SSH;SSH_Key;Local;Distant;Ping;Opt;IP4_6
# Toutes les connexions utilisent la clé dédiée du terminal (colonne SSH_Key ignorée).
#
# Usage : gen-ssh-config.sh [terminalweb.csv]
set -euo pipefail

CSV="${1:-$HOME/terminalweb.csv}"
KEY="${KEY:-$HOME/.ssh/id_ed25519}"
OUT="${OUT:-$HOME/.ssh/config}"

[[ -f "$CSV" ]] || { echo "CSV introuvable : $CSV" >&2; exit 1; }
install -d -m 700 "$(dirname "$OUT")"

{
    echo "# Généré depuis $CSV le $(date -Is) - ne pas éditer à la main"
    echo
    tail -n +2 "$CSV" | tr -d '\r' | while IFS=';' read -r name user host port _key _local _dist _ping _opt ipv _rest; do
        [[ -n "${name// }" ]] || continue
        echo "Host $name"
        echo "    HostName $host"
        echo "    User $user"
        echo "    Port $port"
        case "$ipv" in
            4) echo "    AddressFamily inet" ;;
            5) echo "    AddressFamily inet6" ;;
        esac
        echo
    done
    cat <<EOF
Host *
    IdentityFile $KEY
    IdentitiesOnly yes
    StrictHostKeyChecking accept-new
    ServerAliveInterval 30
    ConnectTimeout 10
EOF
} > "$OUT.tmp"

chmod 600 "$OUT.tmp"
mv "$OUT.tmp" "$OUT"

# Compatibilité avec l'habitude "sshm alias"
if ! grep -q "alias sshm=" "$HOME/.bashrc" 2>/dev/null; then
    echo "alias sshm='ssh'" >> "$HOME/.bashrc"
fi

echo "OK : $(grep -c '^Host ' "$OUT") entrées dans $OUT (dont Host *)"

A exécuter sur proxmox Tiny en mode su

1
2
3
4
pct push 210 terminalweb.csv /home/termuser/terminalweb.csv
pct push 210 gen-ssh-config.sh /home/termuser/gen-ssh-config.sh
pct exec 210 -- chown termuser:termuser /home/termuser/terminalweb.csv /home/termuser/gen-ssh-config.sh
pct exec 210 -- runuser -u termuser -- bash /home/termuser/gen-ssh-config.sh

Ensuite, dans le terminal web, ssh cwwk ouvre la session avec le bon utilisateur, port et famille d’adresse (IPv4 ou IPv6). L’alias sshm est aussi créé, donc sshm cwwk fonctionne comme sur ton poste. À relancer à chaque modification du CSV.

Points d’attention avec ton inventaire

  • skrime est en IPv6 uniquement : le conteneur doit avoir une adresse IPv6 (par exemple ip6=auto sur net0 si ton réseau en distribue), sinon cette connexion échouera.
  • ds723 n’a pas de clé dans le CSV : deploy-key.sh l’ignore, il faudra y ajouter la clé à la main.
  • acer, ds723, um890 pointent vers 82.64.153.201, qui semble être ton IP publique. Depuis ton réseau local, ça ne fonctionne que si ton routeur gère le NAT loopback. Sinon, utilise leur IP locale dans le conteneur.
  • Première connexion : la config contient StrictHostKeyChecking accept-new, donc les nouveaux serveurs sont acceptés automatiquement et une clé hôte modifiée reste refusée.
  • La complétion des alias avec Tab demande apt install bash-completion dans le conteneur.