From 99b8524c16cc99ceeaf1ebf588f2fc0f2c0fbe0a Mon Sep 17 00:00:00 2001 From: Cullum Smith Date: Sat, 12 Oct 2024 08:14:59 -0400 Subject: add a bunch of hostclasses --- files/etc/cron.d/davical.dav_server | 2 + files/etc/cron.d/prosody.xmpp_server | 3 + files/etc/pam.d/znc.znc_server | 2 + .../etc/asterisk/extensions.conf.asterisk_server | 5 + .../local/etc/asterisk/logger.conf.asterisk_server | 3 + .../local/etc/asterisk/pjsip.conf.asterisk_server | 26 +++ .../etc/asterisk/pjsip_wizard.conf.asterisk_server | 65 ++++++++ .../local/etc/asterisk/queues.conf.asterisk_server | 31 ++++ .../local/etc/asterisk/rtp.conf.asterisk_server | 3 + .../etc/asterisk/voicemail.conf.asterisk_server | 31 ++++ .../local/etc/dovecot/rspamd.conf.sh.imap_server | 5 + files/usr/local/etc/nginx/fastcgi_params.common | 31 ++++ files/usr/local/etc/nginx/nginx.conf.common | 37 ++++- .../local/etc/nginx/vhosts.conf.bitwarden_server | 36 +++++ files/usr/local/etc/nginx/vhosts.conf.dav_server | 55 +++++++ files/usr/local/etc/nginx/vhosts.conf.smtp_server | 4 +- files/usr/local/etc/nginx/vhosts.conf.ttrss_server | 43 +++++ files/usr/local/etc/nginx/vhosts.conf.xmpp_server | 21 +++ files/usr/local/etc/nginx/vhosts.conf.znc_server | 21 +++ .../etc/nsd/nsd.conf.authoritative_nameserver | 22 +++ files/usr/local/etc/nslcd.conf.common | 2 + files/usr/local/etc/openldap/ldap.conf.common | 1 + files/usr/local/etc/openldap/ldap.conf.idm_server | 1 + files/usr/local/etc/php-fpm.conf.common | 4 + .../local/etc/php-fpm.d/davical.conf.dav_server | 20 +++ .../local/etc/php-fpm.d/ttrss.conf.ttrss_server | 23 +++ files/usr/local/etc/php.ini.common | 138 ++++++++++++++++ .../local/etc/poudriere.d/pkglist.pkg_repository | 28 ++++ .../local/etc/prosody/prosody.cfg.lua.xmpp_server | 106 ++++++++++++ .../etc/rc.conf.d/vaultwarden.bitwarden_server | 19 +++ files/usr/local/etc/rc.d/ttrssd.ttrss_server | 47 ++++++ .../etc/ssh/sshd_config.d/acmeproxy.conf.common | 11 ++ files/usr/local/etc/ssh/sshd_config.freebsd | 2 +- files/usr/local/etc/sudoers.d/acme.asterisk_server | 1 + .../usr/local/etc/sudoers.d/acme.public_webserver | 1 + files/usr/local/etc/sudoers.d/acme.smtp_server | 2 +- files/usr/local/etc/sudoers.d/acme.xmpp_server | 1 + files/usr/local/etc/turnserver.conf.turn_server | 61 +++++++ .../usr/local/etc/znc/configs/znc.conf.znc_server | 55 +++++++ .../etc/znc/moddata/cyrusauth/.registry.znc_server | 2 + files/usr/local/lib/sasl2/znc.conf.znc_server | 3 + .../dovecot/sieve-pipe/report-ham.sh.imap_server | 12 +- .../dovecot/sieve-pipe/report-spam.sh.imap_server | 12 +- .../local/libexec/idm-ssh-authorized-keys.common | 8 +- files/usr/local/libexec/idm-ssh-known-hosts.common | 4 +- .../local/libexec/prosody-acme-proxy.xmpp_server | 54 +++++++ .../libexec/prosody-update-roster.xmpp_server | 47 ++++++ .../davical/config/administration.yml.dav_server | 4 + .../local/www/davical/config/config.php.dav_server | 49 ++++++ files/usr/local/www/tt-rss/config.php.ttrss_server | 28 ++++ .../plugins.local/auth_idm/init.php.ttrss_server | 177 +++++++++++++++++++++ .../data16/postgresql.conf.postgresql_server | 2 +- lib/60-ldap | 18 ++- lib/60-postgres | 24 +++ scripts/common/10-vars | 1 + scripts/hostclass/asterisk_server | 74 +++++++++ scripts/hostclass/authoritative_nameserver | 27 ++++ scripts/hostclass/bitwarden_server | 58 +++++++ scripts/hostclass/dav_server | 139 ++++++++++++++++ scripts/hostclass/imap_server/30-dovecot | 5 +- scripts/hostclass/postgresql_server | 8 +- scripts/hostclass/public_webserver | 42 +++++ scripts/hostclass/smtp_server/10-rspamd | 8 +- scripts/hostclass/smtp_server/20-postfix | 2 +- scripts/hostclass/ttrss_server | 137 ++++++++++++++++ scripts/hostclass/turn_server | 29 ++++ scripts/hostclass/xmpp_server | 132 +++++++++++++++ scripts/hostclass/znc_server | 68 ++++++++ scripts/hostname/rlaptop1 | 9 -- scripts/hostname/znc1 | 3 + scripts/os/freebsd/60-acme | 35 +++- site/scripts/hostname/rlaptop1 | 9 ++ vars/common | 7 +- vars/hostclass/asterisk_server | 10 ++ vars/hostclass/authoritative_nameserver | 4 + vars/hostclass/bitwarden_server | 3 + vars/hostclass/dav_server | 4 + vars/hostclass/pkg_repository | 1 + vars/hostclass/postgresql_server | 3 + vars/hostclass/public_webserver | 5 + vars/hostclass/ttrss_server | 4 + vars/hostclass/turn_server | 8 + vars/hostclass/xmpp_server | 5 + vars/hostclass/znc_server | 4 + vars/hostname/bitwarden1 | 4 + vars/hostname/dav1 | 3 + vars/hostname/ns1 | 3 + vars/hostname/pbx1 | 3 + vars/hostname/postgres1 | 4 + vars/hostname/ttrss1 | 4 + vars/hostname/turn1 | 3 + vars/hostname/www1 | 5 + vars/hostname/xmpp1 | 5 + vars/os/freebsd | 1 + 94 files changed, 2241 insertions(+), 51 deletions(-) create mode 100644 files/etc/cron.d/davical.dav_server create mode 100644 files/etc/cron.d/prosody.xmpp_server create mode 100644 files/etc/pam.d/znc.znc_server create mode 100644 files/usr/local/etc/asterisk/extensions.conf.asterisk_server create mode 100644 files/usr/local/etc/asterisk/logger.conf.asterisk_server create mode 100644 files/usr/local/etc/asterisk/pjsip.conf.asterisk_server create mode 100644 files/usr/local/etc/asterisk/pjsip_wizard.conf.asterisk_server create mode 100644 files/usr/local/etc/asterisk/queues.conf.asterisk_server create mode 100644 files/usr/local/etc/asterisk/rtp.conf.asterisk_server create mode 100644 files/usr/local/etc/asterisk/voicemail.conf.asterisk_server create mode 100644 files/usr/local/etc/dovecot/rspamd.conf.sh.imap_server create mode 100644 files/usr/local/etc/nginx/fastcgi_params.common create mode 100644 files/usr/local/etc/nginx/vhosts.conf.bitwarden_server create mode 100644 files/usr/local/etc/nginx/vhosts.conf.dav_server create mode 100644 files/usr/local/etc/nginx/vhosts.conf.ttrss_server create mode 100644 files/usr/local/etc/nginx/vhosts.conf.xmpp_server create mode 100644 files/usr/local/etc/nginx/vhosts.conf.znc_server create mode 100644 files/usr/local/etc/nsd/nsd.conf.authoritative_nameserver create mode 100644 files/usr/local/etc/php-fpm.conf.common create mode 100644 files/usr/local/etc/php-fpm.d/davical.conf.dav_server create mode 100644 files/usr/local/etc/php-fpm.d/ttrss.conf.ttrss_server create mode 100644 files/usr/local/etc/php.ini.common create mode 100644 files/usr/local/etc/prosody/prosody.cfg.lua.xmpp_server create mode 100644 files/usr/local/etc/rc.conf.d/vaultwarden.bitwarden_server create mode 100644 files/usr/local/etc/rc.d/ttrssd.ttrss_server create mode 100644 files/usr/local/etc/ssh/sshd_config.d/acmeproxy.conf.common create mode 100644 files/usr/local/etc/sudoers.d/acme.asterisk_server create mode 100644 files/usr/local/etc/sudoers.d/acme.public_webserver create mode 100644 files/usr/local/etc/sudoers.d/acme.xmpp_server create mode 100644 files/usr/local/etc/turnserver.conf.turn_server create mode 100644 files/usr/local/etc/znc/configs/znc.conf.znc_server create mode 100644 files/usr/local/etc/znc/moddata/cyrusauth/.registry.znc_server create mode 100644 files/usr/local/lib/sasl2/znc.conf.znc_server create mode 100644 files/usr/local/libexec/prosody-acme-proxy.xmpp_server create mode 100644 files/usr/local/libexec/prosody-update-roster.xmpp_server create mode 100644 files/usr/local/www/davical/config/administration.yml.dav_server create mode 100644 files/usr/local/www/davical/config/config.php.dav_server create mode 100644 files/usr/local/www/tt-rss/config.php.ttrss_server create mode 100644 files/usr/local/www/tt-rss/plugins.local/auth_idm/init.php.ttrss_server create mode 100644 lib/60-postgres create mode 100644 scripts/hostclass/asterisk_server create mode 100644 scripts/hostclass/authoritative_nameserver create mode 100644 scripts/hostclass/bitwarden_server create mode 100644 scripts/hostclass/dav_server create mode 100644 scripts/hostclass/public_webserver create mode 100644 scripts/hostclass/ttrss_server create mode 100644 scripts/hostclass/turn_server create mode 100644 scripts/hostclass/xmpp_server create mode 100644 scripts/hostclass/znc_server delete mode 100644 scripts/hostname/rlaptop1 create mode 100644 scripts/hostname/znc1 create mode 100644 site/scripts/hostname/rlaptop1 create mode 100644 vars/hostclass/asterisk_server create mode 100644 vars/hostclass/authoritative_nameserver create mode 100644 vars/hostclass/bitwarden_server create mode 100644 vars/hostclass/dav_server create mode 100644 vars/hostclass/postgresql_server create mode 100644 vars/hostclass/public_webserver create mode 100644 vars/hostclass/ttrss_server create mode 100644 vars/hostclass/turn_server create mode 100644 vars/hostclass/xmpp_server create mode 100644 vars/hostclass/znc_server create mode 100644 vars/hostname/bitwarden1 create mode 100644 vars/hostname/dav1 create mode 100644 vars/hostname/ns1 create mode 100644 vars/hostname/pbx1 create mode 100644 vars/hostname/postgres1 create mode 100644 vars/hostname/ttrss1 create mode 100644 vars/hostname/turn1 create mode 100644 vars/hostname/www1 create mode 100644 vars/hostname/xmpp1 diff --git a/files/etc/cron.d/davical.dav_server b/files/etc/cron.d/davical.dav_server new file mode 100644 index 0000000..73f0278 --- /dev/null +++ b/files/etc/cron.d/davical.dav_server @@ -0,0 +1,2 @@ +MAILTO=root +0,15,30,45 * * * * ${nginx_user} ${davical_repo_dir}/scripts/cron-sync-ldap.php ${fqdn} diff --git a/files/etc/cron.d/prosody.xmpp_server b/files/etc/cron.d/prosody.xmpp_server new file mode 100644 index 0000000..b95f010 --- /dev/null +++ b/files/etc/cron.d/prosody.xmpp_server @@ -0,0 +1,3 @@ +MAILTO=root +0 0 * * * * ${prosody_local_user} /usr/local/libexec/prosody-acme-proxy -q ${prosody_user}@${prosody_acme_host} ${prosody_domains} +0 0 * * * * ${prosody_local_user} /usr/local/libexec/prosody-update-roster ${prosody_access_role} > ${prosody_roster_path} diff --git a/files/etc/pam.d/znc.znc_server b/files/etc/pam.d/znc.znc_server new file mode 100644 index 0000000..6479aca --- /dev/null +++ b/files/etc/pam.d/znc.znc_server @@ -0,0 +1,2 @@ +auth required /usr/local/lib/pam_ldap.so +account required /usr/local/lib/pam_ldap.so diff --git a/files/usr/local/etc/asterisk/extensions.conf.asterisk_server b/files/usr/local/etc/asterisk/extensions.conf.asterisk_server new file mode 100644 index 0000000..301fe66 --- /dev/null +++ b/files/usr/local/etc/asterisk/extensions.conf.asterisk_server @@ -0,0 +1,5 @@ +[public] +exten => _X.,1,Hangup(3) + +[default] +exten => _X.,1,Hangup(3) diff --git a/files/usr/local/etc/asterisk/logger.conf.asterisk_server b/files/usr/local/etc/asterisk/logger.conf.asterisk_server new file mode 100644 index 0000000..3bf2a53 --- /dev/null +++ b/files/usr/local/etc/asterisk/logger.conf.asterisk_server @@ -0,0 +1,3 @@ +[logfiles] +console => notice,warning,error +syslog.daemon => notice,warning,error,security,verbose1 diff --git a/files/usr/local/etc/asterisk/pjsip.conf.asterisk_server b/files/usr/local/etc/asterisk/pjsip.conf.asterisk_server new file mode 100644 index 0000000..0f83a81 --- /dev/null +++ b/files/usr/local/etc/asterisk/pjsip.conf.asterisk_server @@ -0,0 +1,26 @@ +[transport-defaults](!) +type = transport +bind = 0.0.0.0 +local_net = 127.0.0.0/8 +local_net = 10.0.0.0/8 +local_net = 172.16.0.0/12 +local_net = 192.168.0.0/16 +external_media_address = ${asterisk_public_ip} +external_signaling_address = ${asterisk_public_ip} + +[transport-udp](transport-defaults) +protocol = udp + +[transport-tcp](transport-defaults) +protocol = tcp + +[transport-tls](transport-defaults) +protocol = tls +bind = 0.0.0.0:5061 +method = tlsv1_2 +cert_file = ${asterisk_public_tls_cert} +priv_key_file = ${asterisk_public_tls_key} +ca_list_file = ${ca_root_nss_bundle} +verify_client = no +verify_server = yes +allow_reload = yes diff --git a/files/usr/local/etc/asterisk/pjsip_wizard.conf.asterisk_server b/files/usr/local/etc/asterisk/pjsip_wizard.conf.asterisk_server new file mode 100644 index 0000000..1de448f --- /dev/null +++ b/files/usr/local/etc/asterisk/pjsip_wizard.conf.asterisk_server @@ -0,0 +1,65 @@ +;;;;;;;;;;; +; Trunks +;;;;;;;;;;; + +[trunk-defaults](!) +type = wizard +sends_auth = yes +sends_registrations = yes +endpoint/rtp_symmetric = yes +endpoint/rewrite_contact = yes +endpoint/send_rpid = yes +endpoint/from_domain = ${asterisk_sip_domain} +endpoint/allow = !all,ulaw +registration/max_retries = 4294967295 +registration/auth_rejection_permanent = no +aor/qualify_frequency = 30 + +$(for trunk in ${asterisk_trunks:-}; do + eval "trunk_proto=\${asterisk_trunk_${trunk}_proto:-'tcp'}" + eval "trunk_remote=\${asterisk_trunk_${trunk}_remote}" + eval "trunk_username=\${asterisk_trunk_${trunk}_username}" + eval "trunk_password=\${asterisk_trunk_${trunk}_password}" + eval "trunk_context=\${asterisk_trunk_${trunk}_context}" + echo "\ +[${trunk}](trunk-defaults) +transport = transport-${trunk_proto} +remote_hosts = ${trunk_remote} +endpoint/context = ${trunk_context} +endpoint/media_encryption = no +outbound_auth/username = ${trunk_username} +outbound_auth/password = ${trunk_password} +"; done) + + +[extension-defaults](!) +type = wizard +accepts_registrations = yes +accepts_auth = yes +aor/remove_existing = yes +endpoint/allow = !all,g722,ulaw +endpoint/from_domain = ${asterisk_sip_domain} +endpoint/subscribe_context = subscribe + +$(for ext in ${asterisk_exts:-}; do + eval "ext_context=\${asterisk_ext_${ext}_context}" + eval "ext_password=\${asterisk_ext_${ext}_password}" + eval "ext_max_contacts=\${asterisk_ext_${ext}_max_contacts:-1}" + eval "ext_qualify_freq=\${asterisk_ext_${ext}_qualify_freq:-30}" + eval "ext_qualify_timeout=\${asterisk_ext_${ext}_qualify_timeout:-3.0}" + eval "ext_direct_media=\${asterisk_ext_${ext}_direct_media:-yes}" + eval "ext_cid_name=\${asterisk_ext_${ext}_cid_name}" + eval "ext_cid_number=\${asterisk_ext_${ext}_cid_number:-$ext}" + eval "ext_mailbox=\${asterisk_ext_${ext}_mailbox:-$ext}" + echo "\ +[${ext}](extension-defaults) +endpoint/context = ${ext_context} +endpoint/mailboxes = ${ext_mailbox}@default +endpoint/callerid = ${ext_cid_name} <${ext_cid_number}> +inbound_auth/username = ${ext} +inbound_auth/password = ${ext_password} +aor/max_contacts = ${ext_max_contacts} +aor/qualify_frequency = ${ext_qualify_freq} +aor/qualify_timeout = ${ext_qualify_timeout} +endpoint/direct_media = ${ext_direct_media} +"; done) diff --git a/files/usr/local/etc/asterisk/queues.conf.asterisk_server b/files/usr/local/etc/asterisk/queues.conf.asterisk_server new file mode 100644 index 0000000..87b8ed4 --- /dev/null +++ b/files/usr/local/etc/asterisk/queues.conf.asterisk_server @@ -0,0 +1,31 @@ +[general] +persistentmembers = yes +autofill = yes +monitor-type = MixMonitor +shared_lastcall = yes +log_membername_as_agent = yes + +$(for queue in ${asterisk_queues:-}; do + eval "queue_strategy=\${asterisk_queue_${queue}_strategy}" + eval "queue_timeout=\${asterisk_queue_${queue}_timeout:-15}" + eval "queue_retry=\${asterisk_queue_${queue}_retry:-5}" + eval "queue_ringinuse=\${asterisk_queue_${queue}_ringinuse:-yes}" + eval "queue_members=\${asterisk_queue_${queue}_members}" + echo "\ +[${queue}] +strategy = ${queue_strategy} +timeout = ${queue_timeout} +retry = ${queue_retry} +timeoutpriority = app +announce-frequency = 0 +announce-holdtime = no +announce-position = no +periodic-announce-frequency = 0 +joinempty = yes +leavewhenempty = no +ringinuse = ${queue_ringinuse} +timeoutrestart = yes" +for member in $queue_members; do + eval "member_name=\${asterisk_ext_${member}_cid_name}" + echo "member => PJSIP/${member},0,${member_name},PJSIP/${member}" +done; done) diff --git a/files/usr/local/etc/asterisk/rtp.conf.asterisk_server b/files/usr/local/etc/asterisk/rtp.conf.asterisk_server new file mode 100644 index 0000000..d16d1f0 --- /dev/null +++ b/files/usr/local/etc/asterisk/rtp.conf.asterisk_server @@ -0,0 +1,3 @@ +[general] +rtpstart=${asterisk_rtp_start_port} +rtpend=${asterisk_rtp_end_port} diff --git a/files/usr/local/etc/asterisk/voicemail.conf.asterisk_server b/files/usr/local/etc/asterisk/voicemail.conf.asterisk_server new file mode 100644 index 0000000..c67559f --- /dev/null +++ b/files/usr/local/etc/asterisk/voicemail.conf.asterisk_server @@ -0,0 +1,31 @@ +[general] +format=wav49|gsm|wav + +serveremail=${asterisk_from_email} +attach=yes +maxmsg=100 +maxsecs=300 +maxgreet=60 +skipms=3000 +maxsilence=10 +silencethreshold=128 +maxlogins=3 + +emailsubject=New voicemail \${VM_MSGNUM} in mailbox \${VM_MAILBOX} +emailbody=Hi \${VM_NAME},\n\nYou have a new voicemail in mailbox \${VM_MAILBOX}.\n\nFrom: \${VM_CALLERID}\nDate: \${VM_DATE}\nDuration: \${VM_DUR}\nMessage Number: \${VM_MSGNUM} +emaildateformat=%A, %B %d, %Y at %r + +tz=myzone +locale=${asterisk_locale} +minpassword=4 + +[zonemessages] +myzone=${asterisk_timezone}|'vm-received' Q 'digits/at' IMp + +[default] +$(for mailbox in ${asterisk_mailboxes:-}; do + eval "mailbox_password=\${asterisk_mailbox_${mailbox}_password:-${asterisk_default_mailbox_password}}" + eval "mailbox_name=\${asterisk_mailbox_${mailbox}_name:-}" + eval "mailbox_email=\${asterisk_mailbox_${mailbox}_email:-}" + echo "${mailbox} => ${mailbox_password},${mailbox_name},${mailbox_email},,," +done) diff --git a/files/usr/local/etc/dovecot/rspamd.conf.sh.imap_server b/files/usr/local/etc/dovecot/rspamd.conf.sh.imap_server new file mode 100644 index 0000000..c1293e4 --- /dev/null +++ b/files/usr/local/etc/dovecot/rspamd.conf.sh.imap_server @@ -0,0 +1,5 @@ +#!/bin/sh + +RSPAMD_HOST="${rspamd_host}.${domain}" +RSPAMD_PASSWORD="${rspamd_rw_password}" +RSPAMD_KEY="${rspamd_pubkey}" diff --git a/files/usr/local/etc/nginx/fastcgi_params.common b/files/usr/local/etc/nginx/fastcgi_params.common new file mode 100644 index 0000000..d0a6c69 --- /dev/null +++ b/files/usr/local/etc/nginx/fastcgi_params.common @@ -0,0 +1,31 @@ +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param PATH_INFO $fastcgi_path_info; +fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param REQUEST_SCHEME $scheme; +fastcgi_param HTTPS $https if_not_empty; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $host; +fastcgi_param REMOTE_USER $remote_user if_not_empty; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; + +# Protect against HTTPoxy vuln +fastcgi_param HTTP_PROXY ""; diff --git a/files/usr/local/etc/nginx/nginx.conf.common b/files/usr/local/etc/nginx/nginx.conf.common index 1da7c3c..98ff9f9 100644 --- a/files/usr/local/etc/nginx/nginx.conf.common +++ b/files/usr/local/etc/nginx/nginx.conf.common @@ -33,8 +33,22 @@ http { ssl_session_timeout 1d; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; - ssl_protocols TLSv1.3; - ssl_prefer_server_ciphers off; +$(if [ "${nginx_public:-}" = true ]; then < + AllowIRC = false + AllowWeb = true + IPv4 = true + IPv6 = false + Host = 127.0.0.1 + Port = ${znc_http_port} + SSL = false + + + + AllowIRC = true + AllowWeb = false + IPv4 = true + IPv6 = true + Port = ${znc_irc_port} + SSL = true + + + + Admin = true + Nick = znc_admin + AltNick = znc_admin_ + Ident = znc_admin + RealName = ZNC Administrator + + + Hash = :: + Method = MD5 + Salt = :: + + + + + Admin = false + Nick = znc_user + AltNick = znc_user_ + Ident = znc_user + RealName = ZNC User + MaxNetworks = ${znc_max_networks} + LoadModule = chansaver + + + Hash = :: + Method = MD5 + Salt = :: + + diff --git a/files/usr/local/etc/znc/moddata/cyrusauth/.registry.znc_server b/files/usr/local/etc/znc/moddata/cyrusauth/.registry.znc_server new file mode 100644 index 0000000..539fee0 --- /dev/null +++ b/files/usr/local/etc/znc/moddata/cyrusauth/.registry.znc_server @@ -0,0 +1,2 @@ +CloneUser ${znc_clone_user} +CreateUser yes diff --git a/files/usr/local/lib/sasl2/znc.conf.znc_server b/files/usr/local/lib/sasl2/znc.conf.znc_server new file mode 100644 index 0000000..f272cc7 --- /dev/null +++ b/files/usr/local/lib/sasl2/znc.conf.znc_server @@ -0,0 +1,3 @@ +mech_list: plain login +pwcheck_method: saslauthd +saslauthd_path: ${saslauthd_runtime_dir}/mux diff --git a/files/usr/local/libexec/dovecot/sieve-pipe/report-ham.sh.imap_server b/files/usr/local/libexec/dovecot/sieve-pipe/report-ham.sh.imap_server index e09674a..b5b0d2d 100644 --- a/files/usr/local/libexec/dovecot/sieve-pipe/report-ham.sh.imap_server +++ b/files/usr/local/libexec/dovecot/sieve-pipe/report-ham.sh.imap_server @@ -1,7 +1,11 @@ #!/bin/sh -exec /usr/local/bin/rspamc \\ - --connect="${rspamd_host}.${domain}" \\ - --password="${rspamd_rw_password}" \\ - --key="${rspamd_pubkey}" \\ +set -e + +. /usr/local/etc/dovecot/rspamd.conf.sh + +exec /usr/local/bin/rspamc \ + --connect="$RSPAMD_HOST" \ + --password="$RSPAMD_PASSWORD" \ + --key="$RSPAMD_KEY" \ learn_ham diff --git a/files/usr/local/libexec/dovecot/sieve-pipe/report-spam.sh.imap_server b/files/usr/local/libexec/dovecot/sieve-pipe/report-spam.sh.imap_server index 825113f..ec46319 100644 --- a/files/usr/local/libexec/dovecot/sieve-pipe/report-spam.sh.imap_server +++ b/files/usr/local/libexec/dovecot/sieve-pipe/report-spam.sh.imap_server @@ -1,7 +1,11 @@ #!/bin/sh -exec /usr/local/bin/rspamc \\ - --connect="${rspamd_host}.${domain}" \\ - --password="${rspamd_rw_password}" \\ - --key="${rspamd_pubkey}" \\ +set -e + +. /usr/local/etc/dovecot/rspamd.conf.sh + +exec /usr/local/bin/rspamc \ + --connect="$RSPAMD_HOST" \ + --password="$RSPAMD_PASSWORD" \ + --key="$RSPAMD_KEY" \ learn_spam diff --git a/files/usr/local/libexec/idm-ssh-authorized-keys.common b/files/usr/local/libexec/idm-ssh-authorized-keys.common index 89d2f20..ef7ba3c 100644 --- a/files/usr/local/libexec/idm-ssh-authorized-keys.common +++ b/files/usr/local/libexec/idm-ssh-authorized-keys.common @@ -7,7 +7,7 @@ use Net::LDAP; use Net::LDAP::Util qw(escape_filter_value); use Authen::SASL; -open my $fh, '<', '/usr/local/etc/openldap/ldap.conf' or quit($!); +open my $fh, '<', '/usr/local/etc/openldap/ldap.conf' or die($!); my %config; while (<$fh>) { chomp; @@ -18,9 +18,9 @@ while (<$fh>) { } close($fh); -my $mech = $config{SASL_MECH} // 'GSSAPI'; -my $uri = $config{URI} // quit('URI not specified'); -my $basedn = $config{USERS_BASE} // quit('USERS_BASE not specified'); +my $mech = $config{SASL_MECH} // 'GSSAPI'; +my $uri = $config{URI} // die("URI not specified\n"); +my $basedn = $config{USERS_BASE} // die("USERS_BASE not specified\n"); @ARGV == 1 or die "usage: $0 USERNAME\n"; my $username = $ARGV[0]; diff --git a/files/usr/local/libexec/idm-ssh-known-hosts.common b/files/usr/local/libexec/idm-ssh-known-hosts.common index 5b784d6..3bbcf65 100644 --- a/files/usr/local/libexec/idm-ssh-known-hosts.common +++ b/files/usr/local/libexec/idm-ssh-known-hosts.common @@ -29,8 +29,8 @@ while (<$fh>) { } close($fh); -my $mech = $config{SASL_MECH} // 'GSSAPI'; -my $uri = $config{URI} // quit('URI not specified'); +my $mech = $config{SASL_MECH} // 'GSSAPI'; +my $uri = $config{URI} // quit('URI not specified'); my $basedn = $config{HOSTS_BASE} // quit('HOSTS_BASE not specified'); my $conn = Net::LDAP->new($uri, version => '3') or quit($@); diff --git a/files/usr/local/libexec/prosody-acme-proxy.xmpp_server b/files/usr/local/libexec/prosody-acme-proxy.xmpp_server new file mode 100644 index 0000000..d69017b --- /dev/null +++ b/files/usr/local/libexec/prosody-acme-proxy.xmpp_server @@ -0,0 +1,54 @@ +#!/bin/sh + +# Retrieves ACME certificates from a different host over SFTP. +# Reloads prosody if any certificates were changed. + +set -eu -o pipefail + +PROSODY_USER=prosody +CERT_DIR=/usr/local/etc/prosody/certs +CHECKSUM_FILE="${CERT_DIR}/certs.md5" + +prog=$(basename "$(readlink -f "$0")") +usage="${prog} [-q] USER@TARGET_HOST DOMAIN..." + +usage(){ + printf 'usage: %s\n' "$usage" 1>&2 + exit 2 +} + +while getopts hq opt; do + case $opt in + h) usage ;; + q) exec 1>/dev/null ;; + esac +done +shift $((OPTIND - 1)) + +[ $# -ge 2 ] || usage +acmeproxy_target=$1; shift + +# Get md5 of any existing certificates. +touch "$CHECKSUM_FILE" +md5_old=$(cat "$CHECKSUM_FILE") + +# Retrieve certs from the proxy host via SFTP. +{ printf 'lcd %s\n' "$CERT_DIR" + printf 'get certs/%s.crt\n' "$@" + printf 'get certs/%s.key\n' "$@" + printf 'quit\n' +} | sftp -b - "$acmeproxy_target" + +# Get md5 of the new certificates. +md5_new=$(md5sum "$CERT_DIR"/*.crt "$CERT_DIR"/*.key | tee "$CHECKSUM_FILE") + +# If any certificates differ, reload prosody. +if [ "$md5_old" != "$md5_new" ]; then + if prosodyctl status >/dev/null 2>&1; then + prosodyctl reload + else + echo 'prosody not running, not reloading' + fi +else + echo 'certificates unchanged' +fi diff --git a/files/usr/local/libexec/prosody-update-roster.xmpp_server b/files/usr/local/libexec/prosody-update-roster.xmpp_server new file mode 100644 index 0000000..1b79747 --- /dev/null +++ b/files/usr/local/libexec/prosody-update-roster.xmpp_server @@ -0,0 +1,47 @@ +#!/usr/local/bin/perl + +use strict; +use warnings; + +use Net::LDAP; +use Authen::SASL; + +@ARGV == 1 or die "usage: $0 ROLE_NAME\n"; +my $role = $ARGV[0]; + +open my $fh, '<', '/usr/local/etc/openldap/ldap.conf' or quit($!); +my %config; +while (<$fh>) { + chomp; + next if /^#/; + my @pair = split(' ', $_, 2); + next unless (@pair == 2); + $config{$pair[0]} = $pair[1]; +} +close($fh); + +my $mech = $config{SASL_MECH} // 'GSSAPI'; +my $uri = $config{URI} // die("URI not specified\n"); +my $users_basedn = $config{USERS_BASE} // die("USERS_BASE not specified\n"); +my $roles_basedn = $config{ROLES_BASE} // die("ROLES_BASE not specified\n"); + +my $conn = Net::LDAP->new($ldap_uris, version => '3') or die "$@"; +my $sasl = Authen::SASL->new($mech); +my $status = $conn->bind(sasl => $sasl); +$status->code and die $status->error; + +my $search = $conn->search( + scope => 'sub', + base => $users_basedn, + filter => "(&(memberOf=cn=$role,$roles_basedn)(mailAddress=*))", + attrs => ['mailAddress', 'cn']); + +print "[Internal]\n"; + +foreach my $entry ($search->entries) { + my $jid = ($entry->get_value('mailAddress'))[0]; + my $cn = ($entry->get_value('cn'))[0] // $jid; + print "$jid=$cn\n"; +} + +system('prosodyctl reload'); diff --git a/files/usr/local/www/davical/config/administration.yml.dav_server b/files/usr/local/www/davical/config/administration.yml.dav_server new file mode 100644 index 0000000..fdd5da2 --- /dev/null +++ b/files/usr/local/www/davical/config/administration.yml.dav_server @@ -0,0 +1,4 @@ +admin_db_user: ${boxconf_username} +admin_db_host: ${davical_dbhost} +admin_db_name: ${davical_dbname} +app_db_user: '"${davical_username}"' diff --git a/files/usr/local/www/davical/config/config.php.dav_server b/files/usr/local/www/davical/config/config.php.dav_server new file mode 100644 index 0000000..ec2cb26 --- /dev/null +++ b/files/usr/local/www/davical/config/config.php.dav_server @@ -0,0 +1,49 @@ +pg_connect[] = 'dbname=${davical_dbname} user=${davical_username} host=${davical_dbhost}'; +\$c->admin_email = '${davical_admin_email}'; + +\$c->restrict_setup_to_admin = true; + +\$c->home_calendar_name = 'calendar'; +\$c->home_addressbook_name = 'addressbook'; +\$c->default_privileges = array('read-free-busy', 'schedule-deliver'); +\$c->external_refresh = 60; +\$c->default_locale = 'en'; +\$c->allow_get_email_visibility = true; + +\$c->trust_x_forwarded = true; + +\$c->authenticate_hook['call'] = 'LDAP_check'; +\$c->authenticate_hook['config'] = array( + 'uri' => '${ldap_uri}', + 'host' => '${ldap_hosts}', + 'port' => '389', + 'sasl' => 'yes', + 'sasl_mech' => 'GSSAPI', + 'baseDNUsers' => '${users_basedn}', + 'baseDNGroups' => '${groups_basedn}', + 'scope' => 'onelevel', + 'protocolVersion' => 3, + 'optReferrals' => 0, + 'filterUsers' => '(memberOf=cn=${davical_access_role},${roles_basedn})', + 'filterGroups' => '(objectclass=groupOfMembers)', + 'mapping_field' => array('username' => 'uid', + 'modified' => 'modifyTimestamp', + 'fullname' => 'cn', + 'email' => 'mailAddress'), + 'group_mapping_field' => array('name' => 'cn', + 'fullname' => 'cn', + 'modified' => 'modifyTimestamp', + 'email' => 'mailAddress', + 'members' => 'member'), + 'group_member_dnfix' => true, + 'default_value' => array('date_format_type' => 'I','locale' => 'en'), + 'format_updated' => array('Y' => array(0,4), + 'm' => array(4,2), + 'd' => array(6,2), + 'H' => array(8,2), + 'M' => array(10,2), + 'S' => array(12,2)), + 'i_use_mode_kerberos' => 'i_know_what_i_am_doing', +); +include_once('drivers_ldap.php'); diff --git a/files/usr/local/www/tt-rss/config.php.ttrss_server b/files/usr/local/www/tt-rss/config.php.ttrss_server new file mode 100644 index 0000000..3598ef2 --- /dev/null +++ b/files/usr/local/www/tt-rss/config.php.ttrss_server @@ -0,0 +1,28 @@ +add_hook($host::HOOK_AUTH_USER, $this); + + Config::add(self::AUTH_IDM_URI, '', Config::T_STRING); + Config::add(self::AUTH_IDM_STARTTLS, false, Config::T_BOOL); + Config::add(self::AUTH_IDM_BASEDN, '', Config::T_STRING); + Config::add(self::AUTH_IDM_SCOPE, 'sub', Config::T_STRING); + Config::add(self::AUTH_IDM_FILTER, '', Config::T_STRING); + Config::add(self::AUTH_IDM_ADMIN_FILTER, '', Config::T_STRING); + Config::add(self::AUTH_IDM_USERNAME_ATTR, 'uid', Config::T_STRING); + Config::add(self::AUTH_IDM_FULLNAME_ATTR, 'cn', Config::T_STRING); + Config::add(self::AUTH_IDM_EMAIL_ATTR, 'mail', Config::T_STRING); + } + + private function ldap_get_user($username, $filter = null) { + switch ($this->scope) { + case 'sub': + $searchfunc = 'ldap_search'; break; + case 'one': + $searchfunc = 'ldap_list'; break; + case 'base': + $searchfunc = 'ldap_read'; break; + default: + Logger::log(E_USER_ERROR, "auth_idm: invalid search scope: $scope"); + return null; + } + + $uid_filter = '(' + . ldap_escape($this->username_attr, '', LDAP_ESCAPE_FILTER) + . '=' + . ldap_escape($username, '', LDAP_ESCAPE_FILTER) + . ')'; + + if (empty($filter)) { + $filter = $uid_filter; + } else { + $filter = "(&$filter$uid_filter)"; + } + + $results = $searchfunc($this->conn, $this->basedn, $filter, [$this->fullname_attr, $this->email_attr]); + if ($results && ldap_count_entries($this->conn, $results) == 1) { + if ($entry = ldap_first_entry($this->conn, $results)) { + if ($dn = ldap_get_dn($this->conn, $entry)) { + if ($attrs = ldap_get_attributes($this->conn, $entry)) { + return array( + 'dn' => $dn, + 'email' => $attrs[$this->email_attr][0], + 'fullname' => $attrs[$this->fullname_attr][0] + ); + } + } + } + } + return null; + } + + function authenticate($username = null, $password = null, $service = '') { + $this->basedn = Config::get(self::AUTH_IDM_BASEDN); + $this->scope = Config::get(self::AUTH_IDM_SCOPE); + $this->username_attr = Config::get(self::AUTH_IDM_USERNAME_ATTR); + $this->fullname_attr = Config::get(self::AUTH_IDM_FULLNAME_ATTR); + $this->email_attr = Config::get(self::AUTH_IDM_EMAIL_ATTR); + $uri = Config::get(self::AUTH_IDM_URI); + $starttls = Config::get(self::AUTH_IDM_STARTTLS); + $filter = Config::get(self::AUTH_IDM_FILTER); + $admin_filter = Config::get(self::AUTH_IDM_ADMIN_FILTER); + + // Get ldap connection handle. + if (!$this->conn = ldap_connect($uri)) { + return false; + } + + // Set protocol version 3. + if (!ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3)) { + return false; + } + + // Bind using kerberos credentials from the environment. + if (!ldap_sasl_bind($this->conn, null, null, 'GSSAPI')) { + return false; + } + + // Initiate STARTTLS (if requested) + if ($starttls and !ldap_start_tls($this->conn)) { + return false; + } + + // If REMOTE_USER was set by the webserver, use that. + if (!empty($_SERVER['REMOTE_USER'])) { + $username = $_SERVER['REMOTE_USER']; + } elseif (empty($username)) { + return false; + } + + $is_admin = false; + $user = null; + + // First, check if the ADIN_FILTER matches (if set). + if (!empty($admin_filter)) { + $user = $this->ldap_get_user($username, $admin_filter); + isset($user) && $is_admin = true; + } + + // If ADMIN_FILTER didn't match, try FILTER. + if (!isset($user)) { + $user = $this->ldap_get_user($username, $filter); + } + + // If no matching user from LDAP, reject. + if (!isset($user)) { + return false; + } + + // If webserver didn't validate the password, try an LDAP bind with the provided creds. + if (empty($_SERVER['REMOTE_USER']) and !ldap_bind($this->conn, $user['dn'], $password)) { + return false; + } + + // Get the TTRSS internal user ID. + if (!($userid = $this->auto_create_user($username))) { + return false; + } + + // Populate user details using the LDAP attributes. + if (Config::get(Config::AUTH_AUTO_CREATE)) { + if (!empty($user['fullname'])) { + $sth = $this->pdo->prepare('UPDATE ttrss_users SET full_name = ? WHERE id = ?'); + $sth->execute([$user['fullname'], $userid]); + } + + if (!empty($user['email'])) { + $sth = $this->pdo->prepare('UPDATE ttrss_users SET email = ? WHERE id = ?'); + $sth->execute([$user['email'], $userid]); + } + + $sth = $this->pdo->prepare('UPDATE ttrss_users SET access_level = ? WHERE id = ?'); + $sth->execute([$is_admin ? 10 : 0, $userid]); + } + + return $userid; + } + + function api_version() { + return 2; + } +} diff --git a/files/var/db/postgres/data16/postgresql.conf.postgresql_server b/files/var/db/postgres/data16/postgresql.conf.postgresql_server index e95104f..55874e7 100644 --- a/files/var/db/postgres/data16/postgresql.conf.postgresql_server +++ b/files/var/db/postgres/data16/postgresql.conf.postgresql_server @@ -5,7 +5,7 @@ krb_server_keyfile = 'FILE:${postgres_keytab}' krb_caseins_users = on ssl = on -ssl_ca_file = '${ca_cert}' +ssl_ca_file = '${site_cacert_path}' ssl_cert_file = '${postgres_tls_cert}' ssl_key_file = '${postgres_tls_key}' ssl_min_protocol_version = 'TLSv1.3' diff --git a/lib/60-ldap b/lib/60-ldap index d262849..249fed0 100644 --- a/lib/60-ldap +++ b/lib/60-ldap @@ -11,7 +11,7 @@ ldap_add(){ if [ "${BOXCONF_LDAP_SASL:-}" = true ]; then ldapadd -Q "$@" else - ldapadd -ZZ -D "$boxconf_dn" -w "$boxconf_password" "$@" + ldapadd -ZZ -x -D "$boxconf_dn" -w "$boxconf_password" "$@" fi } fi @@ -25,7 +25,7 @@ ldap_modify(){ if [ "${BOXCONF_LDAP_SASL:-}" = true ]; then ldapmodify -Q "$@" else - ldapmodify -ZZ -D "$boxconf_dn" -w "$boxconf_password" "$@" + ldapmodify -ZZ -x -D "$boxconf_dn" -w "$boxconf_password" "$@" fi } } @@ -36,7 +36,7 @@ ldap_delete(){ if [ "${BOXCONF_LDAP_SASL:-}" = true ]; then ldapdelete -Q "$@" else - ldapdelete -ZZ -D "$boxconf_dn" -w "$boxconf_password" "$@" + ldapdelete -ZZ -x -D "$boxconf_dn" -w "$boxconf_password" "$@" fi } @@ -46,7 +46,7 @@ ldap_search(){ if [ "${BOXCONF_LDAP_SASL:-}" = true ]; then ldapsearch -QLLL "$@" else - ldapsearch -o ldif_wrap=no -LLLZZ -D "$boxconf_dn" -w "$boxconf_password" "$@" + ldapsearch -o ldif_wrap=no -x -LLLZZ -D "$boxconf_dn" -w "$boxconf_password" "$@" fi } @@ -86,3 +86,13 @@ ldap_dn_exists(){ # $1 = DN ldap_search -s base -b "$1" dn > /dev/null 2>&1 } + +ldap_passwd(){ + # Set the userPassword attribute on a DN. + # $1 = DN, $2 = password + if [ "${BOXCONF_LDAP_SASL:-}" = true ]; then + ldappasswd -Q -s "$2" "$1" + else + ldappasswd -ZZ -x -D "$boxconf_dn" -w "$boxconf_password" -s "$2" "$1" + fi +} diff --git a/lib/60-postgres b/lib/60-postgres new file mode 100644 index 0000000..af37c27 --- /dev/null +++ b/lib/60-postgres @@ -0,0 +1,24 @@ +#!/bin/sh + +postgres_run(){ + PGSSLMODE=require PGPASSWORD="$boxconf_password" psql \ + --no-align \ + --echo-all \ + --tuples-only \ + --username="$boxconf_username" \ + -v ON_ERROR_STOP=1 \ + "$@" +} +postgres_create_role(){ + # $1 = postgres_host, $2 = username + cat < /dev/null 2>&1 < /dev/null diff --git a/scripts/hostclass/dav_server b/scripts/hostclass/dav_server new file mode 100644 index 0000000..b7391bd --- /dev/null +++ b/scripts/hostclass/dav_server @@ -0,0 +1,139 @@ +#!/bin/sh + +: ${davical_username:='s-davical'} +: ${davical_dbname:='davical'} +: ${davical_dbhost:="$postgres_host"} +: ${davical_admin_email:="$root_mail_alias"} +: ${davical_access_role:='dav-access'} +: ${davical_repo:='https://gitlab.com/davical-project/davical.git'} +: ${davical_branch:='master'} +: ${davical_awl_repo:='https://gitlab.com/davical-project/awl.git'} +: ${davical_awl_branch:='master'} + +davical_repo_dir=/usr/local/www/davical +davical_awl_repo_dir=/usr/local/share/awl +davical_webroot="${davical_repo_dir}/htdocs" + +davical_https_cert="${nginx_conf_dir}/davical.crt" +davical_https_key="${nginx_conf_dir}/davical.key" +davical_https_cacert="${nginx_conf_dir}/davical.ca.crt" +davical_keytab="${keytab_dir}/davical.keytab" +davical_client_keytab="${keytab_dir}/davical.client.keytab" +davical_fpm_socket=/var/run/fpm-davical.sock + +davical_psql(){ + postgres_run --host="$davical_dbhost" --dbname="$davical_dbname" "$@" +} + +# Install required packages. +pkg install -y \ + git-lite \ + nginx \ + php${php_version} \ + php${php_version}-calendar \ + php${php_version}-curl \ + php${php_version}-gettext \ + php${php_version}-iconv \ + php${php_version}-ldap \ + php${php_version}-opcache \ + php${php_version}-pdo_pgsql \ + php${php_version}-pgsql \ + php${php_version}-session \ + php${php_version}-xml \ + p5-DBD-Pg \ + p5-DBI \ + p5-YAML + +# Install davical from git. +[ -d "$davical_repo_dir" ] || git clone "$davical_repo" "$davical_repo_dir" +[ -d "$davical_awl_repo_dir" ] || git clone "$davical_awl_repo" "$davical_awl_repo_dir" + +# Update git repos. +git -C "$davical_repo_dir" pull --ff-only +git -C "$davical_repo_dir" switch "$davical_branch" +git -C "$davical_awl_repo_dir" pull --ff-only +git -C "$davical_awl_repo_dir" switch "$davical_awl_branch" + +# Create davical principal and keytab. +add_principal -nokey -x "containerdn=${robots_basedn}" "$davical_username" + +ktadd -k "$davical_client_keytab" "$davical_username" +chgrp "$nginx_user" "$davical_client_keytab" +chmod 640 "$davical_client_keytab" + +nginx_uid=$(id -u "$nginx_user") +install_directory -o "$nginx_user" -m 0700 "/var/krb5/user/${nginx_uid}" +ln -snfv "$davical_client_keytab" "/var/krb5/user/${nginx_uid}/client.keytab" + +# Create HTTP principal and keytab. +add_principal -nokey -x "containerdn=${services_basedn}" "HTTP/${fqdn}" + +ktadd -k "$davical_keytab" "HTTP/${fqdn}" +chgrp "$nginx_user" "$davical_keytab" +chmod 640 "$davical_keytab" + +ln -snfv "$davical_keytab" "/var/krb5/user/${nginx_uid}/keytab" + +# Generate davical configuration. +install_template -m 0644 \ + "${davical_repo_dir}/config/config.php" \ + "${davical_repo_dir}/config/administration.yml" + +# Create postgres user and database. +postgres_create_role "$davical_dbhost" "$davical_username" +postgres_create_database "$davical_dbhost" "$davical_dbname" + +# Initialize davical database. +if ! davical_psql -c 'SELECT 1 FROM awl_db_revision'; then + davical_psql \ + -f "${davical_awl_repo_dir}/dba/awl-tables.sql" \ + -f "${davical_awl_repo_dir}/dba/schema-management.sql" \ + -f "${davical_repo_dir}/dba/davical.sql" + + PGPASSWORD="$boxconf_password" PGSSLMODE=require \ + "${davical_repo_dir}/dba/update-davical-database" --debug --nopatch + + davical_psql -f "${davical_repo_dir}/dba/base-data.sql" + + PGPASSWORD="$boxconf_password" PGSSLMODE=require \ + "${davical_repo_dir}/dba/update-davical-database" --debug + + davical_psql -c "delete from usr where username = 'admin'" +fi + +# Copy TLS certificate for nginx. +install_certificate nginx "$davical_https_cert" +install_certificate_key nginx "$davical_https_key" + +# Generate nginx configuration. +install_file -m 0644 "${nginx_conf_dir}/fastcgi_params" +install_template -m 0644 \ + "${nginx_conf_dir}/nginx.conf" \ + "${nginx_conf_dir}/vhosts.conf" + +# Generate php-fpm configuration. +install_file -m 0644 \ + /usr/local/etc/php.ini \ + /usr/local/etc/php-fpm.conf +install_template -m 0644 \ + /usr/local/etc/php-fpm.d/davical.conf +> /usr/local/etc/php-fpm.d/www.conf + +# Enable and start daemons. +sysrc -v \ + nginx_enable=YES \ + php_fpm_enable=YES +service nginx restart +service php_fpm restart + +# Sync groups from LDAP. +su -m "$nginx_user" -c "${davical_repo_dir}/scripts/cron-sync-ldap.php ${fqdn}" + +# Create cron job for keeping LDAP groups up-to-date. +install_template -m 0644 /etc/cron.d/davical + +# Create access role. +ldap_add "cn=${davical_access_role},${roles_basedn}" < /dev/null 2>&1 < /dev/null psql -c "DO \$$ BEGIN - IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${boxconf_user}') THEN - CREATE ROLE \"${boxconf_user}\" WITH LOGIN SUPERUSER; + IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${boxconf_username}') THEN + CREATE ROLE \"${boxconf_username}\" WITH LOGIN SUPERUSER; END IF; END \$$" diff --git a/scripts/hostclass/public_webserver b/scripts/hostclass/public_webserver new file mode 100644 index 0000000..ccf5991 --- /dev/null +++ b/scripts/hostclass/public_webserver @@ -0,0 +1,42 @@ +#!/bin/sh + +# acme_certs='site1 site2' +# acme_site1_domains='example.net example.com' + +: ${acme_certs:=''} + +vhosts_dir=/usr/local/www + +# Install packages. +pkg install -y \ + nginx \ + rsync + +# Create ZFS dataset for webroots. +create_dataset -o "mountpoint=${vhosts_dir}" "${state_dataset}/vhosts" + +# Configure nginx. +install_template -m 0644 /usr/local/etc/nginx/nginx.conf +install -Cv -m 0644 /dev/null /usr/local/etc/nginx/vhosts.conf +sysrc -v nginx_enable=YES +service nginx restart + +# Acquire public TLS certificates. +install_template -m 0600 /usr/local/etc/sudoers.d/acme +for cert in $acme_certs; do + eval "acme_domains=\${acme_${cert}_domains}" + acme_install_certificate \ + -C "${acme_cert_dir}/${cert}.ca.crt" \ + -c "${acme_cert_dir}/${cert}.crt" \ + -k "${acme_cert_dir}/${cert}.key" \ + -g "$nginx_user" \ + -r 'sudo service nginx reload' \ + $acme_domains +done + +# Now that we have the ACME certs, add the vhosts. +install_template -m 0644 /usr/local/etc/nginx/vhosts.conf +service nginx restart + +# If any acmeproxy_domains were specified, setup the SFTP proxy. +acme_setup_proxy diff --git a/scripts/hostclass/smtp_server/10-rspamd b/scripts/hostclass/smtp_server/10-rspamd index 094dc8a..1794e04 100644 --- a/scripts/hostclass/smtp_server/10-rspamd +++ b/scripts/hostclass/smtp_server/10-rspamd @@ -21,8 +21,8 @@ rspamd_redis_sock=/var/run/redis/rspamd.sock rspamd_bayes_redis_sock=/var/run/redis/rspamd-bayes.sock rspamd_redis_data_dir="${redis_data_dir}/rspamd" rspamd_bayes_redis_data_dir="${redis_data_dir}/rspamd-bayes" -rspamd_tls_cert=/usr/local/etc/nginx/rspamd.crt -rspamd_tls_key=/usr/local/etc/nginx/rspamd.key +rspamd_https_cert="${nginx_conf_dir}/rspamd.crt" +rspamd_https_key="${nginx_conf_dir}/rspamd.key" nginx_keytab="${keytab_dir}/nginx.keytab" pkg install -y \ @@ -97,8 +97,8 @@ chgrp "$nginx_user" "$nginx_keytab" chmod 640 "$nginx_keytab" # Copy TLS certificate for nginx. -install_certificate nginx "$rspamd_tls_cert" -install_certificate_key nginx "$rspamd_tls_key" +install_certificate nginx "$rspamd_https_cert" +install_certificate_key nginx "$rspamd_https_key" # Enable and start rspamd and nginx. sysrc -v \ diff --git a/scripts/hostclass/smtp_server/20-postfix b/scripts/hostclass/smtp_server/20-postfix index e224e9b..68ac474 100644 --- a/scripts/hostclass/smtp_server/20-postfix +++ b/scripts/hostclass/smtp_server/20-postfix @@ -52,7 +52,7 @@ install_certificate_key -m 0640 -o root -g "$postfix_user" postfix "$postfix_loc if [ "$postfix_public_fqdn" != "$fqdn" ]; then # Acquire public TLS certificate. - install_file /usr/local/etc/sudoers.d/acme + install_template -m 0600 /usr/local/etc/sudoers.d/acme acme_install_certificate \ -c "$postfix_public_tls_cert" \ -k "$postfix_public_tls_key" \ diff --git a/scripts/hostclass/ttrss_server b/scripts/hostclass/ttrss_server new file mode 100644 index 0000000..1a2104a --- /dev/null +++ b/scripts/hostclass/ttrss_server @@ -0,0 +1,137 @@ +#!/bin/sh + +: ${ttrss_username:='s-ttrss'} +: ${ttrss_dbname:='ttrss'} +: ${ttrss_dbhost:="$postgres_host"} +: ${ttrss_fqdn:="$fqdn"} +: ${ttrss_access_role:='ttrss-access'} +: ${ttrss_admin_role:='ttrss-admin'} +: ${ttrss_mail_from:="ttrss-noreply@${email_domain}"} + +ttrss_https_cert="${nginx_conf_dir}/ttrss.crt" +ttrss_https_key="${nginx_conf_dir}/ttrss.key" +ttrss_repo='https://git.tt-rss.org/fox/tt-rss.git/' +ttrss_branch=master +ttrss_repo_dir=/usr/local/www/tt-rss +ttrss_keytab="${keytab_dir}/ttrss.keytab" +ttrss_client_keytab="${keytab_dir}/ttrss.client.keytab" +ttrss_fpm_socket=/var/run/fpm-ttrss.sock + +# Install required packages. +pkg install -y \ + ca_root_nss \ + nginx \ + git-lite \ + php${php_version}-ctype \ + php${php_version}-curl \ + php${php_version}-dom \ + php${php_version}-exif \ + php${php_version}-fileinfo \ + php${php_version}-filter \ + php${php_version}-gd \ + php${php_version}-iconv \ + php${php_version}-intl \ + php${php_version}-ldap \ + php${php_version}-mbstring \ + php${php_version}-opcache \ + php${php_version}-pcntl \ + php${php_version}-pdo \ + php${php_version}-pdo_pgsql \ + php${php_version}-pgsql \ + php${php_version}-phar \ + php${php_version}-posix \ + php${php_version}-session \ + php${php_version}-simplexml \ + php${php_version}-sockets \ + php${php_version}-tokenizer \ + php${php_version}-xml \ + php${php_version}-xmlwriter \ + php${php_version}-zip + +# Create ttrss principal and keytab. +add_principal -nokey -x "containerdn=${robots_basedn}" "$ttrss_username" + +ktadd -k "$ttrss_client_keytab" "$ttrss_username" +chgrp "$nginx_user" "$ttrss_client_keytab" +chmod 640 "$ttrss_client_keytab" + +nginx_uid=$(id -u "$nginx_user") +install_directory -o "$nginx_user" -m 0700 "/var/krb5/user/${nginx_uid}" +ln -snfv "$ttrss_client_keytab" "/var/krb5/user/${nginx_uid}/client.keytab" + +# Create HTTP principal and keytab. +add_principal -nokey -x "containerdn=${services_basedn}" "HTTP/${fqdn}" + +ktadd -k "$ttrss_keytab" "HTTP/${fqdn}" +chgrp "$nginx_user" "$ttrss_keytab" +chmod 640 "$ttrss_keytab" + +ln -snfv "$ttrss_keytab" "/var/krb5/user/${nginx_uid}/keytab" + +# Install ttrss from git. +[ -d "$ttrss_repo_dir" ] || git clone "$ttrss_repo" "$ttrss_repo_dir" + +# Update git repos. +git -C "$ttrss_repo_dir" pull --ff-only +git -C "$ttrss_repo_dir" switch "$ttrss_branch" + +# Fix permissions on writable directories. +for dir in lock cache feed-icons ; do + chmod 755 "${ttrss_repo_dir}/${dir}" + chown -R "${nginx_user}:${nginx_user}" "${ttrss_repo_dir}/${dir}" +done + +# Generate config.php. +install_template -m 0644 "${ttrss_repo_dir}/config.php" + +# Create postgres user and database. +postgres_create_role "$ttrss_dbhost" "$ttrss_username" +postgres_create_database "$ttrss_dbhost" "$ttrss_dbname" "$ttrss_username" + +# Initialize the database schema. +su -m "$nginx_user" -c "${ttrss_repo_dir}/update.php --update-schema=force-yes" + +# Copy tt-rss LDAP auth plugin. +install_directory -m 0755 "${ttrss_repo_dir}/plugins.local/auth_idm" +install_file -m 0644 "${ttrss_repo_dir}/plugins.local/auth_idm/init.php" + +# Copy tt-rss rc script. +install_file -m 0555 /usr/local/etc/rc.d/ttrssd + +# Allow ttrss user to perform git queries. +git config --system --replace-all safe.directory "$ttrss_repo_dir" + +# Copy TLS certificate for nginx. +install_certificate nginx "$ttrss_https_cert" +install_certificate_key nginx "$ttrss_https_key" + +# Generate nginx configuration. +install_file -m 0644 /usr/local/etc/nginx/fastcgi_params +install_template -m 0644 \ + /usr/local/etc/nginx/nginx.conf \ + /usr/local/etc/nginx/vhosts.conf + +# Generate php-fpm configuration. +install_file -m 0644 \ + /usr/local/etc/php.ini \ + /usr/local/etc/php-fpm.conf +install_template -m 0644 \ + /usr/local/etc/php-fpm.d/ttrss.conf +> /usr/local/etc/php-fpm.d/www.conf + +# Enable and start daemons. +sysrc -v \ + nginx_enable=YES \ + php_fpm_enable=YES \ + ttrssd_enable=YES +service nginx restart +service php_fpm restart +service ttrssd restart + +# Create roles. +for role in "$ttrss_access_role" "$ttrss_admin_role"; do + ldap_add "cn=${role},${roles_basedn}" < ${prosody_roster_path}" + +# Copy prosody crontab. +install_template -m 0644 /etc/cron.d/prosody + +# Configure nginx. +install_template -m 0644 /usr/local/etc/nginx/nginx.conf +sysrc -v nginx_enable=YES +service nginx restart + +install_template -m 0600 /usr/local/etc/sudoers.d/acme +acme_install_certificate \ + -C "$prosody_https_cacert" \ + -c "$prosody_https_cert" \ + -k "$prosody_https_key" \ + -g "$nginx_user" \ + -r 'sudo service nginx reload' \ + "$prosody_public_fqdn" + +# Now that we have the ACME certs, add the nginx vhost. +install_template -m 0644 /usr/local/etc/nginx/vhosts.conf + +# Enable and start daemons. +sysrc -v prosody_enable=YES +service prosody restart +service nginx restart + +# Create access role. +ldap_add "cn=${prosody_access_role},${roles_basedn}" < 4 )); then +if (( nproc > 4 )); then nginx_worker_processes=4 else nginx_worker_processes=$nproc diff --git a/vars/hostclass/asterisk_server b/vars/hostclass/asterisk_server new file mode 100644 index 0000000..daf5fa6 --- /dev/null +++ b/vars/hostclass/asterisk_server @@ -0,0 +1,10 @@ +#!/bin/sh + +asterisk_rtp_port_start=10000 +asterisk_rtp_port_end=10999 + +allowed_tcp_ports='ssh sip sip-tls' +allowed_udp_ports="ssh sip sip-tls ${asterisk_rtp_port_start}:${asterisk_rtp_port_end}" + +acme=true +acme_standalone=true diff --git a/vars/hostclass/authoritative_nameserver b/vars/hostclass/authoritative_nameserver new file mode 100644 index 0000000..a421b7c --- /dev/null +++ b/vars/hostclass/authoritative_nameserver @@ -0,0 +1,4 @@ +#!/bin/sh + +allowed_tcp_ports='ssh domain' +allowed_udp_ports='domain' diff --git a/vars/hostclass/bitwarden_server b/vars/hostclass/bitwarden_server new file mode 100644 index 0000000..5ae7588 --- /dev/null +++ b/vars/hostclass/bitwarden_server @@ -0,0 +1,3 @@ +#!/bin/sh + +allowed_tcp_ports="ssh http https" diff --git a/vars/hostclass/dav_server b/vars/hostclass/dav_server new file mode 100644 index 0000000..2a4b250 --- /dev/null +++ b/vars/hostclass/dav_server @@ -0,0 +1,4 @@ +#!/bin/sh + +allowed_tcp_ports='ssh http https' +nginx_gssapi=true diff --git a/vars/hostclass/pkg_repository b/vars/hostclass/pkg_repository index dbd49a7..4752685 100644 --- a/vars/hostclass/pkg_repository +++ b/vars/hostclass/pkg_repository @@ -1,3 +1,4 @@ #!/bin/sh allowed_tcp_ports='ssh http' +nginx_redirect=false diff --git a/vars/hostclass/postgresql_server b/vars/hostclass/postgresql_server new file mode 100644 index 0000000..500e59b --- /dev/null +++ b/vars/hostclass/postgresql_server @@ -0,0 +1,3 @@ +#!/bin/sh + +allowed_tcp_ports='ssh postgresql' diff --git a/vars/hostclass/public_webserver b/vars/hostclass/public_webserver new file mode 100644 index 0000000..b6a9c9d --- /dev/null +++ b/vars/hostclass/public_webserver @@ -0,0 +1,5 @@ +#!/bin/sh + +allowed_tcp_ports='ssh http https' +acme=true +nginx_public=true diff --git a/vars/hostclass/ttrss_server b/vars/hostclass/ttrss_server new file mode 100644 index 0000000..2a4b250 --- /dev/null +++ b/vars/hostclass/ttrss_server @@ -0,0 +1,4 @@ +#!/bin/sh + +allowed_tcp_ports='ssh http https' +nginx_gssapi=true diff --git a/vars/hostclass/turn_server b/vars/hostclass/turn_server new file mode 100644 index 0000000..06cc6ae --- /dev/null +++ b/vars/hostclass/turn_server @@ -0,0 +1,8 @@ +#!/bin/sh + +coturn_listen_port=3478 +coturn_min_port=49152 +coturn_max_port=65535 + +allowed_tcp_ports="ssh ${coturn_listen_port}" +allowed_udp_ports="${coturn_listen_port} ${coturn_min_port}:${coturn_max_port}" diff --git a/vars/hostclass/xmpp_server b/vars/hostclass/xmpp_server new file mode 100644 index 0000000..204d1ba --- /dev/null +++ b/vars/hostclass/xmpp_server @@ -0,0 +1,5 @@ +#!/bin/sh + +acme=true +allowed_tcp_ports='ssh http https xmpp-client xmpp-server' +nginx_public=true diff --git a/vars/hostclass/znc_server b/vars/hostclass/znc_server new file mode 100644 index 0000000..7e6ad77 --- /dev/null +++ b/vars/hostclass/znc_server @@ -0,0 +1,4 @@ +#!/bin/sh + +znc_irc_port=6697 +allowed_tcp_ports="ssh http https ${znc_irc_port}" diff --git a/vars/hostname/bitwarden1 b/vars/hostname/bitwarden1 new file mode 100644 index 0000000..659336e --- /dev/null +++ b/vars/hostname/bitwarden1 @@ -0,0 +1,4 @@ +#!/bin/sh + +cnames=bitwarden +vaultwarden_fqdn="bitwarden.${domain}" diff --git a/vars/hostname/dav1 b/vars/hostname/dav1 new file mode 100644 index 0000000..cab4c08 --- /dev/null +++ b/vars/hostname/dav1 @@ -0,0 +1,3 @@ +#!/bin/sh + +cnames=dav diff --git a/vars/hostname/ns1 b/vars/hostname/ns1 new file mode 100644 index 0000000..cb59104 --- /dev/null +++ b/vars/hostname/ns1 @@ -0,0 +1,3 @@ +#!/bin/sh + +cnames=ns diff --git a/vars/hostname/pbx1 b/vars/hostname/pbx1 new file mode 100644 index 0000000..4931dd6 --- /dev/null +++ b/vars/hostname/pbx1 @@ -0,0 +1,3 @@ +#!/bin/sh + +cnames=pbx diff --git a/vars/hostname/postgres1 b/vars/hostname/postgres1 new file mode 100644 index 0000000..a38ba94 --- /dev/null +++ b/vars/hostname/postgres1 @@ -0,0 +1,4 @@ +#!/bin/sh + +memsize=$(( 8 * 1024 * 1024 * 1024)) +cnames=postgres diff --git a/vars/hostname/ttrss1 b/vars/hostname/ttrss1 new file mode 100644 index 0000000..d6fbb39 --- /dev/null +++ b/vars/hostname/ttrss1 @@ -0,0 +1,4 @@ +#!/bin/sh + +cnames=ttrss +ttrss_hostname="ttrss.${domain}" diff --git a/vars/hostname/turn1 b/vars/hostname/turn1 new file mode 100644 index 0000000..86e970a --- /dev/null +++ b/vars/hostname/turn1 @@ -0,0 +1,3 @@ +#!/bin/sh + +cnames=turn diff --git a/vars/hostname/www1 b/vars/hostname/www1 new file mode 100644 index 0000000..88a683e --- /dev/null +++ b/vars/hostname/www1 @@ -0,0 +1,5 @@ +#!/bin/sh + +cnames='www' +acmeproxy_client_group=$prosody_username +acmeproxy_client_gid=$prosody_uid diff --git a/vars/hostname/xmpp1 b/vars/hostname/xmpp1 new file mode 100644 index 0000000..e094b54 --- /dev/null +++ b/vars/hostname/xmpp1 @@ -0,0 +1,5 @@ +#!/bin/sh + +cnames=xmpp +prosody_acme_host=www1 +prosody_public_fqdn=xmpp.example.com diff --git a/vars/os/freebsd b/vars/os/freebsd index 5fae2d6..d13c84e 100644 --- a/vars/os/freebsd +++ b/vars/os/freebsd @@ -14,6 +14,7 @@ export ASSUME_ALWAYS_YES=yes keytab_dir=/var/db/keytabs nfscbd_port=7745 nginx_user=www +nginx_conf_dir=/usr/local/etc/nginx nslcd_user=nslcd php_version=82 postgresql_version=16 -- cgit v1.2.3