[submodule "python/ovh"]
path = python/ovh
url = git://git.immae.eu/github/ovh/python-ovh
+[submodule "modules/ssh_keygen"]
+ path = modules/ssh_keygen
+ url = git://git.immae.eu/github/voxpupuli/puppet-ssh_keygen
[submodule "modules/ssl"]
path = modules/ssl
url = git://git.immae.eu/github/fnerdwq/puppet-ssl
--- /dev/null
+#!/bin/bash
+
+usage() {
+cat <<EOF
+$(basename $0) [options]
+ --help,-h This help
+
+ One of the following options is necessary:
+ --instance-id id Id of the cloud instance
+ --vps-id id Id of the vps
+
+ Optional arguments:
+ --password password Password of the host (only useful in case of no reboot and vps)
+ --reinstall-first Start with reinstalling the vps
+ --host-user user Use another user than the default one
+ --no-reboot Don't reboot
+ --no-reboot-start Don't reboot to rescue at the beginning
+ --no-reboot-end Don't reboot to normal at the end
+ --git-branch branch Use another puppet branch (default: master)
+ --environment env Environment to use for the install (default: production)
+EOF
+}
+
+set -e
+
+git_branch=master
+environment=production
+host_user=""
+password=""
+T=""
+
+while [ -n "$1" ]; do
+ case "$1" in
+ --instance-id)
+ host_id="$2"
+ if [ -z "$host_user" ]; then
+ host_user="arch"
+ fi
+ if [ -z "$password" ]; then
+ password="x"
+ fi
+ [ -n "$T" ] && usage && exit 1
+ T="ovh_cloud_instance"
+ shift
+ ;;
+ --vps-id)
+ host_id="$2"
+ if [ -z "$host_user" ]; then
+ host_user="root"
+ fi
+ [ -n "$T" ] && usage && exit 1
+ T="ovh_vps_ssd"
+ shift
+ ;;
+ --password)
+ password="$2"
+ shift
+ ;;
+ --reinstall-first)
+ reinstall_first=1
+ ;;
+ --host-user)
+ host_user="$2"
+ shift
+ ;;
+ --no-reboot)
+ no_reboot=1
+ ;;
+ --no-reboot-start)
+ no_reboot_start=1
+ ;;
+ --no-reboot-end)
+ no_reboot_end=1
+ ;;
+ --git-branch)
+ git_branch="$2"
+ shift
+ ;;
+ --environment)
+ environment="$2"
+ shift
+ ;;
+ --help|-h)
+ usage
+ exit 0
+ ;;
+ esac
+
+ shift
+done
+
+if [ -z "$T" -o -z "$host_id" ]; then
+ usage
+ exit 1
+fi
+
+DIRECTORY=$(cd `dirname $0` && pwd)
+PYTHON_DIRECTORY="$DIRECTORY/../python"
+SCRIPTS="$DIRECTORY/../scripts"
+
+if [ -n "$reinstall_first" ]; then
+ echo "Réinstallation du système"
+ python $PYTHON_DIRECTORY/reinstall_$T.py --use-current "$host_id"
+
+ read -p "Appuyer sur une touche quand le serveur est prêt" ready
+fi
+
+if [ -z "$no_reboot" -a -z "$no_reboot_start" ]; then
+ echo "Patienter le temps du reboot"
+ python $PYTHON_DIRECTORY/reboot_$T.py --rescue "$host_id"
+
+ read -p "Appuyer sur une touche quand l'instance a redémarré" ready
+fi
+
+if [ -z "$password" ]; then
+ stty -echo
+ read -p "Mot de passe reçu par e-mail : " password; echo
+ stty echo
+fi
+
+ARCH_DIR=`mktemp -d`
+ARCH_HOST_SCRIPT="$SCRIPTS/$T/arch_host_script.sh"
+if [ -f "$SCRIPTS/$T/arch_chroot_script.sh" ]; then
+ ARCH_CHROOT_SCRIPT="$SCRIPTS/$T/arch_chroot_script.sh"
+else
+ ARCH_CHROOT_SCRIPT=""
+fi
+ARCH_INSTALL_SCRIPT="$SCRIPTS/arch_install_script.sh"
+ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT="$SCRIPTS/$T/arch_host_puppet_configuration_script.sh"
+ARCH_PUPPET_CONFIGURATION_SCRIPT="$SCRIPTS/arch_puppet_configuration_script.sh"
+ARCH_PUPPET_INITIAL_CONFIGURATION="$ARCH_DIR/puppet_variables.json"
+
+trap "rm -rf $ARCH_DIR" EXIT
+
+#### Base installation stage
+python $PYTHON_DIRECTORY/get_initial_configuration_$T.py $host_id > $ARCH_PUPPET_INITIAL_CONFIGURATION
+host_address=$(python $PYTHON_DIRECTORY/get_initial_configuration_$T.py $host_id | jq -r '.ips.v4.ipAddress')
+
+dest="$host_user@$host_address"
+files="$ARCH_HOST_SCRIPT $ARCH_CHROOT_SCRIPT $ARCH_PUPPET_INITIAL_CONFIGURATION $ARCH_INSTALL_SCRIPT"
+
+$SCRIPTS/send_and_run.tcl "$dest" "$password" "$git_branch" "$environment" $files
+
+### Role specific stage
+read -p "Press key when LDAP is configured" i
+
+files="$ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT $ARCH_PUPPET_CONFIGURATION_SCRIPT"
+
+$SCRIPTS/send_and_run.tcl "$dest" "$password" "$git_branch" "$environment" $files
+
+### Installation finished
+if [ -z "$no_reboot" -a -z "$no_reboot_end" ]; then
+ echo "Rebooting"
+ python $PYTHON_DIRECTORY/reboot_$T.py --local "$host_id"
+fi
+++ /dev/null
-#!/bin/bash
-
-usage() {
-cat <<EOF
- $0 [options]
- --help,-h This help
- --instance-id id Id of the instance
- --reinstall-first Start with reinstalling the vps
- --host-user user Use another user (default: arch)
- --no-reboot Don't reboot
- --no-reboot-start Don't reboot to rescue at the beginning
- --no-reboot-end Don't reboot to normal at the end
- --git-branch Use another puppet branch (default: master)
- --environment Environment to use for the installl (default: production)
-EOF
-}
-
-set -e
-
-host_user=arch
-git_branch=master
-environment=production
-
-while [ -n "$1" ]; do
- case "$1" in
- --instance-id)
- instance_id="$2"
- shift
- ;;
- --reinstall-first)
- reinstall_first=1
- ;;
- --host-user)
- host_user="$2"
- shift
- ;;
- --no-reboot)
- no_reboot=1
- ;;
- --no-reboot-start)
- no_reboot_start=1
- ;;
- --no-reboot-end)
- no_reboot_end=1
- ;;
- --git-branch)
- git_branch="$2"
- shift
- ;;
- --environment)
- environment="$2"
- shift
- ;;
- --help|-h)
- usage
- exit 0
- ;;
- esac
-
- shift
-done
-
-DIRECTORY=$(cd `dirname $0` && pwd)
-PYTHON_DIRECTORY="$DIRECTORY/../python"
-
-if [ -z "$instance_id" ]; then
- read -p "Id de l'instance : " instance_id
-fi
-
-if [ -n "$reinstall_first" ]; then
- echo "Réinstallation du système"
- python $PYTHON_DIRECTORY/reinstall_cloud_instance.py --use-current "$instance_id"
-
- read -p "Appuyer sur une touche quand le serveur est prêt" ready
-fi
-
-if [ -z "$no_reboot" -a -z "$no_reboot_start" ]; then
- echo "Patienter le temps du reboot"
- python $PYTHON_DIRECTORY/reboot_cloud_instance.py --rescue "$instance_id"
-
- read -p "Appuyer sur une touche quand l'instance a redémarré" ready
-fi
-
-ARCH_DIR=`mktemp -d`
-ARCH_HOST_SCRIPT="$ARCH_DIR/arch_host_script.sh"
-ARCH_INSTALL_SCRIPT="$ARCH_DIR/arch_install_script.sh"
-ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT="$ARCH_DIR/arch_host_puppet_configuration_script.sh"
-ARCH_PUPPET_CONFIGURATION_SCRIPT="$ARCH_DIR/arch_puppet_configuration_script.sh"
-ARCH_PUPPET_INITIAL_CONFIGURATION="$ARCH_DIR/puppet_variables.json"
-
-trap "rm -rf $ARCH_DIR" EXIT
-
-#### Base installation stage
-python $PYTHON_DIRECTORY/get_initial_configuration_cloud_instance.py $instance_id > $ARCH_PUPPET_INITIAL_CONFIGURATION
-host_address=$(python $PYTHON_DIRECTORY/get_initial_configuration_cloud_instance.py $instance_id | jq -r '.ips.v4.ipAddress')
-
-cat > $ARCH_HOST_SCRIPT <<EOF
-#!/bin/bash
-
-sudo haveged &
-sudo pacman -Sy --noconfirm arch-install-scripts
-
-DEVICE=/dev/vdb1
-MOUNTPOINT=/mnt
-
-UUID=\$(lsblk -rno UUID "\$DEVICE")
-PART="/dev/disk/by-uuid/\$UUID"
-
-# mkfs.ext4 -F -U "\$UUID" "\$DEVICE"
-sudo mount "\$DEVICE" /mnt
-
-##### FIXME: mkfs.ext4 would be better ####
-for i in /mnt/*; do
- if [ "\$i" = "/mnt/boot" ]; then
- # keep /boot/grub
- sudo rm -f \$i/*
- else
- sudo rm -rf \$i
- fi
-done
-##### /FIXME ####
-
-sudo pacstrap /mnt base git puppet
-
-echo "\$PART / auto defaults 0 1" | sudo tee /mnt/etc/fstab
-
-sudo cp /tmp/arch_install_script.sh "\$MOUNTPOINT/root/"
-sudo cp /tmp/puppet_variables.json "\$MOUNTPOINT/root/"
-
-sudo arch-chroot "\$MOUNTPOINT" /root/arch_install_script.sh
-EOF
-
-cat > $ARCH_INSTALL_SCRIPT <<EOF
-CODE_PATH="/etc/puppetlabs/code"
-rm -rf \$CODE_PATH
-git clone -b $git_branch --recursive https://git.immae.eu/perso/Immae/Projets/Puppet.git \$CODE_PATH
-puppet apply --environment $environment --tags base_installation --test \$CODE_PATH/manifests/site.pp
-# The password seed requires puppet to be run twice
-puppet apply --environment $environment --tags base_installation --test \$CODE_PATH/manifests/site.pp
-EOF
-
-chmod a+x $ARCH_HOST_SCRIPT $ARCH_INSTALL_SCRIPT
-
-expect -f - <<EOF
-set timeout -1
-spawn scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no $ARCH_PUPPET_INITIAL_CONFIGURATION $ARCH_HOST_SCRIPT $ARCH_INSTALL_SCRIPT $host_user@$host_address:/tmp
-expect eof
-spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no $host_user@$host_address /tmp/arch_host_script.sh
-expect eof
-EOF
-
-### Role specific stage
-read -p "Press key when LDAP is configured" i
-
-cat > $ARCH_PUPPET_CONFIGURATION_SCRIPT <<EOF
-CODE_PATH="/etc/puppetlabs/code"
-puppet apply --environment $environment --tags base_installation --test \$CODE_PATH/manifests/site.pp
-EOF
-
-cat > $ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT <<EOF
-MOUNTPOINT=/mnt
-
-sudo cp /tmp/arch_puppet_configuration_script.sh "\$MOUNTPOINT/root/"
-
-sudo arch-chroot "\$MOUNTPOINT" /root/arch_puppet_configuration_script.sh
-EOF
-
-chmod a+x $ARCH_PUPPET_CONFIGURATION_SCRIPT $ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT
-
-expect -f - <<EOF
-set timeout -1
-spawn scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no $ARCH_PUPPET_CONFIGURATION_SCRIPT $ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT $host_user@$host_address:/tmp
-expect eof
-spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no $host_user@$host_address /tmp/arch_host_puppet_configuration_script.sh
-expect eof
-EOF
-
-### Installation finished
-if [ -z "$no_reboot" -a -z "$no_reboot_end" ]; then
- echo "Rebooting"
- python $PYTHON_DIRECTORY/reboot_cloud_instance.py --local "$instance_id"
-fi
+++ /dev/null
-#!/bin/bash
-
-usage() {
-cat <<EOF
- $0 [options]
- --help,-h This help
- --vps vps_name Name of the vps
- --password password Password of the vps (only useful in case of no reboot)
- --reinstall-first Start with reinstalling the vps
- --host-user user Use another user (default: root)
- --no-reboot Don't reboot
- --no-reboot-start Don't reboot to rescue at the beginning
- --no-reboot-end Don't reboot to normal at the end
- --git-branch Use another puppet branch (default: master)
- --environment Environment to use for the installl (default: production)
-EOF
-}
-
-set -e
-
-host_user=root
-git_branch=master
-environment=production
-
-while [ -n "$1" ]; do
- case "$1" in
- --vps)
- vps_name="$2"
- shift
- ;;
- --reinstall-first)
- reinstall_first=1
- ;;
- --password)
- password="$2"
- shift
- ;;
- --host-user)
- host_user="$2"
- shift
- ;;
- --no-reboot)
- no_reboot=1
- ;;
- --no-reboot-start)
- no_reboot_start=1
- ;;
- --no-reboot-end)
- no_reboot_end=1
- ;;
- --git-branch)
- git_branch="$2"
- shift
- ;;
- --environment)
- environment="$2"
- shift
- ;;
- --help|-h)
- usage
- exit 0
- ;;
- esac
-
- shift
-done
-
-DIRECTORY=$(cd `dirname $0` && pwd)
-PYTHON_DIRECTORY="$DIRECTORY/../python"
-
-if [ -z "$vps_name" ]; then
- read -p "Nom du vps : " vps_name
-fi
-
-if [ -n "$reinstall_first" ]; then
- echo "Réinstallation du système"
- python $PYTHON_DIRECTORY/reinstall_vps_server.py --use-current "$vps_name"
-
- read -p "Appuyer sur une touche quand le serveur est prêt" ready
-fi
-
-if [ -z "$no_reboot" -a -z "$no_reboot_start" ]; then
- echo "Patienter le temps du reboot"
- python $PYTHON_DIRECTORY/reboot_vps_server.py --rescue "$vps_name"
-fi
-
-if [ -z "$password" ]; then
- stty -echo
- read -p "Mot de passe reçu par e-mail : " password; echo
- stty echo
-fi
-
-ARCH_DIR=`mktemp -d`
-ARCH_HOST_SCRIPT="$ARCH_DIR/arch_host_script.sh"
-ARCH_CHROOT_SCRIPT="$ARCH_DIR/arch_chroot_script.sh"
-ARCH_INSTALL_SCRIPT="$ARCH_DIR/arch_install_script.sh"
-ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT="$ARCH_DIR/arch_host_puppet_configuration_script.sh"
-ARCH_PUPPET_CONFIGURATION_SCRIPT="$ARCH_DIR/arch_puppet_configuration_script.sh"
-ARCH_PUPPET_INITIAL_CONFIGURATION="$ARCH_DIR/puppet_variables.json"
-
-trap "rm -rf $ARCH_DIR" EXIT
-
-#### Base installation stage
-python $PYTHON_DIRECTORY/get_initial_configuration.py $vps_name > $ARCH_PUPPET_INITIAL_CONFIGURATION
-
-cat > $ARCH_HOST_SCRIPT <<EOF
-#!/bin/bash
-
-apt-get update
-apt-get install -y haveged
-haveged &
-
-cd /tmp
-
-LATEST=\$(curl https://mirrors.kernel.org/archlinux/iso/latest/sha1sums.txt | grep "bootstrap" | head -n1)
-SHA1=\$(echo "\$LATEST" | cut -d' ' -f1)
-NAME=\$(echo "\$LATEST" | cut -d' ' -f3)
-
-curl -O "https://mirrors.kernel.org/archlinux/iso/latest/\$NAME"
-
-tar -xzf "\$NAME"
-
-echo 'Server = http://archlinux.mirrors.ovh.net/archlinux/\$repo/os/\$arch' > /tmp/root.x86_64/etc/pacman.d/mirrorlist
-
-DEVICE_STR=\$(cat /proc/mounts | grep "/dev/[sv]d.. /mnt/")
-DEVICE=\$(echo "\$DEVICE_STR" | cut -d' ' -f1)
-MOUNTPOINT=\$(echo "\$DEVICE_STR" | cut -d' ' -f2)
-
-umount "\$DEVICE"
-UUID=\$(lsblk -rno UUID "\$DEVICE")
-
-echo "\$UUID" > /tmp/root.x86_64/device_uuid
-
-cp /tmp/arch_chroot_script.sh /tmp/root.x86_64/
-
-/tmp/root.x86_64/bin/arch-chroot /tmp/root.x86_64/ /arch_chroot_script.sh
-
-mount "\$DEVICE"
-
-cp /tmp/arch_install_script.sh "\$MOUNTPOINT/root/"
-cp /tmp/puppet_variables.json "\$MOUNTPOINT/root/"
-
-/tmp/root.x86_64/bin/arch-chroot "\$MOUNTPOINT" /root/arch_install_script.sh
-EOF
-
-
-cat > $ARCH_CHROOT_SCRIPT <<EOF
-#!/bin/bash
-
-pacman-key --init
-pacman-key --populate archlinux
-
-UUID=\$(cat /device_uuid)
-PART="/dev/disk/by-uuid/\$UUID"
-DEVICE=\$(realpath "\$PART")
-
-# mkfs.ext4 -F -U "\$UUID" "\$DEVICE"
-mount "\$DEVICE" /mnt
-
-##### FIXME: mkfs.ext4 would be better ####
-for i in /mnt/*; do
- if [ "\$i" = "/mnt/boot" ]; then
- # keep /boot/grub
- rm -f \$i/*
- else
- rm -rf \$i
- fi
-done
-##### /FIXME ####
-
-pacstrap /mnt base git puppet
-
-echo "\$PART / auto defaults 0 1" > /mnt/etc/fstab
-
-umount /mnt
-EOF
-
-cat > $ARCH_INSTALL_SCRIPT <<EOF
-CODE_PATH="/etc/puppetlabs/code"
-rm -rf \$CODE_PATH
-git clone -b $git_branch --recursive https://git.immae.eu/perso/Immae/Projets/Puppet.git \$CODE_PATH
-puppet apply --environment $environment --tags base_installation --test \$CODE_PATH/manifests/site.pp
-# The password seed requires puppet to be run twice
-puppet apply --environment $environment --tags base_installation --test \$CODE_PATH/manifests/site.pp
-EOF
-
-chmod a+x $ARCH_HOST_SCRIPT $ARCH_CHROOT_SCRIPT $ARCH_INSTALL_SCRIPT
-
-expect -f - <<EOF
-set timeout -1
-spawn scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no $ARCH_PUPPET_INITIAL_CONFIGURATION $ARCH_HOST_SCRIPT $ARCH_CHROOT_SCRIPT $ARCH_INSTALL_SCRIPT $host_user@$vps_name:/tmp
-expect "assword:"
-send "$password\n"
-expect eof
-spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no $host_user@$vps_name /tmp/arch_host_script.sh
-expect "assword:"
-send "$password\r"
-expect eof
-EOF
-
-### Role specific stage
-read -p "Press key when LDAP is configured" i
-
-cat > $ARCH_PUPPET_CONFIGURATION_SCRIPT <<EOF
-CODE_PATH="/etc/puppetlabs/code"
-puppet apply --environment $environment --tags base_installation --test \$CODE_PATH/manifests/site.pp
-EOF
-
-cat > $ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT <<EOF
-DEVICE_STR=\$(cat /proc/mounts | grep "/dev/[sv]d.. /mnt/")
-DEVICE=\$(echo "\$DEVICE_STR" | cut -d' ' -f1)
-MOUNTPOINT=\$(echo "\$DEVICE_STR" | cut -d' ' -f2)
-
-cp /tmp/arch_puppet_configuration_script.sh "\$MOUNTPOINT/root/"
-
-/tmp/root.x86_64/bin/arch-chroot "\$MOUNTPOINT" /root/arch_puppet_configuration_script.sh
-EOF
-
-chmod a+x $ARCH_PUPPET_CONFIGURATION_SCRIPT $ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT
-
-expect -f - <<EOF
-set timeout -1
-spawn scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no $ARCH_PUPPET_CONFIGURATION_SCRIPT $ARCH_HOST_PUPPET_CONFIGURATION_SCRIPT $host_user@$vps_name:/tmp
-expect "assword:"
-send "$password\n"
-expect eof
-spawn ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no $host_user@$vps_name /tmp/arch_host_puppet_configuration_script.sh
-expect "assword:"
-send "$password\r"
-expect eof
-EOF
-
-### Installation finished
-if [ -z "$no_reboot" -a -z "$no_reboot_end" ]; then
- echo "Rebooting"
- python $PYTHON_DIRECTORY/reboot_vps_server.py --local "$vps_name"
-fi
---
lookup_options:
- base_installation::mounts:
+ profile::fstab::mounts:
merge: unique
classes:
merge: deep
base_installation::system_users:
merge: unique
+ letsencrypt::hosts:
+ merge: unique
+ role::backup::backups:
+ merge: unique
+ profile::known_hosts::hosts:
+ merge: unique
classes:
stdlib: ~
base_installation::ldap_server: "ldap.immae.eu"
base_installation::ldap_uri: "ldaps://ldap.immae.eu"
# FIXME: get all mounts without needing that hack?
-base_installation::mounts:
- - "%{facts.ldapvar.self.vars.mounts.0}"
- - "%{facts.ldapvar.self.vars.mounts.1}"
base_installation::puppet_conf_path: "/etc/puppetlabs/puppet"
base_installation::puppet_code_path: "/etc/puppetlabs/code"
base_installation::puppet_pass_seed: "/etc/puppetlabs/puppet/password_seed"
base_installation::puppet_ssl_path: "/etc/puppetlabs/ssl"
base_installation::system_locales: ["fr_FR.UTF-8", "en_US.UTF-8"]
base_installation::system_timezone: "Europe/Paris"
-base_installation::system_users:
- - userid: 1000
- username: "immae"
- groups: ["wheel"]
- keys:
- - host: "immae.eu"
- key: "AAAAB3NzaC1yc2EAAAADAQABAAABAQDi5PgLBwMRyRwzJPnSgUyRAuB9AAxMijsw1pR/t/wmxQne1O5fIPOleHx+D8dyZbwm+XkzlcJpgT0Qy3qC9J8BPhshJvO/tA/8CI/oS/FE0uWsyACH1DMO2dk4gRRZGSE9IuzDMRPlnfZ3n0tdsPzzv3GH4It/oPIgsvkTowKztGLQ7Xmjr5BxzAhXcIQymqA0U3XWHSdWvnSRDaOFG0PDoVMS85IdwlviVKLnV5Sstb4NC/P28LFfgvW8DO/XrOqujgDomqTmR41dK/AyrGGOb2cQUMO4l8Oa+74aOyKaB61rr/rJkr+wCbEttkTvgFa6zZygSk3edfiWE2rgn4+v"
- key_type: "ssh-rsa"
-xmr_stak::mining_pool: "pool.minexmr.com:7777"
-xmr_stak::wallet: "44CA8TxTFYbQqN2kLyk8AnB6Ghz4mcbGpYC2EyXW7A8H9QspvWnTjDn39XUZDPrFwPa5JNwt4TmAxcooPWv4SaJqL87Bcdo"
+base_installation::system_users: [] # Fetched via ldap
+profile::fstab::mounts:
+ - "%{facts.ldapvar.self.vars.mounts.0}"
+ - "%{facts.ldapvar.self.vars.mounts.1}"
+profile::xmr_stak::mining_pool: "" # Fetched via ldap
+profile::xmr_stak::wallet: "" # Fetched via ldap
+profile::mail::mailhub: "" # Fetched via ldap
+role::backup::mailto: "" # Fetched via ldap
+role::backup::backups: [] # Fetched via ldap
+profile::known_hosts::hosts: [] # Fetched via ldap
+letsencrypt::email: ~ # Fetched via ldap
+letsencrypt::try_for_real_hostname: true
--- /dev/null
+---
+classes:
+ role::backup: ~
+role::backup::user: "backup"
+role::backup::group: "backup"
+base_installation::system_users:
+ - username: "%{lookup('role::backup::user')}"
+ userid: 2000
+ system: true
+ password: "!!"
+
---
classes:
role::cryptoportfolio: ~
-cryptoportfolio::slack_webhook: "%{ldapvar.self.vars.cf_slack_webhook.0}"
+letsencrypt::hosts: "%{lookup('base_installation::system_hostname')}"
+role::cryptoportfolio::user: "cryptoportfolio"
+role::cryptoportfolio::group: "cryptoportfolio"
+role::cryptoportfolio::home: "/home/cryptoportfolio"
+role::cryptoportfolio::env: "prod"
+role::cryptoportfolio::webhook_url: "%{ldapvar.self.vars.cf_slack_webhook.0}"
+role::cryptoportfolio::pg_db: "cryptoportfolio"
+role::cryptoportfolio::pg_user: "cryptoportfolio"
+role::cryptoportfolio::pg_user_replication: "cryptoportfolio_replication"
+role::cryptoportfolio::web_host: "%{lookup('base_installation::system_hostname')}"
+role::cryptoportfolio::web_port: ""
+role::cryptoportfolio::web_ssl: true
+base_installation::system_users:
+ - username: "%{lookup('role::cryptoportfolio::user')}"
+ system: true
+ password: "!!"
base_installation::system_hostname: "%{ldapvar.self.vars.host.0}"
base_installation::real_hostname: "%{facts.ec2_metadata.hostname}.v.immae.eu"
base_installation::ldap_cert_path: "/etc/ssl/certs/ca-certificates.crt"
-ssl::try_letsencrypt_for_real_hostname: true
+letsencrypt::try_for_real_hostname: true
+profile::xmr_stak::cpulimit: "30"
base_installation::real_hostname: "%{facts.ec2_metadata.hostname}.ovh.net"
base_installation::grub_device: "/dev/sdb"
base_installation::ldap_cert_path: "/etc/ssl/certs/ca-certificates.crt"
-ssl::try_letsencrypt_for_real_hostname: false
+letsencrypt::try_for_real_hostname: false
+profile::xmr_stak::cpulimit: "90"
hierarchy:
- name: "Initialization variables"
path: "/root/puppet_variables.json"
+ data_hash: json_data
+
+ - name: "Puppet ldap variables"
+ data_hash: ldap_data
- name: "Per-role environment data"
mapped_paths: [ldapvar.self.vars.roles, role, "roles/%{role}.yaml"]
---
-cryptoportfolio::front_version: v0.0.2-3-g6200f9a
-cryptoportfolio::front_sha256: 69d31251ecd4fcea46d93dfee0184b1171019a765b6744b84f6eec6b10e5818f
-cryptoportfolio::bot_version: v0.5-8-g34eb08f
-cryptoportfolio::bot_sha256: f5b99c4a1cc4db0228f757705a5a909aa301e42787bc5842f8ba442fec0d3fd1
+role::cryptoportfolio::front_version: v0.0.2-3-g6200f9a
+role::cryptoportfolio::front_sha256: 69d31251ecd4fcea46d93dfee0184b1171019a765b6744b84f6eec6b10e5818f
---
-cryptoportfolio::front_version: v0.0.2-3-g6200f9a
-cryptoportfolio::front_sha256: 69d31251ecd4fcea46d93dfee0184b1171019a765b6744b84f6eec6b10e5818f
-cryptoportfolio::bot_version: v0.5.1
-cryptoportfolio::bot_sha256: 733789711365b2397bd996689af616a6789207d26c71a31ad1af68620b267d54
+role::cryptoportfolio::front_version: v0.0.2-3-g6200f9a
+role::cryptoportfolio::front_sha256: 69d31251ecd4fcea46d93dfee0184b1171019a765b6744b84f6eec6b10e5818f
+role::cryptoportfolio::bot_version: v0.5.1
+role::cryptoportfolio::bot_sha256: 733789711365b2397bd996689af616a6789207d26c71a31ad1af68620b267d54
node default {
- lookup('classes', Hash, 'deep').each |$class_name, $class_hash| {
+ lookup('classes').each |$class_name, $class_hash| {
if empty($class_hash) {
include $class_name
} else {
#!/bin/bash
-## Run Puppet locally using puppet apply
+## Run Puppet locally using puppet_apply
git submodule update --init
-/usr/bin/puppet apply `pwd`/manifests/site.pp
+/usr/local/sbin/puppet_apply `pwd`/manifests/site.pp
## Log status of the Puppet run
if [ $? -eq 0 ]
--- /dev/null
+#!/bin/bash
+
+lockfile=/var/run/puppet-apply.lock
+path=`dirname $0`
+path=`cd $path/..; pwd`
+
+if [ $(id -u) -gt 0 ]; then
+ echo "You must be root to run this script." >&2
+ exit 2
+fi
+
+if (set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then
+ trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
+
+ puppet apply "$@"
+
+ rm -f "$lockfile"
+ trap - INT TERM EXIT
+else
+ echo "Failed to acquire lockfile: $lockfile." >&2
+ echo "Held by $(cat $lockfile 2>/dev/null)" >&2
+ exit 1
+fi
git reset --hard origin/$branch
git submodule update --init
-puppet apply --test manifests/site.pp
+puppet_apply --test manifests/site.pp
connection.search(base, scope, filter) do |entry|
data_ = entry.to_hash
- data_['vars'] = (data_[Puppet[:ldapstackedattrs]] || [])
- .map { |var| var.split("=", 2) }
- .group_by { |(key, value)| key }
- .map { |key, value| [key, value.map(&:last)] }
- .to_h
+ if data_["objectClass"].any? { |class_| class_ == "puppetClient" }
+ data_['vars'] = (data_[Puppet[:ldapstackedattrs]] || [])
+ .map { |var| var.split("=", 2) }
+ .group_by { |(key, value)| key }
+ .map { |key, value| [key, value.map(&:last)] }
+ .to_h
- data[:other] << data_
+ data[:other] << data_
- if data_["cn"].any? { |cn| cn == host }
- data[:self] = data_
+ if data_["cn"].any? { |cn| cn == host }
+ data[:self] = data_
+ end
end
end
--- /dev/null
+require 'json'
+
+Puppet::Functions.create_function(:ldap_data) do
+ dispatch :ldap_data do
+ param 'Hash', :options
+ param 'Puppet::LookupContext', :context
+ end
+
+ def ldap_data(options, context)
+ begin
+ require 'ldap'
+ require 'puppet/util/ldap/connection'
+ rescue LoadError
+ context.not_found
+ return
+ end
+
+ if !context.cache_has_key("ldap_lookup")
+ begin
+ conn = Puppet::Util::Ldap::Connection.instance
+ conn.start
+ connection = conn.connection
+ rescue ::LDAP::ResultError => e
+ raise Puppet::ParseError, ("ldapquery(): LDAP ResultError - #{e.message}")
+ end
+
+ host = Facter.value('ec2_metadata')["hostname"]
+ base = Puppet[:ldapbase]
+ scope = ::LDAP::LDAP_SCOPE_SUBTREE
+ filter = "(objectclass=*)"
+
+ data = {}
+ connection.search(base, scope, filter) do |entry|
+ data_ = entry.to_hash
+ jsons = data_["immaePuppetJson"] || []
+ jsons.each do |json|
+ data.merge!(JSON.parse(json))
+ end
+ end
+
+ context.cache("ldap_lookup", data)
+ end
+
+ context.cached_value("ldap_lookup")
+ end
+end
}
cron { 'puppet-apply':
ensure => present,
- command => "cd $base_installation::puppet_code_path ; puppet apply $base_installation::puppet_code_path/manifests/site.pp",
+ command => "cd $base_installation::puppet_code_path ; /usr/local/sbin/puppet_apply $base_installation::puppet_code_path/manifests/site.pp",
user => root,
minute => '*/20'
}
cron { 'puppet-apply-reboot':
ensure => present,
- command => "cd $base_installation::puppet_code_path ; puppet apply $base_installation::puppet_code_path/manifests/site.pp",
+ command => "cd $base_installation::puppet_code_path ; /usr/local/sbin/puppet_apply $base_installation::puppet_code_path/manifests/site.pp",
user => root,
special => "reboot"
}
+ cron { 'pacman_keys':
+ ensure => present,
+ command => "pacman-key --populate archlinux",
+ user => root,
+ minute => "0",
+ hour => "1",
+ }
}
}
Optional[String] $ldap_dn = $base_installation::params::ldap_dn,
Optional[String] $ldap_server = $base_installation::params::ldap_server,
Optional[String] $ldap_uri = $base_installation::params::ldap_uri,
- Optional[Array[String]] $mounts = $base_installation::params::mounts,
Optional[String] $puppet_code_path = $base_installation::params::puppet_code_path,
Optional[String] $puppet_conf_path = $base_installation::params::puppet_conf_path,
Optional[String] $puppet_pass_seed = $base_installation::params::puppet_pass_seed,
contain ::base_installation::users
contain ::base_installation::package_managers
contain ::base_installation::puppet
- contain ::base_installation::fstab
}
$ldap_cert_path = "/etc/ssl/certs/ca-certificates.crt"
$ldap_uri = "ldaps://ldap.example.com"
$ldap_server = "ldap.example.com"
- $mounts = []
$real_hostname = "example.com"
$system_hostname = "example.com"
$system_locales = ["en_US.UTF-8"]
source => "puppet:///modules/base_installation/scripts/report_print.rb"
}
+ file { '/usr/local/sbin/puppet_apply':
+ mode => "0755",
+ ensure => present,
+ source => "puppet:///modules/base_installation/scripts/puppet_apply",
+ }
+
unless empty(find_file($password_seed)) {
$ldap_password = generate_password(24, $password_seed, "ldap")
$ssha_ldap_seed = generate_password(5, $password_seed, "ldap_seed")
require => File[$base_installation::puppet_conf_path],
}
- $ips = lookup("ips") |$key| { {} }
+ $ips = lookup("ips", { 'default_value' => undef })
file { "$base_installation::puppet_conf_path/host_ldap.info":
content => template("base_installation/puppet/host_ldap.info.erb"),
require => File[$base_installation::puppet_conf_path],
group => "root"
}
- $ip6 = lookup("ips.v6") |$key| { {} }
+ $ip6 = lookup("ips.v6", { 'default_value' => undef })
file { '/etc/systemd/network/en-dhcp.network':
ensure => "present",
path => "/etc/systemd/network/en-dhcp.network",
ensure => "present",
groups => $user[groups],
managehome => true,
+ system => !!$user[system],
home => "/home/${user[username]}",
- notify => Exec["remove_password"],
+ notify => Exec["remove_password:${user[username]}:${user[userid]}"],
purge_ssh_keys => true
}
- exec { "remove_password":
+ exec { "remove_password:${user[username]}:${user[userid]}":
command => "/usr/bin/chage -d 0 ${user[username]} && /usr/bin/passwd -d ${user[username]}",
+ onlyif => "/usr/bin/test -z '${user[password]}'",
refreshonly => true
}
- $user[keys].each |$key| {
- ssh_authorized_key { "${user[username]}@${key[host]}":
- name => "${user[username]}@${key[host]}",
- user => $user[username],
- type => $key[key_type],
- key => $key[key],
+ if has_key($user, "keys") {
+ $user[keys].each |$key| {
+ ssh_authorized_key { "${user[username]}@${key[host]}":
+ name => "${user[username]}@${key[host]}",
+ user => $user[username],
+ type => $key[key_type],
+ key => $key[key],
+ }
}
}
}
-#### Please add this node to LDAP:
+\e[0;35m#### Please add this node to LDAP:\e[0m
ldapadd -D "cn=root,<%= @ldap_base %>" -W << 'EOF'
dn: <%= @ldap_dn %>
cn: <%= @ldap_cn %>
environment: <%= @environment %>
userpassword: {SSHA}<%= Base64.encode64(Digest::SHA1.digest(@ldap_password+@ssha_ldap_seed)+@ssha_ldap_seed).chomp! %>
EOF
-#### Or modify an existing entry:
+\e[0;35m#### Or modify an existing entry:\e[0m
ldapmodify -D "cn=root,<%= @ldap_base %>" -W << 'EOF'
dn: <%= @ldap_dn %>
changetype: modify
replace: userPassword
userpassword: {SSHA}<%= Base64.encode64(Digest::SHA1.digest(@ldap_password+@ssha_ldap_seed)+@ssha_ldap_seed).chomp! %>
+-
replace: environment
environment: <%= @environment %>
<%- unless @ips.empty? -%>
-Subproject commit 8db3b97081230d5d89f8f1467eec05bf19b03f3c
+Subproject commit 5668cfa6dff56d5965ab2143fd0aeb322518d9c8
install_method => "package",
package_name => "certbot",
package_command => "certbot",
- # FIXME
- email => 'sites+letsencrypt@mail.immae.eu',
+ email => lookup('letsencrypt::email'),
}
- $real_hostname = lookup("base_installation::real_hostname") |$key| { {} }
+ $real_hostname = lookup("base_installation::real_hostname", { "default_value" => undef })
unless empty($real_hostname) {
- if (lookup("ssl::try_letsencrypt_for_real_hostname") |$key| { true }) {
+ if (lookup("letsencrypt::try_for_real_hostname", { "default_value" => true })) {
letsencrypt::certonly { $real_hostname:
before => Apache::Vhost["default_ssl"];
default: * => $::profile::apache::letsencrypt_certonly_default;
}
}
+ lookup("letsencrypt::hosts", { "default_value" => [] }).each |$host| {
+ if ($host != $real_hostname) { # Done above already
+ letsencrypt::certonly { $host: ;
+ default: * => $letsencrypt_certonly_default;
+ }
+ }
+ }
+
apache::vhost { "redirect_no_ssl":
port => '80',
error_log => false,
-class base_installation::fstab (
- $mounts = $base_installation::mounts
-) inherits base_installation {
+class profile::fstab (
+ Optional[Array] $mounts = []
+) {
$mounts.each |$mount| {
unless empty($mount) {
$infos = split($mount, ';')
--- /dev/null
+class profile::known_hosts (
+ Optional[Array] $hosts = []
+) {
+ $hosts.each |$host| {
+ sshkey { $host["name"]:
+ ensure => "present",
+ key => $host["key"],
+ type => $host["type"],
+ }
+ }
+}
--- /dev/null
+class profile::mail (
+ String $mailhub,
+ Optional[Integer] $mailhub_port = 25,
+) {
+ ensure_packages(["s-nail", "ssmtp"])
+
+ $hostname = lookup("base_installation::real_hostname")
+
+ file { "/etc/ssmtp/ssmtp.conf":
+ ensure => "present",
+ content => template("profile/mail/ssmtp.conf.erb"),
+ }
+}
+
class profile::postgresql {
- $password_seed = lookup("base_installation::puppet_pass_seed") |$key| { {} }
+ $password_seed = lookup("base_installation::puppet_pass_seed")
class { '::postgresql::globals':
encoding => 'UTF-8',
database => 'all',
user => $pg_user,
auth_method => 'ident',
- order => "a1",
+ order => "00-01",
}
postgresql::server::pg_hba_rule { 'localhost access as postgres user':
description => 'Allow localhost access to postgres user',
user => $pg_user,
address => "127.0.0.1/32",
auth_method => 'md5',
- order => "a2",
+ order => "00-02",
}
postgresql::server::pg_hba_rule { 'localhost ip6 access as postgres user':
description => 'Allow localhost access to postgres user',
user => $pg_user,
address => "::1/128",
auth_method => 'md5',
- order => "a3",
+ order => "00-03",
}
postgresql::server::pg_hba_rule { 'deny access to postgresql user':
description => 'Deny remote access to postgres user',
user => $pg_user,
address => "0.0.0.0/0",
auth_method => 'reject',
- order => "a4",
+ order => "00-04",
}
postgresql::server::pg_hba_rule { 'local access':
database => 'all',
user => 'all',
auth_method => 'md5',
- order => "b1",
+ order => "10-01",
}
postgresql::server::pg_hba_rule { 'local access with same name':
database => 'all',
user => 'all',
auth_method => 'ident',
- order => "b2",
+ order => "10-02",
}
}
-class profile::xmr_stak {
+class profile::xmr_stak (
+ String $mining_pool,
+ String $wallet,
+ Optional[String] $cpulimit = "50",
+ Optional[String] $password = "x",
+) {
ensure_resource('exec', 'systemctl daemon-reload', {
command => '/usr/bin/systemctl daemon-reload',
refreshonly => true
mode => "0644",
owner => "root",
group => "root",
- source => "puppet:///modules/profile/xmr_stak/xmr-stak.service",
+ content => template("profile/xmr_stak/xmr-stak.service.erb"),
require => User["xmr_stak"],
notify => Exec["systemctl daemon-reload"]
}
- $mining_pool = lookup("xmr_stak::mining_pool") |$key| { {} }
- $wallet = lookup("xmr_stak::wallet") |$key| { {} }
- $password = lookup("xmr_stak::password") |$key| { "x" }
- $instance = regsubst($facts["ec2_metadata"]["hostname"], '\.', "_", "G")
+ $instance = regsubst(lookup("base_installation::ldap_cn"), '\.', "_", "G")
file { "/var/lib/xmr_stak/xmr-stak.conf":
mode => "0644",
--- /dev/null
+#
+# /etc/ssmtp.conf -- a config file for sSMTP sendmail.
+#
+# The person who gets all mail for userids < 1000
+# Make this empty to disable rewriting.
+root=postmaster
+# The place where the mail goes. The actual machine name is required
+# no MX records are consulted. Commonly mailhosts are named mail.domain.com
+# The example will fit if you are in domain.com and you mailhub is so named.
+mailhub=<%= @mailhub %>:<%= @mailhub_port %>
+# Where will the mail seem to come from?
+#rewriteDomain=y
+# The full hostname
+hostname=<%= @hostname %>
Type=simple
User=xmr_stak
Group=xmr_stak
-ExecStart=/usr/bin/cpulimit --limit 90 /usr/bin/xmr-stak -c /var/lib/xmr_stak/xmr-stak.conf
+ExecStart=/usr/bin/cpulimit --limit <%= @cpulimit %> /usr/bin/xmr-stak -c /var/lib/xmr_stak/xmr-stak.conf
Nice=19
[Install]
WantedBy=multi-user.target
+
--- /dev/null
+class role::backup (
+ String $user,
+ String $group,
+ String $mailto,
+ Optional[Array] $backups = [],
+ Optional[String] $mountpoint = "/backup1",
+ Optional[String] $backup_script = "/usr/local/bin/backup.sh",
+) {
+ include "base_installation"
+
+ include "profile::fstab"
+ include "profile::mail"
+ include "profile::tools"
+ include "profile::xmr_stak"
+ include "profile::known_hosts"
+
+ ensure_packages(["rsync"])
+
+ ssh_keygen { $user:
+ notify => Notify_refresh["notify-backup-sshkey-change"]
+ }
+
+ $hosts = $backups.map |$backup| { $backup["host"] }
+
+ notify_refresh { "notify-backup-sshkey-change":
+ message => template("role/backup/ssh_key_changed.info.erb"),
+ refreshonly => true
+ }
+
+ $hosts.each |$host| {
+ notify_refresh { "notify-backup-sshhost-$host-changed":
+ message => template("role/backup/ssh_host_changed.info.erb"),
+ refreshonly => true,
+ subscribe => Sshkey[$host],
+ }
+ }
+
+ concat { $backup_script:
+ ensure => "present",
+ ensure_newline => true,
+ mode => "0755",
+ }
+
+ cron { "backup":
+ ensure => present,
+ command => $backup_script,
+ user => $user,
+ minute => 25,
+ hour => 3,
+ require => Concat[$backup_script],
+ }
+
+ concat::fragment { "backup_head":
+ target => $backup_script,
+ content => template("role/backup/backup_head.sh.erb"),
+ order => "01-50",
+ }
+
+ concat::fragment { "backup_tail":
+ target => $backup_script,
+ content => template("role/backup/backup_tail.sh.erb"),
+ order => "99-50",
+ }
+
+ $backups.each |$infos| {
+ $dirname = $infos["name"]
+ $login = $infos["login"]
+ $host = $infos["host"]
+ $dest = "$login@$host"
+ $base = "$mountpoint/$dirname"
+ $nbr = $infos["nbr"]
+ $order_dirname = $infos["order"]
+
+ file { $base:
+ ensure => "directory",
+ owner => $user,
+ group => $group,
+ require => Mount[$mountpoint],
+ } ->
+ file { "$base/older":
+ ensure => "directory",
+ owner => $user,
+ group => $group,
+ } ->
+ file { "$base/rsync_output":
+ ensure => "directory",
+ owner => $user,
+ group => $group,
+ }
+
+ concat::fragment { "backup_${dirname}_head":
+ target => $backup_script,
+ content => template("role/backup/backup_dirname_head.sh.erb"),
+ order => "$order_dirname-01",
+ }
+
+ concat::fragment { "backup_${dirname}_tail":
+ target => $backup_script,
+ content => template("role/backup/backup_dirname_tail.sh.erb"),
+ order => "$order_dirname-99",
+ }
+
+ $infos["parts"].each |$part| {
+ $local_folder = $part["local_folder"]
+ $remote_folder = $part["remote_folder"]
+ $exclude_from = $part["exclude_from"]
+ $files_from = $part["files_from"]
+ $args = $part["args"]
+ $order_part = $part["order"]
+
+ file { "$base/$local_folder":
+ ensure => "directory",
+ owner => $user,
+ group => $group,
+ require => File[$base],
+ }
+
+ concat::fragment { "backup_${dirname}_${local_folder}":
+ target => $backup_script,
+ content => template("role/backup/backup_dirname_part.sh.erb"),
+ order => "$order_dirname-$order_part",
+ }
+ }
+ }
+}
-class role::cryptoportfolio {
- ensure_resource('exec', 'systemctl daemon-reload', {
- command => '/usr/bin/systemctl daemon-reload',
- refreshonly => true
- })
-
+class role::cryptoportfolio (
+ String $user,
+ String $group,
+ String $home,
+ Optional[String] $env = "prod",
+ Optional[String] $webhook_url = undef,
+ String $pg_user,
+ String $pg_user_replication,
+ String $pg_db,
+ Optional[String] $pg_hostname = "localhost",
+ Optional[String] $pg_port = "5432",
+ Optional[String] $web_host = undef,
+ Optional[String] $web_port = "",
+ Optional[Boolean] $web_ssl = true,
+ Optional[String] $front_version = undef,
+ Optional[String] $front_sha256 = undef,
+ Optional[String] $bot_version = undef,
+ Optional[String] $bot_sha256 = undef,
+) {
include "base_installation"
include "profile::tools"
include "profile::apache"
include "profile::xmr_stak"
- $password_seed = lookup("base_installation::puppet_pass_seed") |$key| { {} }
-
- $cf_pg_user = "cryptoportfolio"
- $cf_pg_user_replication = "cryptoportfolio_replication"
- $cf_pg_db = "cryptoportfolio"
- $cf_pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio")
- $cf_pg_replication_password = generate_password(24, $password_seed, "postgres_cryptoportfolio_replication")
- $cf_pg_hostname = "localhost"
- $cf_pg_port = "5432"
- $cf_pg_host = "${cf_pg_hostname}:${cf_pg_port}"
-
- $cf_user = "cryptoportfolio"
- $cf_group = "cryptoportfolio"
- $cf_home = "/opt/cryptoportfolio"
- $cf_env = "prod"
- $cf_front_app_host = lookup("base_installation::system_hostname") |$key| { "example.com" }
- $cf_front_app_port = ""
- $cf_front_app_ssl = "true"
- $cf_front_app = "${cf_home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front"
- $cf_front_app_api_workdir = "${cf_front_app}/cmd/app"
- $cf_front_app_api_bin = "${cf_front_app_api_workdir}/cryptoportfolio-app"
- $cf_front_app_api_conf = "${cf_home}/conf.toml"
- $cf_front_app_api_secret = generate_password(24, $password_seed, "cryptoportfolio_api_secret")
-
- $cf_front_app_static_conf = "${cf_front_app}/cmd/web/env/prod.env"
-
- $cf_bot_app = "${cf_home}/bot"
- $cf_bot_app_conf = "${cf_home}/bot_config.ini"
- $cf_bot_app_reports = "${cf_home}/bot_reports"
-
- $cf_webhook_url = lookup("cryptoportfolio::slack_webhook") |$key| { "" }
-
- file { "/var/lib/postgres/data/certs":
- ensure => directory,
- mode => "0700",
- owner => $::profile::postgresql::pg_user,
- group => $::profile::postgresql::pg_user,
- require => File["/var/lib/postgres"],
- }
+ contain "role::cryptoportfolio::postgresql"
+ contain "role::cryptoportfolio::apache"
- file { "/var/lib/postgres/data/certs/cert.pem":
- source => "file:///etc/letsencrypt/live/$cf_front_app_host/cert.pem",
- mode => "0600",
- links => "follow",
- owner => $::profile::postgresql::pg_user,
- group => $::profile::postgresql::pg_user,
- require => [Letsencrypt::Certonly[$cf_front_app_host], File["/var/lib/postgres/data/certs"]]
- }
-
- file { "/var/lib/postgres/data/certs/privkey.pem":
- source => "file:///etc/letsencrypt/live/$cf_front_app_host/privkey.pem",
- mode => "0600",
- links => "follow",
- owner => $::profile::postgresql::pg_user,
- group => $::profile::postgresql::pg_user,
- require => [Letsencrypt::Certonly[$cf_front_app_host], File["/var/lib/postgres/data/certs"]]
- }
-
- postgresql::server::config_entry { "wal_level":
- value => "logical",
- }
-
- postgresql::server::config_entry { "ssl":
- value => "on",
- require => Letsencrypt::Certonly[$cf_front_app_host],
- }
-
- postgresql::server::config_entry { "ssl_cert_file":
- value => "/var/lib/postgres/data/certs/cert.pem",
- require => Letsencrypt::Certonly[$cf_front_app_host],
- }
-
- postgresql::server::config_entry { "ssl_key_file":
- value => "/var/lib/postgres/data/certs/privkey.pem",
- require => Letsencrypt::Certonly[$cf_front_app_host],
- }
-
- postgresql::server::db { $cf_pg_db:
- user => $cf_pg_user,
- password => postgresql_password($cf_pg_user, $cf_pg_password),
- }
- ->
- postgresql_psql { "CREATE PUBLICATION ${cf_pg_db}_publication FOR ALL TABLES":
- db => $cf_pg_db,
- unless => "SELECT 1 FROM pg_catalog.pg_publication WHERE pubname = '${cf_pg_db}_publication'",
- }
- ->
- postgresql::server::role { $cf_pg_user_replication:
- db => $cf_pg_db,
- replication => true,
- password_hash => postgresql_password($cf_pg_user_replication, $cf_pg_replication_password),
- }
- ->
- postgresql::server::database_grant { $cf_pg_user_replication:
- db => $cf_pg_db,
- privilege => "CONNECT",
- role => $cf_pg_user_replication,
- }
- ->
- postgresql::server::grant { "all tables in schema:public:$cf_pg_user_replication":
- db => $cf_pg_db,
- role => $cf_pg_user_replication,
- privilege => "SELECT",
- object_type => "ALL TABLES IN SCHEMA",
- object_name => "public",
- }
- ->
- postgresql::server::grant { "all sequences in schema:public:$cf_pg_user_replication":
- db => $cf_pg_db,
- role => $cf_pg_user_replication,
- privilege => "SELECT",
- object_type => "ALL SEQUENCES IN SCHEMA",
- object_name => "public",
- }
-
- postgresql::server::pg_hba_rule { 'allow localhost TCP access to cryptoportfolio user':
- type => 'host',
- database => $cf_pg_db,
- user => $cf_pg_user,
- address => '127.0.0.1/32',
- auth_method => 'md5',
- order => "b0",
- }
- postgresql::server::pg_hba_rule { 'allow localhost ip6 TCP access to cryptoportfolio user':
- type => 'host',
- database => $cf_pg_db,
- user => $cf_pg_user,
- address => '::1/128',
- auth_method => 'md5',
- order => "b0",
- }
-
- postgresql::server::pg_hba_rule { 'allow TCP access to replication user from immae.eu':
- type => 'hostssl',
- database => $cf_pg_db,
- user => $cf_pg_user_replication,
- address => 'immae.eu',
- auth_method => 'md5',
- order => "b0",
- }
-
- letsencrypt::certonly { $cf_front_app_host: ;
- default: * => $::profile::apache::letsencrypt_certonly_default;
- }
-
- class { 'apache::mod::headers': }
- apache::vhost { $cf_front_app_host:
- port => '443',
- docroot => false,
- manage_docroot => false,
- proxy_dest => "http://localhost:8000",
- request_headers => 'set X-Forwarded-Proto "https"',
- ssl => true,
- ssl_cert => "/etc/letsencrypt/live/$cf_front_app_host/cert.pem",
- ssl_key => "/etc/letsencrypt/live/$cf_front_app_host/privkey.pem",
- ssl_chain => "/etc/letsencrypt/live/$cf_front_app_host/chain.pem",
- require => Letsencrypt::Certonly[$cf_front_app_host],
- proxy_preserve_host => true;
- default: * => $::profile::apache::apache_vhost_default;
- }
-
- user { $cf_user:
- name => $cf_user,
- ensure => "present",
- managehome => true,
- home => $cf_home,
- system => true,
- password => '!!',
- }
-
- file { "/usr/local/bin/slack-notify":
- mode => "0755",
- source => "puppet:///modules/role/cryptoportfolio/slack-notify.py",
- }
-
- $front_version = lookup("cryptoportfolio::front_version") |$key| { {} }
- $front_sha256 = lookup("cryptoportfolio::front_sha256") |$key| { {} }
-
- $bot_version = lookup("cryptoportfolio::bot_version") |$key| { {} }
- $bot_sha256 = lookup("cryptoportfolio::bot_sha256") |$key| { {} }
+ contain "role::cryptoportfolio::notify"
unless empty($bot_version) {
- ensure_packages(["python", "python-pip"])
-
- file { $cf_bot_app:
- ensure => "directory",
- mode => "0700",
- owner => $cf_user,
- group => $cf_group,
- require => User[$cf_user],
- }
-
- archive { "${cf_home}/trader_${bot_version}.tar.gz":
- path => "${cf_home}/trader_${bot_version}.tar.gz",
- source => "https://git.immae.eu/releases/cryptoportfolio/trader/trader_${bot_version}.tar.gz",
- checksum_type => "sha256",
- checksum => $bot_sha256,
- cleanup => false,
- extract => true,
- user => $cf_user,
- username => $facts["ec2_metadata"]["hostname"],
- password => generate_password(24, $password_seed, "ldap"),
- extract_path => $cf_bot_app,
- require => [User[$cf_user], File[$cf_bot_app]],
- } ~>
- exec { "py-cryptoportfolio-dependencies":
- cwd => $cf_bot_app,
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- command => "/usr/bin/make install",
- require => User[$cf_user],
- refreshonly => true,
- before => [
- File[$cf_bot_app_conf],
- Cron["py-cryptoportfolio-before"],
- Cron["py-cryptoportfolio-after"],
- ]
- }
-
- file { $cf_bot_app_conf:
- owner => $cf_user,
- group => $cf_group,
- mode => "0600",
- content => template("role/cryptoportfolio/bot_config.ini.erb"),
- require => [
- User[$cf_user],
- Archive["${cf_home}/trader_${bot_version}.tar.gz"],
- ],
- }
-
- cron { "py-cryptoportfolio-before":
- ensure => present,
- command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --before",
- user => "cryptoportfolio",
- weekday => 7, # Sunday
- hour => 22,
- minute => 30,
- environment => ["HOME=${cf_home}","PATH=/usr/bin/"],
- require => [
- File[$cf_bot_app_conf],
- Archive["${cf_home}/trader_${bot_version}.tar.gz"]
- ],
- }
-
- cron { "py-cryptoportfolio-after":
- ensure => present,
- command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --after",
- user => "cryptoportfolio",
- weekday => 1, # Monday
- hour => 1,
- minute => 0,
- environment => ["HOME=${cf_home}","PATH=/usr/bin/"],
- require => [
- File[$cf_bot_app_conf],
- Archive["${cf_home}/trader_${bot_version}.tar.gz"]
- ],
- }
-
- unless empty($cf_webhook_url) {
- exec { "bot-slack-notify":
- refreshonly => true,
- environment => [
- "P_PROJECT=Trader",
- "P_WEBHOOK=${cf_webhook_url}",
- "P_VERSION=${bot_version}",
- "P_HOST=${cf_front_app_host}",
- "P_HTTPS=${cf_front_app_ssl}",
- ],
- command => "/usr/local/bin/slack-notify",
- require => File["/usr/local/bin/slack-notify"],
- subscribe => Exec["py-cryptoportfolio-dependencies"],
- }
- }
+ contain "role::cryptoportfolio::bot"
}
# FIXME: restore backup
unless empty($front_version) {
- ensure_packages(["go", "npm", "nodejs", "yarn"])
-
- file { [
- "${cf_home}/go/",
- "${cf_home}/go/src",
- "${cf_home}/go/src/immae.eu",
- "${cf_home}/go/src/immae.eu/Immae",
- "${cf_home}/go/src/immae.eu/Immae/Projets",
- "${cf_home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies",
- "${cf_home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio",
- $cf_front_app]:
- ensure => "directory",
- mode => "0700",
- owner => $cf_user,
- group => $cf_group,
- require => User[$cf_user],
- }
-
- file { "${cf_home}/front":
- ensure => "link",
- target => $cf_front_app,
- before => File[$cf_front_app],
- }
-
- file { "/etc/systemd/system/cryptoportfolio-app.service":
- mode => "0644",
- owner => "root",
- group => "root",
- content => template("role/cryptoportfolio/cryptoportfolio-app.service.erb"),
- notify => Exec["systemctl daemon-reload"],
- }
-
- service { 'cryptoportfolio-app':
- enable => true,
- ensure => "running",
- subscribe => [Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]],
- require => [
- File["/etc/systemd/system/cryptoportfolio-app.service"],
- Postgresql::Server::Db[$cf_pg_db]
- ],
- } ~>
- exec { "dump $cf_pg_db structure":
- refreshonly => true,
- user => $::profile::postgresql::pg_user,
- group => $::profile::postgresql::pg_user,
- command => "/usr/bin/pg_dump --schema-only --clean --no-publications $cf_pg_db > /var/lib/postgres/${cf_pg_db}.schema",
- }
-
- archive { "${cf_home}/front_${front_version}.tar.gz":
- path => "${cf_home}/front_${front_version}.tar.gz",
- source => "https://git.immae.eu/releases/cryptoportfolio/front/front_${front_version}.tar.gz",
- checksum_type => "sha256",
- checksum => $front_sha256,
- cleanup => false,
- extract => true,
- user => $cf_user,
- username => $facts["ec2_metadata"]["hostname"],
- password => generate_password(24, $password_seed, "ldap"),
- extract_path => $cf_front_app,
- require => [User[$cf_user], File[$cf_front_app]],
- notify => [
- Exec["web-cryptoportfolio-dependencies"],
- Exec["go-get-dep"],
- ]
- }
-
- # Api
- file { $cf_front_app_api_conf:
- owner => $cf_user,
- group => $cf_group,
- mode => "0600",
- content => template("role/cryptoportfolio/api_conf.toml.erb"),
- before => Exec["go-cryptoportfolio-app"],
- }
-
- exec { "go-get-dep":
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- creates => "${cf_home}/go/bin/dep",
- command => "/usr/bin/go get -u github.com/golang/dep/cmd/dep",
- refreshonly => true,
- } ~>
- exec { "go-cryptoportfolio-dependencies":
- cwd => $cf_front_app,
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- command => "${cf_home}/go/bin/dep ensure",
- refreshonly => true,
- } ~>
- exec { "go-cryptoportfolio-app":
- cwd => $cf_front_app_api_workdir,
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- command => "/usr/bin/make build",
- refreshonly => true,
- }
-
- # Static pages
- file { $cf_front_app_static_conf:
- owner => $cf_user,
- group => $cf_group,
- mode => "0600",
- content => template("role/cryptoportfolio/static_conf.env.erb"),
- before => Exec["web-cryptoportfolio-build"],
- }
-
- exec { "web-cryptoportfolio-dependencies":
- cwd => "${cf_front_app}/cmd/web",
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- command => "/usr/bin/make install",
- refreshonly => true,
- require => [Package["npm"], Package["nodejs"], Package["yarn"]]
- } ~>
- exec { "web-cryptoportfolio-build":
- cwd => "${cf_front_app}/cmd/web",
- user => $cf_user,
- environment => ["HOME=${cf_home}"],
- path => ["${cf_front_app}/cmd/web/node_modules/.bin/", "/usr/bin"],
- command => "/usr/bin/make static ENV=${cf_env}",
- refreshonly => true,
- }
-
- unless empty($cf_webhook_url) {
- exec { "front-slack-notify":
- refreshonly => true,
- environment => [
- "P_PROJECT=Front",
- "P_WEBHOOK=${cf_webhook_url}",
- "P_VERSION=${front_version}",
- "P_HOST=${cf_front_app_host}",
- "P_HTTPS=${cf_front_app_ssl}",
- ],
- command => "/usr/local/bin/slack-notify",
- require => File["/usr/local/bin/slack-notify"],
- subscribe => [Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]],
- }
- }
+ contain "role::cryptoportfolio::front"
}
}
--- /dev/null
+class role::cryptoportfolio::apache inherits role::cryptoportfolio {
+ class { 'apache::mod::headers': }
+ apache::vhost { $web_host:
+ port => '443',
+ docroot => false,
+ manage_docroot => false,
+ proxy_dest => "http://localhost:8000",
+ request_headers => 'set X-Forwarded-Proto "https"',
+ ssl => true,
+ ssl_cert => "/etc/letsencrypt/live/$web_host/cert.pem",
+ ssl_key => "/etc/letsencrypt/live/$web_host/privkey.pem",
+ ssl_chain => "/etc/letsencrypt/live/$web_host/chain.pem",
+ require => Letsencrypt::Certonly[$web_host],
+ proxy_preserve_host => true;
+ default: * => $::profile::apache::apache_vhost_default;
+ }
+}
--- /dev/null
+class role::cryptoportfolio::bot inherits role::cryptoportfolio {
+ $password_seed = lookup("base_installation::puppet_pass_seed")
+
+ $cf_bot_app = "${home}/bot"
+ $cf_bot_app_conf = "${home}/bot_config.ini"
+ $cf_bot_app_reports = "${home}/bot_reports"
+
+ ensure_packages(["python", "python-pip"])
+
+ file { $cf_bot_app:
+ ensure => "directory",
+ mode => "0700",
+ owner => $user,
+ group => $group,
+ require => User["$user:"],
+ }
+
+ archive { "${home}/trader_${bot_version}.tar.gz":
+ path => "${home}/trader_${bot_version}.tar.gz",
+ source => "https://git.immae.eu/releases/cryptoportfolio/trader/trader_${bot_version}.tar.gz",
+ checksum_type => "sha256",
+ checksum => $bot_sha256,
+ cleanup => false,
+ extract => true,
+ user => $user,
+ username => lookup("base_installation::ldap_cn"),
+ password => generate_password(24, $password_seed, "ldap"),
+ extract_path => $cf_bot_app,
+ require => [User["$user:"], File[$cf_bot_app]],
+ } ~>
+ exec { "py-cryptoportfolio-dependencies":
+ cwd => $cf_bot_app,
+ user => $user,
+ environment => ["HOME=${home}"],
+ command => "/usr/bin/make install",
+ require => User["$user:"],
+ refreshonly => true,
+ before => [
+ File[$cf_bot_app_conf],
+ Cron["py-cryptoportfolio-before"],
+ Cron["py-cryptoportfolio-after"],
+ ]
+ }
+
+ $pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio")
+ file { $cf_bot_app_conf:
+ owner => $user,
+ group => $group,
+ mode => "0600",
+ content => template("role/cryptoportfolio/bot_config.ini.erb"),
+ require => [
+ User["$user:"],
+ Archive["${home}/trader_${bot_version}.tar.gz"],
+ ],
+ }
+
+ cron { "py-cryptoportfolio-before":
+ ensure => present,
+ command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --before",
+ user => $user,
+ weekday => 7, # Sunday
+ hour => 22,
+ minute => 30,
+ environment => ["HOME=${home}","PATH=/usr/bin/"],
+ require => [
+ File[$cf_bot_app_conf],
+ Archive["${home}/trader_${bot_version}.tar.gz"]
+ ],
+ }
+
+ cron { "py-cryptoportfolio-after":
+ ensure => present,
+ command => "cd $cf_bot_app ; python main.py --config $cf_bot_app_conf --after",
+ user => $user,
+ weekday => 1, # Monday
+ hour => 1,
+ minute => 0,
+ environment => ["HOME=${home}","PATH=/usr/bin/"],
+ require => [
+ File[$cf_bot_app_conf],
+ Archive["${home}/trader_${bot_version}.tar.gz"]
+ ],
+ }
+
+ unless empty($webhook_url) {
+ exec { "bot-slack-notify":
+ refreshonly => true,
+ environment => [
+ "P_PROJECT=Trader",
+ "P_WEBHOOK=${webhook_url}",
+ "P_VERSION=${bot_version}",
+ "P_HOST=${web_host}",
+ "P_HTTPS=${web_ssl}",
+ ],
+ command => "/usr/local/bin/slack-notify",
+ require => File["/usr/local/bin/slack-notify"],
+ subscribe => Exec["py-cryptoportfolio-dependencies"],
+ }
+ }
+}
+
--- /dev/null
+class role::cryptoportfolio::front inherits role::cryptoportfolio {
+ ensure_resource('exec', 'systemctl daemon-reload', {
+ command => '/usr/bin/systemctl daemon-reload',
+ refreshonly => true
+ })
+
+ $password_seed = lookup("base_installation::puppet_pass_seed")
+
+ $cf_front_app = "${home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front"
+ $cf_front_app_api_workdir = "${cf_front_app}/cmd/app"
+ $cf_front_app_api_bin = "${cf_front_app_api_workdir}/cryptoportfolio-app"
+ $cf_front_app_api_conf = "${home}/conf.toml"
+ $cf_front_app_api_secret = generate_password(24, $password_seed, "cryptoportfolio_api_secret")
+
+ $cf_front_app_static_conf = "${cf_front_app}/cmd/web/env/prod.env"
+
+ ensure_packages(["go", "npm", "nodejs", "yarn"])
+
+ file { [
+ "${home}/go/",
+ "${home}/go/src",
+ "${home}/go/src/immae.eu",
+ "${home}/go/src/immae.eu/Immae",
+ "${home}/go/src/immae.eu/Immae/Projets",
+ "${home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies",
+ "${home}/go/src/immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio",
+ $cf_front_app]:
+ ensure => "directory",
+ mode => "0700",
+ owner => $user,
+ group => $group,
+ require => User["$user:"],
+ }
+
+ file { "${home}/front":
+ ensure => "link",
+ target => $cf_front_app,
+ before => File[$cf_front_app],
+ }
+
+ file { "/etc/systemd/system/cryptoportfolio-app.service":
+ mode => "0644",
+ owner => "root",
+ group => "root",
+ content => template("role/cryptoportfolio/cryptoportfolio-app.service.erb"),
+ notify => Exec["systemctl daemon-reload"],
+ }
+
+ service { 'cryptoportfolio-app':
+ enable => true,
+ ensure => "running",
+ subscribe => [File[$cf_front_app_api_conf], Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]],
+ require => [
+ File["/etc/systemd/system/cryptoportfolio-app.service"],
+ Postgresql::Server::Db[$pg_db]
+ ],
+ } ~>
+ exec { "dump $pg_db structure":
+ refreshonly => true,
+ user => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ command => "/usr/bin/pg_dump --schema-only --clean --no-publications $pg_db > /var/lib/postgres/${pg_db}.schema",
+ }
+
+ archive { "${home}/front_${front_version}.tar.gz":
+ path => "${home}/front_${front_version}.tar.gz",
+ source => "https://git.immae.eu/releases/cryptoportfolio/front/front_${front_version}.tar.gz",
+ checksum_type => "sha256",
+ checksum => $front_sha256,
+ cleanup => false,
+ extract => true,
+ user => $user,
+ username => lookup("base_installation::ldap_cn"),
+ password => generate_password(24, $password_seed, "ldap"),
+ extract_path => $cf_front_app,
+ require => [User["$user:"], File[$cf_front_app]],
+ notify => [
+ Exec["web-cryptoportfolio-dependencies"],
+ Exec["go-get-dep"],
+ ]
+ }
+
+ # Api
+ $pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio")
+ $pg_host = "${pg_hostname}:${pg_port}"
+ file { $cf_front_app_api_conf:
+ owner => $user,
+ group => $group,
+ mode => "0600",
+ content => template("role/cryptoportfolio/api_conf.toml.erb"),
+ before => Exec["go-cryptoportfolio-app"],
+ }
+
+ exec { "go-get-dep":
+ user => $user,
+ environment => ["HOME=${home}"],
+ creates => "${home}/go/bin/dep",
+ command => "/usr/bin/go get -u github.com/golang/dep/cmd/dep",
+ refreshonly => true,
+ } ~>
+ exec { "go-cryptoportfolio-dependencies":
+ cwd => $cf_front_app,
+ user => $user,
+ environment => ["HOME=${home}"],
+ command => "${home}/go/bin/dep ensure",
+ refreshonly => true,
+ } ~>
+ exec { "go-cryptoportfolio-app":
+ cwd => $cf_front_app_api_workdir,
+ user => $user,
+ environment => ["HOME=${home}"],
+ command => "/usr/bin/make build",
+ refreshonly => true,
+ }
+
+ # Static pages
+ file { $cf_front_app_static_conf:
+ owner => $user,
+ group => $group,
+ mode => "0600",
+ content => template("role/cryptoportfolio/static_conf.env.erb"),
+ before => Exec["web-cryptoportfolio-build"],
+ }
+
+ exec { "web-cryptoportfolio-dependencies":
+ cwd => "${cf_front_app}/cmd/web",
+ user => $user,
+ environment => ["HOME=${home}"],
+ command => "/usr/bin/make install",
+ refreshonly => true,
+ require => [Package["npm"], Package["nodejs"], Package["yarn"]]
+ } ~>
+ exec { "web-cryptoportfolio-build":
+ cwd => "${cf_front_app}/cmd/web",
+ user => $user,
+ environment => ["HOME=${home}"],
+ path => ["${cf_front_app}/cmd/web/node_modules/.bin/", "/usr/bin"],
+ command => "/usr/bin/make static ENV=${env}",
+ refreshonly => true,
+ }
+
+ unless empty($webhook_url) {
+ exec { "front-slack-notify":
+ refreshonly => true,
+ environment => [
+ "P_PROJECT=Front",
+ "P_WEBHOOK=${webhook_url}",
+ "P_VERSION=${front_version}",
+ "P_HOST=${web_host}",
+ "P_HTTPS=${web_ssl}",
+ ],
+ command => "/usr/local/bin/slack-notify",
+ require => File["/usr/local/bin/slack-notify"],
+ subscribe => [Exec["go-cryptoportfolio-app"], Exec["web-cryptoportfolio-build"]],
+ }
+ }
+
+}
--- /dev/null
+class role::cryptoportfolio::notify inherits role::cryptoportfolio {
+ file { "/usr/local/bin/slack-notify":
+ mode => "0755",
+ source => "puppet:///modules/role/cryptoportfolio/slack-notify.py",
+ }
+}
--- /dev/null
+class role::cryptoportfolio::postgresql inherits role::cryptoportfolio {
+ $password_seed = lookup("base_installation::puppet_pass_seed")
+
+ $pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio")
+ $pg_replication_password = generate_password(24, $password_seed, "postgres_cryptoportfolio_replication")
+
+ file { "/var/lib/postgres/data/certs":
+ ensure => directory,
+ mode => "0700",
+ owner => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ require => File["/var/lib/postgres"],
+ }
+
+ file { "/var/lib/postgres/data/certs/cert.pem":
+ source => "file:///etc/letsencrypt/live/$web_host/cert.pem",
+ mode => "0600",
+ links => "follow",
+ owner => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ require => [Letsencrypt::Certonly[$web_host], File["/var/lib/postgres/data/certs"]]
+ }
+
+ file { "/var/lib/postgres/data/certs/privkey.pem":
+ source => "file:///etc/letsencrypt/live/$web_host/privkey.pem",
+ mode => "0600",
+ links => "follow",
+ owner => $::profile::postgresql::pg_user,
+ group => $::profile::postgresql::pg_user,
+ require => [Letsencrypt::Certonly[$web_host], File["/var/lib/postgres/data/certs"]]
+ }
+
+ postgresql::server::config_entry { "wal_level":
+ value => "logical",
+ }
+
+ postgresql::server::config_entry { "ssl":
+ value => "on",
+ require => Letsencrypt::Certonly[$web_host],
+ }
+
+ postgresql::server::config_entry { "ssl_cert_file":
+ value => "/var/lib/postgres/data/certs/cert.pem",
+ require => Letsencrypt::Certonly[$web_host],
+ }
+
+ postgresql::server::config_entry { "ssl_key_file":
+ value => "/var/lib/postgres/data/certs/privkey.pem",
+ require => Letsencrypt::Certonly[$web_host],
+ }
+
+ postgresql::server::db { $pg_db:
+ user => $pg_user,
+ password => postgresql_password($pg_user, $pg_password),
+ }
+ ->
+ postgresql_psql { "CREATE PUBLICATION ${pg_db}_publication FOR ALL TABLES":
+ db => $pg_db,
+ unless => "SELECT 1 FROM pg_catalog.pg_publication WHERE pubname = '${pg_db}_publication'",
+ }
+ ->
+ postgresql::server::role { $pg_user_replication:
+ db => $pg_db,
+ replication => true,
+ password_hash => postgresql_password($pg_user_replication, $pg_replication_password),
+ }
+ ->
+ postgresql::server::database_grant { $pg_user_replication:
+ db => $pg_db,
+ privilege => "CONNECT",
+ role => $pg_user_replication,
+ }
+ ->
+ postgresql::server::grant { "all tables in schema:public:$pg_user_replication":
+ db => $pg_db,
+ role => $pg_user_replication,
+ privilege => "SELECT",
+ object_type => "ALL TABLES IN SCHEMA",
+ object_name => "public",
+ }
+ ->
+ postgresql::server::grant { "all sequences in schema:public:$pg_user_replication":
+ db => $pg_db,
+ role => $pg_user_replication,
+ privilege => "SELECT",
+ object_type => "ALL SEQUENCES IN SCHEMA",
+ object_name => "public",
+ }
+
+ postgresql::server::pg_hba_rule { 'allow localhost TCP access to cryptoportfolio user':
+ type => 'host',
+ database => $pg_db,
+ user => $pg_user,
+ address => '127.0.0.1/32',
+ auth_method => 'md5',
+ order => "05-01",
+ }
+ postgresql::server::pg_hba_rule { 'allow localhost ip6 TCP access to cryptoportfolio user':
+ type => 'host',
+ database => $pg_db,
+ user => $pg_user,
+ address => '::1/128',
+ auth_method => 'md5',
+ order => "05-01",
+ }
+
+ postgresql::server::pg_hba_rule { 'allow TCP access to replication user from immae.eu':
+ type => 'hostssl',
+ database => $pg_db,
+ user => $pg_user_replication,
+ address => 'immae.eu',
+ auth_method => 'md5',
+ order => "05-01",
+ }
+
+}
--- /dev/null
+##### <%= @dirname %> #####
+DEST="<%= @dest %>"
+BASE="<%= @base %>"
+OLD_BAK_BASE=$BASE/older/j
+BAK_BASE=${OLD_BAK_BASE}0
+RSYNC_OUTPUT=$BASE/rsync_output
+NBR=<%= @nbr %>
+
+if ! ssh \
+ -o PreferredAuthentications=publickey \
+ -o StrictHostKeyChecking=yes \
+ -o ClearAllForwardings=yes \
+ $DEST backup; then
+ echo "Fichier de verrouillage backup sur $DEST ou impossible de se connecter" >&2
+ skip=$DEST
+fi
+
+rm -rf ${OLD_BAK_BASE}${NBR}
+for j in `seq -w $(($NBR-1)) -1 0`; do
+ [ ! -d ${OLD_BAK_BASE}$j ] && continue
+ mv ${OLD_BAK_BASE}$j ${OLD_BAK_BASE}$(($j+1))
+done
+mkdir $BAK_BASE
+mv $RSYNC_OUTPUT $BAK_BASE
+mkdir $RSYNC_OUTPUT
+
+if [ "$skip" != "$DEST" ]; then
--- /dev/null
+### <%= @dirname %> <%= @local_folder %> ###
+LOCAL="<%= @local_folder %>"
+REMOTE="<%= @remote_folder %>"
+
+cd $BASE/$LOCAL
+cat > $EXCL_FROM <<EOF
+<%= @exclude_from.join("\n") %>
+EOF
+cat > $FILES_FROM <<EOF
+<%= @files_from.join("\n") %>
+EOF
+
+OUT=$RSYNC_OUTPUT/$LOCAL
+rsync -XAavbrz --fake-super -e ssh --numeric-ids --delete \
+ --backup-dir=$BAK_BASE/$LOCAL \
+<%- unless @args.empty? -%>
+ <%= @args %>\
+<% end -%>
+<%- unless @exclude_from.empty? -%>
+ --exclude-from=$EXCL_FROM \
+<% end -%>
+<%- unless @files_from.empty? -%>
+ --files-from=$FILES_FROM \
+<% end -%>
+ $DEST:$REMOTE . > $OUT || true
+### End <%= @dirname %> <%= @local_folder %> ###
--- /dev/null
+
+ ssh $DEST sh -c "date > .last_backup"
+fi # [ "$skip" != "$DEST" ]
+##### End <%= @dirname %> #####
--- /dev/null
+#!/bin/bash
+MAILTO="<%= @mailto %>"
+
+EXCL_FROM=`mktemp`
+FILES_FROM=`mktemp`
+TMP_STDERR=`mktemp`
+
+on_exit() {
+ if [ -s "$TMP_STDERR" ]; then
+ cat "$TMP_STDERR" | mail -Ssendwait -s "save_distant rsync error" "$MAILTO"
+ fi
+ rm -f $TMP_STDERR $EXCL_FROM $FILES_FROM
+}
+
+trap "on_exit" EXIT
+
+exec 2> "$TMP_STDERR"
+exec < /dev/null
+
+set -e
--- /dev/null
+#!/bin/bash
+DEST="<%= @dest %>"
+MAILTO="<%= @mailto %>"
+BASE="<%= @base %>"
+OLD_BAK_BASE=$BASE/older/j
+BAK_BASE=${OLD_BAK_BASE}0
+RSYNC_OUTPUT=$BASE/rsync_output
+NBR=7
+
+TMP=`mktemp`
+TMP_STDERR=`mktemp`
+
+trap "rm -f $TMP $TMP_STDERR" EXIT
+
+exec 2> "$TMP_STDERR"
+
+set -e
+if ! `ssh -o ClearAllForwardings=yes $DEST backup`; then
+ echo "Fichier de verrouillage backup sur $DEST"
+ exit 1
+fi
+
+rm -rf ${OLD_BAK_BASE}${NBR}
+for j in `seq -w $(($NBR-1)) -1 0`; do
+ [ ! -d ${OLD_BAK_BASE}$j ] && continue
+ mv ${OLD_BAK_BASE}$j ${OLD_BAK_BASE}$(($j+1))
+done
+mkdir $BAK_BASE
+mv $RSYNC_OUTPUT $BAK_BASE
+mkdir $RSYNC_OUTPUT
+
+##############
+NAME="home"
+FOLDER="/home/immae"
+
+cd $BASE/$NAME
+cat > $TMP <<EOF
+/.no_backup/
+/hosts/florian/nobackup/
+/hosts/connexionswing.com/
+/hosts/connexionswing.immae.eu/
+/hosts/ludivine.immae.eu/
+/hosts/ludivinecassal.com/
+/hosts/piedsjaloux.fr/
+/hosts/piedsjaloux.immae.eu/
+/hosts/spip/sites/*/
+/hosts/spip/spip*
+EOF
+OUT=$RSYNC_OUTPUT/$NAME
+rsync -XAavbrz --fake-super -e ssh --numeric-ids --delete \
+ --backup-dir=$BAK_BASE/$NAME --exclude-from=$TMP \
+ $DEST:$FOLDER . > $OUT || true
+
+##############
+NAME="system"
+FOLDER="/"
+
+cd $BASE/$NAME
+cat > $TMP <<EOF
+/etc/
+/srv/
+/var/lib/
+/var/spool/
+/var/named/
+/usr/local/
+EOF
+OUT=$RSYNC_OUTPUT/$NAME
+rsync -XAavbrz -R --fake-super -e ssh --numeric-ids --delete \
+ --rsync-path='sudo rsync' \
+ --backup-dir=$BAK_BASE/$NAME \
+ --files-from=$TMP \
+ $DEST:$FOLDER . > $OUT || true
+
+##############
+ssh $DEST sh -c "date > .last_backup"
+
+if [ -s "$TMP_STDERR" ]; then
+ cat "$TMP_STDERR" | mail -Ssendwait -s "save_distant rsync error" "$MAILTO"
+fi
--- /dev/null
+Host <%= @host %> added, please send <%= @user %> key if necessary.
+<%- if File.exist?("/home/#{@user}/.ssh/id_rsa.pub") %>
+ <%= File.read("/home/#{@user}/.ssh/id_rsa.pub") %>
+<% end -%>
--- /dev/null
+ssh key of <%= @user %> changed,
+please update hosts:
+<%- @hosts.each do |host| %>
+ - <%= host %>
+<% end -%>
log_level="info"
-mode="<%= @cf_env %>"
+mode="<%= @env %>"
log_out="stdout"
[db]
-user="<%= @cf_pg_user %>"
-password="<%= @cf_pg_password %>"
-database="<%= @cf_pg_db %>"
-address="<%= @cf_pg_host %>"
+user="<%= @pg_user %>"
+password="<%= @pg_password %>"
+database="<%= @pg_db %>"
+address="<%= @pg_host %>"
[api]
-domain="<%= @cf_front_app_host %>"
+domain="<%= @web_host %>"
jwt_secret="<%= @cf_front_app_api_secret %>"
[app]
[postgresql]
-host = <%= @cf_pg_hostname %>
-port = <%= @cf_pg_port %>
-user = <%= @cf_pg_user %>
-password = <%= @cf_pg_password %>
-database = <%= @cf_pg_db %>
+host = <%= @pg_hostname %>
+port = <%= @pg_port %>
+user = <%= @pg_user %>
+password = <%= @pg_password %>
+database = <%= @pg_db %>
[app]
report_path = <%= @cf_bot_app_reports %>
Type=simple
WorkingDirectory=<%= @cf_front_app_api_workdir %>
-User=<%= @cf_user %>
-Group=<%= @cf_group %>
+User=<%= @user %>
+Group=<%= @group %>
UMask=007
ExecStart=<%= @cf_front_app_api_bin %> -conf <%= @cf_front_app_api_conf %>
-API_HOST="<%= @cf_front_app_host %>"
-API_PORT="<%= @cf_front_app_port %>"
-API_HTTPS="<%= @cf_front_app_ssl %>"
+API_HOST="<%= @web_host %>"
+API_PORT="<%= @web_port %>"
+API_HTTPS="<%= @web_ssl %>"
--- /dev/null
+Subproject commit ca53363249b58af96f90cb810c7c51dda8ba803b
# In case it's installed globally
import ovh
import sys
+from ovh_helper import find_cloud_instance
infos = {}
# See ovh/README.rst
client = ovh.Client()
-projects_list = client.get('/cloud/project/')
-if len(projects_list) > 1:
- print("More than one project is not supported, taking the first one")
-project = projects_list[0]
-instances_list = client.get('/cloud/project/{}/instance'.format(project))
-instances = dict(map(lambda x: (x["id"], x), instances_list))
-if sys.argv[-1] in instances:
- instance = instances[sys.argv[-1]]
-else:
- print("Instance not in list:")
- for instance in instances_list:
- print("{}: {}".format(instance["name"], instance["id"]))
- sys.exit(1)
+_, instance = find_cloud_instance(client, sys.argv[-1])
infos["ips"] = {}
for ip_infos in instance["ipAddresses"]:
client = ovh.Client()
+print("OVH cloud instances:")
+projects_list = client.get('/cloud/project/')
+for project_id in projects_list:
+ project = client.get('/cloud/project/{}'.format(project_id))
+ print("\t{}:".format(project["description"]))
+ instances_list = client.get('/cloud/project/{}/instance'.format(project_id))
+ for instance in instances_list:
+ print("\t\t{}: {}".format(instance["name"], instance["id"]))
+
vps_list = client.get('/vps/')
+print("OVH VPS SSD servers:")
for vps in vps_list:
- print(vps)
+ print("\t{}".format(vps))
+
import time
+import sys
def show_progress(client, vps, task_type):
running_task_id = client.get("/vps/{}/tasks?type={}".format(vps, task_type))[0]
time.sleep(3)
print("\rFinished")
+
+def find_cloud_instance(client, instance_id):
+ projects_list = client.get('/cloud/project/')
+ instances_list = []
+ for project in projects_list:
+ instances_list += list(map(lambda x: [project, x],
+ client.get('/cloud/project/{}/instance'.format(project))))
+ instances = dict(map(lambda x: (x[1]["id"], x), instances_list))
+ if instance_id in instances:
+ project_instance = instances[instance_id]
+ else:
+ print("Instance not in list:")
+ for instance in instances_list:
+ print("{}: {}".format(instance[1]["name"], instance[1]["id"]))
+ sys.exit(1)
+ return project_instance
# In case it's installed globally
import ovh
import sys
+from ovh_helper import find_cloud_instance
# Credentials are stored in ~/.ovh.conf
# See ovh/README.rst
client = ovh.Client()
-projects_list = client.get('/cloud/project/')
-if len(projects_list) > 1:
- print("More than one project is not supported, taking the first one")
-project = projects_list[0]
-instances_list = client.get('/cloud/project/{}/instance'.format(project))
-instances = dict(map(lambda x: (x["id"], x), instances_list))
-if sys.argv[-1] in instances:
- instance = instances[sys.argv[-1]]
-else:
- print("Instance not in list:")
- for instance in instances_list:
- print("{}: {}".format(instance["name"], instance["id"]))
- sys.exit(1)
+project, instance = find_cloud_instance(client, sys.argv[-1])
if "--rescue" in sys.argv:
netboot_mode="rescue"
# In case it's installed globally
import ovh
import sys
+from ovh_helper import find_cloud_instance
# Credentials are stored in ~/.ovh.conf
# See ovh/README.rst
client = ovh.Client()
-projects_list = client.get('/cloud/project/')
-if len(projects_list) > 1:
- print("More than one project is not supported, taking the first one")
-project = projects_list[0]
-instances_list = client.get('/cloud/project/{}/instance'.format(project))
-instances = dict(map(lambda x: (x["id"], x), instances_list))
-if sys.argv[-1] in instances:
- instance = instances[sys.argv[-1]]
-else:
- print("Instance not in list:")
- for instance in instances_list:
- print("{}: {}".format(instance["name"], instance["id"]))
- sys.exit(1)
+project, instance = find_cloud_instance(client, sys.argv[-1])
current_image = instance["imageId"]
available_images = client.get('/cloud/project/{}/image'.format(project),
--- /dev/null
+#!/bin/bash
+
+git_branch="$1"
+environment="$2"
+CODE_PATH="/etc/puppetlabs/code"
+
+rm -rf $CODE_PATH
+
+pacman-key --init
+pacman-key --populate archlinux
+
+git clone -b $git_branch --recursive https://git.immae.eu/perso/Immae/Projets/Puppet.git $CODE_PATH
+puppet apply --environment $environment --tags base_installation --test $CODE_PATH/manifests/site.pp
+# The password seed requires puppet to be run twice
+puppet apply --environment $environment --tags base_installation --test $CODE_PATH/manifests/site.pp
+
--- /dev/null
+#!/bin/bash
+
+git_branch="$1"
+environment="$2"
+CODE_PATH="/etc/puppetlabs/code"
+
+puppet apply --environment $environment --tags base_installation --test $CODE_PATH/manifests/site.pp
+
--- /dev/null
+#!/bin/bash
+
+git_branch="$1"
+environment="$2"
+
+MOUNTPOINT=/mnt
+
+sudo cp /tmp/arch_puppet_configuration_script.sh "$MOUNTPOINT/root/"
+
+sudo arch-chroot "$MOUNTPOINT" /root/arch_puppet_configuration_script.sh "$git_branch" "$environment"
+
+sudo umount "$MOUNTPOINT"
--- /dev/null
+#!/bin/bash
+
+set -e
+
+git_branch="$1"
+environment="$2"
+
+# Randomizer
+sudo haveged &
+# /Randomizer
+
+# Prepare an arch chroot
+sudo pacman -Sy --noconfirm arch-install-scripts
+# /Prepare an arch chroot
+
+# Prepare device information
+DEVICE=/dev/vdb1
+MOUNTPOINT=/mnt
+
+UUID=$(lsblk -rno UUID "$DEVICE")
+PART="/dev/disk/by-uuid/$UUID"
+# /Prepare device information
+
+# Install very basic system (base git puppet)
+# mkfs.ext4 -F -U "$UUID" "$DEVICE"
+sudo mount "$DEVICE" /mnt
+
+##### FIXME: mkfs.ext4 would be better ####
+for i in /mnt/*; do
+ if [ "$i" = "/mnt/boot" ]; then
+ # keep /boot/grub
+ sudo rm -f $i/* || true
+ else
+ sudo rm -rf $i
+ fi
+done
+##### /FIXME ####
+
+sudo pacstrap -G /mnt base git puppet
+
+echo "$PART / auto defaults 0 1" | sudo tee /mnt/etc/fstab
+# /Install very basic system
+
+# Install rest of system (via puppet)
+sudo cp /tmp/arch_install_script.sh "$MOUNTPOINT/root/"
+sudo cp /tmp/puppet_variables.json "$MOUNTPOINT/root/"
+
+sudo arch-chroot "$MOUNTPOINT" /root/arch_install_script.sh "$git_branch" "$environment"
+# /Install rest of system
+
--- /dev/null
+#!/bin/bash
+
+pacman-key --init
+pacman-key --populate archlinux
+
+UUID=$(cat /device_uuid)
+PART="/dev/disk/by-uuid/$UUID"
+DEVICE=$(realpath "$PART")
+
+# mkfs.ext4 -F -U "$UUID" "$DEVICE"
+mount "$DEVICE" /mnt
+
+##### FIXME: mkfs.ext4 would be better ####
+for i in /mnt/*; do
+ if [ "$i" = "/mnt/boot" ]; then
+ # keep /boot/grub
+ rm -f $i/*
+ else
+ rm -rf $i
+ fi
+done
+##### /FIXME ####
+
+pacstrap -G /mnt base git puppet
+
+echo "$PART / auto defaults 0 1" > /mnt/etc/fstab
+
+umount /mnt
+
--- /dev/null
+#!/bin/bash
+
+git_branch="$1"
+environment="$2"
+
+DEVICE_STR=$(cat /proc/mounts | grep "/dev/[sv]d.. /mnt/")
+DEVICE=$(echo "$DEVICE_STR" | cut -d' ' -f1)
+MOUNTPOINT=$(echo "$DEVICE_STR" | cut -d' ' -f2)
+
+cp /tmp/arch_puppet_configuration_script.sh "$MOUNTPOINT/root/"
+
+/tmp/root.x86_64/bin/arch-chroot "$MOUNTPOINT" /root/arch_puppet_configuration_script.sh "$git_branch" "$environment"
+
+umount "$MOUNTPOINT"
--- /dev/null
+#!/bin/bash
+
+set -e
+
+git_branch="$1"
+environment="$2"
+
+# Randomizer
+apt-get update
+apt-get install -y haveged
+haveged &
+# /Randomizer
+
+# Prepare an arch chroot
+cd /tmp
+
+LATEST=$(curl -L https://mirrors.kernel.org/archlinux/iso/latest/sha1sums.txt | grep "bootstrap" | head -n1)
+SHA1=$(echo "$LATEST" | cut -d' ' -f1)
+NAME=$(echo "$LATEST" | cut -d' ' -f3)
+
+curl -L -O "https://mirrors.kernel.org/archlinux/iso/latest/$NAME"
+
+tar -xzf "$NAME"
+
+echo 'Server = http://archlinux.mirrors.ovh.net/archlinux/$repo/os/$arch' > /tmp/root.x86_64/etc/pacman.d/mirrorlist
+# /Prepare an arch chroot
+
+# Prepare device information (not available in chroot)
+DEVICE_STR=$(cat /proc/mounts | grep "/dev/[sv]d.. /mnt/")
+DEVICE=$(echo "$DEVICE_STR" | cut -d' ' -f1)
+MOUNTPOINT=$(echo "$DEVICE_STR" | cut -d' ' -f2)
+
+umount "$DEVICE"
+UUID=$(lsblk -rno UUID "$DEVICE")
+
+echo "$UUID" > /tmp/root.x86_64/device_uuid
+# /Prepare device information
+
+# Install very basic system via chroot (base git puppet)
+cp /tmp/arch_chroot_script.sh /tmp/root.x86_64/
+
+/tmp/root.x86_64/bin/arch-chroot /tmp/root.x86_64/ /arch_chroot_script.sh
+# /Install very basic system via chroot
+
+# Mount and install rest of system (via puppet)
+mount "$DEVICE"
+
+cp /tmp/arch_install_script.sh "$MOUNTPOINT/root/"
+cp /tmp/puppet_variables.json "$MOUNTPOINT/root/"
+
+/tmp/root.x86_64/bin/arch-chroot "$MOUNTPOINT" /root/arch_install_script.sh "$git_branch" "$environment"
+# /Mount and install rest of system
+
--- /dev/null
+#!/usr/bin/expect -f
+set dest [lindex $argv 0]
+set password [lindex $argv 1]
+set git_branch [lindex $argv 2]
+set environment [lindex $argv 3]
+set script [lindex $argv 4]
+set files [lrange $argv 4 end]
+
+if {$password == "x"} {
+ set ask_password 0
+} else {
+ set ask_password 1
+}
+
+set scriptname [file tail $script]
+
+set sshopts [split "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no"]
+
+set timeout -1
+spawn scp {*}$sshopts {*}$files $dest:/tmp
+if {$ask_password} {
+ expect "assword:"
+ send "$password\n"
+}
+expect eof
+spawn ssh {*}$sshopts $dest /tmp/$scriptname $git_branch $environment
+if {$ask_password} {
+ expect "assword:"
+ send "$password\n"
+}
+expect eof