#!/bin/sh
set -e -f ${DRY_RUN:+-n} -u
tool=$0
while test -L "$tool"
do tool=$(readlink "$tool")
done
tool=${tool%/*}
. "$tool"/lib/rule.sh
. "$tool"/etc/vm.sh
rule_help () { # SYNTAX: [--hidden]
local hidden; [ ${1:+set} ] || hidden=set
cat >&2 <<-EOF
DESCRIPTION:
ce script regroupe des règles pour administrer la VM ($vm_fqdn)
_depuis_ la VM hébergée ($vm_fqdn) ;
il sert à la fois d'outil (aisément bidouillable)
et de documentation (préçise).
Voir \`$tool/vm_host' pour les règles côté machine hôte ($vm_host).
SYNTAX: $0 \$RULE \${RULE}_SYNTAX
RULES:
$(sed -ne "s/^rule_\(${hidden:+[^_]}[^ ]*\) () {\( *#.*\|\)/ \1\2/p" "$tool"/etc/vm.sh "$0")
ENVIRONMENT:
TRACE # affiche les commandes avant leur exécution
$(sed -ne 's/^readonly \([^ ][^ =]*\).*}\( *#.*\|\)$/\t$\1\2/p' "$tool"/etc/vm.sh "$0")
EOF
}
rule_git_configure () {
(
cd "$tool"
git config --replace branch.master.remote .
git config --replace branch.master.merge refs/remotes/master
local tool
tool=$(cd "$tool"; cd -)
sudo ln -fns "$tool"/vm_hosted /usr/local/sbin/
sudo ln -fns "$tool"/vm_hosted /usr/local/sbin/vm
)
}
rule_git_reset () {
(
cd "$tool"
git checkout -f -B master remotes/master
git clean -f -d -x
)
}
rule_apt_get_install () { # SYNTAX: $package
sudo apt-get install "$@"
}
rule__chrooted_configure () { # NOTE: est-ce bien utile à un moment ?
export LANG=C
export LC_CTYPE=C
. /etc/profile
}
rule_apache2_configure () {
local -; set +f
rule apt_get_install \
apache2-mpm-itk \
libapache2-mod-php5
# VOIR: http://serverfault.com/questions/383526/how-do-i-select-which-apache-mpm-to-use/383634#383634
# VOIR: http://jkroon.blogs.uls.co.za/it/security/using-php-fpm-and-mod_proxy_fcgi-to-optimize-and-secure-lamp-servers
# NOTE: apache2-mpm-itk semble le plus sécurisé,
# car on est certain que tout est exécuté avec les uid/gid
# assignés au VirtualHost/Directory/Location
# néamoins il se peut qu'une combinaison du genre :
# apache2-mpm-{worker,event} + mod_proxy_fcgi + apache2-suexec-custom + php-fpm
# soit plus performante (threads et pas forks),
# cependant l'usage de suexec impose des forks il semble..
# et mod_proxy_fcgi n'apparaît que dans apache 2.4 ;
# donc pour l'instant : apache2-mpm-itk
rule www_configure
cat /dev/stdin "$tool"/etc/apache2/apache2.conf <<-EOF |
ServerName "$vm_fqdn"
EOF
sudo install -m 660 -o root -g root /dev/stdin \
/etc/apache2/apache2.conf
sudo install -m 660 -o root -g root \
"$tool"/etc/apache2/envvars \
/etc/apache2/envvars
sudo install -m 660 -o root -g root \
"$tool"/etc/apache2/httpd.conf \
/etc/apache2/httpd.conf
#sudo install -m 660 -o root -g root /dev/stdin \
# /etc/apache2/suexec/www-data <<-EOF
# /home
# pub/www/cgi
# EOF
sudo install -m 660 -o root -g root \
"$tool"/etc/apache2/ports.conf \
/etc/apache2/ports.conf
sudo a2enmod actions
sudo a2enmod headers
sudo a2enmod rewrite
sudo a2enmod ssl
sudo a2enmod userdir
local conf
sudo a2dissite "*"
sudo ln -fns \
/etc/apache2 \
/home/www/etc/apache2
for conf in "$tool"/etc/apache2/site.d/*/VirtualHost.conf
do conf=${conf#"$tool"/etc/apache2/site.d/}
local port site
IFS=. read -r port site <<-EOF
${conf%\/VirtualHost\.conf}
EOF
assert 'test "${site:+set}"'
assert 'test "${port:+set}"'
local site_user="$user.$port.$site"
local site_dir="$user.$port.$site"
case $port in
(443)
local hint="run vm_remote apache2_key_send before"
assert "sudo test -f /etc/apache2/site.d/\"$site_dir\"/x509/key.pem" hint
sudo install -d -m 770 -o "$user" -g "$user" \
/etc/apache2 \
/etc/apache2/site.d/"$site_dir" \
/etc/apache2/site.d/"$site_dir"/x509 \
/etc/apache2/site.d/"$site_dir"/x509/ca \
/etc/apache2/site.d/"$site_dir"/x509/empty \
/etc/apache2/site.d/"$site_dir"/x509/rvk \
/etc/apache2/site.d/"$site_dir"/x509/usr
sudo install -m 664 -o www -g www \
"$tool"/var/pub/x509/"$site"/crt.self-signed.pem \
/etc/apache2/site.d/"$site_dir"/x509/crt.self-signed.pem
#sudo install -m 664 -o "$user" -g "$user" \
# "$tool"/var/pub/x509/"$site"/rvk.pem \
# /etc/apache2/site.d/"$site_dir"/x509/rvk.pem
sudo install -m 664 -o www -g www \
"$tool"/var/pub/x509/"$site"/ca/crt.self-signed.pem \
/etc/apache2/site.d/"$site_dir"/x509/ca/crt.pem
sudo install -m 664 -o www -g www \
"$tool"/var/pub/x509/"$site"/crt.pem \
/etc/apache2/site.d/"$site_dir"/x509/crt.pem
;;
esac
case $port in
(80)
cat <<-EOF
AssignUserID $site_user $site_user
CustomLog "|/usr/sbin/rotatelogs /home/www/log/$site_dir/apache2/access/%Y-%m-%d.log 86400 60" Combined
#CustomLog "/dev/null" Combined
DocumentRoot /home/www/pub/$site_dir
ErrorLog "|/usr/sbin/rotatelogs /home/www/log/$site_dir/apache2/error/%Y-%m-%d.log 86400 60"
#ErrorLog "/dev/null"
ServerName $site
LogLevel Warn
$(cat "$tool"/etc/apache2/site.d/"$site_dir"/VirtualHost.conf)
EOF
;;
(443)
cat <<-EOF
AssignUserID $site_user $site_user
BrowserMatch "MSIE [2-6]" ssl-unclean-shutdown nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
CustomLog "|/usr/sbin/rotatelogs /home/www/log/$site_dir/apache2/access/%Y-%m-%d.log 86400 60" Combined
#CustomLog "/dev/null" Combined
DocumentRoot /home/www/pub/$site_dir
ErrorLog "|/usr/sbin/rotatelogs /home/www/log/$site_dir/apache2/error/%Y-%m-%d.log 86400 60"
#ErrorLog "/dev/null"
LogLevel Warn
ServerName $site
SSLCACertificateFile /etc/apache2/site.d/$site_dir/x509/crt.self-signed.pem
SSLCACertificatePath /etc/apache2/site.d/$site_dir/x509/usr/
#SSLCARevocationFile /etc/apache2/site.d/$site_dir/x509/rvk.pem
SSLCADNRequestFile /etc/apache2/site.d/$site_dir/x509/crt.self-signed.pem
SSLCADNRequestPath /etc/apache2/site.d/$site_dir/x509/empty/
# NOTE: ne publie pas les certificats d’utilisateur-ice-s acceptés
SSLCARevocationPath /etc/apache2/site.d/$site_dir/x509/rvk/
SSLCertificateChainFile /etc/apache2/site.d/$site_dir/x509/ca/crt.pem
SSLCertificateFile /etc/apache2/site.d/$site_dir/x509/crt.pem
SSLCertificateKeyFile /etc/apache2/site.d/$site_dir/x509/key.pem
SSLCipherSuite AES+RSA+SHA256
SSLEngine On
SSLInsecureRenegotiation Off
SSLOptions +StrictRequire +OptRenegotiate +StdEnvVars
SSLProtocol -All +TLSv1
#SSLRenegBufferSize 262144
SSLSessionCacheTimeout 1200
SSLStrictSNIVHostCheck On
SSLUserName SSL_CLIENT_S_DN_CN
SSLVerifyClient None
SSLVerifyDepth 1
$(cat "$tool"/etc/apache2/site.d/"$site_dir"/VirtualHost.conf)
EOF
;;
esac |
sudo install -m 660 -o root -g root /dev/stdin \
/etc/apache2/site.d/"$site_dir"/VirtualHost.conf
sudo ln -fns \
../site.d/"$site_dir"/VirtualHost.conf \
/etc/apache2/sites-available/"$site_dir"
sudo install -d -m 770 -o "$user" -g "$user" \
/home/www/log/"$site_dir" \
/home/www/log/"$site_dir"/apache2
sudo ln -fns \
/etc/apache2/site.d/"$site_dir" \
/home/www/etc/apache2/"$site_dir"
test -e /home/www/pub/"$site_dir" ||
sudo install -d -m 770 -o "$user" -g "$user" \
/home/www/pub/"$site_dir"
getent passwd "$site_user" >/dev/null ||
sudo adduser \
--disabled-password \
--group \
--no-create-home \
--home /home/www/pub/"$site_dir" \
--shell /bin/false \
--system \
"$site_user"
sudo setfacl -m u:"$site_user":--x \
/home/www/ \
/home/www/pub/ \
/home/www/pub/"$site_dir"/
sudo setfacl -m d:u:"$site_user":rwx \
"$home"/pub/www/"$site_dir"/
test ! -r "$tool"/etc/apache2/site.d/"$site_dir"/configure.sh ||
. "$tool"/etc/apache2/site.d/"$site_dir"/configure.sh
test -e /etc/apache2/sites-enabled/"$site_dir" ||
sudo a2ensite "$site_dir"
done
sudo service apache2 restart
}
rule_apt_configure () {
sudo install -m 660 -o root -g root /dev/stdin /etc/apt/sources.list <<-EOF
deb http://ftp.fr.debian.org/debian $vm_lsb_name main contrib non-free
EOF
sudo install -m 660 -o root -g root /dev/stdin /etc/apt/$vm_lsb_name-backports.list <<-EOF
#deb http://backports.debian.org/debian-backports $vm_lsb_name-backports main contrib non-free
EOF
sudo install -m 660 -o root -g root /dev/stdin /etc/apt/preferences <<-EOF
Package: *
Pin: release a=$vm_lsb_name
Pin-Priority: 170
Package: *
Pin: release a=$vm_lsb_name-backports
Pin-Priority: 200
EOF
sudo install -m 660 -o root -g root /dev/stdin /etc/apt/sources.list.d/openerp.list <<-EOF
deb http://nightly.openerp.com/trunk/nightly/deb/ ./
EOF
sudo apt-get update
rule apt_get_install apticron
sudo install -m 644 -o root -g root /dev/stdin /etc/apticron/apticron.conf <<-EOF
EMAIL="admin@$vm_domainname"
# DIFF_ONLY="1"
# LISTCHANGES_PROFILE="apticron"
# ALL_FQDNS="1"
# SYSTEM="foobar.example.com"
# IPADDRESSNUM="1"
# IPADDRESSES="192.0.2.1 2001:db8:1:2:3::1"
# NOTIFY_HOLDS="0"
# NOTIFY_NEW="0"
# NOTIFY_NO_UPDATES="0"
# CUSTOM_SUBJECT=""
# CUSTOM_NO_UPDATES_SUBJECT=""
# CUSTOM_FROM="root@$vm_fqdn"
EOF
}
rule_boot_configure () {
warn "lors de l'installation Debian, surtout n'installer GRUB sur AUCUN disque proposé !"
rule apt_get_install grub-pc
sudo install -d -m 644 -o root -g root /boot/grub
rule apt_get_install linux-image-$vm_arch
sudo install -m 644 -o root -g root /dev/stdin /etc/default/grub <<-EOF
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=\`lsb_release -i -s 2> /dev/null || echo Debian\`
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX="vt.default_utf8=1 rootfstype=ext4 loglevel=5 console=hvc0 ip=$vm_ipv4::$vm_ipv4:255.255.255.254:$vm:eth0:off resume=/dev/mapper/${vm}_swap_deciphered"
GRUB_DISABLE_RECOVERY="true"
#GRUB_PRELOAD_MODULES="lvm"
EOF
sudo install -m 644 -o root -g root /dev/stdin /boot/grub/device.map <<-EOF
(hd0) /dev/xvda
(hd0) /dev/mapper/domU-$(printf %s $vm_fqdn-disk | sed -e 's/-/--/g')
EOF
sudo update-grub2 # NOTE: prend en compte /boot/grub/device.map
rule initramfs_configure
rule apt_get_install molly-guard
sudo install -m 644 -o root -g root /dev/stdin /etc/molly-guard/rc <<-EOF
ALWAYS_QUERY_HOSTNAME=true
# NOTE: une alternative est de dire à sudo de conserver les SSH_*
# néamoins demander tout le temps n'est pas trop contraignant
# et davantage sécurisant.
EOF
}
rule_dovecot_configure () {
rule apt_get_install dovecot-imapd dovecot-managesieved dovecot-sieve
local hint="run vm_remote dovecot_key_send before"
assert "sudo test -f /etc/dovecot/\"$vm_domainname\"/imap/x509/key.pem" hint
sudo install -m 400 -o root -g root \
"$tool"/var/pub/x509/$vm_domainname/imap/crt+crl.self-signed.pem \
/etc/dovecot/$vm_domainname/imap/x509/crt+crl.self-signed.pem
sudo install -d -m 770 -o root -g adm \
/etc/skel/etc/mail \
/etc/skel/etc/sieve
sudo install -d -m 1777 -o root -g root \
/var/lib/dovecot-control \
/var/lib/dovecot-index
sudo install -m 664 -o root -g root /dev/stdin /etc/dovecot/local.conf <<-EOF
auth_ssl_username_from_cert = yes
listen = *
log_timestamp = "%Y-%m-%d %H:%M:%S "
mail_debug = yes
mail_location = maildir:~/var/mail:INDEX=/var/lib/dovecot-index/%u:CONTROL=/var/lib/dovecot-control/%u
# NOTE: INDEX et CONTROL sont sur une partition sans quota comme le demande la doc
# VOIR: http://wiki2.dovecot.org/Quota/FS
mail_plugins = \$mail_plugins quota
mail_privileged_group = mail
passdb {
args = /home/%u/etc/dovecot/passwd
driver = passwd-file
}
plugin {
quota = fs:user
recipient_delimiter = +
sieve = ~/etc/mail/filter.sieve
sieve_dir = ~/etc/mail/sieve
sieve_global_dir = /var/lib/dovecot/sieve/global/
sieve_max_script_size = 1M
sieve_quota_max_scripts = 0
sieve_quota_max_storage = 10M
sieve_user_log = ~/var/log/mail/sieve.log
}
protocol imap {
mail_plugins = \$mail_plugins imap_quota
}
protocol lda {
auth_socket_path = /var/run/dovecot/auth-master
hostname = $vm_domainname
info_log_path =
log_path =
mail_plugins = \$mail_plugins sieve
postmaster_address = contact+dovecot+lda@$vm_domainname
syslog_facility = mail
}
protocols = imap sieve
service auth {
user = root
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
ssl_ca =
LABEL=${vm_lvm_lv}_boot /boot ext2 defaults 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
/dev/mapper/${vm_lvm_lv}_root_deciphered / ext4 defaults,errors=remount-ro,acl,barrier=1,noatime 0 1
/dev/mapper/${vm_lvm_lv}_var_deciphered /var ext4 defaults,errors=remount-ro,acl,barrier=1,noatime 0 1
/dev/mapper/${vm_lvm_lv}_home_deciphered /home ext4 defaults,errors=remount-ro,acl,barrier=1,noatime,usrquota,grpquota 0 0
# NOTE: barrier=1 réduit drastiquement les performances d'écriture, mais garantit la cohérence du système de fichiers.
/dev/mapper/${vm_lvm_lv}_swap_deciphered swap swap sw 0 0
EOF
sudo install -m 644 -o root -g root /dev/stdin /etc/crypttab <<-EOF
#
${vm_lvm_lv}_root_deciphered /dev/$vm_lvm_vg/${vm_lvm_lv}_root none luks,lvm=$vm_lvm_vg
${vm_lvm_lv}_var_deciphered /dev/$vm_lvm_vg/${vm_lvm_lv}_var ${vm_lvm_lv}_root_deciphered luks,lvm=$vm_lvm_vg,keyscript=/lib/cryptsetup/scripts/decrypt_derived
${vm_lvm_lv}_home_deciphered /dev/$vm_lvm_vg/${vm_lvm_lv}_home ${vm_lvm_lv}_root_deciphered luks,lvm=$vm_lvm_vg,keyscript=/lib/cryptsetup/scripts/decrypt_derived
${vm_lvm_lv}_swap_deciphered /dev/$vm_lvm_vg/${vm_lvm_lv}_swap ${vm_lvm_lv}_root_deciphered luks,lvm=$vm_lvm_vg,keyscript=/lib/cryptsetup/scripts/decrypt_derived
EOF
sudo install -m 644 -o root -g root /dev/stdin /etc/default/tmpfs <<-EOF
LOCK_SIZE=5242880 # NOTE: 5MiB
RAMLOCK=yes
RAMSHM=yes
RAMTMP=yes
RUN_SIZE=10%
SHM_SIZE=
TMP_MODE=1777,nr_inodes=1000k,noatime
TMP_OVERFLOW_LIMIT=1024
# NOTE: mount tmpfs on /tmp if there is less than the limit size (in kiB)
# on the root filesystem (overriding RAMTMP).
TMP_SIZE=200m
TMPFS_SIZE=20%VM
EOF
sudo install -m 775 -o root -g root \
"$tool"/etc/init.d/tmpfs \
/etc/init.d/tmpfs
sudo update-rc.d tmpfs defaults
}
rule_initramfs_configure () {
sudo install -m 644 -o root -g root /dev/stdin /etc/initramfs-tools/initramfs.conf <<-EOF
MODULES=most
BUSYBOX=y
KEYMAP=y
COMPRESS=gzip
DEVICE=eth0
EOF
sudo install -m 644 -o root -g root /dev/stdin /etc/modprobe.d/xen-pv.conf <<-EOF
alias eth0 xennet
alias scsi_hostadapter xenblk
EOF
sudo install -m 644 -o root -g root /dev/stdin /etc/modules <<-EOF
sha1_generic
sha256_generic
sha512_generic
aes-x86_64
xts
# NOTE: pour Xen en mode HVM :
#modprobe xen-platform-pci
EOF
sudo install -m 644 -o root -g root /dev/stdin /etc/initramfs-tools/modules <<-EOF
EOF
sudo sed -e '/^configure_networking /s/ &$//' \
-i /usr/share/initramfs-tools/scripts/init-premount/dropbear
# NOTE: corrige une vermine : dropbear doit attendre que le réseau soit configuré..
ssh-keygen -F "init.$vm_fqdn" -f "$tool"/etc/openssh/known_hosts |
( while IFS= read -r line
do case $line in (*" RSA") return 0; break;; esac
done; return 1 ) ||
{
sudo rm -f \
/etc/initramfs-tools/etc/dropbear/dropbear_rsa_host_key \
/etc/initramfs-tools/etc/dropbear/dropbear_rsa_host_key.pub
sudo dropbearkey -t rsa -s 4096 -f \
/etc/initramfs-tools/etc/dropbear/dropbear_rsa_host_key
}
# NOTE: ne se préoccupe pas de dropbear_dss_host_key ; Debian la génère et l'utilise néamoins.
sudo install -d -m 640 -o root -g root \
/etc/initramfs-tools/root \
/etc/initramfs-tools/root/.ssh
getent group sudo |
while IFS=: read -r group x x users
do while test -n "$users" && IFS=, read -r user users <<-EOF
$users
EOF
do eval local home\; home="~$user"
cat "$home"/etc/ssh/authorized_keys
done
done |
sudo install -m 644 -o root -g root /dev/stdin /etc/initramfs-tools/root/.ssh/authorized_keys
sudo rm -f \
/etc/initramfs-tools/root/.ssh/id_rsa.dropbear \
/etc/initramfs-tools/root/.ssh/id_rsa.pub \
/etc/initramfs-tools/root/.ssh/id_rsa
# NOTE: clefs générées par Debian
sudo update-initramfs -u
}
rule_time_configure () {
sudo install -m 644 -o root -g root /dev/stdin /etc/timezone <<-EOF
Europe/Paris
EOF
sudo dpkg-reconfigure tzdata
rule apt_get_install ntp
}
rule_locale_configure () {
sudo install -m 644 -o root -g root /dev/stdin /etc/locale.gen <<-EOF
fr_FR.UTF-8 UTF-8
EOF
sudo update-locale
}
rule_login_configure () {
sudo install -m 644 -o root -g root /dev/stdin /etc/inittab <<-EOF
# /etc/inittab: init(8) configuration.
# The default runlevel.
id:2:initdefault:
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# What to do in single-user mode.
~~:S:wait:/sbin/sulogin
# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop
# Xen hypervisor console
hvc:2345:respawn:/sbin/getty 38400 hvc0
#xvc:2345:respawn:/sbin/getty 38400 xvc0
EOF
sudo install -m 644 -o root -g root /dev/stdin /etc/login.defs <<-EOF
MAIL_DIR /var/mail
FAILLOG_ENAB yes
LOG_UNKFAIL_ENAB no
LOG_OK_LOGINS no
SYSLOG_SU_ENAB yes
SYSLOG_SG_ENAB yes
FTMP_FILE /var/log/btmp
SU_NAME su
HUSHLOGIN_FILE .hushlogin
ENV_SUPATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV_PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# NOTE: met les sbin/ dans ENV_PATH ;
# - ça n'apporte aucune protection de ne pas les mettre ;
# - ça frustre de ne pas les trouver.
TTYGROUP tty
TTYPERM 0600
ERASECHAR 0177
KILLCHAR 025
UMASK 007
# NOTE: rwxrwx--- ;
# - donne une même confiance au groupe propriétaire qu'au propriétaire ;
# - facilite l'utilisation des ACL, qui sont dépendantes des droits du groupe propriétaire.
PASS_MAX_DAYS 99999
PASS_MIN_DAYS 0
PASS_WARN_AGE 7
UID_MIN 1000
UID_MAX 60000
GID_MIN 1000
GID_MAX 60000
LOGIN_RETRIES 3
LOGIN_TIMEOUT 60
CHFN_RESTRICT rwh
DEFAULT_HOME yes
USERGROUPS_ENAB yes
ENCRYPT_METHOD SHA512
EOF
grep -q '^session optional pam_umask.so\>' /etc/pam.d/common-session ||
sudo install -m 644 -o root -g root /dev/stdin /etc/pam.d/common-session <<-EOF
$(cat /etc/pam.d/common-session)
session optional pam_umask.so
EOF
grep -q '^hvc0$' /etc/securetty ||
sudo install -m 644 -o root -g root /dev/stdin /etc/securetty <<-EOF
$(cat /etc/securetty)
hvc0
EOF
grep -q '^xvc0$' /etc/securetty ||
sudo install -m 644 -o root -g root /dev/stdin /etc/securetty <<-EOF
$(cat /etc/securetty)
xvc0
EOF
}
rule_mail_configure () {
rule postfix_configure
rule postgrey_configure
rule procmail_configure
rule dovecot_configure
}
rule_network_configure () {
sudo install -m 644 -o root -g root /dev/stdin /etc/hostname <<-EOF
$vm
EOF
grep -q " $vm\$" /etc/hosts ||
sudo install -m 644 -o root -g root /dev/stdin /etc/hosts <<-EOF
$(cat /etc/hosts)
127.0.0.1 $vm_fqdn $vm
EOF
sudo install -m 644 -o root -g root /dev/stdin /etc/network/interfaces <<-EOF
auto lo
iface lo inet loopback
auto eth0=grenode
iface grenode inet static
address $vm_ipv4
gateway $vm_ipv4 # NOTE: proxy_arp sur la passerelle permet d'utiliser la même adresse
network $vm_ipv4
broadcast $vm_ipv4
netmask 255.255.255.255
mtu 1300
# NOTE: il y a besoin de ça en l'état actuel du réseau de Grenode
# car la MTU des tunnels GRE/IPsec entre les routeurs de Grenode l'impose.
#
# root@ateliers:~# ping -M do -c 1 -s \$((1500-20-8-200)) soupirail.grenode.net
# PING soupirail.grenode.net (91.216.110.1) 1272(1300) bytes of data.
# 1280 bytes from soupirail.grenode.net (91.216.110.1): icmp_req=1 ttl=63 time=18.0 ms
#
# --- soupirail.grenode.net ping statistics ---
# 1 packets transmitted, 1 received, 0% packet loss, time 0ms
# rtt min/avg/max/mdev = 18.027/18.027/18.027/0.000 ms
# root@ateliers:~# ping -M do -c 1 -s \$((1500-20-8-200+1)) soupirail.grenode.net
# PING soupirail.grenode.net (91.216.110.1) 1273(1301) bytes of data.
# From estran.grenode.net (91.216.110.6) icmp_seq=1 Frag needed and DF set (mtu = 1300)
#
# --- soupirail.grenode.net ping statistics ---
# 0 packets transmitted, 0 received, +1 errors
post-up ip address add $vm_ipv4/32 dev \$IFACE
pre-down ip address delete $vm_ipv4/32 dev \$IFACE
EOF
}
rule_www_configure () {
getent passwd www >/dev/null ||
sudo adduser \
--disabled-login \
--disabled-password \
--group \
--home /home/www \
--shell /bin/false \
--system \
www
sudo adduser \
--disabled-login \
--disabled-password \
--group \
--home ~www/log \
--shell /bin/false \
--system \
log.www
#sudo adduser www www-data
sudo adduser www log.www
#sudo adduser log log.www
usermod --home /home/www/pub www-data
sudo install -d -m 751 -o www -g www \
/home/www
sudo install -d -m 750 -o www -g www \
/home/www/etc
sudo install -d -m 1771 -o www-data -g www-data \
/home/www/pub \
sudo install -d -m 1771 -o log.www -g log.www \
/home/www/log
}
rule_nginx_configure () {
local -; set +f
rule apt_get_install nginx
rule www_configure
sudo rm -rf \
/etc/nginx/conf.d \
/etc/nginx/site.d
sudo install -d -m 770 -o www -g www \
/etc/nginx \
/etc/nginx/conf.d \
/etc/nginx/site.d
sudo ln -fns \
/etc/nginx \
/home/www/etc/nginx
sudo install -m 660 -o www -g www \
"$tool"/etc/nginx/nginx.conf \
/etc/nginx/nginx.conf
local conf
for conf in "$tool"/etc/nginx/conf.d/*.conf
do conf=${conf#"$tool"/etc/nginx/conf.d/}
sudo install -m 660 -o www -g www \
"$tool"/etc/nginx/conf.d/"$conf" \
/etc/nginx/conf.d/"$conf"
done
for conf in "$tool"/etc/nginx/site.d/*/server.conf
do conf=${conf#"$tool"/etc/nginx/site.d/}
local port site
IFS=. read -r port site <<-EOF
${conf%\/server\.conf}
EOF
assert 'test "${port:+set}"'
assert 'test "${site:+set}"'
site="$port.$site"
getent passwd www."$site" >/dev/null ||
sudo adduser \
--disabled-login \
--disabled-password \
--group \
--home ~www-data/"$site" \
--shell /bin/false \
--system \
www."$site"
getent passwd log."$site" >/dev/null ||
sudo adduser \
--disabled-login \
--disabled-password \
--group \
--shell /bin/false \
--system \
log."$site"
sudo usermod --home ~www/log/"$site"/nginx log."$site"
sudo install -d -m 770 -o www -g www \
/etc/nginx/site.d/"$site"
case $port in
(443)
local hint="run vm_remote nginx_key_send before"
assert "sudo test -f /etc/nginx/\"$site\"/x509/key.pem" hint
sudo install -m 664 -o www -g www \
"$tool"/var/pub/x509/"$site"/crt+ca.pem \
/etc/nginx/site.d/"$site"/x509/crt.pem
;;
esac
case $port in
(80)
cat <<-EOF
server {
listen $port;
access_log /home/www/log/$site/nginx/access.log main;
error_log /home/www/log/$site/nginx/error.log warn;
root /home/www/pub/$site;
server_name $site;
$(cat "$tool"/etc/nginx/site.d/"$site"/server.conf)
}
EOF
;;
(443)
cat <<-EOF
server {
listen $port;
access_log /home/www/log/$site/nginx/access.log main;
error_log /home/www/log/$site/nginx/error.log warn;
keepalive_timeout 70;
root /home/www/pub/$site;
server_name $site;
# DOC: http://wiki.nginx.org/HttpSslModule
ssl on;
ssl_certificate /home/www/etc/nginx/site.d/$site/x509/crt.pem;
ssl_certificate_key /home/www/etc/nginx/site.d/$site/x509/key.pem;
ssl_ciphers HIGH:!ADH:!MD5;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
$(cat "$tool"/etc/nginx/site.d/"$site"/server.conf)
}
EOF
;;
esac |
sudo install -m 660 -o www -g www /dev/stdin \
/etc/nginx/site.d/"$site"/server.conf
adduser www-data "$site"
test -e /home/www/pub/"$site" ||
sudo install -d -m 3770 -o "$site" -g "$site" \
/home/www/pub/"$site"
sudo install -d -m 3770 -o log."$site" -g log."$site" \
/home/www/log/"$site"/nginx
test ! -r "$tool"/etc/nginx/site.d/"$site"/configure.sh ||
. "$tool"/etc/nginx/site.d/"$site"/configure.sh
done
rule apt_get_install spawn-fcgi fcgiwrap
sudo insserv --remove fcgiwrap
rule tmpfs_configure
sudo service nginx restart
}
rule_php5_fpm_configure () {
local -; set +f
rule apt_get_install \
php5-fpm \
php-apc
getent passwd php5 >/dev/null ||
sudo adduser \
--disabled-login \
--disabled-password \
--group \
--shell /bin/false \
--system \
php5
local conf
sudo ln -fns \
/etc/php5-fpm \
/home/www/etc/php5
sudo rm -f /etc/php5/fpm/pool.d/*
for conf in "$tool"/etc/php5/fpm/pool.d/*.conf
do conf=${conf#"$tool"/etc/php5/fpm/pool.d/}
local port site
IFS=. read -r port site <<-EOF
${conf%\.conf}
EOF
assert 'test "${port:+set}"'
assert 'test "${site:+set}"'
site="$port.$site"
getent passwd php5"$site" >/dev/null ||
sudo adduser \
--disabled-login \
--disabled-password \
--group \
--no-create-home \
--home ~www/pub/"$site" \
--shell /bin/false \
--system \
php5."$site"
sudo install -d -m 770 -o php5 -g php5 \
/home/www/log/php5 \
/home/www/log/php5/fpm
sudo install -d -m 770 -o log."$site" -g log."$site" \
/home/www/log/"$site"
sudo adduser php5."$user" www."$site"
sudo install -m 660 -o root -g root /dev/stdin \
/etc/php5/fpm/pool.d/"$conf" <<-EOF
[php5.$site]
access.log = /home/www/log/$site/php5/fpm/access.log
catch_workers_output = yes
chdir = /
env[HOSTNAME] = \$HOSTNAME
env[TEMP] = /tmp
env[TMPDIR] = /tmp
env[TMP] = /tmp
group = www-data
listen = /run/nginx/fastcgi/php5.$site
#listen = 127.0.0.1:9000
#listen.allowed_clients = 127.0.0.1
listen.backlog = -1
pm = dynamic
pm.max_children = 5
pm.max_requests = 200
pm.max_spare_servers = 4
pm.min_spare_servers = 2
pm.start_servers = 3
pm.status_path = /status
request_slowlog_timeout = 5s
request_terminate_timeout = 120s
rlimit_core = unlimited
rlimit_files = 131072
slowlog = /home/www/log/$site/php5/fpm/slow.log
user = $php5_user
$(cat "$tool"/etc/php5/fpm/pool.d/"$conf")
EOF
sudo install -m 664 -o root -g root \
"$tool"/etc/php5/fpm/php.ini \
/etc/php5/fpm/php.ini
done
rule tmpfs_configure
sudo service php5-fpm restart
}
rule_postfix_configure () {
local hint="run vm_remote postfix_key_send before"
assert "test -f /etc/postfix/$vm_domainname/smtpd/x509/key.pem" hint
warn "lors de l'installation Debian, ne sélectionner aucune configuration pour postfix"
rule apt_get_install postfix
sudo install -m 640 -o root -g root /dev/stdin /etc/postfix/.gitignore <<-EOF
*.db
EOF
sudo install -d -m 770 -o root -g root \
/etc/postfix/$vm_domainname/ \
/etc/postfix/$vm_domainname/smtp \
/etc/postfix/$vm_domainname/smtp/x509 \
/etc/postfix/$vm_domainname/smtp/x509/ca \
/etc/postfix/$vm_domainname/smtpd \
/etc/postfix/$vm_domainname/smtpd/x509 \
/etc/postfix/$vm_domainname/smtpd/x509/ca
sudo install -d -m 770 -o root -g root \
/etc/postfix/$vm_domainname/ \
/etc/postfix/$vm_domainname/smtp \
/etc/postfix/$vm_domainname/smtp/x509 \
/etc/postfix/$vm_domainname/smtp/x509/ca \
/etc/postfix/$vm_domainname/smtpd \
/etc/postfix/$vm_domainname/smtpd/x509 \
/etc/postfix/$vm_domainname/smtpd/x509/ca
sudo ln -fns \
../crt+crl.self-signed.pem \
/etc/postfix/$vm_domainname/smtpd/x509/ca/crt.pem
sudo install -m 400 -o root -g root \
"$tool"/var/pub/x509/$vm_domainname/smtpd/crt+crl.self-signed.pem \
/etc/postfix/$vm_domainname/smtpd/x509/crt+crl.self-signed.pem
sudo install -m 400 -o root -g root \
"$tool"/var/pub/x509/$vm_domainname/smtpd/crt.pem \
/etc/postfix/$vm_domainname/smtpd/x509/crt.pem
sudo install -m 400 -o root -g root \
"$tool"/var/pub/x509/$vm_domainname/smtpd/crt+ca.pem \
/etc/postfix/$vm_domainname/smtpd/x509/crt+ca.pem
sudo install -m 400 -o root -g root \
"$tool"/var/pub/x509/$vm_domainname/smtpd/crt+crl.self-signed.pem \
/etc/postfix/$vm_domainname/smtpd/x509/crt+crl.self-signed.pem
sudo install -m 660 -o root -g root \
"$tool"/etc/postfix/$vm_domainname/header_checks \
/etc/postfix/$vm_domainname/header_checks
sudo install -m 664 -o root -g root /dev/stdin \
/etc/postfix/aliases <<-EOF
# See man 5 aliases for format
abuse: root
admin: root
contact: root
postmaster: root
root: $(getent group sudo | cut -f 4 -d : | tr , ' ')
EOF
sudo newaliases -oA/etc/postfix/aliases
cat /dev/stdin "$tool"/etc/postfix/main.cf <<-EOF |
mydomain = $vm_domainname
myorigin = \$mydomain
myhostname = $vm_hostname.\$mydomain
mail_name = \$myhostname
mydestination = $vm_hostname \$myhostname \$myorigin
EOF
sudo install -m 664 -o root -g root /dev/stdin \
/etc/postfix/main.cf
sudo install -m 664 -o root -g root \
"$tool"/etc/postfix/master.cf \
/etc/postfix/master.cf
sudo install -m 660 -o root -g root \
"$tool"/etc/postfix/$vm_domainname/smtp/x509/policy \
/etc/postfix/$vm_domainname/smtp/x509/policy
sudo postmap hash:/etc/postfix/$vm_domainname/smtp/x509/policy
sudo install -m 660 -o root -g root \
"$tool"/etc/postfix/$vm_domainname/smtp/header_checks \
/etc/postfix/$vm_domainname/smtp/header_checks
sudo install -m 660 -o root -g root \
"$tool"/etc/postfix/$vm_domainname/smtpd/sender_access \
/etc/postfix/$vm_domainname/smtpd/sender_access
sudo postmap hash:/etc/postfix/$vm_domainname/smtpd/sender_access
sudo install -m 660 -o root -g root \
"$tool"/etc/postfix/$vm_domainname/smtpd/client_blacklist \
/etc/postfix/$vm_domainname/smtpd/client_blacklist
sudo postmap hash:/etc/postfix/$vm_domainname/smtpd/client_blacklist
sudo install -m 660 -o root -g root \
"$tool"/etc/postfix/$vm_domainname/smtpd/relay_clientcerts \
/etc/postfix/$vm_domainname/smtpd/relay_clientcerts
sudo postmap hash:/etc/postfix/$vm_domainname/smtpd/relay_clientcerts
sudo install -m 660 -o root -g root \
"$tool"/etc/postfix/$vm_domainname/transport \
/etc/postfix/$vm_domainname/transport
sudo postmap hash:/etc/postfix/$vm_domainname/transport
sudo install -m 660 -o root -g root \
"$tool"/etc/postfix/$vm_domainname/virtual_alias \
/etc/postfix/$vm_domainname/virtual_alias
sudo postmap hash:/etc/postfix/$vm_domainname/virtual_alias
sudo service postfix restart
}
rule_postgrey_configure () {
rule apt_get_install postgrey
sudo service postgrey restart
}
rule_procmail_configure () {
rule apt_get_install procmail
sudo install -d -m 770 -o root -g adm \
/etc/skel/etc/mail \
/etc/skel/var/cache/mail \
/etc/skel/var/log/mail \
/etc/skel/var/mail
sudo install -m 660 -o root -g adm \
"$tool"/etc/skel/etc/mail/delivery.procmailrc \
/etc/skel/etc/mail/delivery.procmailrc
}
rule_ssh_configure () {
ssh-keygen -F "$vm_fqdn" -f "$tool"/etc/openssh/known_hosts |
( while IFS= read -r line
do case $line in (*" RSA") return 0; break;; esac
done; return 1 ) ||
sudo ssh-keygen -t rsa -b 4096 -N '' -f /etc/ssh/ssh_host_rsa_key
sudo rm -f \
/etc/ssh/ssh_host_dsa_key \
/etc/ssh/ssh_host_dsa_key.pub \
/etc/ssh/ssh_host_ecdsa_key \
/etc/ssh/ssh_host_ecdsa_key.pub
# NOTE: clefs générées par Debian
sudo install -m 644 -o root -g root /dev/stdin /etc/ssh/sshd_config <<-EOF
Port 22
ListenAddress $vm_ipv4
#ListenAddress ::
Protocol 2
Compression yes
HostKey /etc/ssh/ssh_host_rsa_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 768
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/etc/ssh/authorized_keys
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
IgnoreUserKnownHosts no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
PasswordAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
X11Forwarding no
X11DisplayOffset 10
PrintMotd no
DebianBanner no
PrintLastLog yes
TCPKeepAlive yes
ClientAliveInterval 0
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
UsePAM yes
EOF
sudo service ssh restart
}
rule_sysctl_configure () {
local -; set +f
for conf in "$tool"/etc/sysctl.d/*.conf
do conf=${conf#"$tool"/etc/sysctl.d/}
sudo install -m 660 -o root -g root \
"$tool"/etc/sysctl.d/"$conf" \
/etc/sysctl.d/"$conf"
done
sudo sysctl --system
}
rule_user_add () { # SYNTAX: $user
rule user_configure
local user=$1
id "$user" >/dev/null ||
sudo adduser --disabled-password "$user"
# NOTE: le mot-de-passe doit être initialisé par l'utilisateur à l'aide de passwd-init .
eval local home\; home="~$user"
sudo adduser "$user" users
sudo install -m 640 -o root -g root \
"$tool"/var/pub/ssh/"$user".key \
"$home"/etc/ssh/authorized_keys
local key; local -; set +f
for key in "$tool"/var/pub/openpgp/*.key
do sudo -u "$user" gpg --import - <"$key"
done
}
rule_user_configure () {
true
}
rule_user_admin_add () { # SYNTAX: $user
rule user_configure
local user=$1
id "$user" >/dev/null ||
sudo adduser --disabled-password "$user"
eval local home\; home="~$user"
sudo adduser "$user" sudo
sudo adduser "$user" users
sudo install -m 640 -o root -g root \
"$tool"/var/pub/ssh/"$user".key \
"$home"/etc/ssh/authorized_keys
local key; local -; set +f
for key in "$tool"/var/pub/openpgp/*.key
do sudo -u "$user" gpg --import - <"$key"
done
rule user_admin_configure
}
rule_user_admin_configure () {
rule initramfs_configure
rule user_root_configure
}
rule_user_configure () {
sudo install -d -m 750 -o root -g adm \
/etc/skel/etc \
/etc/skel/etc/gpg \
/etc/skel/etc/ssh
sudo install -d -m 770 -o root -g adm \
/etc/skel/var \
/etc/skel/var/cache \
/etc/skel/var/log \
/etc/skel/var/run \
/etc/skel/var/run/ssh
sudo ln -fns etc/ssh /etc/skel/.ssh
sudo ln -fns etc/gpg /etc/skel/.gnupg
sudo install -m 640 -o root -g root /dev/stdin /etc/sudoers.d/passwd-init <<-EOF
%sudo ALL=(ALL) NOPASSWD: /bin/sh -e -f -u -c \\
case \$(/usr/bin/passwd --status "\$SUDO_USER") in \\
("\$SUDO_USER L "*) /usr/bin/passwd \$SUDO_USER;; esac
EOF
sudo install -m 640 -o root -g root /dev/stdin /etc/sudoers.d/etckeeper-unclean <<-EOF
%sudo ALL=(ALL) NOPASSWD: /usr/sbin/etckeeper unclean
EOF
sudo install -m 640 -o root -g root /dev/stdin /etc/sudoers.d/env_keep <<-EOF
Defaults env_keep = " \\
EDITOR \\
GIT_AUTHOR_NAME \\
GIT_AUTHOR_EMAIL \\
GIT_COMMITTER_NAME \\
GIT_COMMITTER_EMAIL \\
"
EOF
sudo install -m 755 -o root -g root /dev/stdin /usr/local/bin/passwd-init <<-EOF
#!/bin/sh -efu
# DESCRIPTION: permet à un-e utilisateurice d'initialiser ellui-même son mot-de-passe système.
sudo /bin/sh -e -f -u -c \
'case \$(/usr/bin/passwd --status "\$SUDO_USER") in ("\$SUDO_USER L "*) /usr/bin/passwd \$SUDO_USER;; esac'
EOF
sudo install -m 644 -o root -g root \
"$tool"/etc/bash.bashrc \
/etc/bash.bashrc
sudo install -m 644 -o root -g root \
"$tool"/etc/screenrc \
/etc/screenrc
}
rule_user_root_configure () {
sudo install -d -m 750 -o root -g adm \
/root/etc \
/root/etc/gpg \
/root/etc/ssh
sudo ln -fns etc/gpg /root/.gnupg
sudo ln -fns etc/ssh /root/.ssh
getent group sudo |
while IFS=: read -r group x x users
do while test -n "$users" && IFS=, read -r user users <<-EOF
$users
EOF
do eval local home\; home="~$user"
cat "$home"/etc/ssh/authorized_keys
done
done |
sudo install -m 640 -o root -g root /dev/stdin /root/etc/ssh/authorized_keys
local key; local -; set +f
for key in "$tool"/var/pub/openpgp/*.key
do sudo gpg --import "$key"
done
}
rule_configure () {
rule apt_configure
rule git_configure
rule etckeeper_configure
rule locale_configure
rule time_configure
rule network_configure
rule filesystem_configure
rule login_configure
rule ssh_configure
rule user_root_configure
rule boot_configure
rule sysctl_configure
rule user_configure
rule mail_configure
#rule apache2_configure
rule nginx_configure
rule php5_fpm_configure
}
rule_luks_key_change () {
sudo cryptsetup luksChangeKey /dev/$vm_lvm_vg/${vm_lvm_lv}_root
}
rule=${1:-help}
${1+shift}
case $rule in
(help);;
(*)
assert 'test "$(hostname --fqdn)" = "$vm_fqdn"' vm_fqdn
;;
esac
rule $rule "$@"