Mercurial > repos > other > Puppet
view manifests/templates.pp @ 335:aa9f570d6a9c
Switch to PHP 7.4 now that NextCloud has reached v18
7.3 only lasted until December 2020 with active support.
7.4 is good until December 2021 with security until 2022.
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sun, 22 Mar 2020 19:41:50 +0000 |
parents | ee4760967d2f |
children | 445aaaf228cc |
line wrap: on
line source
# Make sure packages come after their repos File<| tag == 'repo-config' |> -> YumRepo<| |> -> Package<| |> # Make sure all files are in place before starting services # FIXME: Title matches are to fix a dependency cycle File<| tag != 'post-service' and title != '/etc/sysconfig/ip6tables' and title != '/etc/sysconfig/iptables' |> -> Service<| |> # Set some shortcut variables #$os = $operatingsystem $osver = $operatingsystemmajrelease $server = '' class basenode { include sudo include defaultusers include logwatch file { '/etc/puppet/hiera.yaml': ensure => present, content => " # Let the system set defaults version: 5 ", } } class basevpsnode ( $primary_ip, $proxy_4to6_ip_prefix = undef, $proxy_upstream = undef, $nat64_ranges = [], $mailserver, $imapserver, $mailrelays = [], $firewall_cmd = 'iptables', ) { if $firewall_cmd == 'iptables' { class { 'vpsfirewall': fw_protocol => $primary_ip =~ Stdlib::IP::Address::V6 ? { true => 'IPv6', default => 'IPv4'}, } } #VPS is a self-mastered Puppet machine, so bodge a Hosts file if $primary_ip =~ Stdlib::IP::Address::V6 { $lo_ip = '::1' } else { $lo_ip = '127.0.0.1' } file { '/etc/hosts': ensure => present, content => "${lo_ip} localhost\n${primary_ip} ${fqdn}", } if $proxy_4to6_ip_prefix != undef { # …:1 to …:9 for websites, …:10 for mail $ipv6_addresses = Integer[1, 10].map |$octet| { "$proxy_4to6_ip_prefix:$octet" } $ipv6_secondaries = join($ipv6_addresses, " ") augeas {'IPv6 secondary addresses': context => "/files/etc/sysconfig/network-scripts/ifcfg-eth0", changes => "set IPV6ADDR_SECONDARIES '\"$ipv6_secondaries\"'", } } require repos include basenode include privat include dnsresolver include ssh::server include vcs::server include vcs::client class { 'webserver': primary_ip => $primary_ip, proxy_4to6_ip_prefix => $proxy_4to6_ip_prefix, proxy_4to6_mask => 124, proxy_upstream => $proxy_upstream, } include cronjobs include logrotate class { 'fail2ban': firewall_cmd => $firewall_cmd, } include tools class { 'email': mailserver => $mailserver, imapserver => $imapserver, mailserver_ip => $primary_ip, proxy_ip => $proxy_4to6_ip_prefix != undef ? { true => "${proxy_4to6_ip_prefix}:10", default => undef }, proxy_upstream => $proxy_upstream, nat64_ranges => $nat64_ranges, mailrelays => $mailrelays, } } ## Classes to allow facet behaviour using preconfigured setups of classes class vpsfirewall ($fw_protocol) { resources { "firewall": purge => false, } class { "my_fw": ip_version => $fw_protocol, } # Control what does and doesn't get pruned in the main filter chain firewallchain { "INPUT:filter:$fw_protocol": purge => true, ignore => [ '-j f2b-[^ ]+$', '^(:|-A )f2b-', '--comment "Great Firewall of China"', '--comment "Do not purge', ], } if ($fw_protocol != "IPv6") { firewall { '010 Whitelist Googlebot': source => '66.249.64.0/19', dport => [80,443], proto => tcp, action => accept, } # Block a spammer hitting our contact forms (also on StopForumSpam list A LOT) firewall { '099 Blacklist spammers 1': source => '107.181.78.172', dport => [80, 443], proto => tcp, action => 'reject', } firewall { '099 Blacklist IODC bot': # IODC bot makes too many bad requests, and contact form is broken # They don't publish a robots.txt name, so firewall it! source => '86.153.145.149', dport => [ 80, 443 ], proto => tcp, action => 'reject', } firewall { '099 Blacklist Baidu Brazil': #Baidu got a Brazilian netblock and are hitting us hard #Baidu doesn't honour "crawl-delay" in robots.txt #Baidu gets firewalled source => '131.161.8.0/22', dport => [ 80, 443 ], proto => tcp, action => 'reject', } } firewallchain { "GREATFIREWALLOFCHINA:filter:$fw_protocol": ensure => present, } firewall { '050 Check our Great Firewall Against China': chain => 'INPUT', jump => 'GREATFIREWALLOFCHINA', } firewallchain { "Fail2Ban:filter:$fw_protocol": ensure => present, } firewall { '060 Check Fail2Ban': chain => 'INPUT', jump => 'Fail2Ban', } } class dnsresolver { package { 'unbound': ensure => present, } package { 'named': ensure => absent, } service { 'named': ensure => stopped, enable => false, } service { 'unbound': ensure => running, enable => true, } file { '/etc/named.conf': ensure => absent, } file { '/etc/unbound/unbound.conf': ensure => present, source => [ "puppet:///common/unbound.conf-${::hostname}", "puppet:///common/unbound.conf", ], group => 'named', require => Package['unbound'], notify => Service['unbound'], } file { '/etc/NetworkManager/conf.d/local-dns-resolver.conf': ensure => present, content => "[main] dns=none", } file { '/etc/sysconfig/named': ensure => absent, } file { '/etc/resolv.conf': ensure => present, # "ipaddress" key only exists for machines with IPv4 addresses content => has_key($facts, 'ipaddress') ? { true => "nameserver 127.0.0.1", default => "nameserver ::1" }, require => Service['unbound'], tag => 'post-service', } } class repos { yumrepo { 'epel': mirrorlist => 'https://mirrors.fedoraproject.org/metalink?repo=epel-$releasever&arch=$basearch', descr => "Extra Packages for Enterprise Linux", enabled => 1, failovermethod => 'priority', gpgcheck => 1, gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$osver", } file { "/etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$osver": ensure => present, source => "puppet:///common/RPM-GPG-KEY-EPEL-$osver", tag => 'repo-config', } yumrepo { 'ibboard': baseurl => 'https://download.opensuse.org/repositories/home:/IBBoard:/server/CentOS_$releasever/', descr => 'Extra packages from IBBoard', enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ibboard', } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-ibboard': ensure => present, source => 'puppet:///common/RPM-GPG-KEY-ibboard', tag => 'repo-config', } yumrepo { 'webtatic': ensure => absent, } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-webtatic-andy': ensure => absent, } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-webtatic-el7': ensure => absent, } if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') >= 0 { $python_ver = 'python3' } else { $python_ver = 'system' } class { 'python': ensure => 'present', version => $python_ver, pip => 'present', virtualenv => 'present', use_epel => false, } } class tools { $packages = [ 'sqlite', 'bash-completion', 'nano', 'bzip2', 'mlocate', 'patch', 'tmux', 'wget', 'yum-utils', 'rsync' ] package { $packages: ensure => installed; } } class logrotate { package { 'logrotate': ensure => installed; } file { '/etc/logrotate.d/httpd': ensure => present, source => 'puppet:///common/logrotate-httpd', require => Package['logrotate'], } file { '/etc/logrotate.d/trac': ensure => present, source => 'puppet:///common/logrotate-trac', require => Package['logrotate'], } } class logwatch { package { 'logwatch': ensure => installed; } File { ensure => present, require => Package['logwatch'], } file { '/etc/cron.daily/0logwatch': source => 'puppet:///common/0logwatch'; } $logwatch_dirs = [ '/etc/logwatch/', '/etc/logwatch/conf/', '/etc/logwatch/conf/logfiles/', '/etc/logwatch/conf/services/', ] file { $logwatch_dirs: ensure => directory, } file { '/etc/logwatch/conf/logwatch.conf': content => 'Detail = Med', } file { '/etc/logwatch/conf/logfiles/http.conf': content => 'LogFile = apache/access_*.log', } file { '/etc/logwatch/conf/logfiles/http-error.conf': source => 'puppet:///common/logwatch/logfiles_http-error.conf', } file { '/etc/logwatch/conf/logfiles/mysql.conf': source => 'puppet:///common/logwatch/logfiles_mysql.conf', } file { '/etc/logwatch/conf/logfiles/php.conf': source => 'puppet:///common/logwatch/logfiles_php.conf', } file { '/etc/logwatch/conf/services/php.conf': source => 'puppet:///common/logwatch/services_php.conf', } } #Our web server with our configs, not just a stock one class webserver ( $primary_ip, $proxy_4to6_ip_prefix = undef, $proxy_4to6_mask = undef, $proxy_upstream = undef, ) { #Setup base website parameters class { 'website': base_dir => '/srv/sites', primary_ip => $primary_ip, proxy_4to6_ip_prefix => $proxy_4to6_ip_prefix, proxy_4to6_mask => $proxy_4to6_mask, proxy_upstream => $proxy_upstream, default_owner => $defaultusers::default_user, default_group => $defaultusers::default_user, default_tld => 'co.uk', default_extra_tlds => [ 'com' ], } $php_suffix = '' if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') >= 0 { yumrepo { 'remirepo-safe': mirrorlist => 'http://cdn.remirepo.net/enterprise/$releasever/safe/$basearch/mirror', descr => "Extra CentOS packages from Remi", enabled => 1, failovermethod => 'priority', gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', } yumrepo { 'remirepo-php': mirrorlist => 'http://cdn.remirepo.net/enterprise/8/modular/$basearch/mirror', descr => 'Remi\'s Modular repository for Enterprise Linux 8 - $basearch', enabled => 1, failovermethod => 'priority', gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-remi': ensure => present, source => 'puppet:///common/RPM-GPG-KEY-remi.el8', tag => 'repo-config', } } else { yumrepo { 'remirepo-safe': mirrorlist => 'http://cdn.remirepo.net/enterprise/$releasever/safe/mirror', descr => "Extra CentOS packages from Remi", enabled => 1, failovermethod => 'priority', gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', } yumrepo { 'remirepo-php': mirrorlist => 'http://cdn.remirepo.net/enterprise/$releasever/php74/mirror', descr => "PHP7.4 for CentOS from Remi", enabled => 1, failovermethod => 'priority', gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', } file { '/etc/pki/rpm-gpg/RPM-GPG-KEY-remi': ensure => present, source => 'puppet:///common/RPM-GPG-KEY-remi', tag => 'repo-config', } } #Configure the PHP version to use class { 'website::php': suffix => $php_suffix, opcache => 'opcache', module => ($operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '8') >= 0) ? { true => 'remi-7.4', default => undef }, extras => [ 'process', 'intl', 'pecl-imagick', 'bcmath', 'pecl-zip', 'json' ], } #Setup MySQL, using (private) templates to make sure that we set non-std passwords and a default user if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '7') >= 0 { $mysqlpackage = 'mariadb' $mysqlsuffix = '' # Required for SELinux rule setting/status checks if versioncmp($operatingsystemrelease, '8') >= 0 { $semanage_package_name = 'policycoreutils-python-utils' } else { $semanage_package_name = 'policycoreutils-python' } package { 'policycoreutils-python': name => $semanage_package_name, ensure => present, } $extra_packages = [ 'perl-Sys-Syslog', #Required for Perl SPF checking ] package { $extra_packages: ensure => installed } } else { $mysqlpackage = 'mysql' $mysqlsuffix = '55w' } class { 'website::mysql': mysqluser => template('defaultusers/mysql-user'), mysqlpassword => template('defaultusers/mysql-password'), mysqlprefix => $mysqlpackage, mysqlsuffix => $mysqlsuffix, phpsuffix => $php_suffix, phpmysqlsuffix => 'nd' } } class ibboardvpsnode ( $primary_ip, $proxy_4to6_ip_prefix = undef, $proxy_upstream = undef, $nat64_ranges = [], $mailserver, $imapserver, $mailrelays = [], $firewall_cmd = 'iptables', ){ class { 'basevpsnode': primary_ip => $primary_ip, proxy_4to6_ip_prefix => $proxy_4to6_ip_prefix, proxy_upstream => $proxy_upstream, nat64_ranges => $nat64_ranges, mailserver => $mailserver, imapserver => $imapserver, mailrelays => $mailrelays, firewall_cmd => $firewall_cmd, } # Set timezone to something sensible file { "/etc/localtime": ensure => 'link', target => '/usr/share/zoneinfo/Europe/London', } # Common modules used by multiple sites (mod_auth_basic is safe because we HTTPS all the things) $mods = [ 'auth_basic', 'authn_file', 'authz_user', 'deflate', 'xsendfile' ] apache::mod { $mods:; } if $operatingsystem == 'CentOS' and versioncmp($operatingsystemrelease, '7') >= 0 { apache::mod { 'authn_core':; } } #Configure our sites, using templates for the custom fragments where the extra content is too long class { "devsite": proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:01", default => undef } } class { "adminsite": proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:02", default => undef } } website::https::multitld { 'www.ibboard': proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:03", default => undef }, custom_fragment => template("privat/apache/ibboard.fragment"), letsencrypt_name => 'ibboard.co.uk', csp_override => { "report-uri" => "https://ibboard.report-uri.com/r/d/csp/enforce", "default-src" => "'none'", "img-src" => "'self' https://live.staticflickr.com/", "script-src" => "'self'", "style-src" => "'self'", "font-src" => "'self'", "form-action" => "'self'", "connect-src" => "'self'", } } class { "hiveworldterrasite": proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:04", default => undef } } class { "bdstrikesite": proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:05", default => undef } } website::https::multitld { 'www.abiknight': proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:06", default => undef }, custom_fragment => "$website::htmlphpfragment ErrorDocument 404 /error.php", letsencrypt_name => 'abiknight.co.uk', } website::https::multitld { 'www.warfoundry': proxy_4to6_ip => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:07", default => undef }, letsencrypt_name => 'warfoundry.co.uk', custom_fragment => template("privat/apache/warfoundry.fragment"), } class { "webmailpimsite": proxy_4to6_ip_pim => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:08", default => undef }, proxy_4to6_ip_webmail => $proxy_4to6_ip_prefix != undef ? { true => "$proxy_4to6_ip_prefix:09", default => undef }, } } class adminsite ($proxy_4to6_ip) { apache::mod { 'info':; 'status':; 'cgi':; } website::https::multitld { 'admin.ibboard': proxy_4to6_ip => $proxy_4to6_ip, force_no_index => false, ssl_ca_chain => '', custom_fragment => template("privat/apache/admin.fragment"), } cron { 'loadavg': command => '/usr/local/bin/run-loadavg-logger', user => apache, minute => '*/6' } cron { 'awstats': command => '/usr/local/bin/update-awstats > /srv/sites/admin/awstats.log', user => apache, hour => '*/6', minute => '0' } } class hiveworldterrasite ($proxy_4to6_ip) { website::https::multitld { 'www.hiveworldterra': proxy_4to6_ip => $proxy_4to6_ip, force_no_www => false, letsencrypt_name => 'hiveworldterra.co.uk', custom_fragment => template("privat/apache/hwt.fragment"), } website::https::multitld { 'forums.hiveworldterra': proxy_4to6_ip => $proxy_4to6_ip, letsencrypt_name => 'forums.hiveworldterra.co.uk', custom_fragment => template("privat/apache/forums.fragment"), } website::https::multitld { 'skins.hiveworldterra': proxy_4to6_ip => $proxy_4to6_ip, letsencrypt_name => 'skins.hiveworldterra.co.uk', custom_fragment => template("privat/apache/skins.fragment"), } website::https::redir { 'hiveworldterra.ibboard.co.uk': proxy_4to6_ip => $proxy_4to6_ip, redir => 'https://www.hiveworldterra.co.uk/', docroot => "${website::basedir}/hiveworldterra", letsencrypt_name => 'hiveworldterra.ibboard.co.uk', separate_log => true, } } class bdstrikesite ($proxy_4to6_ip) { website::https::multitld { 'www.bdstrike': proxy_4to6_ip => $proxy_4to6_ip, docroot_owner => $defaultusers::secondary_user, docroot_group => 'editors', letsencrypt_name => 'bdstrike.co.uk', custom_fragment => template("privat/apache/bdstrike.fragment"), csp_override => {"frame-ancestors" => "'self'"}, csp_report_override => { "font-src" => "'self' https://fonts.gstatic.com/", "img-src" => "'self' https://secure.gravatar.com/", "style-src" => "'self' https://fonts.googleapis.com/" }, } $aliases = [ 'strikecreations.co.uk', 'strikecreations.com', 'www.strikecreations.com' ] website::https::redir { 'www.strikecreations.co.uk': proxy_4to6_ip => $proxy_4to6_ip, redir => 'https://bdstrike.co.uk/', serveraliases => $aliases, docroot => "${website::basedir}/bdstrike", docroot_owner => $defaultusers::secondary_user, docroot_group => 'editors', letsencrypt_name => 'strikecreations.com', separate_log => true, } cron { 'wordpress_cron': # Run "php -f wp-cron.php" on a schedule so that we can auto-update # without giving Apache full write access! command => "/usr/local/bin/bdstrike-cron", user => $defaultusers::default_user, minute => '*/15', } } class devsite ($proxy_4to6_ip) { if versioncmp($operatingsystemrelease, '8') >= 0 { # Apache::Mod doesn't map this correctly for CentOS 8 yet $mod_wsgi_lib = 'mod_wsgi_python3.so' } else { $mod_wsgi_lib = undef } apache::mod { # mod_wsgi for Python support 'wsgi': lib => $mod_wsgi_lib, } # Create Python virtualenvs for the dev site apps file { "/srv/rhodecode": ensure => 'directory'; "/srv/trac": ensure => 'directory'; } -> python::virtualenv { # Distribute is described as "simple compatibility layer that installs Setuptools 0.7+" # and leads to 'module "importlib._bootstrap" has no attribute "SourceFileLoader"' "/srv/rhodecode/virtualenv": distribute => false, version => '3'; "/srv/trac/virtualenv": distribute => false, version => '3'; } # Graphviz for Trac "master ticket" graphs package { 'graphviz': ensure => installed, } website::https::multitld { 'dev.ibboard': proxy_4to6_ip => $proxy_4to6_ip, #Make sure we're the first one hit for the tiny fraction of "no support" cases we care about (potentially Python for Mercurial!) # http://en.wikipedia.org/wiki/Server_Name_Indication#No_support priority => 1, letsencrypt_name => 'dev.ibboard.co.uk', custom_fragment => template("privat/apache/dev.fragment"), proxy_fragment => template("privat/apache/dev-proxy.fragment"), force_no_index => false, } } class webmailpimsite ($proxy_4to6_ip_pim, $proxy_4to6_ip_webmail) { # Webmail and Personal Information Management (PIM) sites website::https { 'webmail.ibboard.co.uk': proxy_4to6_ip => $proxy_4to6_ip_webmail, force_no_index => false, ssl_ca_chain => '', custom_fragment => template("privat/apache/webmail.fragment"), } website::https { 'pim.ibboard.co.uk': proxy_4to6_ip => $proxy_4to6_ip_pim, docroot_owner => 'apache', docroot_group => 'editors', force_no_index => false, lockdown_requests => false, ssl_ca_chain => '', csp => false, csp_report => false, custom_fragment => template("privat/apache/pim.fragment"), } cron { 'owncloudcron': command => "/usr/local/bin/owncloud-cron", user => 'apache', minute => '*/15', } } class email ( $mailserver, $imapserver, $mailserver_ip, $proxy_ip = undef, $proxy_upstream = [], $nat64_ranges = [], $mailrelays = [], ){ class { 'postfix': mailserver => $mailserver, mailserver_ip => $mailserver_ip, mailserver_proxy => $proxy_ip, proxy_upstream => $proxy_upstream, mailrelays => $mailrelays, nat64_ranges => $nat64_ranges, protocols => $mailserver_ip =~ Stdlib::IP::Address::V6 ? { true => 'all', default => 'ipv4' }, } class { 'dovecot': imapserver => $imapserver, imapserver_ip => $mailserver_ip, imapserver_proxy => $proxy_ip, proxy_upstream => $proxy_upstream, } # Unspecified SpamAssassin config dependencies that started # showing up as errors in our logs package { ['perl-File-MimeInfo']: ensure => installed, } package { [ 'amavisd-new' ]: ensure => installed, tag => 'av', } service { 'amavisd': ensure => 'running', enable => 'true', } service { 'clamd@amavisd': ensure => 'stopped', enable=> 'mask', } file { '/etc/amavisd/amavisd.conf': ensure => present, source => 'puppet:///private/postfix/amavisd.conf', tag => 'av', } file { '/etc/mail/spamassassin/local.cf': ensure => present, source => 'puppet:///private/postfix/spamassassin-local.cf', tag => 'av', } file { '/etc/mail/spamassassin/ole2macro.cf': ensure => present, source => 'puppet:///common/ole2macro.cf', tag => 'av', } file { '/etc/mail/spamassassin/ole2macro.pm': ensure => present, source => 'puppet:///common/spamassassin-vba-macro-master/ole2macro.pm', tag => 'av', } Package<| tag == 'av' |> -> File<| tag == 'av' |> File<| tag == 'av' |> { notify => Service['amavisd'], } cron { 'Postwhite': command => "/usr/local/bin/postwhite 2>&1| grep -vE '^(Starting|Recursively|Getting|Querying|Removing|Sorting|$)'", user => 'root', weekday => 0, hour => 2, minute => 0, } } class cronjobs { # Add Mutt for scripts that send emails, but stop it clogging the disk by keeping copies of emails package { 'mutt': ensure => installed, } file { '/etc/Muttrc.local': content => 'set copy = no', require => Package['mutt'], } # General server-wide cron jobs Cron { user => 'root' } cron { 'backupalldbs': command => "/usr/local/bin/backupalldbs", monthday => "*/2", hour => "4", minute => "9" } # Only run the Great Firewall Against China on IPv4 (since we don't have an IPv6 list # and the PROXY forwards the IPs to services, but not at the network level) cron { 'greatfirewallofchina': command => '/usr/local/bin/update-great-firewall-of-china', ensure => has_key($facts, 'ipaddress') ? { true => "present", default => "absent" }, hour => 3, minute => 30 } cron { 'permissions': command => '/usr/local/bin/set-permissions', hour => 3, minute => 2 } # Since we're only managing the local server, use our script that wraps "puppet apply" instead of PuppetMaster cron { 'puppet': command => '/usr/local/bin/puppet-apply | grep -v "Compiled catalog for\|Finished catalog run in\|Applied catalog in"', hour => '*/6', minute => 5 } cron { 'purgecaches': command => "/usr/local/bin/purge-caches", hour => '4', minute => '15', weekday => '1', } # Notify of uncommitted files cron { 'check-mercurial-committed': command => "/usr/local/bin/check-hg-status", hour => '4', minute => '20', weekday => '0-6/3', #Sunday, Wednesday and Saturday morning } # Notify of available updates cron { 'check-yum-updates': command => '/usr/bin/yum check-update | tail -2 | grep -Ev "^ \* [[:alnum:]-]+: [[:alnum:]\.]+$"', hour => '4', minute => '30', weekday => '0-6/3', #Sunday, Wednesday and Saturday morning } # And check whether anything needs restarting cron { 'check-needs-restarting': command => '/usr/bin/needs-restarting|grep -v "/usr/lib/systemd\|/usr/sbin/lvmetad\|/usr/lib/polkit-1/polkitd"', hour => '4', minute => '45', weekday => '0-6/3', #Sunday, Wednesday and Saturday morning } }