#! /usr/bin/env bash
#
# LXC container creator
#
# Release: 1.2 of 2023/11/26
# 2023, Joseph Maillardet
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU  General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

set -euo pipefail

# Default config

myself="$(basename $0)"
ct_distro="debian"
ct_release="bookworm"
ct_arch="amd64"
ct_path="$HOME/.local/share/lxc"
user_name="user"
user_pass="-+"
user_key=""
used_key_file="$HOME/.ssh/id_rsa.pub"


# Plumbing

msg() {
	printf "%s\n" "$1"
}

error() {
	printf "Error: %s\n" "$1"
	[ -n "${2-}" ] && exit $2
}

usage() {
	cat <<- EOF
		Usage: $myself [--directory DIR] [--help]

		    -n,         --name : give a name to your container
		    -d,       --distro : distro to use (default: debian)
		    -r,      --release : distro release to use (default: bookworm)
		    -a, --architecture : distro architecture (default: amd64)

		    -u,         --user : user name to create (default: user)
		    -p,     --password : user password (default: -+)
		    -k,          --key : the public key file to use for ssh (ex: ~/.ssh/id_rsa.pub)

		    -h,         --help : affiche cette aide
	EOF
}

read_key_file() {
	if [ -f "$1" ]; then
		used_key_file="$1"
		user_key=$(cat "$1" || error "Unable to read file: $1" 2)
	else
		error "file: $1 not found" 3
	fi
}

# Manage dash options
OPTS=$(getopt -o n:d:r:a:u:p:k:h --long name:,distro:,release:,architecture:,user:,password:,key:,help -n "$myself" -- "$@") \
    || error "getopt failed with error code: $?" 1
eval set -- "$OPTS"

while true; do
    case "$1" in
        -n|--name)         ct_name="$2";       shift 2 ;;
        -d|--distro)       ct_distro="$2";     shift 2 ;;
        -r|--release)      ct_release="$2";    shift 2 ;;
        -a|--architecture) ct_arch="$2";       shift 2 ;;
        -u|--user)         user_name="$2";     shift 2 ;;
        -p|--password)     user_pass="$2";     shift 2 ;;
        -k|--key)          read_key_file "$2"; shift 2 ;;
        -h|--help)         usage; exit 0 ;;
        --)                shift; break ;;
        *)                 break ;;
    esac
done


if [ "$UID" = 0 ]; then
        msg "Attention, les conteneurs privilégiés sont dangereux !"
        ct_path="/var/lib/lxc"
fi

if [ -z "${ct_name-}" ]; then
	if [ -n "${1-}" ]; then
		ct_name="$1"
	else
		error "Il faut un nom en argument" 4
	fi
fi

[ -d "$ct_path/$ct_name" ] && error "Ce conteneur existe déjà : $ct_path/$ct_name" 5

# If no ssh key was given, look for classic default ssh key file
if [ -z "$user_key" ]; then
	for key in id_ed25519_sk id_ed25519 id_rsa id_dsa id_ecdsa_sk id_ecdsa; do
		file="$HOME/.ssh/$key.pub"
		if [ -f "$file" ]; then
			read_key_file "$file"
			break
		fi
	done
fi

# Ajout du conteneur
cat <<- EOF
	Création du conteneur: $ct_name
	Distribution: $ct_distro
	     Version: $ct_release
	Architecture: $ct_arch
	 Utilisateur: $user_name
	    Password: ******
	         Clé: $used_key_file
EOF

lxc-create -t download -n "$ct_name" -- --dist "$ct_distro" --release "$ct_release" --arch "$ct_arch" \
	|| error "Unable to create VM : $ct_name (d:$ct_distro, r:$ct_release, a:$ct_arch)" 6

# Lancement
msg "Lancement du conteneur: $ct_name"
lxc-start -n "$ct_name" || error "Impossible de lancer le conteneur: $ct_name" 7

# Attente du bon démarrage
lxc-wait -n "$ct_name" -s RUNNING || error "Problème durant l'attente du lancement de: $ct_name" 8

# Mise en place du script d'init dans l'arbo du conteneur
init_file="/tmp/initlxc"

cat << EOF | lxc-attach -n "$ct_name" -- bash -c "cat > '$init_file'; chmod +x '$init_file'"
#! /usr/bin/env bash

set -euo pipefail

msg() { printf "%s\n" "\$1"; }

if [ \$UID != 0 ]; then
	msg "Il faut être root b**let"
	exit 1
fi

msg "Configuration de la locale française"
sed -i 's,# fr_FR.UTF-8 UTF-8,fr_FR.UTF-8 UTF-8,' /etc/locale.gen
locale-gen --purge fr_FR.UTF-8
update-locale LANG=fr_FR.UTF-8
timedatectl set-timezone Europe/Paris

printf "Waiting for network"
while ! ping -c 1 deb.debian.org &>/dev/null; do
	sleep 1
	printf "."
done
msg "."

msg "Installation des dépendances de ce script"
apt update
apt install -y lsb-release whois ssh sudo wget

msg "Téléchargement du script de gestion des mises à jours"
wget jo.welibre.org/upt
chmod +x upt
bash upt ins

msg "Mise à jour"
upt y fp

msg "Nettoyage"
upt y superclean

msg "Ajout de l'utilisateur et config des droits d'admin"
name="$user_name"
useradd -m -p "\$(mkpasswd -m sha-512 -- '$user_pass')" -s /bin/bash "$user_name"
adduser "$user_name" sudo

mkdir "/home/$user_name/.ssh"
printf "$user_key\n" >> "/home/$user_name/.ssh/authorized_keys"
chown -R "$user_name": "/home/$user_name"

msg "Terminé."
exit 0
EOF

msg "Configuration initial du conteneur: $ct_name"
lxc-attach -n "$ct_name" "$init_file"

# Affichage de l'IP actuelle
ct_ip=$(lxc-ls --fancy | grep "$ct_name" | awk '{print $5}')

cat << EOF
Configuration terminée.
Vous pouvez accéder au conteneur en saisissant la commande :
ssh $user_name@$ct_ip
EOF

exit 0

