From 853a7234a41c45cf65a8d313f4e851be583dfbd3 Mon Sep 17 00:00:00 2001 From: Ghislain Date: Thu, 18 Dec 2025 21:26:22 +0100 Subject: [PATCH] Init repo --- .gitignore | 1 + .pre-commit-config.yaml | 5 ++ README.md | 58 +++++++++++++ ansible/add-ssh.yml | 19 +++++ ansible/install-docker.yml | 51 ++++++++++++ ansible/install-tools.yml | 149 ++++++++++++++++++++++++++++++++++ ansible/provisioning.yml | 5 ++ build.sh | 52 ++++++++++++ debian-amd64-proxmox.pkr.hcl | 153 +++++++++++++++++++++++++++++++++++ http/preseed.cfg.j2 | 89 ++++++++++++++++++++ vars.json | 4 + 11 files changed, 586 insertions(+) create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 README.md create mode 100755 ansible/add-ssh.yml create mode 100755 ansible/install-docker.yml create mode 100755 ansible/install-tools.yml create mode 100755 ansible/provisioning.yml create mode 100755 build.sh create mode 100644 debian-amd64-proxmox.pkr.hcl create mode 100755 http/preseed.cfg.j2 create mode 100644 vars.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8932c65 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +ssh/*.pub diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..108805c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: +- repo: https://github.com/sirosen/fix-smartquotes + rev: 0.1.1 + hooks: + - id: fix-smartquotes \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..0ccce7c --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +![Proxmox](https://img.shields.io/static/v1?style=for-the-badge&message=Proxmox&color=E57000&logo=Proxmox&logoColor=FFFFFF&label=) ![Packer](https://img.shields.io/badge/packer-%23E7EEF0.svg?style=for-the-badge&logo=packer&logoColor=%2302A8EF) + +# Déploiement Packer d'une machine Debian sur Proxmox + +## Qu'est ce que Packer ? + +> Packer est une solution opensource permettant de construire des images machine pour de multiples plateformes cloud. Il est utilisé dans une approche « d'infrastructure as code » afin de pouvoir maintenir facilement les logiciels déployés sur les serveurs. - Syloe + +L'objectif de ce dépôt est de déployer une template de machine virtuelle Debian pré-configurée. *(Authentification par clé SSH, ou installation d'un agent de supervision à la fin de l'installation)* + +## Démarrer le projet + +Pré-requis: +- [j2cli](https://pypi.org/project/j2cli/) +- [Packer](https://packer.io) + +Editez le fichier `build.sh` pour y mettre les identifiants de votre Proxmox : +```bash +export proxmox_url="https://IP_PROXMOX:8006/api2/json" +export proxmox_node="NOM_NOEUD" +export proxmox_username="root@pam" # packer@pve si vous créez un utilisateur "packer". +export proxmox_password="Password" +``` +*Pensez à vérifier que les noms des pools de stockages sont les mêmes que vous (local, local-zfs)*. + +Il sera **obligatoire** de fournir une clé ssh qui sera ajoutée à l'utilisateur *root* de la machine. +```bash +export vm_keys=$(echo "$(cat ~/.ssh/id_ed25519.pub)") +``` + +Il est possible d'ajouter plusieurs clés de cette manière : +```bash +export vm_keys=$(echo "$(cat ./KeyDEPLOY.id_rsa.pub)\n$(cat ./KeyINFRA.id_rsa.pub)\n$(cat ~/.ssh/id_rsa.pub)") +``` +Valider la config : +```bash +packer validate *.pkr.hcl +``` + +Commande de démarrage : +```bash +source ./build.sh +``` + +# TroubleShooting +## No matching host key type found +Si vous êtes sur Ubuntu, vous devrez ajouter le ssh-rsa en algorithme de chiffrement compatible. +Voici l'erreur sur laquelle vous tomberez : +``` + proxmox: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Unable to negotiate with 127.0.0.1 port 32985: no matching host key type found. Their offer: ssh-rsa", "unreachable": true} +``` + +La solution est d'accepter cet algorithme dans votre fichier `~/.ssh/config`. +``` +Host 127.0.0.1 + HostKeyAlgorithms +ssh-rsa + PubkeyAcceptedAlgorithms +ssh-rsa +``` \ No newline at end of file diff --git a/ansible/add-ssh.yml b/ansible/add-ssh.yml new file mode 100755 index 0000000..c757d39 --- /dev/null +++ b/ansible/add-ssh.yml @@ -0,0 +1,19 @@ +--- +- hosts: all + gather_facts: true + + vars: + ansible_python_interpreter: /usr/bin/python3 + tasks: + + - name: Show keys to add + debug: + msg: "{{ item }}" + loop: "{{ lookup('fileglob', '../ssh/*.pub', wantlist=True) }}" + + - name: Set authorized key took from file + authorized_key: + user: root + state: present + key: "{{ lookup('pipe','cat ../ssh/*.pub') }}" + diff --git a/ansible/install-docker.yml b/ansible/install-docker.yml new file mode 100755 index 0000000..b5cb55a --- /dev/null +++ b/ansible/install-docker.yml @@ -0,0 +1,51 @@ +- hosts: all + remote_user: deploy + become: yes + become_user: root + become_method: sudo + + tasks: + - name: Update all packages to the latest version + apt: + upgrade: dist + autoremove: true + become: true + + - name: Ensure old versions of Docker are not installed. + ansible.builtin.package: + name: + - docker + - docker-engine + - docker.io + - containerd + - runc + state: absent + - name: Ensure dependencies are installed. + ansible.builtin.package: + name: + - apt-transport-https + - ca-certificates + - curl + - gnupg + - lsb-release + state: present + + - name: Add Docker apt key. + ansible.builtin.apt_key: + url: https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg + id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88 + state: present + + - name: Add Docker repository. + ansible.builtin.apt_repository: + repo: deb [arch=amd64] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable + state: present + update_cache: true + + - name: Install docker + ansible.builtin.package: + name: + - docker-ce + - docker-ce-cli + - containerd.io + state: present \ No newline at end of file diff --git a/ansible/install-tools.yml b/ansible/install-tools.yml new file mode 100755 index 0000000..8ea5d07 --- /dev/null +++ b/ansible/install-tools.yml @@ -0,0 +1,149 @@ +--- +- hosts: all + gather_facts: true + vars: + ansible_python_interpreter: /usr/bin/python3 + + tasks: + - name: "Install packages" + apt: + state: present + name: + - vim + - exa + - grc + - most + - highlight + - source-highlight + - python3-pygments + - gawk + - python3-apt + - tmux + - htop + - fdisk + + - name: configure .vimrc + copy: + content: 'set mouse=r' + dest: "/root/.vimrc" + owner: root + group: root + mode: '0644' + + - name: config /etc/vim/vimrc syntax on + lineinfile: + path: /etc/vim/vimrc + regexp: '^"syntax on' + line: syntax on + + - name: config /etc/vim/vimrc set background=dark + lineinfile: + path: /etc/vim/vimrc + regexp: '^"set background=dark' + line: set background=dark + + - name: config .bashrc add cat color alias + lineinfile: + path: /root/.bashrc + line: 'alias cat="highlight -O ansi --force --syntax=bash"' + create: no + + - name: config .bashrc set alias ll + lineinfile: + path: /root/.bashrc + regexp: '^# alias ll(.*)' + line: 'alias ll\1' + backrefs: yes + + - name: config .bashrc set alias ls + lineinfile: + path: /root/.bashrc + regexp: '^# alias ls(.*)' + line: 'alias ls\1' + backrefs: yes + + - name: config .bashrc set alias l + lineinfile: + path: /root/.bashrc + regexp: '^# alias l(.*)' + line: 'alias l\1' + backrefs: yes + + - name: config .bashrc set export LSOPTIONS + lineinfile: + path: /root/.bashrc + regexp: '^# export LS_OPTIONS(.*)' + line: 'export LS_OPTIONS\1' + backrefs: yes + + - name: config .bashrc set eval OPTIONS + lineinfile: + path: /root/.bashrc + regexp: '^# eval(.*)' + line: '# eval\1' + backrefs: yes + + + - name: config .bashrc add vim alias + lineinfile: + path: /root/.bashrc + line: "alias vi='vim'" + create: no + + - name: config .bashrc add export LESS Color1 + lineinfile: + path: /root/.bashrc + line: 'export LESSOPEN="| /usr/share/source-highlight/src-hilite-lesspipe.sh %s"' + create: no + + - name: config .bashrc add export LESS Color2 + lineinfile: + path: /root/.bashrc + line: "export LESS=' -R'" + create: no + + - name: config .bashrc add export pager + lineinfile: + path: /root/.bashrc + line: 'export PAGER="most"' + create: no + + - name: config .bashrc alias grep color + lineinfile: + path: /root/.bashrc + line: "alias grep='grep --color=auto'" + create: no + + - name: configure yaml color syntax + copy: + dest: "/usr/share/source-highlight/yaml.lang" + owner: root + group: root + mode: '0644' + content: | + include "script_comment.lang" + include "number.lang" + keyword = "true|false|null" + section start '^---' + (symbol,name,symbol) = `(^[[:blank:]-]*)([[:alnum:]_]+)(:)` + symbol = '^[[:blank:]]*-' + string delim "\"" "\"" escape "\\" + string delim "'" "'" escape "\\" + + - name: config lang.map yaml + lineinfile: + path: /usr/share/source-highlight/lang.map + line: 'yaml = yaml.lang' + create: no + + - name: config lang.map yaml + lineinfile: + path: /usr/share/source-highlight/lang.map + line: 'yml = yaml.lang' + create: no + + - name: config .bashrc set Prompt + lineinfile: + path: /root/.bashrc + line: "export PS1='\\[\\033[1;31m\\]\\u\\[\\033[0;37m\\]@\\[\\033[1;32m\\]\\h\\[\\033[00m\\]:\\[\\033[1;34m\\]\\w\\[\\033[00m\\] (\\d - \\t)\\n\\$ '" + create: no diff --git a/ansible/provisioning.yml b/ansible/provisioning.yml new file mode 100755 index 0000000..3a36d43 --- /dev/null +++ b/ansible/provisioning.yml @@ -0,0 +1,5 @@ +- import_playbook: install-tools.yml +# - import_playbook: add-ssh.yml +- import_playbook: postinstall-vm.yml +- import_playbook: install-docker.yml + diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..9ca93d4 --- /dev/null +++ b/build.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +packerfile="debian-amd64-proxmox.pkr.hcl" + +# Paramètres du Proxmox +export proxmox_url="https://192.168.1.57:8006/api2/json" +export proxmox_node="BETELGEUSE" +export proxmox_username="packer@pve" +export proxmox_password="Koc89qo!R2UfXR*t" # Il est préférable d'utiliser un utilisateur dédié à Proxmox +export proxmox_vm_storage="Haumea" +export proxmox_iso_url="https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.2.0-amd64-netinst.iso" +export proxmox_iso_checksum="sha256:677c4d57aa034dc192b5191870141057574c1b05df2b9569c0ee08aa4e32125d" +export proxmox_iso_storage="local" +export proxmox_network="vmbr0" + +# Ressources attribuées à la VM +export vm_id="9000" +export vm_name="debian-13-tf" +export template_description="VM debian" +export vm_default_user="root" +export vm_cpu="4" +export vm_disk="16G" +export vm_memory="2048" + +# Paramètres de la VM Template +export prefix_disk="vd" +export ssh_username="root" +export ssh_password="8s6pcD7hdIwbaALrBqtPp7WVAmVdHtls1ORij1BcOkuIdxpCXrKA5O2tejKmHkaZ" +export userdeploy_password="8s6pcD7hdIwbaALrBqtPp7WVAmVdHtls1ORij1BcOkuIdxpCXrKA5O2tejKmHkaZ" + +export vm_keys=$(echo "$(cat ~/.ssh/id_ed25519.pub)") +#export vm_keys=$(echo "$(cat ./KeyDEPLOY.id_rsa.pub)\n$(cat ./KeyINFRA.id_rsa.pub)\n$(cat ~/.ssh/id_rsa.pub)") + +# set variables +python3 << 'EOF' +from jinja2 import Environment, FileSystemLoader +import os + +env = Environment(loader=FileSystemLoader('.')) +template = env.get_template('http/preseed.cfg.j2') +output = template.render(os.environ) + +with open('http/preseed.cfg', 'w') as f: + f.write(output) +EOF + +#PACKER_LOG=1 packer build $packerfile +packer init $packerfile +packer build $packerfile + +rm -f http/preseed.cfg + diff --git a/debian-amd64-proxmox.pkr.hcl b/debian-amd64-proxmox.pkr.hcl new file mode 100644 index 0000000..697fd6a --- /dev/null +++ b/debian-amd64-proxmox.pkr.hcl @@ -0,0 +1,153 @@ +packer { + required_plugins { + proxmox = { + version = ">= 1.1.2" + source = "github.com/hashicorp/proxmox" + } + } +} + +variable "proxmox_iso_checksum" { + type = string + default = "${env("proxmox_iso_checksum")}" +} + +variable "proxmox_iso_storage" { + type = string + default = "${env("proxmox_iso_storage")}" +} + +variable "proxmox_iso_url" { + type = string + default = "${env("proxmox_iso_url")}" +} + +variable "proxmox_network" { + type = string + default = "${env("proxmox_network")}" +} + +variable "proxmox_node" { + type = string + default = "${env("proxmox_node")}" +} + +variable "proxmox_password" { + type = string + default = "${env("proxmox_password")}" + sensitive = true +} + +variable "proxmox_storage" { + type = string + default = "${env("proxmox_storage")}" +} + +variable "proxmox_url" { + type = string + default = "${env("proxmox_url")}" +} + +variable "proxmox_username" { + type = string + default = "${env("proxmox_username")}" +} + +variable "proxmox_vm_storage" { + type = string + default = "${env("proxmox_vm_storage")}" +} + +variable "ssh_password" { + type = string + default = "${env("ssh_password")}" + sensitive = true +} + +variable "ssh_username" { + type = string + default = "root" +} + +variable "template_description" { + type = string + default = "${env("template_description")}" +} + +variable "vm_default_user" { + type = string + default = "${env("vm_default_user")}" +} + +variable "vm_disk" { + type = string + default = "${env("vm_disk")}" +} + +variable "vm_id" { + type = number + default = 9000 +} + +variable "vm_memory" { + type = number + default = 2048 +} + +variable "vm_cpu" { + type = number + default = 4 +} + +variable "vm_name" { + type = string + default = "${env("vm_name")}" +} + +source "proxmox" "build-template" { + boot_command = ["", "auto ", "console-keymaps-at/keymap=fr ", "console-setup/ask_detect=false ", "debconf/frontend=noninteractive ", "debian-installer=fr_FR ", "fb=false ", "install ", "packer_host={{ .HTTPIP }} ", "packer_port={{ .HTTPPort }} ", "kbd-chooser/method=fr ", "keyboard-configuration/xkb-keymap=fr ", "locale=fr_FR ", "netcfg/get_hostname=${var.vm_name} ", "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ", ""] + boot_wait = "10s" + disks { + disk_size = "${var.vm_disk}" + format = "raw" + storage_pool = "${var.proxmox_vm_storage}" + storage_pool_type = "directory" + type = "virtio" + } + http_directory = "http" + insecure_skip_tls_verify = true + iso_checksum = "${var.proxmox_iso_checksum}" + iso_storage_pool = "${var.proxmox_iso_storage}" + iso_url = "${var.proxmox_iso_url}" + network_adapters { + bridge = "${var.proxmox_network}" + model = "virtio" + } + node = "${var.proxmox_node}" + os = "l26" + password = "${var.proxmox_password}" + proxmox_url = "${var.proxmox_url}" + qemu_agent = "true" + ssh_password = "${var.ssh_password}" + ssh_timeout = "30m" + ssh_username = "${var.ssh_username}" + template_description = "${var.template_description}" + unmount_iso = true + username = "${var.proxmox_username}" + vm_name = "${var.vm_name}" + cores = var.vm_cpu + memory = var.vm_memory + vm_id = var.vm_id +} + +build { + description = "Debian 13 (Bookworm)" + + sources = ["source.proxmox.build-template"] + + provisioner "ansible" { + ansible_env_vars = ["ANSIBLE_FORCE_COLOR=1", "ANSIBLE_HOST_KEY_CHECKING=False"] + playbook_file = "ansible/provisioning.yml" + } + +} diff --git a/http/preseed.cfg.j2 b/http/preseed.cfg.j2 new file mode 100755 index 0000000..518c8a9 --- /dev/null +++ b/http/preseed.cfg.j2 @@ -0,0 +1,89 @@ +debconf debconf/language string fr +d-i debconf/language string fr +d-i debian-installer/language string fr +d-i debian-installer/locale string fr_FR.UTF-8 +d-i debian-installer/splash boolean false +d-i debian-installer/language string fr +d-i debian-installer/country string FR +d-i console-setup/ask_detect boolean false +d-i console-setup/layoutcode string fr +d-i keyboard-configuration/xkb-keymap select fr +d-i keyboard-configuration/layoutcode string fr +d-i preseed/early_command string anna-install parted-udeb cryptsetup-udeb crypto-dm-modules lvm2-udeb mdadm-udeb md-modules +d-i mirror/country string manual +d-i mirror/http/hostname string deb.debian.org +d-i mirror/http/directory string /debian +d-i mirror/http/proxy string +d-i netcfg/get_hostname string {{ vm_name }} +d-i netcfg/choose_interface select auto +d-i netcfg/get_ipaddress string 192.168.1.90 +d-i netcfg/get_netmask string 255.255.255.0 +d-i netcfg/get_gateway string 192.168.1.254 +d-i netcfg/get_nameservers string 192.168.1.25 9.9.9.9 +d-i netcfg/confirm_static boolean true +d-i netcfg/get_hostname string debian-13-tf +d-i netcfg/get_domain string local +d-i netcfg/wireless_wep string +d-i apt-setup/non-free boolean true +d-i apt-setup/contrib boolean true +d-i apt-setup/use_mirror boolean true +d-i partman-auto/disk string /dev/{{ prefix_disk }}a +d-i partman-auto/method string lvm +d-i partman-lvm/device_remove_lvm boolean true +d-i partman-lvm/device_remove_lvm_span boolean true +d-i partman-auto/purge_lvm_from_device boolean true +d-i partman-auto-lvm/new_vg_name string vg00 +d-i partman-auto/choose_recipe select boot-root +d-i partman-lvm/confirm boolean true +d-i partman-lvm/confirm_nooverwrite boolean true +d-i partman/confirm_write_new_label boolean true +d-i partman/choose_partition select Finish partitioning and write changes to disk +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +d-i partman/mount_style select uuid +d-i clock-setup/utc boolean true +d-i clock-setup/ntp boolean true +d-i clock-setup/ntp-server string ntp.ubuntu.com +d-i time/zone string Europe/Paris +d-i passwd/root-login boolean true +d-i passwd/root-password password {{ ssh_password }} +d-i passwd/root-password-again password {{ ssh_password }} +d-i passwd/make-user boolean true +d-i passwd/user-fullname string ansible deploy +d-i passwd/username string deploy +d-i passwd/user-password password {{ userdeploy_password }} +d-i passwd/user-password-again password {{ userdeploy_password }} +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean false +d-i grub-installer/choose_bootdev string /dev/{{ prefix_disk }}a +d-i partman/mount_style select uuid +d-i clock-setup/utc boolean true +d-i clock-setup/ntp boolean true +d-i clock-setup/ntp-server string ntp.ubuntu.com +d-i time/zone string Europe/Paris +d-i pkgsel/upgrade select safe-upgrade +d-i pkgsel/language-packs multiselect +d-i pkgsel/update-policy select none +d-i pkgsel/updatedb boolean true +tasksel tasksel/first multiselect standard, openssh-server +d-i grub-installer/only_debian boolean true +d-i finish-install/keep-consoles boolean true +d-i finish-install/reboot_in_progress note +d-i cdrom-detect/eject boolean true +d-i debian-installer/exit/halt boolean false +d-i debian-installer/exit/poweroff boolean false + +d-i ebian-installer/add-kernel-opts string net.ifnames=0 biosdevname=0 + +d-i pkgsel/include string vim openssh-server sudo htop iotop rsync mc curl python3 python3-pip python3-apt dnsutils net-tools net-tools gnupg2 wget hostname ansible qemu-guest-agent parted + +d-i preseed/late_command string \ + in-target sed -i '/^#PermitRootLogin/c\PermitRootLogin yes' /etc/ssh/sshd_config; \ + in-target mkdir -p /root/.ssh; \ + in-target /bin/sh -c "echo '{{ vm_keys }}' > /root/.ssh/authorized_keys"; \ + in-target chmod -R go-rwx /root/.ssh/authorized_keys; \ + in-target sed -i 's/# alias ll/alias ll/g' /root/.bashrc; \ + in-target sed -i 's/# alias ls/alias ls/g' /root/.bashrc; \ + in-target sed -i 's/# alias l/alias l/g' /root/.bashrc; \ + in-target sed -i 's/# export LS_OPTIONS/export LS_OPTIONS/g' /root/.bashrc; \ + in-target sed -i 's/# eval/eval/g' /root/.bashrc; diff --git a/vars.json b/vars.json new file mode 100644 index 0000000..38b7f22 --- /dev/null +++ b/vars.json @@ -0,0 +1,4 @@ +{ + "proxy_host": "", + "proxy_port": "" +}