aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCullum Smith <cullum@sacredheartsc.com>2024-10-12 08:14:59 -0400
committerCullum Smith <cullum@sacredheartsc.com>2024-10-12 08:15:33 -0400
commit99b8524c16cc99ceeaf1ebf588f2fc0f2c0fbe0a (patch)
tree3ffa4113f23eca6cea8ff2c94ba7ce60188d943e
parent1c882c769e5476b5cb3fa294257c76165a7a6f46 (diff)
downloadinfrastructure-99b8524c16cc99ceeaf1ebf588f2fc0f2c0fbe0a.tar.gz
add a bunch of hostclasses
-rw-r--r--files/etc/cron.d/davical.dav_server2
-rw-r--r--files/etc/cron.d/prosody.xmpp_server3
-rw-r--r--files/etc/pam.d/znc.znc_server2
-rw-r--r--files/usr/local/etc/asterisk/extensions.conf.asterisk_server5
-rw-r--r--files/usr/local/etc/asterisk/logger.conf.asterisk_server3
-rw-r--r--files/usr/local/etc/asterisk/pjsip.conf.asterisk_server26
-rw-r--r--files/usr/local/etc/asterisk/pjsip_wizard.conf.asterisk_server65
-rw-r--r--files/usr/local/etc/asterisk/queues.conf.asterisk_server31
-rw-r--r--files/usr/local/etc/asterisk/rtp.conf.asterisk_server3
-rw-r--r--files/usr/local/etc/asterisk/voicemail.conf.asterisk_server31
-rw-r--r--files/usr/local/etc/dovecot/rspamd.conf.sh.imap_server5
-rw-r--r--files/usr/local/etc/nginx/fastcgi_params.common31
-rw-r--r--files/usr/local/etc/nginx/nginx.conf.common37
-rw-r--r--files/usr/local/etc/nginx/vhosts.conf.bitwarden_server36
-rw-r--r--files/usr/local/etc/nginx/vhosts.conf.dav_server55
-rw-r--r--files/usr/local/etc/nginx/vhosts.conf.smtp_server4
-rw-r--r--files/usr/local/etc/nginx/vhosts.conf.ttrss_server43
-rw-r--r--files/usr/local/etc/nginx/vhosts.conf.xmpp_server21
-rw-r--r--files/usr/local/etc/nginx/vhosts.conf.znc_server21
-rw-r--r--files/usr/local/etc/nsd/nsd.conf.authoritative_nameserver22
-rw-r--r--files/usr/local/etc/nslcd.conf.common2
-rw-r--r--files/usr/local/etc/openldap/ldap.conf.common1
-rw-r--r--files/usr/local/etc/openldap/ldap.conf.idm_server1
-rw-r--r--files/usr/local/etc/php-fpm.conf.common4
-rw-r--r--files/usr/local/etc/php-fpm.d/davical.conf.dav_server20
-rw-r--r--files/usr/local/etc/php-fpm.d/ttrss.conf.ttrss_server23
-rw-r--r--files/usr/local/etc/php.ini.common138
-rw-r--r--files/usr/local/etc/poudriere.d/pkglist.pkg_repository28
-rw-r--r--files/usr/local/etc/prosody/prosody.cfg.lua.xmpp_server106
-rw-r--r--files/usr/local/etc/rc.conf.d/vaultwarden.bitwarden_server19
-rw-r--r--files/usr/local/etc/rc.d/ttrssd.ttrss_server47
-rw-r--r--files/usr/local/etc/ssh/sshd_config.d/acmeproxy.conf.common11
-rw-r--r--files/usr/local/etc/ssh/sshd_config.freebsd2
-rw-r--r--files/usr/local/etc/sudoers.d/acme.asterisk_server1
-rw-r--r--files/usr/local/etc/sudoers.d/acme.public_webserver1
-rw-r--r--files/usr/local/etc/sudoers.d/acme.smtp_server2
-rw-r--r--files/usr/local/etc/sudoers.d/acme.xmpp_server1
-rw-r--r--files/usr/local/etc/turnserver.conf.turn_server61
-rw-r--r--files/usr/local/etc/znc/configs/znc.conf.znc_server55
-rw-r--r--files/usr/local/etc/znc/moddata/cyrusauth/.registry.znc_server2
-rw-r--r--files/usr/local/lib/sasl2/znc.conf.znc_server3
-rw-r--r--files/usr/local/libexec/dovecot/sieve-pipe/report-ham.sh.imap_server12
-rw-r--r--files/usr/local/libexec/dovecot/sieve-pipe/report-spam.sh.imap_server12
-rw-r--r--files/usr/local/libexec/idm-ssh-authorized-keys.common8
-rw-r--r--files/usr/local/libexec/idm-ssh-known-hosts.common4
-rw-r--r--files/usr/local/libexec/prosody-acme-proxy.xmpp_server54
-rw-r--r--files/usr/local/libexec/prosody-update-roster.xmpp_server47
-rw-r--r--files/usr/local/www/davical/config/administration.yml.dav_server4
-rw-r--r--files/usr/local/www/davical/config/config.php.dav_server49
-rw-r--r--files/usr/local/www/tt-rss/config.php.ttrss_server28
-rw-r--r--files/usr/local/www/tt-rss/plugins.local/auth_idm/init.php.ttrss_server177
-rw-r--r--files/var/db/postgres/data16/postgresql.conf.postgresql_server2
-rw-r--r--lib/60-ldap18
-rw-r--r--lib/60-postgres24
-rw-r--r--scripts/common/10-vars1
-rw-r--r--scripts/hostclass/asterisk_server74
-rw-r--r--scripts/hostclass/authoritative_nameserver27
-rw-r--r--scripts/hostclass/bitwarden_server58
-rw-r--r--scripts/hostclass/dav_server139
-rw-r--r--scripts/hostclass/imap_server/30-dovecot5
-rw-r--r--scripts/hostclass/postgresql_server8
-rw-r--r--scripts/hostclass/public_webserver42
-rw-r--r--scripts/hostclass/smtp_server/10-rspamd8
-rw-r--r--scripts/hostclass/smtp_server/20-postfix2
-rw-r--r--scripts/hostclass/ttrss_server137
-rw-r--r--scripts/hostclass/turn_server29
-rw-r--r--scripts/hostclass/xmpp_server132
-rw-r--r--scripts/hostclass/znc_server68
-rw-r--r--scripts/hostname/znc13
-rw-r--r--scripts/os/freebsd/60-acme35
-rw-r--r--site/scripts/hostname/rlaptop1 (renamed from scripts/hostname/rlaptop1)0
-rw-r--r--vars/common7
-rw-r--r--vars/hostclass/asterisk_server10
-rw-r--r--vars/hostclass/authoritative_nameserver4
-rw-r--r--vars/hostclass/bitwarden_server3
-rw-r--r--vars/hostclass/dav_server4
-rw-r--r--vars/hostclass/pkg_repository1
-rw-r--r--vars/hostclass/postgresql_server3
-rw-r--r--vars/hostclass/public_webserver5
-rw-r--r--vars/hostclass/ttrss_server4
-rw-r--r--vars/hostclass/turn_server8
-rw-r--r--vars/hostclass/xmpp_server5
-rw-r--r--vars/hostclass/znc_server4
-rw-r--r--vars/hostname/bitwarden14
-rw-r--r--vars/hostname/dav13
-rw-r--r--vars/hostname/ns13
-rw-r--r--vars/hostname/pbx13
-rw-r--r--vars/hostname/postgres14
-rw-r--r--vars/hostname/ttrss14
-rw-r--r--vars/hostname/turn13
-rw-r--r--vars/hostname/www15
-rw-r--r--vars/hostname/xmpp15
-rw-r--r--vars/os/freebsd1
93 files changed, 2232 insertions, 42 deletions
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 <<EOF
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
+ ssl_dhparam ${dhparams_path};
+ ssl_stapling on;
+ ssl_stapling_verify on;
+ resolver ${resolvers};
+ resolver_timeout 5s;
+EOF
+else
+ cat <<EOF
+ ssl_protocols TLSv1.3;
+EOF
+fi
+)
+ ssl_prefer_server_ciphers off;
map \$http_upgrade \$connection_upgrade {
default upgrade;
@@ -47,10 +61,11 @@ $([ "${nginx_gssapi:-}" = true ] && cat <<EOF
EOF
)
-$([ "${acme:-}" = true ] && [ "${acme_standalone:-}" != true ] && cat <<EOF
+$(if [ "${acme:-}" = true ] && [ "${acme_standalone:-}" != true ]; then
+cat <<EOF
server {
- listen 0.0.0.0:80 default_server;
- listen [::]:80 default_server;
+ listen 0.0.0.0:80;
+ listen [::]:80;
location /.well-known/acme-challenge/ {
root ${acme_webroot};
@@ -62,6 +77,18 @@ $([ "${acme:-}" = true ] && [ "${acme_standalone:-}" != true ] && cat <<EOF
}
}
EOF
+ elif [ "${nginx_redirect:-}" != false ]; then
+cat <<EOF
+ server {
+ listen 0.0.0.0:80;
+ listen [::]:80;
+
+ location / {
+ return 301 https://\$host\$request_uri;
+ }
+ }
+EOF
+ fi
)
include vhosts.conf;
diff --git a/files/usr/local/etc/nginx/vhosts.conf.bitwarden_server b/files/usr/local/etc/nginx/vhosts.conf.bitwarden_server
new file mode 100644
index 0000000..0ef31bb
--- /dev/null
+++ b/files/usr/local/etc/nginx/vhosts.conf.bitwarden_server
@@ -0,0 +1,36 @@
+upstream vaultwarden {
+ zone vaultwarden 64k;
+ server 127.0.0.1:${vaultwarden_port};
+ keepalive 2;
+}
+
+map \$http_upgrade \$connection_upgrade {
+ default upgrade;
+ '' "";
+}
+
+server {
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ http2 on;
+
+ client_max_body_size 256M;
+
+ ssl_certificate ${vaultwarden_https_cert};
+ ssl_certificate_key ${vaultwarden_https_key};
+
+ add_header Strict-Transport-Security "max-age=63072000" always;
+
+ location / {
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade \$http_upgrade;
+ proxy_set_header Connection \$connection_upgrade;
+
+ proxy_set_header Host \$host;
+ proxy_set_header X-Real-IP \$remote_addr;
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto \$scheme;
+
+ proxy_pass http://vaultwarden/;
+ }
+}
diff --git a/files/usr/local/etc/nginx/vhosts.conf.dav_server b/files/usr/local/etc/nginx/vhosts.conf.dav_server
new file mode 100644
index 0000000..71bbc71
--- /dev/null
+++ b/files/usr/local/etc/nginx/vhosts.conf.dav_server
@@ -0,0 +1,55 @@
+server {
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ http2 on;
+
+ root ${davical_webroot};
+ index index.html index.php;
+
+ ssl_certificate ${davical_https_cert};
+ ssl_certificate_key ${davical_https_key};
+
+ add_header Strict-Transport-Security "max-age=63072000" always;
+
+ auth_gss_keytab ${davical_keytab};
+ auth_gss_allow_basic_fallback off;
+
+ location / {
+ auth_gss on;
+ satisfy any;
+$(printf ' deny %s;\n' $kerberized_cidrs)
+ allow all;
+ try_files \$uri \$uri/ /caldav.php\$uri?\$query_string;
+ }
+
+ location /.well-known/ {
+ try_files \$uri \$uri/ /caldav.php\$uri?\$query_string;
+ }
+
+ location ~ ^/caldav\.php/\.well-known/ {
+ fastcgi_split_path_info ^(.+?\.php)(/.*)$;
+ if (!-f \$document_root\$fastcgi_script_name) {
+ return 404;
+ }
+ fastcgi_index index.php;
+ fastcgi_intercept_errors on;
+ include fastcgi_params;
+ fastcgi_pass unix:${davical_fpm_socket};
+ }
+
+ location ~ [^/]\.php(/|$) {
+ auth_gss on;
+ satisfy any;
+$(printf ' deny %s;\n' $kerberized_cidrs)
+ allow all;
+
+ fastcgi_split_path_info ^(.+?\.php)(/.*)$;
+ if (!-f \$document_root\$fastcgi_script_name) {
+ return 404;
+ }
+ fastcgi_index index.php;
+ fastcgi_intercept_errors on;
+ include fastcgi_params;
+ fastcgi_pass unix:${davical_fpm_socket};
+ }
+}
diff --git a/files/usr/local/etc/nginx/vhosts.conf.smtp_server b/files/usr/local/etc/nginx/vhosts.conf.smtp_server
index 4b84ede..322ca34 100644
--- a/files/usr/local/etc/nginx/vhosts.conf.smtp_server
+++ b/files/usr/local/etc/nginx/vhosts.conf.smtp_server
@@ -4,8 +4,8 @@ server {
http2 on;
- ssl_certificate ${rspamd_tls_cert};
- ssl_certificate_key ${rspamd_tls_key};
+ ssl_certificate ${rspamd_https_cert};
+ ssl_certificate_key ${rspamd_https_key};
add_header Strict-Transport-Security "max-age=63072000" always;
diff --git a/files/usr/local/etc/nginx/vhosts.conf.ttrss_server b/files/usr/local/etc/nginx/vhosts.conf.ttrss_server
new file mode 100644
index 0000000..fb0343d
--- /dev/null
+++ b/files/usr/local/etc/nginx/vhosts.conf.ttrss_server
@@ -0,0 +1,43 @@
+server {
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ http2 on;
+
+ root ${ttrss_repo_dir};
+ index index.php index.html;
+
+ ssl_certificate ${ttrss_https_cert};
+ ssl_certificate_key ${ttrss_https_key};
+
+ add_header Strict-Transport-Security "max-age=63072000" always;
+
+ auth_gss_keytab ${ttrss_keytab};
+ auth_gss_allow_basic_fallback off;
+
+ location ~ ^/index\.php$ {
+ auth_gss on;
+ satisfy any;
+$(printf ' deny %s;\n' $kerberized_cidrs)
+ allow all;
+
+ fastcgi_split_path_info ^(.+?\.php)(/.*)$;
+ if (!-f \$document_root\$fastcgi_script_name) {
+ return 404;
+ }
+ fastcgi_index index.php;
+ fastcgi_intercept_errors on;
+ include fastcgi_params;
+ fastcgi_pass unix:${ttrss_fpm_socket};
+ }
+
+ location ~ [^/]\.php(/|$) {
+ fastcgi_split_path_info ^(.+?\.php)(/.*)$;
+ if (!-f \$document_root\$fastcgi_script_name) {
+ return 404;
+ }
+ fastcgi_index index.php;
+ fastcgi_intercept_errors on;
+ include fastcgi_params;
+ fastcgi_pass unix:${ttrss_fpm_socket};
+ }
+}
diff --git a/files/usr/local/etc/nginx/vhosts.conf.xmpp_server b/files/usr/local/etc/nginx/vhosts.conf.xmpp_server
new file mode 100644
index 0000000..732a6de
--- /dev/null
+++ b/files/usr/local/etc/nginx/vhosts.conf.xmpp_server
@@ -0,0 +1,21 @@
+server {
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+
+ http2 on;
+
+ ssl_certificate ${prosody_https_cert};
+ ssl_certificate_key ${prosody_https_key};
+ ssl_trusted_certificate ${prosody_https_cacert};
+
+ add_header Strict-Transport-Security "max-age=63072000" always;
+
+ location / {
+ proxy_http_version 1.1;
+ proxy_set_header Host \$host;
+ proxy_set_header X-Real-IP \$remote_addr;
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto \$scheme;
+ proxy_pass http://127.0.0.1:${prosody_http_port};
+ }
+}
diff --git a/files/usr/local/etc/nginx/vhosts.conf.znc_server b/files/usr/local/etc/nginx/vhosts.conf.znc_server
new file mode 100644
index 0000000..ee75878
--- /dev/null
+++ b/files/usr/local/etc/nginx/vhosts.conf.znc_server
@@ -0,0 +1,21 @@
+server {
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ http2 on;
+
+ ssl_certificate ${znc_tls_cert};
+ ssl_certificate_key ${znc_tls_key};
+
+ add_header Strict-Transport-Security "max-age=63072000" always;
+
+ location / {
+ proxy_http_version 1.1;
+
+ proxy_set_header Host \$host;
+ proxy_set_header X-Real-IP \$remote_addr;
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto \$scheme;
+
+ proxy_pass http://127.0.0.1:${znc_http_port}/;
+ }
+}
diff --git a/files/usr/local/etc/nsd/nsd.conf.authoritative_nameserver b/files/usr/local/etc/nsd/nsd.conf.authoritative_nameserver
new file mode 100644
index 0000000..b6d1e11
--- /dev/null
+++ b/files/usr/local/etc/nsd/nsd.conf.authoritative_nameserver
@@ -0,0 +1,22 @@
+server:
+ server-count: ${nsd_threads}
+ log-only-syslog: yes
+ verbosity: 1
+ hide-version: yes
+ minimal-responses: yes
+ refuse-any: yes
+$(for zone in ${nsd_zones:-}; do
+ eval "zone_name=\${nsd_${zone}_domain}"
+ eval "zone_slaves=\${nsd_${zone}_slaves:-}"
+ echo "zone:
+ name: ${zone_name}
+ zonefile: ${nsd_conf_dir}/${zone_name}.zone"
+ for slave in $zone_slaves; do
+ echo " notify: ${slave} NOKEY"
+ echo " provide-xfr: ${slave} NOKEY"
+ done
+done)
+
+remote-control:
+ control-enable: yes
+ control-interface: ${nsd_run_dir}/nsd.ctl
diff --git a/files/usr/local/etc/nslcd.conf.common b/files/usr/local/etc/nslcd.conf.common
index ca27337..9798ba9 100644
--- a/files/usr/local/etc/nslcd.conf.common
+++ b/files/usr/local/etc/nslcd.conf.common
@@ -12,3 +12,5 @@ sasl_mech GSSAPI
nss_min_uid ${nslcd_min_uid}
nss_initgroups_ignoreusers ALLLOCAL
nss_nested_groups yes
+
+pam_authz_search (&(uid=\$username)(memberOf=cn=\$service-access,${roles_basedn}))
diff --git a/files/usr/local/etc/openldap/ldap.conf.common b/files/usr/local/etc/openldap/ldap.conf.common
index 2be3425..22b20bb 100644
--- a/files/usr/local/etc/openldap/ldap.conf.common
+++ b/files/usr/local/etc/openldap/ldap.conf.common
@@ -11,3 +11,4 @@ ACCOUNTS_BASE ${accounts_basedn}
USERS_BASE ${users_basedn}
GROUPS_BASE ${groups_basedn}
HOSTS_BASE ${hosts_basedn}
+ROLES_BASE ${roles_basedn}
diff --git a/files/usr/local/etc/openldap/ldap.conf.idm_server b/files/usr/local/etc/openldap/ldap.conf.idm_server
index 2e77244..4c7a929 100644
--- a/files/usr/local/etc/openldap/ldap.conf.idm_server
+++ b/files/usr/local/etc/openldap/ldap.conf.idm_server
@@ -11,3 +11,4 @@ ACCOUNTS_BASE ${accounts_basedn}
USERS_BASE ${users_basedn}
GROUPS_BASE ${groups_basedn}
HOSTS_BASE ${hosts_basedn}
+ROLES_BASE ${roles_basedn}
diff --git a/files/usr/local/etc/php-fpm.conf.common b/files/usr/local/etc/php-fpm.conf.common
new file mode 100644
index 0000000..e4c8f88
--- /dev/null
+++ b/files/usr/local/etc/php-fpm.conf.common
@@ -0,0 +1,4 @@
+[global]
+pid = run/php-fpm.pid
+error_log = syslog
+include=/usr/local/etc/php-fpm.d/*.conf
diff --git a/files/usr/local/etc/php-fpm.d/davical.conf.dav_server b/files/usr/local/etc/php-fpm.d/davical.conf.dav_server
new file mode 100644
index 0000000..faf5f62
--- /dev/null
+++ b/files/usr/local/etc/php-fpm.d/davical.conf.dav_server
@@ -0,0 +1,20 @@
+[davical]
+user = ${nginx_user}
+group = ${nginx_user}
+
+listen = ${davical_fpm_socket}
+
+listen.owner = ${nginx_user}
+listen.group = ${nginx_user}
+listen.mode = 0660
+
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+
+chdir = ${davical_webroot}
+
+catch_workers_output = yes
+decorate_workers_output = no
diff --git a/files/usr/local/etc/php-fpm.d/ttrss.conf.ttrss_server b/files/usr/local/etc/php-fpm.d/ttrss.conf.ttrss_server
new file mode 100644
index 0000000..9519ab5
--- /dev/null
+++ b/files/usr/local/etc/php-fpm.d/ttrss.conf.ttrss_server
@@ -0,0 +1,23 @@
+[ttrss]
+user = ${nginx_user}
+group = ${nginx_user}
+
+listen = ${ttrss_fpm_socket}
+
+listen.owner = ${nginx_user}
+listen.group = ${nginx_user}
+listen.mode = 0660
+
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+
+chdir = ${ttrss_repo_dir}
+
+catch_workers_output = yes
+decorate_workers_output = no
+
+; ttrss needs git to show its version info.
+env["PATH"] = "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin"
diff --git a/files/usr/local/etc/php.ini.common b/files/usr/local/etc/php.ini.common
new file mode 100644
index 0000000..40cfa9e
--- /dev/null
+++ b/files/usr/local/etc/php.ini.common
@@ -0,0 +1,138 @@
+[PHP]
+engine = On
+short_open_tag = Off
+precision = 14
+output_buffering = 4096
+zlib.output_compression = Off
+implicit_flush = Off
+unserialize_callback_func =
+serialize_precision = -1
+disable_functions =
+disable_classes =
+zend.enable_gc = On
+zend.exception_ignore_args = On
+zend.exception_string_param_max_len = 0
+expose_php = On
+max_execution_time = 30
+max_input_time = 60
+memory_limit = 128M
+error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
+display_errors = Off
+display_startup_errors = Off
+log_errors = On
+ignore_repeated_errors = Off
+ignore_repeated_source = Off
+report_memleaks = On
+html_errors = Off
+error_log = syslog
+syslog.ident = php
+syslog.facility = user
+variables_order = "GPCS"
+request_order = "GP"
+register_argc_argv = Off
+auto_globals_jit = On
+post_max_size = 8M
+auto_prepend_file =
+auto_append_file =
+default_mimetype = "text/html"
+default_charset = "UTF-8"
+doc_root =
+user_dir =
+enable_dl = Off
+file_uploads = On
+upload_max_filesize = 2M
+max_file_uploads = 20
+allow_url_fopen = On
+allow_url_include = Off
+default_socket_timeout = 60
+
+[CLI Server]
+cli_server.color = On
+
+[Date]
+;date.timezone =
+
+[Pdo_mysql]
+pdo_mysql.default_socket=
+
+
+[mail function]
+mail.add_x_header = Off
+mail.mixed_lf_and_crlf = Off
+
+[ODBC]
+odbc.allow_persistent = On
+odbc.check_persistent = On
+odbc.max_persistent = -1
+odbc.max_links = -1
+odbc.defaultlrl = 4096
+odbc.defaultbinmode = 1
+
+[MySQLi]
+mysqli.max_persistent = -1
+mysqli.allow_persistent = On
+mysqli.max_links = -1
+mysqli.default_port = 3306
+mysqli.default_socket =
+mysqli.default_host =
+mysqli.default_user =
+mysqli.default_pw =
+
+[mysqlnd]
+mysqlnd.collect_statistics = On
+mysqlnd.collect_memory_statistics = Off
+
+
+[PostgreSQL]
+pgsql.allow_persistent = On
+pgsql.auto_reset_persistent = Off
+pgsql.max_persistent = -1
+pgsql.max_links = -1
+pgsql.ignore_notice = 0
+pgsql.log_notice = 0
+
+[bcmath]
+bcmath.scale = 0
+
+[browscap]
+
+[Session]
+session.save_handler = files
+session.use_strict_mode = 1
+session.use_cookies = 1
+session.use_only_cookies = 1
+session.name = PHPSESSID
+session.auto_start = 0
+session.cookie_lifetime = 0
+session.cookie_path = /
+session.cookie_domain =
+session.cookie_httponly =
+session.cookie_samesite =
+session.serialize_handler = php
+session.gc_probability = 1
+session.gc_divisor = 1000
+session.gc_maxlifetime = 1440
+session.referer_check =
+session.cache_limiter = nocache
+session.cache_expire = 180
+session.use_trans_sid = 0
+session.sid_length = 26
+session.trans_sid_tags = "a=href,area=href,frame=src,form="
+session.sid_bits_per_character = 5
+
+[Assertion]
+zend.assertions = -1
+
+
+[Tidy]
+tidy.clean_output = Off
+
+[soap]
+soap.wsdl_cache_enabled=1
+soap.wsdl_cache_dir="/tmp"
+soap.wsdl_cache_ttl=86400
+soap.wsdl_cache_limit = 5
+
+[opcache]
+opcache.enable=1
+opcache.enable_cli=0
diff --git a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
index d24ce06..848e558 100644
--- a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
@@ -1,4 +1,10 @@
+archivers/php${php_version}-phar
+archivers/php${php_version}-zip
converters/php${php_version}-iconv
+converters/php${php_version}-mbstring
+databases/luadbi
+databases/p5-DBD-Pg
+databases/p5-DBI
databases/php${php_version}-pdo_pgsql
databases/php${php_version}-pgsql
databases/postgresql${postgresql_version}-client
@@ -7,6 +13,9 @@ databases/redis
devel/ccache
devel/git@lite
devel/php${php_version}-gettext
+devel/php${php_version}-intl
+devel/php${php_version}-pcntl
+devel/php${php_version}-tokenizer
dns/bind-tools
dns/nsd
dns/powerdns
@@ -14,6 +23,10 @@ dns/unbound
editors/vim@console
editors/vim@tiny
ftp/php${php_version}-curl
+graphics/php${php_version}-exif
+graphics/php${php_version}-gd
+irc/znc
+irc/znc-clientbuffer
java/openjdk21
lang/python
lang/php${php_version}
@@ -25,6 +38,8 @@ mail/postfix
mail/rspamd
mail/sieve-connect
misc/php${php_version}-calendar
+net/asterisk18
+net/lualdap
net/nss-pam-ldapd-sasl
net/openldap26-client
net/openldap26-server
@@ -32,6 +47,10 @@ net/p5-perl-ldap
net/php${php_version}-ldap
net/py-python-ldap
net/rsync
+net/php${php_version}-sockets
+net/turnserver
+net-im/prosody
+net-im/prosody-modules
ports-mgmt/poudriere
security/acme.sh
security/cyrus-sasl2-saslauthd
@@ -41,16 +60,25 @@ security/krb5@ldap
security/openssh-portable
security/pam_krb5@mit
security/pam_mkhomedir
+security/php${php_version}-filter
security/sshpass
security/sudo
+security/vaultwarden
sysutils/htop
sysutils/lsof
sysutils/p5-Sys-Syslog
+sysutils/php${php_version}-fileinfo
+sysutils/php${php_version}-posix
sysutils/pwgen
sysutils/stow
sysutils/tmux
sysutils/tree
+textproc/p5-YAML
+textproc/php${php_version}-ctype
+textproc/php${php_version}-dom
+textproc/php${php_version}-simplexml
textproc/php${php_version}-xml
+textproc/php${php_version}-xmlwriter
www/nginx
www/php${php_version}-opcache
www/php${php_version}-session
diff --git a/files/usr/local/etc/prosody/prosody.cfg.lua.xmpp_server b/files/usr/local/etc/prosody/prosody.cfg.lua.xmpp_server
new file mode 100644
index 0000000..083a6ce
--- /dev/null
+++ b/files/usr/local/etc/prosody/prosody.cfg.lua.xmpp_server
@@ -0,0 +1,106 @@
+$([ -n "${prosody_admins:-}" ] && echo "admins = { \"$(join '", "' $prosody_admins)\" }")
+pidfile = "/var/run/prosody/prosody.pid"
+
+plugin_paths = { "/usr/local/lib/prosody-modules" }
+
+modules_enabled = {
+
+ -- Generally required
+ "disco"; -- Service discovery
+ "roster"; -- Allow users to have a roster. Recommended ;)
+ "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
+ "tls"; -- Add support for secure TLS on c2s/s2s connections
+
+ -- Not essential, but recommended
+ "blocklist"; -- Allow users to block communications with other users
+ "bookmarks"; -- Synchronise the list of open rooms between clients
+ "carbons"; -- Keep multiple online clients in sync
+ "dialback"; -- Support for verifying remote servers using DNS
+ "limits"; -- Enable bandwidth limiting for XMPP connections
+ "pep"; -- Allow users to store public and private data in their account
+ "private"; -- Legacy account storage mechanism (XEP-0049)
+ "smacks"; -- Stream management and resumption (XEP-0198)
+ "vcard4"; -- User profiles (stored in PEP)
+ "vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard
+
+ -- Nice to have
+ "ping"; -- Replies to XMPP pings with pongs
+ "register"; -- Allow users to register on this server using a client and change passwords
+ "time"; -- Let others know the time here on this server
+ "uptime"; -- Report how long server has been running
+ "version"; -- Replies to server version requests
+ "mam"; -- Store recent messages to allow multi-device synchronization
+ "turn_external"; -- Provide external STUN/TURN service for e.g. audio/video calls
+
+ -- Admin interfaces
+ "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
+ "admin_shell"; -- Allow secure administration via 'prosodyctl shell'
+
+ -- Other specific functionality
+ "groups"; -- Shared roster support
+ "csi_battery_saver";
+ "reload_modules";
+}
+
+reload_modules = { "groups", "tls" }
+
+groups_file = "${prosody_roster_path}"
+
+s2s_secure_auth = true
+
+limits = {
+ c2s = {
+ rate = "10kb/s";
+ };
+ s2sin = {
+ rate = "30kb/s";
+ };
+}
+
+authentication = "ldap"
+ldap_server = "${ldap_hosts}"
+ldap_tls = true
+ldap_base = "${users_basedn}"
+ldap_scope = "subtree"
+ldap_filter = "(&(memberOf=cn=${prosody_access_role},${roles_basedn})(mailAddress=\$user@\$host))"
+ldap_rootdn = "${prosody_dn}"
+ldap_password = "${prosody_ldap_password}"
+
+storage = "sql"
+sql = { driver = "PostgreSQL", database = "${prosody_dbname}", username = "${prosody_username}", host = "${prosody_dbhost}" }
+
+archive_expires_after = "${prosody_archive_expiration}"
+
+turn_external_host = "${prosody_turn_host}"
+turn_external_port = ${prosody_turn_port}
+turn_external_secret = "${prosody_turn_secret}"
+
+log = {
+ info = "*syslog";
+}
+
+certificates = "certs"
+
+http_ports = { ${prosody_http_port} }
+http_interfaces = { "127.0.0.1" }
+https_interfaces = { }
+https_ports = { }
+http_external_url = "https://${prosody_public_fqdn}/"
+https_external_url = "https://${prosody_public_fqdn}/"
+trusted_proxies = { "127.0.0.1" }
+http_max_content_size = ${prosody_upload_sizelimit}
+
+Component "${prosody_public_fqdn}" "http_upload"
+http_upload_file_size_limit = ${prosody_upload_sizelimit}
+http_upload_expire_after = ${prosody_upload_expiration}
+http_upload_quota = ${prosody_upload_quota}
+
+$(for vhost in $prosody_domains; do cat <<EOF
+VirtualHost "${vhost}"
+ disco_items = {
+ { "${prosody_public_fqdn}" }
+ }
+Component "conference.${vhost}" "muc"
+ modules_enabled = { "muc_mam"}
+EOF
+done)
diff --git a/files/usr/local/etc/rc.conf.d/vaultwarden.bitwarden_server b/files/usr/local/etc/rc.conf.d/vaultwarden.bitwarden_server
new file mode 100644
index 0000000..a0923d6
--- /dev/null
+++ b/files/usr/local/etc/rc.conf.d/vaultwarden.bitwarden_server
@@ -0,0 +1,19 @@
+export ROCKET_ADDRESS=127.0.0.1
+export ROCKET_PORT="${vaultwarden_port}"
+export ROCKET_CLI_COLORS=false
+export LOG_LEVEL=warn
+export EXTENDED_LOGGING=true
+export IP_HEADER=X-Forwarded-For
+
+export DATABASE_URL="postgresql://${vaultwarden_username}@${vaultwarden_dbhost}/${vaultwarden_dbname}"
+
+export SIGNUPS_ALLOWED=true
+export SIGNUPS_VERIFY=true
+
+export INVITATIONS_ALLOWED=false
+
+export DOMAIN="https://${vaultwarden_fqdn}"
+
+export USE_SENDMAIL=true
+export SMTP_FROM="bitwarden-noreply@${email_domain}"
+export SMTP_FROM_NAME=Bitwarden
diff --git a/files/usr/local/etc/rc.d/ttrssd.ttrss_server b/files/usr/local/etc/rc.d/ttrssd.ttrss_server
new file mode 100644
index 0000000..d04fa3d
--- /dev/null
+++ b/files/usr/local/etc/rc.d/ttrssd.ttrss_server
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# PROVIDE: ttrssd
+# REQUIRE: NETWORKING kstart
+# KEYWORD: shutdown
+
+. /etc/rc.subr
+
+name='ttrssd'
+rcvar='ttrssd_enable'
+
+load_rc_config "$name"
+: ${ttrssd_enable='NO'}
+: ${ttrssd_webroot='/usr/local/www/tt-rss'}
+: ${ttrssd_user='www'}
+: ${ttrssd_syslog_priority:='info'}
+: ${ttrssd_syslog_facility:='daemon'}
+
+ttrssd_syslog_tag=$name
+ttrssd_chdir=$ttrssd_webroot
+
+pidfile="/var/run/${name}/${name}.pid"
+procname=/usr/local/bin/php
+
+command=/usr/sbin/daemon
+command_args="-f \
+-s ${ttrssd_syslog_priority} \
+-l ${ttrssd_syslog_facility} \
+-T ${ttrssd_syslog_tag} \
+-p ${pidfile} \
+-t ${name} \
+/usr/local/bin/php \
+-d syslog.ident=${ttrssd_syslog_tag} \
+-d syslog.facility=${ttrssd_syslog_facility} \
+${ttrssd_webroot}/update_daemon2.php"
+
+required_files="${ttrssd_webroot}/config.php"
+start_precmd=ttrssd_prestart
+
+ttrssd_prestart(){
+ install -d -m 0755 -o ${ttrssd_user} "/var/run/${name}"
+}
+
+# ttrss needs git to show its version info.
+PATH='/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin'
+
+run_rc_command "$1"
diff --git a/files/usr/local/etc/ssh/sshd_config.d/acmeproxy.conf.common b/files/usr/local/etc/ssh/sshd_config.d/acmeproxy.conf.common
new file mode 100644
index 0000000..63022e3
--- /dev/null
+++ b/files/usr/local/etc/ssh/sshd_config.d/acmeproxy.conf.common
@@ -0,0 +1,11 @@
+Match Group ${acmeproxy_client_group}
+ ChrootDirectory ${acmeproxy_home}
+ ForceCommand internal-sftp -R
+ DisableForwarding yes
+ PermitUserRC no
+ PermitTTY no
+ GSSAPIAuthentication yes
+ KbdInteractiveAuthentication no
+ PasswordAuthentication no
+ PubkeyAuthentication no
+ AuthenticationMethods gssapi-with-mic
diff --git a/files/usr/local/etc/ssh/sshd_config.freebsd b/files/usr/local/etc/ssh/sshd_config.freebsd
index 52d9bfe..eca2276 100644
--- a/files/usr/local/etc/ssh/sshd_config.freebsd
+++ b/files/usr/local/etc/ssh/sshd_config.freebsd
@@ -1,4 +1,4 @@
-Include /etc/ssh/sshd_config.d/*.conf
+Include /usr/local/etc/ssh/sshd_config.d/*.conf
PermitRootLogin prohibit-password
AuthorizedKeysFile .ssh/authorized_keys
diff --git a/files/usr/local/etc/sudoers.d/acme.asterisk_server b/files/usr/local/etc/sudoers.d/acme.asterisk_server
new file mode 100644
index 0000000..6ca9cd6
--- /dev/null
+++ b/files/usr/local/etc/sudoers.d/acme.asterisk_server
@@ -0,0 +1 @@
+${acme_user} ALL=(root) NOPASSWD: /usr/sbin/service asterisk reload
diff --git a/files/usr/local/etc/sudoers.d/acme.public_webserver b/files/usr/local/etc/sudoers.d/acme.public_webserver
new file mode 100644
index 0000000..9ca89b8
--- /dev/null
+++ b/files/usr/local/etc/sudoers.d/acme.public_webserver
@@ -0,0 +1 @@
+${acme_user} ALL=(root) NOPASSWD: /usr/sbin/service nginx reload
diff --git a/files/usr/local/etc/sudoers.d/acme.smtp_server b/files/usr/local/etc/sudoers.d/acme.smtp_server
index 5180fdc..4e8c381 100644
--- a/files/usr/local/etc/sudoers.d/acme.smtp_server
+++ b/files/usr/local/etc/sudoers.d/acme.smtp_server
@@ -1 +1 @@
-acme ALL=(root) NOPASSWD: /usr/sbin/service postfix reload
+${acme_user} ALL=(root) NOPASSWD: /usr/sbin/service postfix reload
diff --git a/files/usr/local/etc/sudoers.d/acme.xmpp_server b/files/usr/local/etc/sudoers.d/acme.xmpp_server
new file mode 100644
index 0000000..9ca89b8
--- /dev/null
+++ b/files/usr/local/etc/sudoers.d/acme.xmpp_server
@@ -0,0 +1 @@
+${acme_user} ALL=(root) NOPASSWD: /usr/sbin/service nginx reload
diff --git a/files/usr/local/etc/turnserver.conf.turn_server b/files/usr/local/etc/turnserver.conf.turn_server
new file mode 100644
index 0000000..dc62883
--- /dev/null
+++ b/files/usr/local/etc/turnserver.conf.turn_server
@@ -0,0 +1,61 @@
+relay-threads=${coturn_threads}
+listening-port=${coturn_listen_port}
+tls-listening-port=0
+
+listening-ip=${BOXCONF_DEFAULT_IPV4}
+relay-ip=${BOXCONF_DEFAULT_IPV4}
+external-ip=${coturn_external_ip}
+
+min-port=${coturn_min_port}
+max-port=${coturn_max_port}
+
+verbose
+
+use-auth-secret
+static-auth-secret=${coturn_secret}
+
+realm=${coturn_realm}
+
+no-tls
+no-dtls
+
+syslog
+
+no-software-attribute
+no-multicast-peers
+
+denied-peer-ip=0.0.0.0-0.255.255.255
+denied-peer-ip=10.0.0.0-10.255.255.255
+denied-peer-ip=100.64.0.0-100.127.255.255
+denied-peer-ip=127.0.0.0-127.255.255.255
+denied-peer-ip=169.254.0.0-169.254.255.255
+denied-peer-ip=172.16.0.0-172.31.255.255
+denied-peer-ip=192.0.0.0-192.0.0.255
+denied-peer-ip=192.0.2.0-192.0.2.255
+denied-peer-ip=192.88.99.0-192.88.99.255
+denied-peer-ip=192.168.0.0-192.168.255.255
+denied-peer-ip=198.18.0.0-198.19.255.255
+denied-peer-ip=198.51.100.0-198.51.100.255
+denied-peer-ip=203.0.113.0-203.0.113.255
+denied-peer-ip=240.0.0.0-255.255.255.255
+denied-peer-ip=::1
+denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff
+denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255
+denied-peer-ip=100::-100::ffff:ffff:ffff:ffff
+denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff
+denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+
+secure-stun
+
+# You can't drop privileges here, due to a FreeBSD issue with SO_REUSEPORT:
+# https://github.com/coturn/coturn/issues/1098
+# Do this in /etc/rc.conf instead.
+#proc-user=coturn
+#proc-group=coturn
+
+no-cli
+no-rfc5780
+no-stun-backward-compatibility
+response-origin-only-with-rfc5780
diff --git a/files/usr/local/etc/znc/configs/znc.conf.znc_server b/files/usr/local/etc/znc/configs/znc.conf.znc_server
new file mode 100644
index 0000000..487db8e
--- /dev/null
+++ b/files/usr/local/etc/znc/configs/znc.conf.znc_server
@@ -0,0 +1,55 @@
+LoadModule = cyrusauth saslauthd
+LoadModule = webadmin
+LoadModule = corecaps
+SSLCertFile = ${znc_tls_cert}
+SSLKeyFile = ${znc_tls_key}
+Version = 1.9.0
+
+<Listener web>
+ AllowIRC = false
+ AllowWeb = true
+ IPv4 = true
+ IPv6 = false
+ Host = 127.0.0.1
+ Port = ${znc_http_port}
+ SSL = false
+</Listener>
+
+<Listener irc>
+ AllowIRC = true
+ AllowWeb = false
+ IPv4 = true
+ IPv6 = true
+ Port = ${znc_irc_port}
+ SSL = true
+</Listener>
+
+<User admin>
+ Admin = true
+ Nick = znc_admin
+ AltNick = znc_admin_
+ Ident = znc_admin
+ RealName = ZNC Administrator
+
+ <Pass password>
+ Hash = ::
+ Method = MD5
+ Salt = ::
+ </Pass>
+</User>
+
+<User ${znc_clone_user}>
+ Admin = false
+ Nick = znc_user
+ AltNick = znc_user_
+ Ident = znc_user
+ RealName = ZNC User
+ MaxNetworks = ${znc_max_networks}
+ LoadModule = chansaver
+
+ <Pass password>
+ Hash = ::
+ Method = MD5
+ Salt = ::
+ </Pass>
+</User>
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 @@
+<?php
+\$c->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 @@
+<?php
+putenv('TTRSS_DB_TYPE=pgsql');
+putenv('TTRSS_DB_HOST=${ttrss_dbhost}');
+putenv('TTRSS_DB_USER=${ttrss_username}');
+putenv('TTRSS_DB_NAME=${ttrss_dbname}');
+
+putenv('TTRSS_SELF_URL_PATH=https://${ttrss_fqdn}/');
+putenv('TTRSS_PHP_EXECUTABLE=/usr/local/bin/php');
+
+putenv('TTRSS_SESSION_COOKIE_LIFETIME=604800');
+
+putenv('TTRSS_SMTP_FROM_NAME=Tiny Tiny RSS');
+putenv('TTRSS_SMTP_FROM_ADDRESS=${ttrss_mail_from}');
+
+putenv('TTRSS_CHECK_FOR_UPDATES=false');
+putenv('TTRSS_CHECK_FOR_PLUGIN_UPDATES=false');
+putenv('TTRSS_ENABLE_PLUGIN_INSTALLER=false');
+putenv('TTRSS_ENABLE_GZIP_OUTPUT=false');
+putenv('TTRSS_PLUGINS=auth_idm');
+
+putenv('TTRSS_LOG_DESTINATION=syslog');
+
+putenv('TTRSS_AUTH_IDM_URI=${ldap_uri}');
+putenv('TTRSS_AUTH_IDM_STARTTLS=false');
+putenv('TTRSS_AUTH_IDM_BASEDN=${users_basedn}');
+putenv('TTRSS_AUTH_IDM_SCOPE=sub');
+putenv('TTRSS_AUTH_IDM_FILTER=(memberOf=cn=${ttrss_access_role},${roles_basedn})');
+putenv('TTRSS_AUTH_IDM_ADMIN_FILTER=(memberOf=cn=${ttrss_admin_role},${roles_basedn})');
diff --git a/files/usr/local/www/tt-rss/plugins.local/auth_idm/init.php.ttrss_server b/files/usr/local/www/tt-rss/plugins.local/auth_idm/init.php.ttrss_server
new file mode 100644
index 0000000..c025026
--- /dev/null
+++ b/files/usr/local/www/tt-rss/plugins.local/auth_idm/init.php.ttrss_server
@@ -0,0 +1,177 @@
+<?php
+/**
+ * The following options may be specified in config.php:
+ *
+ * putenv('TTRSS_AUTH_IDM_URI=ldap://ldap.idm.example.com');
+ * putenv('TTRSS_AUTH_IDM_BASEDN=ou=users,dc=idm,dc=example,dc=com');
+ * putenv('TTRSS_AUTH_IDM_FILTER=(memberOf=cn=ttrss-users,ou=groups,dc=idm,dc=example,dc=com)');
+ * putenv('TTRSS_AUTH_IDM_ADMIN_FILTER=(memberOf=cn=ttrss-admins,ou=groups,dc=idm,dc=example,dc=com)');
+ * putenv('TTRSS_AUTH_IDM_FULLNAME_ATTRIBUTE=cn');
+ * putenv('TTRSS_AUTH_IDM_EMAIL_ATTRIBUTE=mail');
+ */
+
+class Auth_Idm extends Auth_Base {
+
+ const AUTH_IDM_URI = 'AUTH_IDM_URI';
+ const AUTH_IDM_STARTTLS = 'AUTH_IDM_STARTTLS';
+ const AUTH_IDM_BASEDN = 'AUTH_IDM_BASEDN';
+ const AUTH_IDM_SCOPE = 'AUTH_IDM_SCOPE';
+ const AUTH_IDM_FILTER = 'AUTH_IDM_FILTER';
+ const AUTH_IDM_ADMIN_FILTER = 'AUTH_IDM_ADMIN_FILTER';
+ const AUTH_IDM_USERNAME_ATTR = 'AUTH_IDM_USERNAME_ATTRIBUTE';
+ const AUTH_IDM_FULLNAME_ATTR = 'AUTH_IDM_FULLNAME_ATTRIBUTE';
+ const AUTH_IDM_EMAIL_ATTR = 'AUTH_IDM_EMAIL_ATTRIBUTE';
+
+ function about() {
+ return array(null,
+ 'Authenticates against REMOTE_USER variable and LDAP server',
+ 'cullum@sacredheartsc.com',
+ true);
+ }
+
+ function init($host) {
+ $host->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 <<EOF | postgres_run -h "${1}" -d postgres
+SELECT 'CREATE ROLE "${2}" WITH LOGIN' WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${2}')\\gexec
+EOF
+}
+
+postgres_create_database(){
+ # $1 = postgres_host, $2 = dbname, $3 = owner
+ cat <<EOF | postgres_run -h "${1}" -d postgres
+SELECT 'CREATE DATABASE "${2}" OWNER "${3:-postgres}"' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${2}')\\gexec
+EOF
+}
diff --git a/scripts/common/10-vars b/scripts/common/10-vars
index 6ea7cad..cae4496 100644
--- a/scripts/common/10-vars
+++ b/scripts/common/10-vars
@@ -12,6 +12,7 @@ idm_hostnames=$(echo "$idm_server_list" | awk '{print $1}')
fqdn="${BOXCONF_HOSTNAME}.${domain}"
: ${smtp_host:="smtp.${domain}"}
+: ${postgres_host:="postgres.${domain}"}
realm=$(echo "$domain" | tr '[:lower:]' '[:upper:]')
diff --git a/scripts/hostclass/asterisk_server b/scripts/hostclass/asterisk_server
new file mode 100644
index 0000000..d519730
--- /dev/null
+++ b/scripts/hostclass/asterisk_server
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+: ${asterisk_public_fqdn:='pbx.example.com'}
+: ${asterisk_public_ip:="$BOXCONF_DEFAULT_IPV4"}
+: ${asterisk_from_email:="asterisk-noreply@${email_domain}"}
+: ${asterisk_sip_domain:="${email_domain}"}
+: ${asterisk_locale:='en_US.UTF-8'}
+: ${asterisk_timezone:='America/New_York'}
+: ${asterisk_default_mailbox_password:='1234'}
+
+# asterisk_mailboxes='1001 1002'
+# asterisk_mailbox_1001_name='John Doe'
+# asterisk_mailbox_1001_email='johndoe@example.com'
+#
+# asterisk_trunks='upstream1 upstream2'
+# asterisk_trunk_upstream1_username=myusername
+# asterisk_trunk_upstream1_password=changeme
+# asterisk_trunk_upstream1_context=from-pstn
+# asterisk_trunk_upstream1_proto=tcp
+# asterisk_trunk_upstream1_remote='server.example.com:5060'
+#
+# asterisk_exts='1001 1002'
+# asterisk_ext_1001_password=changeme
+# asterisk_ext_1001_context=from-internal
+# asterisk_ext_1001_mailbox=1001
+# asterisk_ext_1001_cid_name='Bob Office'
+#
+# asterisk_queues=home
+# asterisk_queue_home_stragegy=ringall
+# asterisk_queue_home_timeout=30
+# asterisk_queue_home_retry=1
+# asterisk_queue_home_members='1001 1002'
+
+asterisk_public_tls_cert="${acme_cert_dir}/asterisk.crt"
+asterisk_public_tls_key="${acme_cert_dir}/asterisk.key"
+asterisk_conf_dir=/usr/local/etc/asterisk
+asterisk_db_dir=/var/db/asterisk
+asterisk_user=asterisk
+
+# Install packages.
+pkg install -y \
+ asterisk18 \
+ ca_root_nss
+
+# Create ZFS dataset for Asterisk DB.
+create_dataset -o "mountpoint=${asterisk_db_dir}" "${state_dataset}/asterisk"
+install_directory -o "$asterisk_user" -g "$asterisk_user" -m 0755 "$asterisk_db_dir"
+
+# Generate asterisk configuration.
+install_file -m 0644 \
+ "${asterisk_conf_dir}/extensions.conf" \
+ "${asterisk_conf_dir}/logger.conf" \
+ "${asterisk_conf_dir}/queues.conf" \
+ "${asterisk_conf_dir}/voicemail.conf"
+
+install_template -m 0644 \
+ "${asterisk_conf_dir}/voicemail.conf" \
+ "${asterisk_conf_dir}/pjsip.conf" \
+ "${asterisk_conf_dir}/rtp.conf"
+
+install_template -m 0640 \
+ "${asterisk_conf_dir}/pjsip_wizard.conf"
+
+# Acquire public TLS certificate.
+install_template -m 0600 /usr/local/etc/sudoers.d/acme
+acme_install_certificate \
+ -c "$asterisk_public_tls_cert" \
+ -k "$asterisk_public_tls_key" \
+ -r 'sudo service asterisk reload' \
+ "$asterisk_public_fqdn"
+
+# Enable and start asterisk.
+sysrc -v asterisk_enable=YES
+service asterisk restart
diff --git a/scripts/hostclass/authoritative_nameserver b/scripts/hostclass/authoritative_nameserver
new file mode 100644
index 0000000..69a7dde
--- /dev/null
+++ b/scripts/hostclass/authoritative_nameserver
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+: ${nsd_zones:=''}
+: ${nsd_threads:='2'}
+
+# nsd_zones='example1 example2'
+# nsd_example1_domain=example.com
+# nsd_example1_slaves='1.2.3.4 5.6.7.8'
+
+nsd_conf_dir=/usr/local/etc/nsd
+nsd_run_dir=/var/run/nsd
+
+# Install packages.
+pkg install -y nsd
+
+# Generate nsd configuration.
+install_template -m 0644 /usr/local/etc/nsd/nsd.conf
+
+# Copy zone files.
+for zone in $nsd_zones; do
+ eval "zone_name=\${nsd_${zone}_zone}"
+ install_file -m 0644 "${nsd_conf_dir}/${zone_name}.zone"
+done
+
+# Enable and start nsd.
+sysrc -v nsd_enable=YES
+service nsd restart
diff --git a/scripts/hostclass/bitwarden_server b/scripts/hostclass/bitwarden_server
new file mode 100644
index 0000000..5e19bdd
--- /dev/null
+++ b/scripts/hostclass/bitwarden_server
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+: ${vaultwarden_username:='s-vaultwarden'}
+: ${vaultwarden_dbname:='vaultwarden'}
+: ${vaultwarden_dbhost:="$postgres_host"}
+: ${vaultwarden_fqdn:="$fqdn"}
+
+vaultwarden_local_username=$nginx_user
+vaultwarden_uid=$(id -u "$vaultwarden_local_username")
+vaultwarden_https_cert="${nginx_conf_dir}/vaultwarden.crt"
+vaultwarden_https_key="${nginx_conf_dir}/vaultwarden.key"
+vaultwarden_home=/usr/local/www/vaultwarden
+vaultwarden_port=8080
+vaultwarden_client_keytab="${keytab_dir}/vaultwarden.client.keytab"
+
+pkg install -y \
+ vaultwarden \
+ nginx
+
+# Create vaultwarden principal and keytab.
+add_principal -nokey -x "containerdn=${robots_basedn}" "$vaultwarden_username"
+
+ktadd -k "$vaultwarden_client_keytab" "$vaultwarden_username"
+chgrp "$vaultwarden_local_username" "$vaultwarden_client_keytab"
+chmod 640 "$vaultwarden_client_keytab"
+
+install_directory -o "$vaultwarden_local_username" -m 0700 "/var/krb5/user/${vaultwarden_uid}"
+ln -snfv "$vaultwarden_client_keytab" "/var/krb5/user/${vaultwarden_uid}/client.keytab"
+
+# Create postgres user and database.
+postgres_create_role "$vaultwarden_dbhost" "$vaultwarden_username"
+postgres_create_database "$vaultwarden_dbhost" "$vaultwarden_dbname" "$vaultwarden_username"
+
+# Generate vaultwarden configuration.
+install_template -m 0644 /usr/local/etc/rc.conf.d/vaultwarden
+
+# Copy TLS certificate for nginx.
+install_certificate nginx "$vaultwarden_https_cert"
+install_certificate_key nginx "$vaultwarden_https_key"
+
+# Generate nginx configuration.
+install_template -m 0644 \
+ /usr/local/etc/nginx/nginx.conf \
+ /usr/local/etc/nginx/vhosts.conf
+
+# Enable and start daemons.
+sysrc -v \
+ vaultwarden_enable=YES \
+ vaultwarden_user="$vaultwarden_local_username" \
+ vaultwarden_group="$vaultwarden_local_username" \
+ nginx_enable=YES \
+
+service nginx restart
+
+# The vaultwarden rc script seems to hold onto open descriptors, which causes
+# the parent boxconf SSH process to never close.
+echo 'Restarting vaultwarden.'
+service vaultwarden restart > /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}" <<EOF
+objectClass: groupOfMembers
+cn: ${davical_access_role}
+EOF
diff --git a/scripts/hostclass/imap_server/30-dovecot b/scripts/hostclass/imap_server/30-dovecot
index 07c089e..ff41da5 100644
--- a/scripts/hostclass/imap_server/30-dovecot
+++ b/scripts/hostclass/imap_server/30-dovecot
@@ -75,9 +75,10 @@ install_template -m 0644 \
"${dovecot_conf_dir}/conf.d/90-sieve-extprograms.conf" \
"${dovecot_conf_dir}/conf.d/auth-ldap.conf.ext"
-install_template -m 0550 -o root -g "$dovecot_user" \
+install_template -m 0640 -o root -g "$dovecot_user" "${dovecot_conf_dir}/rspamd.conf.sh"
+install_file -m 0555 \
"${dovecot_sieve_pipe_bin_dir}/report-spam.sh" \
- "${dovecot_sieve_pipe_bin_dir}/report-ham.sh" \
+ "${dovecot_sieve_pipe_bin_dir}/report-ham.sh"
install_file -m 0555 \
"${dovecot_script_dir}/quota-warning.sh"
diff --git a/scripts/hostclass/postgresql_server b/scripts/hostclass/postgresql_server
index a09c9f4..fb0ddcd 100644
--- a/scripts/hostclass/postgresql_server
+++ b/scripts/hostclass/postgresql_server
@@ -1,5 +1,7 @@
#!/bin/sh
+# PostgreSQL jails need allow.sysvipc=1.
+
: ${postgres_max_connections:='128'}
: ${postgres_shared_buffers:="$(( memsize / 2 ))"}
: ${postgres_work_mem:="$(( memsize / 4 / ${postgres_max_connections} ))"}
@@ -9,7 +11,7 @@
postgres_user=postgres
postgres_home=/var/db/postgres
-postgres_data_dir="${postgres_home}/data${postgres_version}"
+postgres_data_dir="${postgres_home}/data${postgresql_version}"
postgres_tls_cert="${postgres_home}/postgres.crt"
postgres_tls_key="${postgres_home}/postgres.key"
postgres_keytab="${keytab_dir}/postgres.keytab"
@@ -67,8 +69,8 @@ service postgresql restart > /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}" <<EOF
+objectClass: groupOfMembers
+cn: ${role}
+EOF
+done
diff --git a/scripts/hostclass/turn_server b/scripts/hostclass/turn_server
new file mode 100644
index 0000000..2c01e30
--- /dev/null
+++ b/scripts/hostclass/turn_server
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+: ${coturn_secret:="$turn_secret"}
+: ${coturn_external_ip:="$BOXCONF_DEFAULT_IPV4"}
+: ${coturn_realm:="$turn_domain"}
+: ${coturn_threads:="$nproc"}
+
+coturn_user=coturn
+coturn_uid=792
+
+add_user \
+ -u "$coturn_uid" \
+ -c 'Turnserver Psuedo-User' \
+ -d /nonexistent \
+ -s /usr/sbin/nologin \
+ "$coturn_user"
+
+# Install required packages.
+pkg install -y turnserver
+
+# Copy coturn config file.
+install_template -o root -g "$coturn_user" -m 0640 /usr/local/etc/turnserver.conf
+
+# Start turnserver.
+sysrc -v \
+ turnserver_enable=YES \
+ turnserver_user="$coturn_user" \
+ turnserver_group="$coturn_user"
+service turnserver restart
diff --git a/scripts/hostclass/xmpp_server b/scripts/hostclass/xmpp_server
new file mode 100644
index 0000000..1889447
--- /dev/null
+++ b/scripts/hostclass/xmpp_server
@@ -0,0 +1,132 @@
+#!/bin/sh
+
+# The LDAP library used by prosody (lualdap) does not support SASL binds.
+# Therefore, you must specify the prosody_ldap_password variable.
+
+# prosody_acme_host=
+: ${prosody_admins:=''}
+: ${prosody_public_fqdn:="$fqdn"}
+: ${prosody_domains:="$email_domain"}
+: ${prosody_ldap_passwd:='changeme'}
+: ${prosody_dbname:='prosody'}
+: ${prosody_dbhost:="$postgres_host"}
+: ${prosody_access_role:='xmpp-access'}
+: ${prosody_archive_expiration:='1w'}
+: ${prosody_upload_sizelimit:='104857600'} # 100 MB
+: ${prosody_upload_expiration:='604800'} # 1 week
+: ${prosody_upload_quota:='25769803776'} # 24 GB
+: ${prosody_turn_port:='3478'}
+: ${prosody_turn_host:="$turn_domain"}
+: ${prosody_turn_realm:="$turn_domain"}
+: ${prosody_turn_secret="$turn_secret"}
+
+prosody_dn="uid=${prosody_username},${robots_basedn}"
+prosody_local_user=prosody
+prosody_conf_dir=/usr/local/etc/prosody
+prosody_certs_dir="${prosody_conf_dir}/certs"
+prosody_keytab="${keytab_dir}/prosody.keytab"
+prosody_roster_path="${prosody_conf_dir}/roster.ini"
+prosody_http_port=8080
+prosody_upload_dir=/var/db/prosody/http_upload
+
+prosody_https_cacert="${acme_cert_dir}/nginx.ca.crt"
+prosody_https_cert="${acme_cert_dir}/nginx.crt"
+prosody_https_key="${acme_cert_dir}/nginx.key"
+
+# Install required packages.
+pkg install -y \
+ prosody \
+ prosody-modules \
+ lua54-luadbi \
+ lua54-lualdap \
+ nginx
+
+# Create ZFS dataset for HTTP upload files.
+create_dataset -o "mountpoint=${prosody_upload_dir}" "${state_dataset}/http_upload"
+
+# Set ownership on http_upload directory.
+install_directory -o "$prosody_local_user" -g "$prosody_local_user" -m 0750 "$prosody_upload_dir"
+
+# Create prosody user private group.
+ldap_add "cn=${prosody_username},${private_groups_basedn}" <<EOF
+objectClass: groupOfMembers
+objectClass: posixGroup
+cn: ${prosody_username}
+gidNumber: ${prosody_uid}
+member: uid=${prosody_username},${robots_basedn}
+EOF
+
+# Create prosody user account.
+ldap_add "$prosody_dn" <<EOF
+objectClass: account
+objectClass: posixAccount
+uid: ${prosody_username}
+cn: ${prosody_username}
+uidNumber: ${prosody_uid}
+gidNumber: ${prosody_uid}
+gecos: Prosody Pseudo-User
+loginShell: /sbin/nologin
+homeDirectory: /nonexistent
+EOF
+
+# Create principal and keytab.
+add_principal -nokey -x "dn=${prosody_dn}" "$prosody_username"
+
+ktadd -k "$prosody_keytab" "$prosody_username"
+chgrp "$prosody_local_user" "$prosody_keytab"
+chmod 640 "$prosody_keytab"
+
+prosody_local_uid=$(id -u "$prosody_local_user")
+install_directory -o "$prosody_local_user" -m 0700 "/var/krb5/user/${prosody_local_uid}"
+ln -snfv "$prosody_keytab" "/var/krb5/user/${prosody_local_uid}/client.keytab"
+
+# Set LDAP password for prosody user.
+ldap_passwd "$prosody_dn" "$prosody_ldap_password"
+
+# Create postgres user and database.
+postgres_create_role "$prosody_dbhost" "$prosody_username"
+postgres_create_database "$prosody_dbhost" "$prosody_dbname" "$prosody_username"
+
+# Retrieve prosody certificates via ACME proxy.
+install_directory -o root -g "$prosody_local_user" -m 0770 "$prosody_certs_dir"
+install_file -m 0555 /usr/local/libexec/prosody-acme-proxy
+su -m "$prosody_local_user" -c "/usr/local/libexec/prosody-acme-proxy ${prosody_username}@${prosody_acme_host} ${prosody_domains}"
+
+# Copy prosody configuration.
+install_template -o root -g "$prosody_local_user" -m 0640 /usr/local/etc/prosody/prosody.cfg.lua
+
+# Configure automatic roster.
+install_file -m 0555 /usr/local/libexec/prosody-update-roster
+install -Cv -m 0640 -o "$prosody_local_user" -g "$prosody_local_user" /dev/null "${prosody_conf_dir}/roster.ini"
+su -m "$prosody_local_user" -c "/usr/local/libexec/prosody-update-roster ${prosody_access_role} > ${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}" <<EOF
+objectClass: groupOfMembers
+cn: ${prosody_access_role}
+EOF
diff --git a/scripts/hostclass/znc_server b/scripts/hostclass/znc_server
new file mode 100644
index 0000000..c9f3780
--- /dev/null
+++ b/scripts/hostclass/znc_server
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+: ${znc_max_networks:='16'}
+: ${znc_access_role:='znc-access'}
+
+znc_http_port=8443
+znc_home=/usr/local/etc/znc
+znc_user=znc
+znc_tls_cert="${znc_home}/znc.crt"
+znc_tls_key="${znc_home}/znc.key"
+znc_clone_user='clone___'
+
+# Install required packages.
+pkg install -y \
+ cyrus-sasl-saslauthd \
+ nginx \
+ znc
+
+# Create ZFS dataset for ZNC configs.
+create_dataset -o "mountpoint=${znc_home}" "${state_dataset}/znc"
+
+# Set ownership on ZNC dir.
+install_directory -o "$znc_user" -g "$znc_user" -m 0755 "$znc_home"
+
+# Copy TLS certificate for ZNC.
+install_certificate -o "$znc_user" -g "$znc_user" znc "$znc_tls_cert"
+install_certificate_key -o "$znc_user" -g "$znc_user" znc "$znc_tls_key"
+
+# Generate ZNC configs.
+install_directory -o "$znc_user" -g "$znc_user" -m 0700 \
+ "${znc_home}/configs" \
+ "${znc_home}/moddata" \
+ "${znc_home}/moddata/cyrusauth"
+
+[ -f "${znc_home}/configs/znc.conf" ] \
+ || install_template -o "$znc_user" -g "$znc_user" -m 0600 "${znc_home}/configs/znc.conf"
+
+install_template -o "$znc_user" -g "$znc_user" -m 0600 "${znc_home}/moddata/cyrusauth/.registry"
+
+# Copy saslauthd configuration.
+# TODO: use ldap module for saslauthd.
+install_template -m 0644 \
+ /usr/local/lib/sasl2/znc.conf \
+ /etc/pam.d/znc
+
+# Allow znc to read the saslauthd socket.
+install_directory -m 0750 -o "$saslauthd_user" -g "$znc_user" "$saslauthd_runtime_dir"
+
+# Generate nginx configuration.
+install_template -m 0644 \
+ /usr/local/etc/nginx/nginx.conf \
+ /usr/local/etc/nginx/vhosts.conf
+
+sysrc -v \
+ saslauthd_enable=YES \
+ saslauthd_flags='-a pam' \
+ znc_enable=YES \
+ nginx_enable=YES
+
+service saslauthd restart
+service znc status || service znc start
+service nginx restart
+
+# Create access role.
+ldap_add "cn=${znc_access_role},${roles_basedn}" <<EOF
+objectClass: groupOfMembers
+cn: ${znc_access_role}
+EOF
diff --git a/scripts/hostname/znc1 b/scripts/hostname/znc1
new file mode 100644
index 0000000..dc11b11
--- /dev/null
+++ b/scripts/hostname/znc1
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cnames=znc
diff --git a/scripts/os/freebsd/60-acme b/scripts/os/freebsd/60-acme
index 902e674..94b832d 100644
--- a/scripts/os/freebsd/60-acme
+++ b/scripts/os/freebsd/60-acme
@@ -10,6 +10,9 @@ acme_standalone_port=9080
acme_user=acme
acme_home=/var/db/acme
acme_webroot=/usr/local/www/acme
+acmeproxy_home=/var/spool/acmeproxy
+
+dhparams_path=/etc/ssl/dhparams.pem
pkg install -y acme.sh
@@ -22,14 +25,20 @@ else
su -m "$acme_user" -c "acme.sh --home ${acme_home} --register-account --email ${acme_email}"
fi
+if [ "${nginx_public:-}" = true ] && ! [ -f "$dhparams_path" ]; then
+ openssl dhparam -out "$dhparams_path" 2048
+fi
+
acme_install_certificate(){
_aic_group=0
_aic_cert_path=
_aic_key_path=
+ _aic_ca_path=
_aic_reload_cmd=
- while getopts c:g:k:r: _aic_opt; do
+ while getopts C:c:g:k:r: _aic_opt; do
case $_aic_opt in
+ C) _aic_ca_path=$OPTARG ;;
c) _aic_cert_path=$OPTARG ;;
g) _aic_group=$OPTARG ;;
k) _aic_key_path=$OPTARG ;;
@@ -68,8 +77,28 @@ acme_install_certificate(){
fi
if [ -n "$_aic_reload_cmd" ]; then
- su -m "$acme_user" -c "acme.sh --home ${acme_home} --install-cert --domain ${_aic_name} --key-file ${_aic_key_path} --fullchain-file ${_aic_cert_path} --reloadcmd '${_aic_reload_cmd}'"
+ su -m "$acme_user" -c "acme.sh --home ${acme_home} --install-cert --domain ${_aic_name} --key-file ${_aic_key_path} --fullchain-file ${_aic_cert_path} --ca-file ${aic_ca_path} --reloadcmd '${_aic_reload_cmd}'"
else
- su -m "$acme_user" -c "acme.sh --home ${acme_home} --install-cert --domain ${_aic_name} --key-file ${_aic_key_path} --fullchain-file ${_aic_cert_path}"
+ su -m "$acme_user" -c "acme.sh --home ${acme_home} --install-cert --domain ${_aic_name} --key-file ${_aic_key_path} --fullchain-file ${_aic_cert_path} --ca-file ${aic_ca_path} "
fi
}
+
+acme_setup_proxy(){
+ [ -n "${acmeproxy_domains:-}" ] || return 0
+
+ install_directory -o root -g wheel -m 0755 "$acmeproxy_home"
+ install_directory -o "$acme_user" -g "${acmeproxy_client_gid:-${acmeproxy_client_group}}" -m 0750 "${acmeproxy_home}/certs"
+
+ # Configure SSHD for acmeproxy.
+ install_template -m 0644 /usr/local/etc/ssh/sshd_config.d/acmeproxy.conf
+ service sshd reload
+
+ # Acquire ACME certificates for client SFTP.
+ for domain in $acmeproxy_domains; do
+ acme_install_certificate \
+ -c "${acmeproxy_home}/certs/${domain}.crt" \
+ -k "${acmeproxy_home}/certs/${domain}.key" \
+ -g "${acmeproxy_client_gid:-${acmeproxy_client_group}}" \
+ $domain
+ done
+}
diff --git a/scripts/hostname/rlaptop1 b/site/scripts/hostname/rlaptop1
index f346965..f346965 100644
--- a/scripts/hostname/rlaptop1
+++ b/site/scripts/hostname/rlaptop1
diff --git a/vars/common b/vars/common
index 18d0e52..92a0c96 100644
--- a/vars/common
+++ b/vars/common
@@ -3,6 +3,7 @@
site=myhomelab
domain=idm.example.com
email_domain=example.com
+turn_domain=turn.example.com
locale=en_US.UTF-8
ntp_pools='pool.ntp.org'
root_password=changeme
@@ -21,6 +22,8 @@ idm2 2 5.6.7.8"
reverse_dns_zones="0.168.192.in-addr.arpa 12.11.10.in-addr.arpa"
+kerberized_cidrs=192.168.0.0/24
+
rspamd_privkey='changeme with: rspamadm keypair'
rspamd_pubkey='changeme with: rspamadm keypair'
rspamd_ro_password='changeme'
@@ -46,6 +49,8 @@ krb5_renew_lifetime=7d
nslcd_min_uid=1000
nscd_ttl=600
nscd_negative_ttl=20
+prosody_username='s-prosody'
+prosody_uid=20005
rspamd_port=11334
ssh_authzkeys_uid=789
ssh_authzkeys_username=sshkeys
@@ -53,7 +58,7 @@ tcp_buffer_size=2097152 # suitable for 1 GigE
nginx_nofile=2048
nginx_worker_connections=768
-if $(( nproc > 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