define etc_file($owner = 'root', $group = 'root', $mode = 644, $source_suffix = '', $notify = [], $template = false) {
if $template {
file { "/etc/$name":
ensure => file, owner => $owner, group => $group, mode => $mode,
content => template($name),
notify => $notify
}
} else {
file { "/etc/$name":
ensure => file, owner => $owner, group => $group, mode => $mode,
source => "puppet:///files/etc/$name$source_suffix",
notify => $notify
}
}
}
define ssl_certificat() {
file { "/etc/ssl/private/$name.pem":
ensure => file, owner => root, group => root, mode => 640,
source => "puppet:///private/ssl/$name.pem",
require => File["/etc/ssl/private"]
}
# TODO could be created by a package
file { ["/etc/ssl","/etc/ssl/private"]:
ensure => directory
}
}
define bin_script() {
file { "/usr/local/bin/$name":
mode => 755,
source => "puppet:///files/bin/$name"
}
}
define sbin_script() {
file { "/usr/local/sbin/$name":
mode => 755,
source => "puppet:///files/bin/$name"
}
}
class users {
# TODO ca semble très lent, on pourrait passer par un tar
file { "/etc/skel":
recurse => true,
source => "puppet:///files/home/skeleton/"
}
define admin($comment = '') {
user { $name:
ensure => present,
comment => $comment ? { '' => $name, default => $comment },
shell => "/bin/zsh",
require => Package[zsh],
groups => "adm"
}
file { "/home/$name":
ensure => directory,
owner => $name,
group => $name
}
exec { "$name homedir":
command => "find /etc/skel -mindepth 1 -maxdepth 1 | xargs cp -Rt /home/$name; /bin/chown -R $name:$name /home/$name",
# '/home/$name' can already exist, test one of the installed files
creates => "/home/$name/.zshrc",
require => [User[$name], File["/home/$name"], File["/etc/skel"]]
}
file { "/home/$name/.ssh":
ensure => directory,
owner => $name,
group => $name,
require => Exec["$name homedir"],
mode => 700
}
file { "/home/$name/.ssh/authorized_keys2":
source => "puppet:///files/home/$name/id_rsa.pub",
owner => $name,
group => $name,
mode => 400,
}
}
users::admin { [ alban ]: }
sbin_script { mypasswd: }
sudo::user_line { mypasswd:
line => "%adm ALL=NOPASSWD: /usr/local/sbin/mypasswd",
require => File["/usr/local/sbin/mypasswd"]
}
sbin_script { add-admins-group: }
package { ["zsh","less"]: ensure => installed }
mailalias { "root":
ensure => present,
recipient => 'root@tryphon.org'
}
# TODO change root password
}
class sudo {
package { sudo: ensure => installed }
define user_line($line) {
line { "sudo-$name":
file => "/etc/sudoers",
line => $line
}
}
user_line { root: line => "root ALL=(ALL) ALL" }
user_line { adm: line => "%adm ALL=(ALL) ALL" }
}
class apt {
etc_file { "apt/sources.list": }
exec { "apt-get update":
alias => apt-update,
refreshonly => true,
subscribe => File["/etc/apt/sources.list"]
}
file { "/etc/apt/tryphon-debian-packagers-public.asc":
source => "puppet:///files/etc/debarchiver/tryphon-debian-packagers-public.asc",
}
# TODO utiliser une URL et factoriser
exec { "apt-key-add-tryphon-debian-packagers":
command => "apt-key add /etc/apt/tryphon-debian-packagers-public.asc",
unless => "apt-key list | grep C6ADBBD5",
require => File["/etc/apt/tryphon-debian-packagers-public.asc"],
before => File["/etc/apt/sources.list"]
}
}
# required by puppet module
class bc {
package { bc: ensure => installed }
}
class mysql-server {
package { "mysql-server-5.0":
ensure => installed,
alias => mysql-server
}
# TODO support a root password .. not empty
# TODO support user privileges change
define user($password, $database, $privileges) {
exec { "mysql -e \"grant $privileges on $database.* to '$name'@'localhost' identified by '$password';\" mysql && mysqladmin flush-privileges":
unless => "mysql -Bs -e \"select User from user where User = '$name' and Password = password('$password');\" mysql | grep $name",
require => Package[mysql-server]
}
}
munin::anode::plugin {
[mysql_bytes,mysql_queries,mysql_slowqueries,mysql_threads]:
}
}
class mysql-client {
package { "mysql-client-5.0":
ensure => installed,
alias => mysql-client
}
}
class postfixadmin {
include mysql-client
include mysql-server
package { postfixadmin:
ensure => installed
}
etc_file { "postfixadmin/config.inc.php":
require => Package[postfixadmin]
}
package { php5-cli:
ensure => installed
}
exec { "postfixadmin-setup":
command => "cd /usr/share/postfixadmin/www ; php upgrade.php | tee /tmp/postfixadmin-setup.html | egrep -q '(done|up to date)$' && rm setup.php",
onlyif => "test -f /usr/share/postfixadmin/www/setup.php",
# mysql-client is required by helpers (which require this setup)
require => [File["/etc/postfixadmin/config.inc.php"], Package[mysql-client], Package[php5-cli]]
}
define admin($password) {
exec { "postfixadmin-create-admin-$name":
command => "mysql -u root -e \"insert ignore into admin (username, password) values ('$name', '$password')\" postfixadmin",
require => Exec["postfixadmin-setup"]
}
}
define super_admin($password) {
admin { "$name": password => $password }
exec { "postfixadmin-domain-all-for-$name":
command => "mysql -u root -e \"insert into domain_admins (username, domain) values ('$name', 'ALL');\" postfixadmin",
unless => "mysql -Bs -u root -e \"select username from domain_admins where username = '$name' and domain = 'ALL';\" postfixadmin | grep $name",
require => Exec["postfixadmin-setup"]
}
}
postfixadmin::super_admin { "admin":
password => $postfixadmin_superadmin_password # secret
}
define domain() {
exec { "postfixadmin-create-domain-$name":
command => "mysql -u root -e \"insert ignore into domain (domain) values ('$name')\" postfixadmin",
require => Exec["postfixadmin-setup"]
}
}
postfixadmin::domain { "ALL": }
postfixadmin::domain { "tryphon.test": }
define mailbox($username, $password, $domain) {
$email = "$username@$domain"
exec { "postfixadmin-create-mailbox-$name":
command => "mysql -u root -e \"delete from mailbox where username = '$username@$domain' ; insert into mailbox (username, password, domain, maildir) values ('$username@$domain','$password','$domain','$domain/$username/')\" postfixadmin",
unless => "mysql -Bs -u root -e \"select username from mailbox where username = '$username@$domain' and password = '$password'\" postfixadmin | grep $username@$domain",
require => Exec[postfixadmin-setup]
}
postfixadmin::alias { "$name": goto => "$username@$domain", domain => $domain }
}
define alias($goto, $domain) {
exec { "postfixadmin-create-alias-$name":
command => "mysql -u root -e \"insert ignore into alias (address, goto, domain) values ('$name','$goto','$domain')\" postfixadmin",
require => Exec["postfixadmin-setup"]
}
}
postfixadmin::mailbox { "test@tryphon.test":
username => "test",
password => $mail_tester_password, # secret
domain => "tryphon.test"
}
}
class postfixadmin-fetchmail {
include fetchmail
bin_script { fetchmail-all:
require => [File["/etc/postfixadmin/fetchmail.conf"], Package[liblockfile-simple-perl]]
}
file { "/var/run/fetchmail":
ensure => directory,
owner => fetchmail,
require => Package[fetchmail]
}
package { liblockfile-simple-perl:
ensure => present
}
etc_file { "postfixadmin/fetchmail.conf":
owner => fetchmail,
mode => 640,
template => true,
require => [Package[fetchmail], Package[postfixadmin]]
}
mysql-server::user { fetchmail:
password => $fetchmail_mysql_password, # secret
database => "postfixadmin",
privileges => "SELECT,UPDATE",
require => Package[mysql-server]
}
file { "/etc/cron.d/fetchmail-all":
# newline is important
content => "*/5 * * * * fetchmail /usr/local/bin/fetchmail-all
",
require => Bin_script[fetchmail-all]
}
}
class postfixadmin-vacation {
user { vacation:
ensure => present,
shell => "/bin/false",
}
bin_script { vacation:
require => [
Package[libmail-sendmail-perl], Package[libdbd-pg-perl], Package[libemail-valid-perl],
Package[libmime-perl], Package[libmime-charset-perl], Package[libmime-encwords-perl]]
}
etc_file { "postfixadmin/vacation.conf":
template => true,
mode => 640,
owner => vacation,
require => [User[vacation], Package[postfixadmin]]
}
package {
[libmail-sendmail-perl,
libdbd-pg-perl,
libemail-valid-perl,
libmime-perl,
libmime-charset-perl,
libmime-encwords-perl]:
ensure => present
}
mysql-server::user { vacation:
password => $vacation_mysql_password, # secret
database => "postfixadmin",
privileges => "SELECT,INSERT"
}
}
class postfix-virtual {
include mail-virtual
include spamassassin
include postgrey
package { [postfix, postfix-mysql, libsasl2-modules-sql]:
ensure => installed
}
service { postfix:
ensure => running,
hasrestart => true
}
etc_file { ["postfix/main.cf", "postfix/master.cf"] :
require => [Package[postfix-mysql], Ssl_certificat["mail.tryphon.org"]],
notify => Service[postfix]
}
file { "/etc/postfix/transports" :
content => "autoreply.tryphon.org vacation:",
require => Package[postfix],
notify => Exec[postmap-transports]
}
exec { postmap-transports:
command => "postmap /etc/postfix/transports",
refreshonly => true,
require => File["/etc/postfix/transports"]
}
etc_file {
["postfix/mysql_virtual_alias_maps.cf","postfix/mysql_virtual_domains_maps.cf","postfix/mysql_virtual_mailbox_maps.cf","postfix/sasl/smtpd.conf"]:
mode => 640,
group => postfix,
require => Package[postfix-mysql],
notify => Service[postfix],
template => true
}
file {"/etc/postfix/spam_headercheck":
content => "/^X-Spam-Status: Yes/ REJECT Looks like spam to me.",
require => Package[postfix-mysql]
}
munin::anode::plugin {
[postfix_mailqueue,postfix_mailvolume]:
}
}
class mail-virtual {
user { mailuser:
ensure => present,
shell => "/bin/false",
# used into main.cf
uid => "1100"
}
file { "/var/mail/virtual":
ensure => directory,
owner => mailuser,
require => User[mailuser]
}
ssl_certificat { "mail.tryphon.org": }
mysql-server::user { postfix:
password => $postfix_mysql_password, # secret
database => "postfixadmin",
privileges => "SELECT",
require => Package[mysql-server]
}
}
class dovecot {
include mail-virtual
package { [dovecot-imapd, dovecot-pop3d]:
ensure => installed,
notify => Service[dovecot]
}
package { dovecot-common:
alias => dovecot
}
etc_file { "dovecot/dovecot.conf":
notify => Service[dovecot],
require => [Package[dovecot], Ssl_certificat["mail.tryphon.org"]]
}
etc_file { "dovecot/dovecot-mysql.conf":
mode => 640,
notify => Service[dovecot],
require => Package[dovecot],
template => true
}
service { dovecot:
ensure => running,
require => [Package[dovecot],Exec[postfixadmin-setup]]
}
}
class spamassassin {
package { [spampd, spamassassin]: ensure => present }
file { "/etc/default/spampd":
source => "puppet:///files/etc/spampd/spampd.default",
notify => Service[spampd]
}
service { spampd:
ensure => running,
require => Package[spampd]
}
# Fixe auto-whitelist permissions (root/spampd u+rw set by the package
file { "/var/cache/spampd/auto-whitelist":
owner => root, group => spampd, mode => 660,
require => Package[spampd]
}
}
class postgrey {
package { postgrey: ensure => present }
service { postgrey:
ensure => running,
require => Package[postgrey]
}
etc_file { "postgrey/whitelist_clients.local":
notify => Service[postgrey],
require => Package[postgrey]
}
}
class apache2 {
# TODO support for mpm-worker ?
package { apache2-mpm-prefork:
alias => apache2,
ensure => installed
}
service { apache2:
ensure => running,
subscribe => File["/etc/apache2"],
require => Package[apache2],
hasrestart => true
}
define site($link = '') {
# install and enable a given site configuration
file { "/etc/apache2/sites-available/$name":
source => "puppet:///files/etc/apache2/sites-available/$name",
notify => Service[apache2],
require => Package[apache2]
}
file {
$link ? {
'' => "/etc/apache2/sites-enabled/$name",
default => "/etc/apache2/sites-enabled/$link"
} :
ensure => "/etc/apache2/sites-available/$name",
require => File["/etc/apache2/sites-available/$name"],
notify => Service[apache2]
}
}
define confd_file() {
file { "/etc/apache2/conf.d/$name":
source => "puppet:///files/etc/apache2/conf.d/$name",
notify => Service[apache2],
require => Package[apache2]
}
}
# configuration de base (log, ...)
confd_file { ["base","log","serverstatus"]: }
# histoire de reloader apache2 quand la conf change
# fonctionne partiellement
file { "/etc/apache2":
ensure => directory,
recurse => true
}
file { ["/var/www","/var/www/default"]:
ensure => directory
}
file { "/var/www/default/index.html":
ensure => present
}
site { "default":
link => "000-default",
require => File["/var/www/default"]
}
# root directory for tryphon web site
file { "/var/www/tryphon.org":
ensure => directory
}
munin::anode::plugin {
[apache_accesses, apache_processes, apache_volume]:
}
}
class mail-website {
include apache2
file { "/var/www/tryphon.org/mail":
ensure => directory
}
file { "/var/www/tryphon.org/mail/index.html":
ensure => present
}
apache2::site { "tryphon-mail":
require => Package[postfixadmin]
}
}
class roundcube {
package { roundcube:
ensure => present,
require => File["/etc/dbconfig-common/roundcube.conf"]
}
line { "roundcube-include-local":
file => "/etc/roundcube/main.inc.php",
line => '<?php include_once("/etc/roundcube/local-main.inc.php"); ?>',
require => Package[roundcube]
}
etc_file { "roundcube/local-main.inc.php":
require => Package[roundcube],
group => www-data,
mode => 640,
template => true
}
# overrides default roundcube.conf (with uses mysql ...)
etc_file { "dbconfig-common/roundcube.conf":
}
file { ["/var/log/roundcube","/var/cache/roundcube"]:
ensure => directory,
owner => www-data,
group => www-data,
mode => 640,
require => Package[roundcube]
}
}
class fetchmail {
package { fetchmail:
ensure => present
}
}
class ntp-client {
package { ntp: ensure => present }
}
class ssh {
package { ssh: ensure => present }
line { sshd-port :
line => "Port $ssh_listen_port",
file => "/etc/ssh/sshd_config",
require => Package[ssh],
notify => Service[ssh]
}
line { sshd-alternate-port :
line => "Port 22",
file => "/etc/ssh/sshd_config",
require => Package[ssh],
notify => Service[ssh]
}
service { ssh:
ensure => running,
require => Package[ssh]
}
file { "/etc/ssh/sshd_config":
ensure => file,
notify => Service[ssh]
}
}
class munin::anode::local inherits munin::anode {
# customize munin::anode
# some default plugins
munin::anode::plugin { [ cpu, df, iostat, load, memory, netstat, swap ]: }
munin::anode::plugin { if_eth0: script => if_ }
# remove some debian default plugin
munin::anode::plugin {
[ open_inodes, open_files, irqstats, interrupts, entropy, df_inode, if_err_eth0, if_err_eth1, vmstat, forks ]:
ensure => absent
}
# disable the (verbose) cron for /etc/munin/plugins/apt_all
exec { "sed -i '/apt_all/ s/^\\(.*\\)$/# \\1/' /etc/cron.d/munin-node":
unless => "/bin/grep -q '#.*apt_all' /etc/cron.d/munin-node",
require => Package["munin-node"]
}
}
class shorewall {
package { shorewall: ensure => installed }
file { "/etc/shorewall":
ensure => directory,
source => "puppet:///files/etc/shorewall",
recurse => true,
notify => Service[shorewall]
}
file { "/etc/default/shorewall":
source => "puppet:///files/etc/shorewall/shorewall.default",
notify => Service[shorewall]
}
service { shorewall:
ensure => running,
require => Package[shorewall],
hasrestart => true,
status => '/sbin/shorewall status'
}
etc_file { "shorewall/params":
template => true
}
}
class puppet::puppetmaster::local inherits puppet::puppetmaster {
# required by storeconfigs
package { libsqlite3-ruby: ensure => installed }
}
class xen::local inherits xen {
etc_file { ["xen-tools/xen-tools.conf", "xen-tools/xm.tmpl"]:
require => Package[xen-tools]
}
etc_file { "xen-tools/role.d/puppet":
require => Package[xen-tools],
mode => 755
}
define domain($ip) {
xen::domain { $name:
ip => $ip,
domain => 'dbx.tryphon.priv',
role => 'udev,puppet',
require => [File["/etc/xen-tools/xen-tools.conf"], File["/etc/xen-tools/role.d/puppet"], File["/etc/xen-tools/xm.tmpl"]]
}
}
}
class base-server {
include apt
include users
include sudo
include puppet
include ssh
include munin::anode::local
}
class mail-server inherits base-server {
include mysql-server
include postfix-virtual
include postfixadmin
include mail-website
include dovecot
include roundcube
include postfixadmin-fetchmail
include postfixadmin-vacation
}