aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--files/etc/cron.d/zfs-autosnapshot.freebsd5
-rw-r--r--files/etc/cron.d/zfs.freebsd (renamed from files/etc/cron.d/zfs-trim.freebsd)1
-rw-r--r--files/etc/login.access.freebsd13
-rw-r--r--files/etc/pam.d/kde.freebsd2
-rw-r--r--files/etc/pam.d/login.freebsd3
-rw-r--r--files/etc/pam.d/other.freebsd8
-rw-r--r--files/etc/pam.d/sddm.freebsd3
-rw-r--r--files/etc/pam.d/sshd.freebsd4
-rw-r--r--files/etc/pam.d/su.freebsd10
-rw-r--r--files/etc/pam.d/sudo.freebsd3
-rw-r--r--files/etc/pam.d/system.freebsd8
-rw-r--r--files/etc/pf.conf.nfs_server52
-rw-r--r--files/usr/local/etc/nginx/vhosts.conf.nfs_server38
-rw-r--r--files/usr/local/etc/poudriere.d/pkglist.pkg_repository3
-rw-r--r--files/usr/local/etc/rc.d/syncthing_user.nfs_server86
-rw-r--r--files/usr/local/etc/syncthing.template.xml.nfs_server131
-rw-r--r--files/usr/share/skel/dot.login.freebsd4
-rw-r--r--files/usr/share/skel/dot.profile.freebsd6
-rw-r--r--files/usr/share/skel/dot.shrc.freebsd19
-rw-r--r--lib/10-core2
-rw-r--r--scripts/hostclass/asterisk_server4
-rw-r--r--scripts/hostclass/cups_server1
-rw-r--r--scripts/hostclass/desktop6
-rw-r--r--scripts/hostclass/idm_server/10-slapd5
-rw-r--r--scripts/hostclass/imap_server/10-solr4
-rw-r--r--scripts/hostclass/imap_server/30-dovecot5
-rw-r--r--scripts/hostclass/nfs_server/10-nfs (renamed from scripts/hostclass/nfs_server)0
-rw-r--r--scripts/hostclass/nfs_server/20-syncthing61
-rw-r--r--scripts/hostclass/pkg_repository3
-rw-r--r--scripts/hostclass/postgresql_server5
-rw-r--r--scripts/hostclass/public_webserver4
-rw-r--r--scripts/hostclass/smtp_server/10-rspamd4
-rw-r--r--scripts/hostclass/unifi_controller4
-rw-r--r--scripts/hostclass/znc_server4
-rw-r--r--scripts/hostname/nfs1/10-homedirs6
-rw-r--r--scripts/hostname/nfs1/20-shares5
-rw-r--r--scripts/os/80-zfs1
-rw-r--r--scripts/os/freebsd/20-zfs2
-rw-r--r--scripts/os/freebsd/50-idm17
-rw-r--r--scripts/os/freebsd/90-snapshots10
-rw-r--r--vars/hostclass/desktop3
-rw-r--r--vars/hostclass/freebsd_hypervisor1
-rw-r--r--vars/hostclass/nfs_server3
43 files changed, 546 insertions, 13 deletions
diff --git a/files/etc/cron.d/zfs-autosnapshot.freebsd b/files/etc/cron.d/zfs-autosnapshot.freebsd
new file mode 100644
index 0000000..0cc1e3b
--- /dev/null
+++ b/files/etc/cron.d/zfs-autosnapshot.freebsd
@@ -0,0 +1,5 @@
+15,30,45 * * * * root /usr/local/sbin/zfs-auto-snapshot frequent 4
+0 * * * * root /usr/local/sbin/zfs-auto-snapshot hourly 24
+7 0 * * * root /usr/local/sbin/zfs-auto-snapshot daily 7
+14 0 * * 7 root /usr/local/sbin/zfs-auto-snapshot weekly 4
+28 0 1 * * root /usr/local/sbin/zfs-auto-snapshot monthly 12
diff --git a/files/etc/cron.d/zfs-trim.freebsd b/files/etc/cron.d/zfs.freebsd
index 80e0cd5..477f1df 100644
--- a/files/etc/cron.d/zfs-trim.freebsd
+++ b/files/etc/cron.d/zfs.freebsd
@@ -1 +1,2 @@
@weekly root zpool list -Ho name | xargs -r -n1 zpool trim
+@monthly root zpool list -Ho name | xargs -r zpool scrub
diff --git a/files/etc/login.access.freebsd b/files/etc/login.access.freebsd
new file mode 100644
index 0000000..e6667db
--- /dev/null
+++ b/files/etc/login.access.freebsd
@@ -0,0 +1,13 @@
+# Always allow root logins.
++:root:ALL
+
+$(if [ -n "${login_access_groups:-}" ] || [ -n "${login_access_users:-}" ]; then
+ printf -- '-:ALL EXCEPT '
+if [ -n "${login_access_groups:-}" ]; then
+ printf '(%s) ' ${login_access_groups}
+fi
+if [ -n "${login_access_users:-}" ]; then
+ printf '%s ' ${login_access_users}
+fi
+ printf ':ALL\n'
+fi)
diff --git a/files/etc/pam.d/kde.freebsd b/files/etc/pam.d/kde.freebsd
index 8f87b98..cb89294 100644
--- a/files/etc/pam.d/kde.freebsd
+++ b/files/etc/pam.d/kde.freebsd
@@ -1,5 +1,5 @@
auth required /usr/local/lib/security/pam_krb5.so try_first_pass
account required /usr/local/lib/security/pam_krb5.so
-account required pam_login_access.so
+account required pam_login_access.so nodefgroup
account required pam_unix.so
diff --git a/files/etc/pam.d/login.freebsd b/files/etc/pam.d/login.freebsd
index 164fcb0..ae50bbe 100644
--- a/files/etc/pam.d/login.freebsd
+++ b/files/etc/pam.d/login.freebsd
@@ -5,12 +5,13 @@ auth required pam_unix.so no_warn try_first_pass nullok
account requisite pam_securetty.so
account required pam_nologin.so
account required /usr/local/lib/security/pam_krb5.so
-account required pam_login_access.so
+account required pam_login_access.so nodefgroup
account required pam_unix.so
session required pam_lastlog.so no_fail
session required pam_xdg.so
session required /usr/local/lib/security/pam_krb5.so
+session optional /usr/local/lib/pam_mkhomedir.so mode=0700
password sufficient /usr/local/lib/security/pam_krb5.so try_first_pass
password required pam_unix.so no_warn try_first_pass
diff --git a/files/etc/pam.d/other.freebsd b/files/etc/pam.d/other.freebsd
new file mode 100644
index 0000000..38db8c5
--- /dev/null
+++ b/files/etc/pam.d/other.freebsd
@@ -0,0 +1,8 @@
+auth required pam_unix.so no_warn try_first_pass
+
+account required pam_nologin.so
+account required pam_unix.so
+
+session required pam_permit.so
+
+password required pam_permit.so
diff --git a/files/etc/pam.d/sddm.freebsd b/files/etc/pam.d/sddm.freebsd
index 6a75823..c222750 100644
--- a/files/etc/pam.d/sddm.freebsd
+++ b/files/etc/pam.d/sddm.freebsd
@@ -10,12 +10,13 @@ auth optional pam_kwallet5.so
account requisite pam_securetty.so
account required pam_nologin.so
account required /usr/local/lib/security/pam_krb5.so
-account required pam_login_access.so
+account required pam_login_access.so nodefgroup
account required pam_unix.so
session required pam_lastlog.so no_fail
session required pam_xdg.so no_fail
session required /usr/local/lib/security/pam_krb5.so
+session optional /usr/local/lib/pam_mkhomedir.so mode=0700
session optional pam_kwallet5.so auto_start
password required /usr/local/lib/security/pam_krb5.so try_first_pass
diff --git a/files/etc/pam.d/sshd.freebsd b/files/etc/pam.d/sshd.freebsd
index 559a980..1f81b48 100644
--- a/files/etc/pam.d/sshd.freebsd
+++ b/files/etc/pam.d/sshd.freebsd
@@ -3,11 +3,11 @@ auth required pam_unix.so no_warn try_first_pass
account required pam_nologin.so
account required /usr/local/lib/security/pam_krb5.so
-account required pam_login_access.so
+account required pam_login_access.so nodefgroup
account required pam_unix.so
session required /usr/local/lib/security/pam_krb5.so
-session required pam_permit.so
+session required /usr/local/lib/pam_mkhomedir.so mode=0700
password sufficient /usr/local/lib/security/pam_krb5.so try_first_pass
password required pam_unix.so no_warn try_first_pass
diff --git a/files/etc/pam.d/su.freebsd b/files/etc/pam.d/su.freebsd
new file mode 100644
index 0000000..0bd3ea0
--- /dev/null
+++ b/files/etc/pam.d/su.freebsd
@@ -0,0 +1,10 @@
+auth sufficient pam_rootok.so no_warn
+auth sufficient pam_self.so no_warn
+auth requisite pam_group.so no_warn group=wheel root_only fail_safe ruser
+auth sufficient /usr/local/lib/security/pam_krb5.so try_first_pass
+auth required pam_unix.so no_warn try_first_pass nullok
+
+account required /usr/local/lib/security/pam_krb5.so
+account required pam_unix.so
+
+session required pam_permit.so
diff --git a/files/etc/pam.d/sudo.freebsd b/files/etc/pam.d/sudo.freebsd
index 6a6b0a4..6c0a573 100644
--- a/files/etc/pam.d/sudo.freebsd
+++ b/files/etc/pam.d/sudo.freebsd
@@ -2,10 +2,9 @@ auth sufficient /usr/local/lib/security/pam_krb5.so try_first_pass
auth required pam_unix.so no_warn try_first_pass
account required /usr/local/lib/security/pam_krb5.so
-account required pam_login_access.so
account required pam_unix.so
-account required pam_permit.so
+session required pam_permit.so
password sufficient /usr/local/lib/security/pam_krb5.so try_first_pass
password required pam_unix.so no_warn try_first_pass
diff --git a/files/etc/pam.d/system.freebsd b/files/etc/pam.d/system.freebsd
new file mode 100644
index 0000000..b85310c
--- /dev/null
+++ b/files/etc/pam.d/system.freebsd
@@ -0,0 +1,8 @@
+auth required pam_unix.so no_warn try_first_pass nullok
+
+account required pam_unix.so
+
+session required pam_lastlog.so no_fail
+session required pam_xdg.so
+
+password required pam_unix.so no_warn try_first_pass
diff --git a/files/etc/pf.conf.nfs_server b/files/etc/pf.conf.nfs_server
new file mode 100644
index 0000000..628ed7c
--- /dev/null
+++ b/files/etc/pf.conf.nfs_server
@@ -0,0 +1,52 @@
+$(if [ -n "${pf_egress_interfaces:-}" ]; then
+ printf 'egress = "{ %s }"\n' "$(join ', ' $pf_egress_interfaces)"
+ else
+ printf 'egress = "%s"\n' "$BOXCONF_DEFAULT_INTERFACE"
+ fi)
+allowed_tcp_ports = "{ $(join ', ' ${allowed_tcp_ports:-}) }"
+allowed_udp_ports = "{ $(join ', ' ${allowed_udp_ports:-}) }"
+
+$([ "${acme_standalone:-}" = true ] && cat <<EOF
+acme_standalone_port = ${acme_standalone_port}
+acme_standalone_user = $(id -u "$acme_user")
+EOF
+)
+nfscbd_port = ${nfscbd_port}
+
+set block-policy return
+set skip on lo
+$([ -n "${pf_skip_interfaces:-}" ] && printf \
+ 'set skip on %s\n' $pf_skip_interfaces)
+
+scrub in on \$egress all fragment reassemble no-df
+
+$([ "${acme_standalone:-}" = true ] && echo \
+ 'rdr on $egress inet proto tcp to port http -> ($egress) port $acme_standalone_port'
+
+[ -n "${redirect_tcp_ports:-}" ] && printf \
+ 'rdr on $egress inet proto tcp to port %s -> ($egress) port %s\n' $redirect_tcp_ports
+
+[ -n "${redirect_udp_ports:-}" ] && printf \
+ 'rdr on $egress inet proto udp to port %s -> ($egress) port %s\n' $redirect_udp_ports)
+
+antispoof quick for \$egress
+
+block all
+pass out quick on \$egress inet
+pass in quick on \$egress inet proto icmp all icmp-type { echoreq, unreach }
+
+$([ "${acme_standalone:-}" = true ] && echo \
+ 'pass in quick on $egress inet proto tcp to port $acme_standalone_port user $acme_standalone_user'
+
+[ -n "${allowed_tcp_ports:-}" ] && echo \
+ 'pass in quick on $egress inet proto tcp to port $allowed_tcp_ports'
+
+[ -n "${allowed_udp_ports:-}" ] && echo \
+ 'pass in quick on $egress inet proto udp to port $allowed_udp_ports'
+
+[ "$BOXCONF_VIRTUALIZATION_TYPE" == jail ] || echo \
+ 'pass in quick on $egress inet proto { tcp, udp } to port $nfscbd_port'
+
+for user in ${syncthing_users:-}; do uid=$(id -u "$user"); eval "port=\$syncthing_${user}_port"; printf \
+ 'pass in quick on $egress inet proto { tcp, udp } to port %s user %s\n' "$port" "$(id -u "$user")"
+done)
diff --git a/files/usr/local/etc/nginx/vhosts.conf.nfs_server b/files/usr/local/etc/nginx/vhosts.conf.nfs_server
new file mode 100644
index 0000000..e6fa55b
--- /dev/null
+++ b/files/usr/local/etc/nginx/vhosts.conf.nfs_server
@@ -0,0 +1,38 @@
+$(for user in ${syncthing_users:-}; do cat <<EOF
+upstream syncthing_${user} {
+ server unix:///var/run/syncthing/${user}/syncthing.sock;
+}
+
+EOF
+done)
+
+server {
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ http2 on;
+
+ ssl_certificate ${syncthing_https_cert};
+ ssl_certificate_key ${syncthing_https_key};
+
+ add_header Strict-Transport-Security "max-age=63072000" always;
+
+ auth_gss_keytab ${nginx_keytab};
+ auth_gss_allow_basic_fallback off;
+
+$(for user in ${syncthing_users:-}; do cat <<EOF
+ location /${user}/ {
+ proxy_http_version 1.1;
+ proxy_set_header Connection "";
+ 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_read_timeout 600s;
+ proxy_send_timeout 600s;
+ proxy_pass http://syncthing_${user}/;
+ auth_gss on;
+ auth_gss_authorized_principal ${user};
+ }
+EOF
+done)
+}
diff --git a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
index 883a88d..7d2a7ab 100644
--- a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
@@ -88,6 +88,7 @@ net/php${php_version}-ldap
net/php${php_version}-sockets
net/py-python-ldap
net/rsync
+net/syncthing
net/turnserver
net/wireguard-tools
ports-mgmt/poudriere
@@ -102,6 +103,7 @@ security/kstart
security/openssh-portable
security/pam_krb5@mit
security/pam_mkhomedir
+security/pam_mkhomedir
security/php${php_version}-filter
security/py-omemo-dr
security/sshpass
@@ -120,6 +122,7 @@ sysutils/pwgen
sysutils/stow
sysutils/tmux
sysutils/tree
+sysutils/zfstools
textproc/hs-pandoc
textproc/jq
textproc/p5-YAML
diff --git a/files/usr/local/etc/rc.d/syncthing_user.nfs_server b/files/usr/local/etc/rc.d/syncthing_user.nfs_server
new file mode 100644
index 0000000..0229047
--- /dev/null
+++ b/files/usr/local/etc/rc.d/syncthing_user.nfs_server
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+# PROVIDE: syncthing_user
+# REQUIRE: DAEMON nslcd
+# KEYWORD: shutdown
+#
+# syncthing_user_enable=YES
+# syncthing_user_instances="bob joe"
+# syncthing_user_bob_port="22000"
+# syncthing_user_joe_port="22001"
+
+. /etc/rc.subr
+
+name=syncthing_user
+rcvar=syncthing_user_enable
+
+load_rc_config $name
+
+: ${syncthing_user_enable:='NO'}
+: ${syncthing_user_socket_group:='www'}
+
+syncthing_user_rundir=/var/run/syncthing
+syncthing_user_confdir=/var/db/syncthing
+syncthing_user_args='serve --no-browser --no-upgrade --no-default-folder --logflags=0 --logfile=-'
+syncthing_config_template=/usr/local/etc/syncthing.template.xml
+
+procname="/usr/local/bin/syncthing"
+command="/usr/sbin/daemon"
+start_precmd=syncthing_user_startprecmd
+required_files="${syncthing_config_template}"
+
+syncthing_user_startprecmd()
+{
+ [ -d "$syncthing_user_rundir" ] || install -d -m 0755 "$syncthing_user_rundir"
+ [ -d "$syncthing_user_irundir" ] || install -d -m 2750 -o "$syncthing_user_user" -g "$syncthing_user_socket_group" "$syncthing_user_irundir"
+ [ -d "$syncthing_user_iconfdir" ] || install -d -m 0750 -o "$syncthing_user_user" -g "$syncthing_user_user" "$syncthing_user_iconfdir"
+
+ if [ ! -f "${syncthing_user_iconfdir}/config.xml" ]; then
+ su -m "$syncthing_user_user" -c "${procname} generate --home=${syncthing_user_iconfdir}"
+
+ deviceid=$("$procname" serve --home="$syncthing_user_iconfdir" --device-id)
+ fqdn=$(hostname -f)
+ sed -E \
+ -e "s|__DEVICEID__|${deviceid}|" \
+ -e "s|__PORT__|${syncthing_user_port}|" \
+ -e "s|__FQDN__|${fqdn}|" \
+ -e "s|__SOCK__|${syncthing_user_irundir}/syncthing.sock|" \
+ "$syncthing_config_template" > "${syncthing_user_iconfdir}/config.xml"
+ fi
+}
+
+if [ -n "$syncthing_user_instances" ]; then
+ _1=$1
+ if [ $# -gt 1 ]; then
+ shift
+ syncthing_user_instances=$*
+ fi
+
+ rc=0
+ for syncthing_user_user in $syncthing_user_instances; do
+ syncthing_user_group=$syncthing_user_user
+ syncthing_user_iconfdir="${syncthing_user_confdir}/${syncthing_user_user}"
+ syncthing_user_irundir="${syncthing_user_rundir}/${syncthing_user_user}"
+ unset syncthing_user_port
+ eval "syncthing_user_port=\$syncthing_user_${syncthing_user_user}_port"
+
+ if [ -z "${syncthing_user_port:-}" ]; then
+ echo "syncthing_user_${syncthing_user_user}_port not defined in /etc/rc.conf - skipping" 1>&2
+ continue
+ fi
+
+ pidfile="${syncthing_user_rundir}/${syncthing_user_user}/syncthing.pid"
+ command_args="-cf -s info -l daemon -T syncthing-${syncthing_user_user} -p ${pidfile} -t syncthing-${syncthing_user_user} \
+ ${procname} ${syncthing_user_args} --home=${syncthing_user_iconfdir} --gui-address=unix://${syncthing_user_irundir}/syncthing.sock"
+
+ run_rc_command "$_1"
+ if [ $? -ne 0 ]; then rc=1; fi
+
+ unset _pidcmd _rc_restart_done
+ done
+
+ exit $rc
+else
+ echo 'No users defined. Set syncthing_user_instances in /etc/rc.conf.' 1>&2
+ exit 1
+fi
diff --git a/files/usr/local/etc/syncthing.template.xml.nfs_server b/files/usr/local/etc/syncthing.template.xml.nfs_server
new file mode 100644
index 0000000..3ee90a1
--- /dev/null
+++ b/files/usr/local/etc/syncthing.template.xml.nfs_server
@@ -0,0 +1,131 @@
+<configuration version="37">
+ <device id="__DEVICEID__" name="__FQDN__" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
+ <address>tcp://__FQDN__:__PORT__</address>
+ <paused>false</paused>
+ <autoAcceptFolders>false</autoAcceptFolders>
+ <maxSendKbps>0</maxSendKbps>
+ <maxRecvKbps>0</maxRecvKbps>
+ <maxRequestKiB>0</maxRequestKiB>
+ <untrusted>false</untrusted>
+ <remoteGUIPort>0</remoteGUIPort>
+ <numConnections>0</numConnections>
+ </device>
+ <gui enabled="true" tls="false" debugging="false" sendBasicAuthPrompt="false">
+ <address>unix://__SOCK__</address>
+ <unixSocketPermissions>770</unixSocketPermissions>
+ <theme>default</theme>
+ <insecureSkipHostcheck>true</insecureSkipHostcheck>
+ </gui>
+ <ldap></ldap>
+ <options>
+ <listenAddress>quic://0.0.0.0:__PORT__</listenAddress>
+ <listenAddress>tcp://0.0.0.0:__PORT__</listenAddress>
+ <globalAnnounceServer>default</globalAnnounceServer>
+ <globalAnnounceEnabled>false</globalAnnounceEnabled>
+ <localAnnounceEnabled>false</localAnnounceEnabled>
+ <localAnnouncePort>0</localAnnouncePort>
+ <localAnnounceMCAddr>[ff12::8384]:0</localAnnounceMCAddr>
+ <maxSendKbps>0</maxSendKbps>
+ <maxRecvKbps>0</maxRecvKbps>
+ <reconnectionIntervalS>60</reconnectionIntervalS>
+ <relaysEnabled>false</relaysEnabled>
+ <relayReconnectIntervalM>10</relayReconnectIntervalM>
+ <startBrowser>false</startBrowser>
+ <natEnabled>false</natEnabled>
+ <natLeaseMinutes>60</natLeaseMinutes>
+ <natRenewalMinutes>30</natRenewalMinutes>
+ <natTimeoutSeconds>10</natTimeoutSeconds>
+ <urAccepted>-1</urAccepted>
+ <urSeen>0</urSeen>
+ <urUniqueID></urUniqueID>
+ <urURL>https://data.syncthing.net/newdata</urURL>
+ <urPostInsecurely>false</urPostInsecurely>
+ <urInitialDelayS>1800</urInitialDelayS>
+ <autoUpgradeIntervalH>0</autoUpgradeIntervalH>
+ <upgradeToPreReleases>false</upgradeToPreReleases>
+ <keepTemporariesH>24</keepTemporariesH>
+ <cacheIgnoredFiles>false</cacheIgnoredFiles>
+ <progressUpdateIntervalS>5</progressUpdateIntervalS>
+ <limitBandwidthInLan>false</limitBandwidthInLan>
+ <minHomeDiskFree unit="%">1</minHomeDiskFree>
+ <releasesURL>https://upgrades.syncthing.net/meta.json</releasesURL>
+ <overwriteRemoteDeviceNamesOnConnect>false</overwriteRemoteDeviceNamesOnConnect>
+ <tempIndexMinBlocks>10</tempIndexMinBlocks>
+ <trafficClass>0</trafficClass>
+ <setLowPriority>false</setLowPriority>
+ <maxFolderConcurrency>0</maxFolderConcurrency>
+ <crashReportingURL>https://crash.syncthing.net/newcrash</crashReportingURL>
+ <crashReportingEnabled>false</crashReportingEnabled>
+ <stunKeepaliveStartS>0</stunKeepaliveStartS>
+ <stunKeepaliveMinS>0</stunKeepaliveMinS>
+ <stunServer>default</stunServer>
+ <databaseTuning>auto</databaseTuning>
+ <maxConcurrentIncomingRequestKiB>0</maxConcurrentIncomingRequestKiB>
+ <announceLANAddresses>true</announceLANAddresses>
+ <sendFullIndexOnUpgrade>false</sendFullIndexOnUpgrade>
+ <connectionLimitEnough>0</connectionLimitEnough>
+ <connectionLimitMax>0</connectionLimitMax>
+ <insecureAllowOldTLSVersions>false</insecureAllowOldTLSVersions>
+ <connectionPriorityTcpLan>10</connectionPriorityTcpLan>
+ <connectionPriorityQuicLan>20</connectionPriorityQuicLan>
+ <connectionPriorityTcpWan>30</connectionPriorityTcpWan>
+ <connectionPriorityQuicWan>40</connectionPriorityQuicWan>
+ <connectionPriorityRelay>50</connectionPriorityRelay>
+ <connectionPriorityUpgradeThreshold>0</connectionPriorityUpgradeThreshold>
+ </options>
+ <defaults>
+ <folder id="" label="" path="~" type="sendreceive" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
+ <filesystemType>basic</filesystemType>
+ <device id="__DEVICEID__" introducedBy="">
+ <encryptionPassword></encryptionPassword>
+ </device>
+ <minDiskFree unit="%">1</minDiskFree>
+ <versioning>
+ <cleanupIntervalS>3600</cleanupIntervalS>
+ <fsPath></fsPath>
+ <fsType>basic</fsType>
+ </versioning>
+ <copiers>0</copiers>
+ <pullerMaxPendingKiB>0</pullerMaxPendingKiB>
+ <hashers>0</hashers>
+ <order>random</order>
+ <ignoreDelete>false</ignoreDelete>
+ <scanProgressIntervalS>0</scanProgressIntervalS>
+ <pullerPauseS>0</pullerPauseS>
+ <maxConflicts>10</maxConflicts>
+ <disableSparseFiles>false</disableSparseFiles>
+ <disableTempIndexes>false</disableTempIndexes>
+ <paused>false</paused>
+ <weakHashThresholdPct>25</weakHashThresholdPct>
+ <markerName>.stfolder</markerName>
+ <copyOwnershipFromParent>false</copyOwnershipFromParent>
+ <modTimeWindowS>0</modTimeWindowS>
+ <maxConcurrentWrites>2</maxConcurrentWrites>
+ <disableFsync>false</disableFsync>
+ <blockPullOrder>standard</blockPullOrder>
+ <copyRangeMethod>standard</copyRangeMethod>
+ <caseSensitiveFS>false</caseSensitiveFS>
+ <junctionsAsDirs>false</junctionsAsDirs>
+ <syncOwnership>false</syncOwnership>
+ <sendOwnership>false</sendOwnership>
+ <syncXattrs>false</syncXattrs>
+ <sendXattrs>false</sendXattrs>
+ <xattrFilter>
+ <maxSingleEntrySize>1024</maxSingleEntrySize>
+ <maxTotalSize>4096</maxTotalSize>
+ </xattrFilter>
+ </folder>
+ <device id="" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
+ <address>dynamic</address>
+ <paused>false</paused>
+ <autoAcceptFolders>false</autoAcceptFolders>
+ <maxSendKbps>0</maxSendKbps>
+ <maxRecvKbps>0</maxRecvKbps>
+ <maxRequestKiB>0</maxRequestKiB>
+ <untrusted>false</untrusted>
+ <remoteGUIPort>0</remoteGUIPort>
+ <numConnections>0</numConnections>
+ </device>
+ <ignores></ignores>
+ </defaults>
+</configuration>
diff --git a/files/usr/share/skel/dot.login.freebsd b/files/usr/share/skel/dot.login.freebsd
new file mode 100644
index 0000000..6afb9f2
--- /dev/null
+++ b/files/usr/share/skel/dot.login.freebsd
@@ -0,0 +1,4 @@
+# .login - csh login script, read by login shell, after `.cshrc' at login.
+
+# Query terminal size; useful for serial lines.
+if ( -x /usr/bin/resizewin ) /usr/bin/resizewin -z
diff --git a/files/usr/share/skel/dot.profile.freebsd b/files/usr/share/skel/dot.profile.freebsd
new file mode 100644
index 0000000..0197635
--- /dev/null
+++ b/files/usr/share/skel/dot.profile.freebsd
@@ -0,0 +1,6 @@
+export CLICOLOR=1
+export PAGER=less
+export LESS='-iMRS -x2'
+export EDITOR=vi
+export LSCOLORS=DxfxgxgxcxxbxbaCacADAd
+export ENV="${HOME}/.shrc"
diff --git a/files/usr/share/skel/dot.shrc.freebsd b/files/usr/share/skel/dot.shrc.freebsd
new file mode 100644
index 0000000..bc8e8da
--- /dev/null
+++ b/files/usr/share/skel/dot.shrc.freebsd
@@ -0,0 +1,19 @@
+reset=$'\e[0m'
+blue=$'\e[0;34m'
+green=$'\e[0;32m'
+PS1="\[${green}\]\u@\h\[${reset}\]:\[${blue}\]\W\[${green}\]\$\[${reset}\] "
+unset reset blue green
+
+alias ls='ls -FHh'
+alias ll='ls -l'
+alias la='ls -la'
+alias ..='cd ..'
+alias ...='cd ../..'
+alias mkdir='mkdir -p'
+alias df='df -h'
+alias du='du -ch'
+
+bind ^[[A ed-search-prev-history
+bind ^[[B ed-search-next-history
+bind "\\e[1;5C" em-next-word
+bind "\\e[1;5D" ed-prev-word
diff --git a/lib/10-core b/lib/10-core
index bd4e80a..60d1101 100644
--- a/lib/10-core
+++ b/lib/10-core
@@ -351,7 +351,7 @@ _boxconf_run(){
"${BOXCONF_SITE_SCRIPT_DIR}/hostname/${BOXCONF_HOSTNAME}"
# Reboot the target host if requested.
- if [ "${BOXCONF_NEED_REBOOT:-}" = true ]; then
+ if [ "${BOXCONF_NEED_REBOOT:-}" = true ] && [ "${boxconf_reboot:-}" != false ]; then
log '$BOXCONF_NEED_REBOOT was set. Rebooting host...'
reboot
fi
diff --git a/scripts/hostclass/asterisk_server b/scripts/hostclass/asterisk_server
index d519730..fe10f51 100644
--- a/scripts/hostclass/asterisk_server
+++ b/scripts/hostclass/asterisk_server
@@ -44,6 +44,10 @@ pkg install -y \
# Create ZFS dataset for Asterisk DB.
create_dataset -o "mountpoint=${asterisk_db_dir}" "${state_dataset}/asterisk"
+zfs set \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/asterisk"
install_directory -o "$asterisk_user" -g "$asterisk_user" -m 0755 "$asterisk_db_dir"
# Generate asterisk configuration.
diff --git a/scripts/hostclass/cups_server b/scripts/hostclass/cups_server
index d9b6e66..0fd624c 100644
--- a/scripts/hostclass/cups_server
+++ b/scripts/hostclass/cups_server
@@ -11,6 +11,7 @@ cups_tls_key="${cups_tls_dir}/${fqdn}.key"
# Create dataset for persistent CUPS configuration.
create_dataset -o "mountpoint=${cups_conf_dir}" "${state_dataset}/cups"
+zfs set com.sun:auto-snapshot:daily=true "${state_dataset}/cups"
# Install required packages.
pkg install -y cups cups-filters
diff --git a/scripts/hostclass/desktop b/scripts/hostclass/desktop
index ed71393..ac8bdda 100644
--- a/scripts/hostclass/desktop
+++ b/scripts/hostclass/desktop
@@ -1,6 +1,5 @@
#!/bin/sh
-: ${desktop_access_role:='desktop-access'}
: ${desktop_access_gid:='40000'}
: ${sddm_min_uid:='10000'}
: ${sddm_max_uid:='19999'}
@@ -38,6 +37,11 @@ install_file -m 0555 \
# Create ZFS dataset for local homedirs.
create_dataset -o mountpoint=/usr/local/home "${state_dataset}/home"
+zfs set \
+ com.sun:auto-snapshot:hourly=true \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/home"
# Enable sndio.
sysrc -v sndiod_enable=YES
diff --git a/scripts/hostclass/idm_server/10-slapd b/scripts/hostclass/idm_server/10-slapd
index d01db70..12640a4 100644
--- a/scripts/hostclass/idm_server/10-slapd
+++ b/scripts/hostclass/idm_server/10-slapd
@@ -36,6 +36,11 @@ pkg install -y \
# Create ZFS dataset for OpenLDAP DB.
create_dataset -o "mountpoint=${slapd_data_dir}" "${state_dataset}/openldap-data"
+zfs set \
+ com.sun:auto-snapshot:hourly=true \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/openldap-data"
# To prevent a circular dependency in poudriere, we have to make a special "set"
# of packages for the IDM hosts in which cyrus-sasl-gssapi is built with the
diff --git a/scripts/hostclass/imap_server/10-solr b/scripts/hostclass/imap_server/10-solr
index 252a8c3..a30d6fd 100644
--- a/scripts/hostclass/imap_server/10-solr
+++ b/scripts/hostclass/imap_server/10-solr
@@ -28,6 +28,10 @@ add_user \
# Create ZFS dataset for solr DB.
create_dataset -o "mountpoint=${solr_data_dir}" "${state_dataset}/solr"
+zfs set \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/solr"
# Set ownership on solr DB dir.
install_directory -m 0770 -o "$solr_user" -g "$solr_user" "$solr_data_dir"
diff --git a/scripts/hostclass/imap_server/30-dovecot b/scripts/hostclass/imap_server/30-dovecot
index ff41da5..66edd1d 100644
--- a/scripts/hostclass/imap_server/30-dovecot
+++ b/scripts/hostclass/imap_server/30-dovecot
@@ -35,6 +35,11 @@ add_user \
# Create ZFS dataset for virtual maildirs.
create_dataset -o "mountpoint=${dovecot_vmail_dir}" "${state_dataset}/mailboxes"
+zfs set \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ com.sun:auto-snapshot:monthly=true \
+ "${state_dataset}/mailboxes"
# Set ownership on vmail dir.
install_directory -m 0770 -o "$dovecot_vmail_user" -g "$dovecot_vmail_user" "$dovecot_vmail_dir"
diff --git a/scripts/hostclass/nfs_server b/scripts/hostclass/nfs_server/10-nfs
index a775859..a775859 100644
--- a/scripts/hostclass/nfs_server
+++ b/scripts/hostclass/nfs_server/10-nfs
diff --git a/scripts/hostclass/nfs_server/20-syncthing b/scripts/hostclass/nfs_server/20-syncthing
new file mode 100644
index 0000000..095b55c
--- /dev/null
+++ b/scripts/hostclass/nfs_server/20-syncthing
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# syncthing_users='user1 user2'
+# syncthing_user1_port=22000
+# syncthing_user2_port=22001
+
+if [ -z "${syncthing_users:-}" ]; then
+ return 0
+fi
+
+syncthing_https_cert="${nginx_conf_dir}/syncthing.crt"
+syncthing_https_key="${nginx_conf_dir}/syncthing.key"
+syncthing_conf_dir=/var/db/syncthing
+nginx_keytab="${keytab_dir}/nginx.keytab"
+
+pkg install -y \
+ syncthing \
+ nginx
+
+# Create ZFS dataset for syncthing configuration.
+create_dataset -o "mountpoint=$syncthing_conf_dir" "${state_dataset}/syncthing"
+zfs set \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/syncthing"
+install_directory -m 0755 "$syncthing_conf_dir"
+
+# Copy syncthing_user rc script.
+install_file -m 0644 /usr/local/etc/syncthing.template.xml
+install_file -m 0555 /usr/local/etc/rc.d/syncthing_user
+
+# Generate nginx configuration.
+install_template -m 0644 \
+ /usr/local/etc/nginx/nginx.conf \
+ /usr/local/etc/nginx/vhosts.conf
+
+# Create HTTP service principal and keytab.
+add_principal -nokey -x "containerdn=${services_basedn}" "HTTP/${fqdn}"
+
+ktadd -k "$nginx_keytab" "HTTP/${fqdn}"
+chgrp "$nginx_user" "$nginx_keytab"
+chmod 640 "$nginx_keytab"
+
+# Copy TLS certificate for nginx.
+install_certificate nginx "$syncthing_https_cert"
+install_certificate_key nginx "$syncthing_https_key"
+
+# Enable and start daemons.
+sysrc -v nginx_enable=YES
+service nginx restart
+
+sysrc -v \
+ syncthing_user_enable=YES \
+ "syncthing_user_instances+=${syncthing_users}"
+
+for user in $syncthing_users; do
+ eval "port=\$syncthing_${user}_port"
+ sysrc -v "syncthing_user_${user}_port=${port}"
+done
+
+service syncthing_user restart
diff --git a/scripts/hostclass/pkg_repository b/scripts/hostclass/pkg_repository
index 969dff7..7044f96 100644
--- a/scripts/hostclass/pkg_repository
+++ b/scripts/hostclass/pkg_repository
@@ -18,6 +18,9 @@ poudriere_patch_dir="${poudriere_conf_dir}/patches"
# Create poudriere datasets.
create_dataset -o "mountpoint=${poudriere_data_dir}" "${state_dataset}/poudriere"
create_dataset -o "mountpoint=${poudriere_conf_dir}" "${state_dataset}/poudriere-config"
+zfs set com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/poudriere" \
+ "${state_dataset}/poudriere-config"
# Since we're doing a ton of compilation, disable sync on the poudriere dataset.
# Possibly snakeoil, but my hope is that most file I/O will end up in the ARC cache
diff --git a/scripts/hostclass/postgresql_server b/scripts/hostclass/postgresql_server
index 10bafc8..dbb84b4 100644
--- a/scripts/hostclass/postgresql_server
+++ b/scripts/hostclass/postgresql_server
@@ -28,6 +28,11 @@ create_dataset \
-o primarycache=metadata \
-o atime=off \
"${state_dataset}/postgres"
+zfs set \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ com.sun:auto-snapshot:monthly=true \
+ "${state_dataset}/postgres"
install_directory -m 0755 -o "$postgres_user" -g "$postgres_user" "$postgres_home"
# Initialize the database.
diff --git a/scripts/hostclass/public_webserver b/scripts/hostclass/public_webserver
index ccf5991..721cbfc 100644
--- a/scripts/hostclass/public_webserver
+++ b/scripts/hostclass/public_webserver
@@ -14,6 +14,10 @@ pkg install -y \
# Create ZFS dataset for webroots.
create_dataset -o "mountpoint=${vhosts_dir}" "${state_dataset}/vhosts"
+zfs set \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/vhosts"
# Configure nginx.
install_template -m 0644 /usr/local/etc/nginx/nginx.conf
diff --git a/scripts/hostclass/smtp_server/10-rspamd b/scripts/hostclass/smtp_server/10-rspamd
index 7b1aae9..215788b 100644
--- a/scripts/hostclass/smtp_server/10-rspamd
+++ b/scripts/hostclass/smtp_server/10-rspamd
@@ -33,6 +33,10 @@ pkg install -y \
# Create ZFS dataset for Redis DBs.
create_dataset -o "mountpoint=${redis_data_dir}" "${state_dataset}/redis"
+zfs set \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/redis"
# Generate config files for redis instances.
install_template -m 0644 \
diff --git a/scripts/hostclass/unifi_controller b/scripts/hostclass/unifi_controller
index 32df063..9fd161e 100644
--- a/scripts/hostclass/unifi_controller
+++ b/scripts/hostclass/unifi_controller
@@ -11,6 +11,10 @@ pkg install -y unifi8
# Create ZFS dataset for unifi data.
create_dataset -o "mountpoint=${unifi_home}/data" "${state_dataset}/unifi"
+zfs set \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/unifi"
# Set ownership on unifi data dir.
install_directory -o "$unifi_user" -g "$unifi_user" -m 0700 "${unifi_home}/data"
diff --git a/scripts/hostclass/znc_server b/scripts/hostclass/znc_server
index 58f1d8a..e2c2fa6 100644
--- a/scripts/hostclass/znc_server
+++ b/scripts/hostclass/znc_server
@@ -18,6 +18,10 @@ pkg install -y \
# Create ZFS dataset for ZNC configs.
create_dataset -o "mountpoint=${znc_home}" "${state_dataset}/znc"
+zfs set \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${state_dataset}/znc"
# Set ownership on ZNC dir.
install_directory -o "$znc_user" -g "$znc_user" -m 0755 "$znc_home"
diff --git a/scripts/hostname/nfs1/10-homedirs b/scripts/hostname/nfs1/10-homedirs
index f2cd25c..3a6d923 100644
--- a/scripts/hostname/nfs1/10-homedirs
+++ b/scripts/hostname/nfs1/10-homedirs
@@ -14,6 +14,9 @@ for userquota in ${nfs_homedirs:-}; do
zfs set "refquota=${privquota:-$default_priv_quota}" "${nfs_dataset}/user/${user}/priv"
zfs set "refquota=${pubquota:-$default_pub_quota}" "${nfs_dataset}/user/${user}/pub"
+ zfs set 'com.sun:auto-snapshot=true' \
+ "${nfs_dataset}/user/${user}/priv" \
+ "${nfs_dataset}/user/${user}/pub"
chown "${user}:${user}" \
"${nfs_root}/user/${user}/priv" \
@@ -34,6 +37,9 @@ for groupquota in ${nfs_groupdirs:-}; do
zfs set "refquota=${privquota:-$default_priv_quota}" "${nfs_dataset}/group/${group}/priv"
zfs set "refquota=${pubquota:-$default_pub_quota}" "${nfs_dataset}/group/${group}/pub"
+ zfs set 'com.sun:auto-snapshot=true' \
+ "${nfs_dataset}/group/${group}/priv" \
+ "${nfs_dataset}/group/${group}/pub"
chown "root:${group}" \
"${nfs_root}/group/${group}/priv" \
diff --git a/scripts/hostname/nfs1/20-shares b/scripts/hostname/nfs1/20-shares
index ef013cc..beb3b11 100644
--- a/scripts/hostname/nfs1/20-shares
+++ b/scripts/hostname/nfs1/20-shares
@@ -2,6 +2,11 @@
# media/music
create_dataset -p "${nfs_dataset}/media/music"
+zfs set \
+ compression=off \
+ com.sun:auto-snapshot:daily=true \
+ com.sun:auto-snapshot:weekly=true \
+ "${nfs_dataset}/media/music"
chgrp media-admin "${nfs_root}/media/music"
chmod 2770 "${nfs_root}/media/music"
set_facl "${nfs_root}/media/music" \
diff --git a/scripts/os/80-zfs b/scripts/os/80-zfs
new file mode 100644
index 0000000..1a24852
--- /dev/null
+++ b/scripts/os/80-zfs
@@ -0,0 +1 @@
+#!/bin/sh
diff --git a/scripts/os/freebsd/20-zfs b/scripts/os/freebsd/20-zfs
index 1cdc465..5d86df4 100644
--- a/scripts/os/freebsd/20-zfs
+++ b/scripts/os/freebsd/20-zfs
@@ -7,5 +7,5 @@ create_dataset -o mountpoint=none "$state_dataset"
# If this is baremetal host or a VM, trim the zpools periodically.
if [ "$BOXCONF_VIRTUALIZATION_TYPE" != jail ]; then
- install_file -m 0644 /etc/cron.d/zfs-trim
+ install_file -m 0644 /etc/cron.d/zfs
fi
diff --git a/scripts/os/freebsd/50-idm b/scripts/os/freebsd/50-idm
index ab7c2fd..1585c6f 100644
--- a/scripts/os/freebsd/50-idm
+++ b/scripts/os/freebsd/50-idm
@@ -15,14 +15,20 @@ pkg install -y \
pam_krb5 \
perl5 \
p5-perl-ldap \
- p5-Authen-SASL
+ p5-Authen-SASL \
+ pam_mkhomedir
# Configure PAM/NSS integration.
install_file -m 0644 \
/etc/nsswitch.conf \
+ /etc/pam.d/system \
/etc/pam.d/login \
/etc/pam.d/sshd \
- /etc/pam.d/sudo
+ /etc/pam.d/sudo \
+ /etc/pam.d/su \
+ /etc/pam.d/other
+
+install_template -m 0644 /etc/login.access
install_template -m 0644 \
/etc/krb5.conf \
@@ -30,6 +36,13 @@ install_template -m 0644 \
/usr/local/etc/openldap/ldap.conf \
/usr/local/etc/nslcd.conf
+# Ensure /home exists and configure skel files.
+install_directory -m 0755 /home
+install_file -m 0644 \
+ /usr/share/skel/dot.login \
+ /usr/share/skel/dot.profile \
+ /usr/share/skel/dot.shrc
+
# Create ldap.conf symlink.
ln -snfv /usr/local/etc/openldap/ldap.conf /usr/local/etc/ldap.conf
diff --git a/scripts/os/freebsd/90-snapshots b/scripts/os/freebsd/90-snapshots
new file mode 100644
index 0000000..fce9c34
--- /dev/null
+++ b/scripts/os/freebsd/90-snapshots
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Don't run autosnapshot within jails. Otherwise we will create duplicate
+# snapshots with the host system.
+if [ "$BOXCONF_VIRTUALIZATION_TYPE" = jail ]; then
+ return 0
+fi
+
+pkg install -y zfstools
+install_file -m 0644 /etc/cron.d/zfs-autosnapshot
diff --git a/vars/hostclass/desktop b/vars/hostclass/desktop
index 6c2e45f..4d97d4e 100644
--- a/vars/hostclass/desktop
+++ b/vars/hostclass/desktop
@@ -1,5 +1,8 @@
#!/bin/sh
+desktop_access_role='desktop-access'
+login_access_groups="${login_access_groups:-} ${desktop_access_role}"
+
# Let users run gdb/truss.
allow_proc_debug=1
diff --git a/vars/hostclass/freebsd_hypervisor b/vars/hostclass/freebsd_hypervisor
index f3d6ac1..818afc8 100644
--- a/vars/hostclass/freebsd_hypervisor
+++ b/vars/hostclass/freebsd_hypervisor
@@ -4,3 +4,4 @@ enable_pf=false
enable_idm=false
smtp_host=${smtp_host_ip}
resolvers=$bootstrap_resolvers
+boxconf_reboot=false
diff --git a/vars/hostclass/nfs_server b/vars/hostclass/nfs_server
index 2957aec..cd9963e 100644
--- a/vars/hostclass/nfs_server
+++ b/vars/hostclass/nfs_server
@@ -1,3 +1,4 @@
#!/bin/sh
-allowed_tcp_ports='ssh nfsd'
+allowed_tcp_ports='ssh nfsd http https'
+nginx_gssapi=true