aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--files/etc/auto_master.common2
-rw-r--r--files/etc/cron.d/freeradius.radius_server2
-rw-r--r--files/etc/cron.d/invidious.invidious_server2
-rw-r--r--files/etc/dma/dma.conf.freebsd1
-rw-r--r--files/etc/exports.common2
-rw-r--r--files/etc/login.conf.desktop64
l---------files/etc/login.conf.laptop1
l---------files/etc/login.conf.roadwarrior_laptop1
-rw-r--r--files/etc/pam.d/cups.cups_server8
-rw-r--r--files/etc/pam.d/kde.freebsd2
-rw-r--r--files/etc/pam.d/postgresql.postgresql_server2
-rw-r--r--files/etc/pam.d/sddm.freebsd16
-rw-r--r--files/etc/pam.d/sudo.freebsd15
-rw-r--r--files/etc/profile.d/kde.sh.common6
-rw-r--r--files/etc/profile.d/local-homedir.sh.common25
-rw-r--r--files/etc/syslog.conf.freebsd3
-rw-r--r--files/usr/local/etc/nginx/vhosts.conf.invidious_server22
-rw-r--r--files/usr/local/etc/nginx/vhosts.conf.pkg_repository7
-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/polkit-1/rules.d/51-desktop.rules.desktop8
-rw-r--r--files/usr/local/etc/poudriere.d/make.conf.pkg_repository4
-rw-r--r--files/usr/local/etc/poudriere.d/patches/chromium-gssapi.patch.pkg_repository54
-rw-r--r--files/usr/local/etc/poudriere.d/pkglist.pkg_repository57
-rw-r--r--files/usr/local/etc/raddb/mods-available/eap.radius_server42
-rw-r--r--files/usr/local/etc/raddb/radiusd.conf.radius_server80
-rw-r--r--files/usr/local/etc/rc.d/invidious.invidious_server41
-rw-r--r--files/usr/local/etc/sddm.conf.common9
-rw-r--r--files/usr/local/etc/ssh/sshd_config.freebsd2
-rw-r--r--files/usr/local/invidious/invidious.git/config/config.yml.invidious_server35
-rw-r--r--files/usr/local/libexec/idm-autofs-map.common44
-rw-r--r--files/usr/local/libexec/invidious-update.invidious_server48
-rw-r--r--files/usr/local/libexec/pam-create-local-homedir.common10
-rw-r--r--files/usr/local/override/applications/signal-desktop.desktop.common12
-rw-r--r--files/usr/local/www/davical/config/config.php.dav_server8
-rw-r--r--files/var/db/postgres/data16/pg_hba.conf.postgresql_server2
-rw-r--r--hostclasses3
-rw-r--r--scripts/common/10-vars2
-rw-r--r--scripts/hostclass/bitwarden_server2
-rw-r--r--scripts/hostclass/cups_server3
-rw-r--r--scripts/hostclass/desktop126
-rw-r--r--scripts/hostclass/freebsd_hypervisor3
-rw-r--r--scripts/hostclass/idm_server/10-slapd15
-rw-r--r--scripts/hostclass/idm_server/90-idm6
-rw-r--r--scripts/hostclass/invidious_server91
-rw-r--r--scripts/hostclass/laptop20
-rw-r--r--scripts/hostclass/nfs_server47
-rw-r--r--scripts/hostclass/pkg_repository10
-rw-r--r--scripts/hostclass/postgresql_server25
-rw-r--r--scripts/hostclass/radius_server56
-rw-r--r--scripts/hostclass/smtp_server/10-rspamd4
-rw-r--r--scripts/hostclass/unifi_controller40
-rw-r--r--scripts/hostname/nfs129
-rw-r--r--scripts/os/freebsd/10-cpu2
-rw-r--r--scripts/os/freebsd/10-sysctls2
-rw-r--r--scripts/os/freebsd/20-zfs2
-rw-r--r--scripts/os/freebsd/50-idm9
-rw-r--r--scripts/os/freebsd/51-autofs33
-rw-r--r--vars/common2
-rw-r--r--vars/hostclass/cups_server3
-rw-r--r--vars/hostclass/desktop45
-rw-r--r--vars/hostclass/invidious_server3
l---------vars/hostclass/laptop1
-rw-r--r--vars/hostclass/nfs_server3
-rw-r--r--vars/hostclass/pkg_repository2
-rw-r--r--vars/hostclass/radius_server3
l---------vars/hostclass/roadwarrior_laptop/desktop1
-rw-r--r--vars/hostclass/roadwarrior_laptop/vars (renamed from vars/hostclass/roadwarrior_laptop)2
-rw-r--r--vars/hostclass/unifi_controller8
-rw-r--r--vars/hostname/invidious14
-rw-r--r--vars/hostname/nfs13
-rw-r--r--vars/hostname/radius13
-rw-r--r--vars/hostname/unifi13
-rw-r--r--vars/hostname/znc1 (renamed from scripts/hostname/znc1)0
74 files changed, 1165 insertions, 90 deletions
diff --git a/files/etc/auto_master.common b/files/etc/auto_master.common
new file mode 100644
index 0000000..37f3e34
--- /dev/null
+++ b/files/etc/auto_master.common
@@ -0,0 +1,2 @@
+/net -hosts -nobrowse,nosuid,intr
++auto_master
diff --git a/files/etc/cron.d/freeradius.radius_server b/files/etc/cron.d/freeradius.radius_server
new file mode 100644
index 0000000..20f3ada
--- /dev/null
+++ b/files/etc/cron.d/freeradius.radius_server
@@ -0,0 +1,2 @@
+MAILTO=root
+@daily ${freeradius_user} find ${freeradius_tlscache_dir} -mindepth 1 -mtime +2 -exec rm -vf {} +
diff --git a/files/etc/cron.d/invidious.invidious_server b/files/etc/cron.d/invidious.invidious_server
new file mode 100644
index 0000000..89fa336
--- /dev/null
+++ b/files/etc/cron.d/invidious.invidious_server
@@ -0,0 +1,2 @@
+MAILTO=root
+0 3 * * * root /usr/local/libexec/invidious-update -q ${invidious_local_username} ${invidious_repo_dir}
diff --git a/files/etc/dma/dma.conf.freebsd b/files/etc/dma/dma.conf.freebsd
index ff8aae0..6975ed1 100644
--- a/files/etc/dma/dma.conf.freebsd
+++ b/files/etc/dma/dma.conf.freebsd
@@ -2,4 +2,3 @@ SMARTHOST ${smtp_host}
SECURETRANSFER
STARTTLS
OPPORTUNISTIC_TLS
-MAILNAME ${email_domain}
diff --git a/files/etc/exports.common b/files/etc/exports.common
new file mode 100644
index 0000000..4ea7fd2
--- /dev/null
+++ b/files/etc/exports.common
@@ -0,0 +1,2 @@
+V4: ${nfs_root}
+# The default is to not export anything.
diff --git a/files/etc/login.conf.desktop b/files/etc/login.conf.desktop
new file mode 100644
index 0000000..558c80a
--- /dev/null
+++ b/files/etc/login.conf.desktop
@@ -0,0 +1,64 @@
+default:\\
+ :passwd_format=sha512:\\
+ :copyright=/etc/COPYRIGHT:\\
+ :welcome=/var/run/motd:\\
+ :setenv=BLOCKSIZE=K,XDG_DATA_DIRS=/usr/local/override\\c/usr/local/share,XDG_DATA_HOME=/usr/local/home/\$/.local/share,XDG_STATE_HOME=/usr/local/home/\$/.local/state,XDG_CACHE_HOME=/usr/local/home/\$/.cache,XDG_CONFIG_HOME=/usr/local/home/\$/.config,KDEHOME=/usr/local/home/\$/.kde:\\
+ :mail=/var/mail/\$:\\
+ :path=/sbin /bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin ~/bin:\\
+ :nologin=/var/run/nologin:\\
+ :cputime=unlimited:\\
+ :datasize=unlimited:\\
+ :stacksize=unlimited:\\
+ :memorylocked=64M:\\
+ :memoryuse=unlimited:\\
+ :filesize=unlimited:\\
+ :coredumpsize=unlimited:\\
+ :openfiles=unlimited:\\
+ :maxproc=unlimited:\\
+ :sbsize=unlimited:\\
+ :vmemoryuse=unlimited:\\
+ :swapuse=unlimited:\\
+ :pseudoterminals=unlimited:\\
+ :kqueues=unlimited:\\
+ :umtxp=unlimited:\\
+ :priority=0:\\
+ :ignoretime@:\\
+ :umask=022:\\
+ :charset=UTF-8:\\
+ :lang=${locale}:
+
+#
+# A collection of common class names - forward them all to 'default'
+# (login would normally do this anyway, but having a class name
+# here suppresses the diagnostic)
+#
+standard:\\
+ :tc=default:
+xuser:\\
+ :tc=default:
+staff:\\
+ :tc=default:
+
+# This PATH may be clobbered by individual applications. Notably, by default,
+# rc(8), service(8), and cron(8) will all override it with a default PATH that
+# may not include /usr/local/sbin and /usr/local/bin when starting services or
+# jobs.
+daemon:\\
+ :path=/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin:\\
+ :mail@:\\
+ :memorylocked=128M:\\
+ :tc=default:
+news:\\
+ :tc=default:
+dialer:\\
+ :tc=default:
+
+#
+# Root can always login
+#
+# N.B. login_getpwclass(3) will use this entry for the root account,
+# in preference to 'default'.
+root:\\
+ :ignorenologin:\\
+ :memorylocked=unlimited:\\
+ :tc=default:
diff --git a/files/etc/login.conf.laptop b/files/etc/login.conf.laptop
new file mode 120000
index 0000000..2dde3a4
--- /dev/null
+++ b/files/etc/login.conf.laptop
@@ -0,0 +1 @@
+login.conf.desktop \ No newline at end of file
diff --git a/files/etc/login.conf.roadwarrior_laptop b/files/etc/login.conf.roadwarrior_laptop
new file mode 120000
index 0000000..2dde3a4
--- /dev/null
+++ b/files/etc/login.conf.roadwarrior_laptop
@@ -0,0 +1 @@
+login.conf.desktop \ No newline at end of file
diff --git a/files/etc/pam.d/cups.cups_server b/files/etc/pam.d/cups.cups_server
new file mode 100644
index 0000000..b61c074
--- /dev/null
+++ b/files/etc/pam.d/cups.cups_server
@@ -0,0 +1,8 @@
+# auth
+auth sufficient /usr/local/lib/security/pam_krb5.so try_first_pass
+auth required pam_unix.so no_warn try_first_pass
+
+# account
+account required /usr/local/lib/security/pam_krb5.so
+account required pam_login_access.so
+account required pam_unix.so
diff --git a/files/etc/pam.d/kde.freebsd b/files/etc/pam.d/kde.freebsd
new file mode 100644
index 0000000..2604c78
--- /dev/null
+++ b/files/etc/pam.d/kde.freebsd
@@ -0,0 +1,2 @@
+auth required /usr/local/lib/security/pam_krb5.so try_first_pass
+account required /usr/local/lib/security/pam_krb5.so
diff --git a/files/etc/pam.d/postgresql.postgresql_server b/files/etc/pam.d/postgresql.postgresql_server
deleted file mode 100644
index 8475a53..0000000
--- a/files/etc/pam.d/postgresql.postgresql_server
+++ /dev/null
@@ -1,2 +0,0 @@
-auth required /usr/local/lib/security/pam_krb5.so try_first_pass keytab=${postgres_keytab} no_ccache ignore_k5login no_update_user minimum_uid=0
-account required pam_permit.so
diff --git a/files/etc/pam.d/sddm.freebsd b/files/etc/pam.d/sddm.freebsd
new file mode 100644
index 0000000..ef359ff
--- /dev/null
+++ b/files/etc/pam.d/sddm.freebsd
@@ -0,0 +1,16 @@
+# NB: FreeBSD has no pam_stack.so or substack functionality, so we can't
+# try multiple authentication sources (like krb5 but fall back to pam_unix)
+# if we want pam_kwallet5 to execute.
+# Hence, for sddm, we try krb5 only (no local accounts).
+auth required /usr/local/lib/security/pam_krb5.so try_first_pass
+auth optional pam_exec.so /usr/local/libexec/pam-create-local-homedir
+auth optional pam_kwallet5.so
+
+account required /usr/local/lib/security/pam_krb5.so
+account required pam_login_access.so
+account required pam_unix.so
+
+session required pam_lastlog.so no_fail
+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/sudo.freebsd b/files/etc/pam.d/sudo.freebsd
new file mode 100644
index 0000000..425bf4e
--- /dev/null
+++ b/files/etc/pam.d/sudo.freebsd
@@ -0,0 +1,15 @@
+# auth
+auth sufficient /usr/local/lib/security/pam_krb5.so try_first_pass
+auth required pam_unix.so no_warn try_first_pass
+
+# account
+account required /usr/local/lib/security/pam_krb5.so
+account required pam_login_access.so
+account required pam_unix.so
+
+# session
+account required pam_permit.so
+
+# password
+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/profile.d/kde.sh.common b/files/etc/profile.d/kde.sh.common
new file mode 100644
index 0000000..010d5c1
--- /dev/null
+++ b/files/etc/profile.d/kde.sh.common
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if [ "$XDG_CURRENT_DESKTOP" = KDE ]; then
+ export SSH_ASKPASS_REQUIRE=prefer
+ export SSH_ASKPASS=/usr/local/bin/ksshaskpass
+fi
diff --git a/files/etc/profile.d/local-homedir.sh.common b/files/etc/profile.d/local-homedir.sh.common
new file mode 100644
index 0000000..d5abb90
--- /dev/null
+++ b/files/etc/profile.d/local-homedir.sh.common
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# This file contains various environment variables and hacks to accomodate
+# applications that don't play well with NFS-mounted home directories.
+
+if [ "$(id -u)" -lt 1000 ]; then
+ return 0
+fi
+
+LOCAL_HOME="/usr/local/home/${USER}"
+
+export PYTHONUSERBASE="${LOCAL_HOME}/.local"
+export npm_config_cache="${LOCAL_HOME}/.npm"
+export CARGO_HOME="${LOCAL_HOME}/.cargo"
+export GOPATH="${LOCAL_HOME}/go"
+
+# firefox
+mkdir -p "${LOCAL_HOME}/.mozilla"
+ln -sfn "${LOCAL_HOME}/.mozilla" "${HOME}/.mozilla"
+
+# kwallet
+# The kwallet PAM module hard-codes ~/.local/share/kwalletd, but kwallet itself
+# honors XDG_DATA_HOME! So we symlink from the local disk back into NFS. Gross!
+mkdir -p "${LOCAL_HOME}/.local/share/kwalletd"
+ln -sfn "${HOME}/.local/share/kwalletd/kwallet.salt" "${LOCAL_HOME}/.local/share/kwalletd/kdewallet.salt"
diff --git a/files/etc/syslog.conf.freebsd b/files/etc/syslog.conf.freebsd
index dda6710..021836e 100644
--- a/files/etc/syslog.conf.freebsd
+++ b/files/etc/syslog.conf.freebsd
@@ -1,4 +1,5 @@
*.err;kern.warning;auth.notice;mail.crit /dev/console
+!-devd
*.info;authpriv.none;auth.none;cron.none;kern.debug;mail.crit;news.err /var/log/messages
security.* /var/log/security
auth.info;authpriv.info /var/log/auth.log
@@ -7,6 +8,8 @@ cron.* /var/log/cron
!-devd
*.=debug /var/log/debug.log
*.emerg *
+!devd
+*.>=info /var/log/devd.log
!*
include /etc/syslog.d
include /usr/local/etc/syslog.d
diff --git a/files/usr/local/etc/nginx/vhosts.conf.invidious_server b/files/usr/local/etc/nginx/vhosts.conf.invidious_server
new file mode 100644
index 0000000..35947dc
--- /dev/null
+++ b/files/usr/local/etc/nginx/vhosts.conf.invidious_server
@@ -0,0 +1,22 @@
+server {
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ http2 on;
+
+ ssl_certificate ${invidious_https_cert};
+ ssl_certificate_key ${invidious_https_key};
+
+ add_header Strict-Transport-Security "max-age=63072000" always;
+
+ location / {
+ 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_pass http://127.0.0.1:${invidious_port};
+ }
+}
diff --git a/files/usr/local/etc/nginx/vhosts.conf.pkg_repository b/files/usr/local/etc/nginx/vhosts.conf.pkg_repository
index 8177626..73c5754 100644
--- a/files/usr/local/etc/nginx/vhosts.conf.pkg_repository
+++ b/files/usr/local/etc/nginx/vhosts.conf.pkg_repository
@@ -1,9 +1,14 @@
server {
listen 0.0.0.0:80 default_server;
- listen [::]:80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
server_name ${fqdn};
root ${poudriere_data_dir}/data/packages;
+ ssl_certificate ${poudriere_https_cert};
+ ssl_certificate_key ${poudriere_https_key};
+
include mime.types;
types {
text/plain log;
diff --git a/files/usr/local/etc/openldap/ldap.conf.common b/files/usr/local/etc/openldap/ldap.conf.common
index 22b20bb..af1781e 100644
--- a/files/usr/local/etc/openldap/ldap.conf.common
+++ b/files/usr/local/etc/openldap/ldap.conf.common
@@ -12,3 +12,4 @@ USERS_BASE ${users_basedn}
GROUPS_BASE ${groups_basedn}
HOSTS_BASE ${hosts_basedn}
ROLES_BASE ${roles_basedn}
+AUTOMOUNT_BASE ${automount_basedn}
diff --git a/files/usr/local/etc/openldap/ldap.conf.idm_server b/files/usr/local/etc/openldap/ldap.conf.idm_server
index 4c7a929..aa6f8c9 100644
--- a/files/usr/local/etc/openldap/ldap.conf.idm_server
+++ b/files/usr/local/etc/openldap/ldap.conf.idm_server
@@ -12,3 +12,4 @@ USERS_BASE ${users_basedn}
GROUPS_BASE ${groups_basedn}
HOSTS_BASE ${hosts_basedn}
ROLES_BASE ${roles_basedn}
+AUTOMOUNT_BASE ${automount_basedn}
diff --git a/files/usr/local/etc/polkit-1/rules.d/51-desktop.rules.desktop b/files/usr/local/etc/polkit-1/rules.d/51-desktop.rules.desktop
new file mode 100644
index 0000000..d57c4b9
--- /dev/null
+++ b/files/usr/local/etc/polkit-1/rules.d/51-desktop.rules.desktop
@@ -0,0 +1,8 @@
+polkit.addRule(function (action, subject) {
+ if ((action.id == "org.freedesktop.consolekit.system.restart" ||
+ action.id == "org.freedesktop.consolekit.system.stop" ||
+ action.id == "org.freedesktop.consolekit.system.suspend")
+ && subject.isInGroup("${desktop_access_role}")) {
+ return polkit.Result.YES;
+ }
+});
diff --git a/files/usr/local/etc/poudriere.d/make.conf.pkg_repository b/files/usr/local/etc/poudriere.d/make.conf.pkg_repository
index 6ef6f4a..7c69474 100644
--- a/files/usr/local/etc/poudriere.d/make.conf.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/make.conf.pkg_repository
@@ -10,8 +10,8 @@ OPTIONS_SET=GSSAPI GSSAPI_MIT MIT NONFREE LIBEDIT
# Per-port options
databases_akonadi_SET=MYSQL
databases_luadbi_SET=PGSQL
-databases_postgresql${postgresql_version}-client_SET=PAM
-databases_postgresql${postgresql_version}-server_SET=PAM
+databases_postgresql${postgresql_version}-client_SET=PAM LDAP
+databases_postgresql${postgresql_version}-server_SET=PAM LDAP
devel_apr1_SET=LDAP
devel_gitolite_SET=GITUSER
devel_kio-extras_UNSET=AFC
diff --git a/files/usr/local/etc/poudriere.d/patches/chromium-gssapi.patch.pkg_repository b/files/usr/local/etc/poudriere.d/patches/chromium-gssapi.patch.pkg_repository
new file mode 100644
index 0000000..7cb0372
--- /dev/null
+++ b/files/usr/local/etc/poudriere.d/patches/chromium-gssapi.patch.pkg_repository
@@ -0,0 +1,54 @@
+--- www/chromium/Makefile 2024-10-14 22:31:01.044557000 -0400
++++ www/chromium/Makefile 2024-10-14 22:37:11.304192000 -0400
+@@ -144,19 +144,20 @@
+ SUB_FILES= chromium-browser.desktop chrome
+ SUB_LIST+= COMMENT="${COMMENT}"
+
+-OPTIONS_DEFINE= CODECS CUPS DEBUG DRIVER KERBEROS LTO PIPEWIRE TEST WIDEVINE
+-OPTIONS_DEFAULT= CODECS CUPS DRIVER KERBEROS PIPEWIRE SNDIO ALSA PULSEAUDIO
++OPTIONS_DEFINE= CODECS CUPS DEBUG DRIVER LTO PIPEWIRE TEST WIDEVINE
++OPTIONS_DEFAULT= CODECS CUPS DRIVER KERBEROS PIPEWIRE SNDIO ALSA PULSEAUDIO GSSAPI_MIT
+ OPTIONS_EXCLUDE_aarch64=LTO
+ OPTIONS_GROUP= AUDIO
+ OPTIONS_GROUP_AUDIO= ALSA PULSEAUDIO SNDIO
+-OPTIONS_RADIO= KERBEROS
+-OPTIONS_RADIO_KERBEROS= HEIMDAL HEIMDAL_BASE MIT
++OPTIONS_SINGLE= KERBEROS
++OPTIONS_SINGLE_KERBEROS=GSSAPI_NONE GSSAPI_BASE GSSAPI_HEIMDAL GSSAPI_MIT
+ OPTIONS_SUB= yes
+ CODECS_DESC= Compile and enable patented codecs like H.264
+ DRIVER_DESC= Install chromedriver
+-HEIMDAL_BASE_DESC= Heimdal Kerberos (base)
+-HEIMDAL_DESC= Heimdal Kerberos (security/heimdal)
+-MIT_DESC= MIT Kerberos (security/krb5)
++GSSAPI_NONE_DESC= Build without GSSAPI support
++GSSAPI_BASE_DESC= Use GSSAPI from base
++GSSAPI_HEIMDAL_DESC= Use Heimdal GSSAPI from security/heimdal
++GSSAPI_MIT_DESC= Use MIT GSSAPI from security/krb5
+
+ ALSA_LIB_DEPENDS= libasound.so:audio/alsa-lib
+ ALSA_RUN_DEPENDS= ${LOCALBASE}/lib/alsa-lib/libasound_module_pcm_oss.so:audio/alsa-plugins \
+@@ -189,16 +190,19 @@
+
+ DRIVER_MAKE_ARGS= chromedriver
+
+-HEIMDAL_LIB_DEPENDS= libkrb.so.26:security/heimdal
+-KERBEROS_VARS= GN_ARGS+=use_kerberos=true
+-KERBEROS_VARS_OFF= GN_ARGS+=use_kerberos=false
++GSSAPI_BASE_USES= gssapi
++GSSAPI_HEIMDAL_USES= gssapi:heimdal
++GSSAPI_MIT_USES= gssapi:mit
++GSSAPI_BASE_VARS= GN_ARGS+=use_kerberos=true
++GSSAPI_MIT_VARS= GN_ARGS+=use_kerberos=true
++GSSAPI_HEIMDAL_VARS= GN_ARGS+=use_kerberos=true
++GSSAPI_NONE_VARS= GN_ARGS+=use_kerberos=false
+
+ LTO_VARS= GN_ARGS+=use_thin_lto=true \
+ GN_ARGS+=thin_lto_enable_optimizations=true \
+ WANTSPACE="14 GB"
+ LTO_VARS_OFF= GN_ARGS+=use_thin_lto=false
+
+-MIT_LIB_DEPENDS= libkrb.so.3:security/krb5
+
+ PIPEWIRE_DESC= Screen capture via PipeWire
+ PIPEWIRE_LIB_DEPENDS= libpipewire-0.3.so:multimedia/pipewire
diff --git a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
index ec63f48..35b8f9a 100644
--- a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
@@ -1,5 +1,11 @@
+archivers/7-zip
archivers/php${php_version}-phar
archivers/php${php_version}-zip
+archivers/unzip
+archivers/zip
+audio/juk
+audio/kid3
+audio/kmix
converters/php${php_version}-iconv
converters/php${php_version}-mbstring
databases/luadbi
@@ -11,25 +17,38 @@ databases/postgresql${postgresql_version}-client
databases/postgresql${postgresql_version}-server
databases/redis
devel/ccache
+devel/cgit
devel/git@lite
+devel/gitolite
devel/php${php_version}-gettext
devel/php${php_version}-intl
devel/php${php_version}-pcntl
devel/php${php_version}-tokenizer
+devel/py-pip
+devel/shards
dns/bind-tools
dns/nsd
dns/powerdns
dns/unbound
+editors/libreoffice
editors/vim@console
editors/vim@tiny
+finance/gnucash
+finance/kmymoney
ftp/php${php_version}-curl
+graphics/ImageMagick7@nox11
+graphics/drm-kmod
+graphics/p5-Image-ExifTool
graphics/php${php_version}-exif
graphics/php${php_version}-gd
+irc/konversation
irc/znc
irc/znc-clientbuffer
+java/eclipse
java/openjdk21
-lang/python
+lang/crystal
lang/php${php_version}
+lang/python
mail/dovecot
mail/dovecot-pigeonhole
mail/isync
@@ -38,27 +57,37 @@ mail/postfix
mail/rspamd
mail/sieve-connect
misc/php${php_version}-calendar
+multimedia/audacious
+multimedia/libva-intel-media-driver
+multimedia/makemkv
+net-im/dino
+net-im/gajim
+net-im/prosody
+net-im/prosody-modules
+net-im/signal-desktop
+net-mgmt/unifi8
net/asterisk18
+net/freeradius3
net/lualdap
net/nss-pam-ldapd-sasl
net/openldap26-client
net/openldap26-server
net/p5-perl-ldap
net/php${php_version}-ldap
+net/php${php_version}-sockets
net/py-python-ldap
net/rsync
-net/php${php_version}-sockets
net/turnserver
-net-im/prosody
-net-im/prosody-modules
+net/wireguard-tools
ports-mgmt/poudriere
print/cups
print/cups-filters
security/acme.sh
+security/bitwarden-cli
security/cyrus-sasl2-saslauthd
-security/kstart
security/krb5@default
security/krb5@ldap
+security/kstart
security/openssh-portable
security/pam_krb5@mit
security/pam_mkhomedir
@@ -67,20 +96,38 @@ security/sshpass
security/sudo
security/vaultwarden
sysutils/htop
+sysutils/k3b
sysutils/lsof
sysutils/p5-Sys-Syslog
+sysutils/password-store
sysutils/php${php_version}-fileinfo
sysutils/php${php_version}-posix
sysutils/pwgen
sysutils/stow
sysutils/tmux
sysutils/tree
+textproc/hs-pandoc
+textproc/jq
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
+textproc/py-docutils
+textproc/py-markdown
+textproc/py-pygments
+www/chromium
+www/fcgiwrap
+www/firefox
+www/linux-widevine-cdm
www/nginx
www/php${php_version}-opcache
www/php${php_version}-session
+www/w3m
+x11-fonts/terminus-font
+x11-fonts/terminus-ttf
+x11/kde5
+x11/sddm
+x11/xev
+x11/xorg
diff --git a/files/usr/local/etc/raddb/mods-available/eap.radius_server b/files/usr/local/etc/raddb/mods-available/eap.radius_server
new file mode 100644
index 0000000..5c1aafd
--- /dev/null
+++ b/files/usr/local/etc/raddb/mods-available/eap.radius_server
@@ -0,0 +1,42 @@
+eap {
+ default_eap_type = tls
+ timer_expire = 60
+ ignore_unknown_eap_types = yes
+ cisco_accounting_username_bug = no
+ max_sessions = \${max_requests}
+
+ tls-config tls-common {
+ private_key_password =
+ private_key_file = ${freeradius_tls_key}
+ certificate_file = ${freeradius_tls_cert}
+ ca_file = ${site_cacert_path}
+ ca_path = \${cadir}
+ auto_chain = no
+ check_crl = no
+ cipher_list = "DEFAULT"
+ cipher_server_preference = no
+ tls_min_version = "1.2"
+ tls_max_version = "1.3"
+ ecdh_curve = ""
+
+ cache {
+ enable = yes
+ lifetime = 24 # hours
+ name = "EAP module"
+ persist_dir = "${freeradius_tlscache_dir}"
+ store {
+ Tunnel-Private-Group-Id
+ }
+ }
+
+ verify { }
+
+ ocsp {
+ enable = no
+ }
+ }
+
+ tls {
+ tls = tls-common
+ }
+}
diff --git a/files/usr/local/etc/raddb/radiusd.conf.radius_server b/files/usr/local/etc/raddb/radiusd.conf.radius_server
new file mode 100644
index 0000000..cc5a7a3
--- /dev/null
+++ b/files/usr/local/etc/raddb/radiusd.conf.radius_server
@@ -0,0 +1,80 @@
+prefix = /usr/local
+exec_prefix = \${prefix}
+sysconfdir = \${prefix}/etc
+localstatedir = /var
+sbindir = \${exec_prefix}/sbin
+logdir = /var/log
+raddbdir = \${sysconfdir}/raddb
+radacctdir = \${logdir}/radacct
+
+name = radiusd
+
+confdir = \${raddbdir}
+modconfdir = \${confdir}/mods-config
+certdir = \${confdir}/certs
+cadir = \${confdir}/certs
+run_dir = \${localstatedir}/run/\${name}
+
+db_dir = \${raddbdir}
+
+libdir = /usr/local/lib/freeradius-${freeradius_version}
+
+pidfile = \${run_dir}/\${name}.pid
+
+max_request_time = 30
+
+cleanup_delay = 5
+
+max_requests = 16384
+
+hostname_lookups = no
+
+log {
+ destination = syslog
+ colourise = no
+ file = \${logdir}/radius.log
+ syslog_facility = daemon
+ stripped_names = no
+ auth = yes
+ auth_badpass = no
+ auth_goodpass = no
+ msg_denied = "You are already logged in - access denied"
+}
+
+checkrad = \${sbindir}/checkrad
+
+ENV { }
+
+security {
+ allow_core_dumps = no
+ max_attributes = 200
+ reject_delay = 1
+ status_server = yes
+}
+
+proxy_requests = yes
+\$INCLUDE proxy.conf
+
+\$INCLUDE clients.conf
+
+
+thread pool {
+ start_servers = 5
+ max_servers = 32
+ min_spare_servers = 3
+ max_spare_servers = 10
+ max_requests_per_server = 0
+ auto_limit_acct = no
+}
+
+modules {
+ \$INCLUDE mods-enabled/
+}
+
+instantiate { }
+
+policy {
+ \$INCLUDE policy.d/
+}
+
+\$INCLUDE sites-enabled/
diff --git a/files/usr/local/etc/rc.d/invidious.invidious_server b/files/usr/local/etc/rc.d/invidious.invidious_server
new file mode 100644
index 0000000..44acbad
--- /dev/null
+++ b/files/usr/local/etc/rc.d/invidious.invidious_server
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# PROVIDE: invidious
+# REQUIRE: NETWORKING
+# KEYWORD: shutdown
+
+. /etc/rc.subr
+
+name=invidious
+rcvar=invidious_enable
+
+load_rc_config "$name"
+
+: ${invidious_enable:='NO'}
+: ${invidious_dir:='/usr/local/invidious/invidious.git'}
+: ${invidious_user='www'}
+: ${invidious_syslog_priority:='info'}
+: ${invidious_syslog_facility:='daemon'}
+
+invidious_syslog_tag=invidious
+
+invidious_chdir=$invidious_dir
+pidfile=/var/run/invidious/invidious.pid
+command=/usr/sbin/daemon
+
+command_args="-f \
+-s ${invidious_syslog_priority} \
+-l ${invidious_syslog_facility} \
+-T ${invidious_syslog_tag} \
+-p ${pidfile} \
+-t invidious \
+${invidious_dir}/invidious"
+
+procname="${invidious_dir}/invidious"
+start_precmd=invidious_prestart
+
+invidious_prestart(){
+ install -d -m 0755 -o ${invidious_user} /var/run/invidious
+}
+
+run_rc_command "$1"
diff --git a/files/usr/local/etc/sddm.conf.common b/files/usr/local/etc/sddm.conf.common
new file mode 100644
index 0000000..09c2000
--- /dev/null
+++ b/files/usr/local/etc/sddm.conf.common
@@ -0,0 +1,9 @@
+[General]
+DisplayServer = x11
+
+[Wayland]
+SessionDir = /dev/null
+
+[Users]
+MinimumUid = ${sddm_min_uid}
+MaximumUid = ${sddm_max_uid}
diff --git a/files/usr/local/etc/ssh/sshd_config.freebsd b/files/usr/local/etc/ssh/sshd_config.freebsd
index eca2276..0e0d730 100644
--- a/files/usr/local/etc/ssh/sshd_config.freebsd
+++ b/files/usr/local/etc/ssh/sshd_config.freebsd
@@ -13,4 +13,6 @@ GSSAPICleanupCredentials yes
UsePAM yes
UseDNS no
+# TODO: require group to login?
+
Subsystem sftp /usr/local/libexec/sftp-server
diff --git a/files/usr/local/invidious/invidious.git/config/config.yml.invidious_server b/files/usr/local/invidious/invidious.git/config/config.yml.invidious_server
new file mode 100644
index 0000000..fb7fe54
--- /dev/null
+++ b/files/usr/local/invidious/invidious.git/config/config.yml.invidious_server
@@ -0,0 +1,35 @@
+log_level: info
+domain: ${invidious_fqdn}
+external_port: 443
+channel_threads: 1
+feed_threads: 1
+database_url: postgres://${invidious_username}:${invidious_password}@${invidious_dbhost}/${invidious_dbname}?sslmode=verify-full&auth_methods=cleartext
+use_pubsub_feeds: false
+hmac_key: ${invidious_hmac_key}
+https_only: true
+registration_enabled: true
+port: ${invidious_port}
+host_binding: 127.0.0.1
+popular_enabled: false
+captcha_enabled: false
+check_tables: true
+cache_annotations: true
+po_token: ${invidious_po_token}
+visitor_data: ${invidious_visitor_data}
+signature_server: ${invidious_signature_sock}
+
+default_user_preferences:
+ dark_mode: auto
+ autoplay: false
+ continue: true
+ continue_autoplay: false
+ local: true
+ quality: dash
+ quality_dash: 1080p
+ locale: en-US
+ region: US
+ related_videos: true
+ video_loop: false
+ player_style: invidious
+ default_home: Subscriptions
+ feed_menu: [Subscriptions, Playlists]
diff --git a/files/usr/local/libexec/idm-autofs-map.common b/files/usr/local/libexec/idm-autofs-map.common
new file mode 100644
index 0000000..296bf91
--- /dev/null
+++ b/files/usr/local/libexec/idm-autofs-map.common
@@ -0,0 +1,44 @@
+#!/usr/local/bin/perl
+
+use strict;
+use warnings;
+
+use Net::LDAP;
+use Net::LDAP::Util qw(escape_dn_value);
+use Authen::SASL;
+
+open my $fh, '<', '/usr/local/etc/openldap/ldap.conf' or die($!);
+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 $basedn = $config{AUTOMOUNT_BASE} // die("AUTOMOUNT_BASE not specified\n");
+
+@ARGV == 1 or die "usage: $0 MAPNAME\n";
+my $mapname = $ARGV[0];
+
+my $conn = Net::LDAP->new($uri, version => '3') or die "$0: $@";
+my $sasl = Authen::SASL->new($mech);
+my $status = $conn->bind(sasl => $sasl);
+$status->code and die "$0: ".$status->error."\n";
+
+my $search = $conn->search(
+ scope => 'one',
+ base => 'automountMapName='.escape_dn_value($mapname).",$basedn",
+ filter => '(objectClass=automount)',
+ attrs => ['automountKey', 'automountInformation']);
+$search->code and die "$0: $mapname: ".$search->error."\n";
+
+foreach my $entry ($search->entries) {
+ my $key = ($entry->get_value('automountKey'))[0];
+ my $info = ($entry->get_value('automountInformation'))[0];
+ print "$key $info\n";
+}
diff --git a/files/usr/local/libexec/invidious-update.invidious_server b/files/usr/local/libexec/invidious-update.invidious_server
new file mode 100644
index 0000000..b89b4bf
--- /dev/null
+++ b/files/usr/local/libexec/invidious-update.invidious_server
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+set -eu -o pipefail
+
+prog=$(basename "$(readlink -f "$0")")
+usage="${prog} [-q] INVIDIOUS_USER INVIDIOUS_SRCDIR"
+
+die() {
+ printf '%s: %s\n' "$prog" "$*" 1>&2
+ exit 1
+}
+
+usage(){
+ printf 'usage: %s\n' "$usage" 1>&2
+ exit 2
+}
+
+as_invidious(){
+ su -m "$invidious_user" -c "HOME=$(dirname "$invidious_dir") ${@}"
+}
+
+while getopts hq opt; do
+ case $opt in
+ h) usage ;;
+ q) exec 1>/dev/null ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+[ $# -eq 2 ] || usage
+
+invidious_user=$1
+invidious_dir=$2
+
+cd "$invidious_dir"
+
+su -m "$invidious_user" -c 'git fetch'
+local_rev=$(as_invidious 'git rev-parse HEAD')
+upstream_rev=$(as_invidious 'git rev-parse "@{u}"')
+
+if [ "$local_rev" != "$upstream_rev" ]; then
+ echo "updating invidious to rev ${upstream_rev}"
+ as_invidious 'git pull --ff-only && shards install --production && crystal build src/invidious.cr --release'
+else
+ echo "invidious already up to date at rev ${local_rev}"
+fi
+
+service invidious restart
diff --git a/files/usr/local/libexec/pam-create-local-homedir.common b/files/usr/local/libexec/pam-create-local-homedir.common
new file mode 100644
index 0000000..a956d65
--- /dev/null
+++ b/files/usr/local/libexec/pam-create-local-homedir.common
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+
+uid=$(id -u "$PAM_USER")
+
+if [ "$uid" -ge 1000 ]; then
+ install -m 0755 -d /usr/local/home
+ install -o "$uid" -g "$uid" -m 0700 -d "/usr/local/home/${PAM_USER}"
+fi
diff --git a/files/usr/local/override/applications/signal-desktop.desktop.common b/files/usr/local/override/applications/signal-desktop.desktop.common
new file mode 100644
index 0000000..d0c9160
--- /dev/null
+++ b/files/usr/local/override/applications/signal-desktop.desktop.common
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Type=Application
+Name=Signal
+Comment=Signal - Private Messenger
+Icon=signal-desktop
+Exec=signal-desktop --use-tray-icon -- %u
+Terminal=false
+Categories=Network;InstantMessaging;
+StartupWMClass=Signal
+MimeType=x-scheme-handler/sgnl;
+Keywords=sgnl;chat;im;messaging;messenger;sms;security;privat;
+X-GNOME-UsesNotifications=true
diff --git a/files/usr/local/www/davical/config/config.php.dav_server b/files/usr/local/www/davical/config/config.php.dav_server
index ec2cb26..3d1174d 100644
--- a/files/usr/local/www/davical/config/config.php.dav_server
+++ b/files/usr/local/www/davical/config/config.php.dav_server
@@ -20,8 +20,12 @@
'port' => '389',
'sasl' => 'yes',
'sasl_mech' => 'GSSAPI',
- 'baseDNUsers' => '${users_basedn}',
+ 'baseDNUsers' => '${people_basedn}',
'baseDNGroups' => '${groups_basedn}',
+ /* Must use scope=onelevel here because if davical picks up a user and group
+ * with the same name, then the group takes precedence and the user is lost.
+ * Sad for us because we store user private groups in LDAP.
+ */
'scope' => 'onelevel',
'protocolVersion' => 3,
'optReferrals' => 0,
@@ -44,6 +48,6 @@
'H' => array(8,2),
'M' => array(10,2),
'S' => array(12,2)),
- 'i_use_mode_kerberos' => 'i_know_what_i_am_doing',
+ 'i_use_mode_kerberos' => 'allow_fallback_to_ldap_auth',
);
include_once('drivers_ldap.php');
diff --git a/files/var/db/postgres/data16/pg_hba.conf.postgresql_server b/files/var/db/postgres/data16/pg_hba.conf.postgresql_server
index 0e98783..4810eb9 100644
--- a/files/var/db/postgres/data16/pg_hba.conf.postgresql_server
+++ b/files/var/db/postgres/data16/pg_hba.conf.postgresql_server
@@ -2,4 +2,4 @@
local all postgres peer map=postgres
local all all peer
hostgssenc all all all gss include_realm=0 krb_realm=${realm}
-hostssl all all all pam
+hostssl all all all ldap ldapserver="${ldap_hosts}" ldaptls=1 ldapbinddn="${postgres_dn}" ldapbindpasswd="${postgres_ldap_password}" ldapbasedn="${users_basedn}" ldapsearchattribute=uid
diff --git a/hostclasses b/hostclasses
index 22b77ce..92c1d38 100644
--- a/hostclasses
+++ b/hostclasses
@@ -5,6 +5,7 @@ smtp_server ^smtp[0-9]
imap_server ^imap[0-9]
dev_server ^dev[0-9]
radius_server ^radius[0-9]
+desktop ^desktop[0-9]
laptop ^laptop[0-9]
roadwarrior_laptop ^rlaptop[0-9]
postgresql_server ^postgres[0-9]
@@ -21,7 +22,7 @@ internal_webserver ^web[0-9]
public_webserver ^www[0-9]
authoritative_nameserver ^ns[0-9]
asterisk_server ^pbx[0-9]
-nfs_server ^nas[0-9]
+nfs_server ^nfs[0-9]
turn_server ^turn[0-9]
syncthing_server ^syncthing[0-9]
icinga_server ^icinga[0-9]
diff --git a/scripts/common/10-vars b/scripts/common/10-vars
index cae4496..361bb7b 100644
--- a/scripts/common/10-vars
+++ b/scripts/common/10-vars
@@ -34,4 +34,4 @@ sudo_basedn="ou=sudo,${basedn}"
dns_basedn="ou=dns,${basedn}"
kdc_basedn="cn=kdc,${basedn}"
-boxconf_dn="krbPrincipalName=${boxconf_username}@${realm},${robots_basedn}"
+boxconf_dn="uid=${boxconf_username},${robots_basedn}"
diff --git a/scripts/hostclass/bitwarden_server b/scripts/hostclass/bitwarden_server
index 5e19bdd..1f025fe 100644
--- a/scripts/hostclass/bitwarden_server
+++ b/scripts/hostclass/bitwarden_server
@@ -6,7 +6,6 @@
: ${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
@@ -24,6 +23,7 @@ ktadd -k "$vaultwarden_client_keytab" "$vaultwarden_username"
chgrp "$vaultwarden_local_username" "$vaultwarden_client_keytab"
chmod 640 "$vaultwarden_client_keytab"
+vaultwarden_uid=$(id -u "$vaultwarden_local_username")
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"
diff --git a/scripts/hostclass/cups_server b/scripts/hostclass/cups_server
index e3ad928..6667829 100644
--- a/scripts/hostclass/cups_server
+++ b/scripts/hostclass/cups_server
@@ -16,6 +16,9 @@ pkg install -y cups cups-filters
install_certificate -g "$cups_user" cups "$cups_tls_cert"
install_certificate_key -g "$cups_user" cups "$cups_tls_key"
+# Generate CUPS pam configuration.
+install_file -m 0644 /etc/pam.d/cups
+
# Copy CUPS configuration.
install_template -o root -g "$cups_user" -m 0640 \
"${cups_conf_dir}/cupsd.conf" \
diff --git a/scripts/hostclass/desktop b/scripts/hostclass/desktop
index 561fb8d..35237fd 100644
--- a/scripts/hostclass/desktop
+++ b/scripts/hostclass/desktop
@@ -1,75 +1,75 @@
#!/bin/sh
-load_kernel_module linux linux64 acpi_ibm
-
-pkg install -y \
- chromium \
- compton \
- dino \
- dmenu \
- eclipse \
- firefox \
- git \
- gnupg \
- krb5 \
- i3 \
- libreoffice \
- libva-intel-media-driver \
- networkmgr \
- password-store \
- py${python_version}-pip \
- stow \
- terminus-font \
- terminus-ttf \
- tmux \
- tree \
- wireguard-tools \
- xfontsel \
- xidle \
- xorg \
- xterm
+: ${desktop_access_role:='desktop-access'}
+: ${desktop_access_gid:='40000'}
+
+: ${sddm_min_uid:='10000'}
+: ${sddm_max_uid:='19999'}
+
+if [ "${enable_idm:-}" = false ]; then
+ desktop_access_role=operator
+else
+ ldap_add "cn=${desktop_access_role},${roles_basedn}" <<EOF
+objectClass: groupOfMembers
+objectClass: posixGroup
+cn: ${desktop_access_role}
+gidNumber: ${desktop_access_gid}
+EOF
+fi
+
+# Load linux kernel modules.
+load_kernel_module linux linux64
+set_loader_conf \
+ linux_load=YES \
+ linux64_load=YES
+
+# Install packages common to all DEs.
+pkg install -y $desktop_common_packages
+
+# Install scripts for creating local (non-NFS) home directories.
+install_file -m 0555 \
+ /usr/local/libexec/pam-create-local-homedir \
+ /etc/profile.d/local-homedir.sh
+install_directory -m 0755 /usr/local/home
case $desktop_type in
i3)
- pkg install \
- dunst \
- i3 \
- i3lock \
- i3status \
- profanity
+ pkg install -y $desktop_i3_packages
;;
kde)
- pkg install \
- juk \
- k3b \
- kde5 \
- kid3-qt6 \
- kmix \
- konversation \
- sddm
+ # Install KDE packages.
+ pkg install -y $desktop_kde_packages
+
+ # Configure pam services.
+ install_file -m 0644 \
+ /etc/pam.d/sddm \
+ /etc/pam.d/kde
+
+ # Copy SDDM config file.
+ install_template -m 0644 /usr/local/etc/sddm.conf
+
+ # Create profile script for KDE environment variables.
+ install_file -m 0644 /etc/profile.d/kde.sh
+
+ # Create SDDM local homedir.
+ install_directory -o sddm -g sddm -m 0700 /usr/local/home/sddm
+
+ # Enable sddm.
+ sysrc -v sddm_enable=YES
;;
esac
+# Tune sysctls for desktop usage.
set_sysctl \
net.local.stream.recvspace=65536 \
net.local.stream.sendspace=65536 \
kern.sched.preempt_thresh=224 \
- vfs.usermount=1 \
- hw.snd.latency=7
+ vfs.usermount=1
set_loader_conf \
kern.ipc.shmseg=1024 \
kern.ipc.shmmni=1024 \
kern.maxproc=100000 \
- linux_load=YES \
- linux64_load=YES \
- acpi_ibm_load=YES \
- compat.linuxkpi.i915_enable_dc=2 \
- compat.linuxkpi.i915_enable_fbc=1 \
- compat.linuxkpi.i915_fastboot=1 \
- compat.linuxkpi.i915_disable_power_well=1 \
- machdep.hwpstate_pkg_ctrl=0 \
- vfs.zfs.txg.timeout=10 \
hw.pci.do_power_nodriver=3
# Create policy file for firefox.
@@ -88,6 +88,18 @@ install_file -m 0644 /usr/local/lib/libreoffice/program/sofficerc
# Add terminus font to X11
install_file -m 0644 /usr/local/etc/X11/xorg.conf.d/terminus.conf
+# Create xdg override directory.
+install_directory -m 0755 \
+ /usr/local/override \
+ /usr/local/override/applications
+
+# Create xdg application overrides.
+install_file -m 0644 \
+ /usr/local/override/applications/signal-desktop.desktop
+
+# Create polkit rules for shutdown/reboot/suspend
+install_template -m 0644 /usr/local/etc/polkit-1/rules.d/51-desktop.rules
+
# Enable dbus.
sysrc -v dbus_enable=YES
service dbus status || service dbus start
@@ -98,6 +110,9 @@ case $graphics_type in
pkg install -y drm-kmod
sysrc -v kld_list+=i915kms
load_kernel_module i915kms
+ set_loader_conf \
+ compat.linuxkpi.i915_enable_fbc=1 \
+ compat.linuxkpi.i915_fastboot=1 \
;;
esac
@@ -164,3 +179,8 @@ xterm-256color|xterm with 256 colors,
tbc=\E[3g, u6=\E[%i%d;%dR, u7=\E[6n,
u8=\E[?%[;0123456789]c, u9=\E[c, vpa=\E[%i%p1%dd,
EOF
+
+# Start login manager.
+case $desktop_type in
+ kde) service sddm status || service sddm start > /dev/null 2>&1 < /dev/null || die 'failed to start sddm' ;;
+esac
diff --git a/scripts/hostclass/freebsd_hypervisor b/scripts/hostclass/freebsd_hypervisor
index bdaa3c0..24c1da5 100644
--- a/scripts/hostclass/freebsd_hypervisor
+++ b/scripts/hostclass/freebsd_hypervisor
@@ -24,6 +24,9 @@ hypervisor_jail_bpf_ruleset=1000
# Required for vnet jails.
set_sysctl net.link.tap.up_on_open=1
+# Required to for kerberized NFS within jails.
+sysrc -v kld_list+='kgssapi kgssapi_krb5'
+
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=262189
set_sysctl vfs.zfs.vol.mode=2
diff --git a/scripts/hostclass/idm_server/10-slapd b/scripts/hostclass/idm_server/10-slapd
index d108ae2..f6c9b4a 100644
--- a/scripts/hostclass/idm_server/10-slapd
+++ b/scripts/hostclass/idm_server/10-slapd
@@ -180,6 +180,21 @@ objectClass: organizationalUnit
ou: $(ldap_rdn_value "$automount_basedn")
EOF
+ # automountMapName=auto_master,ou=automount,dc=example,dc=com
+ ldap_add "automountMapName=auto_master,${automount_basedn}" <<EOF
+objectClass: automountMap
+automountMapName: auto_master
+EOF
+ ldap_add "automountKey=/home,automountMapName=auto_master,${automount_basedn}" <<EOF
+objectClass: automount
+automountKey: /home
+automountInformation: auto_home
+EOF
+ ldap_add "automountMapName=auto_home,${automount_basedn}" <<EOF
+objectClass: automountMap
+automountMapName: auto_home
+EOF
+
# ou=sudo,dc=example,dc=com
ldap_add "$sudo_basedn" <<EOF
objectClass: organizationalUnit
diff --git a/scripts/hostclass/idm_server/90-idm b/scripts/hostclass/idm_server/90-idm
index adfdf36..1f6920b 100644
--- a/scripts/hostclass/idm_server/90-idm
+++ b/scripts/hostclass/idm_server/90-idm
@@ -93,11 +93,11 @@ install_file -m 0555 \
# Create the boxconf administrative user.
if is_primary_server && ! ldap_dn_exists "$boxconf_dn"; then
ldap_add "$boxconf_dn" <<EOF
-objectClass: krbPrincipal
+objectClass: account
objectClass: simpleSecurityObject
-krbPrincipalName: ${boxconf_username}@${realm}
+uid: ${boxconf_username}
userPassword: {SASL}${boxconf_username}@${realm}
EOF
- kadmin.local change_password -pw "$boxconf_password" "$boxconf_username"
+ kadmin.local add_principal -x "dn=${boxconf_dn}" -pw "$boxconf_password" "$boxconf_username"
fi
diff --git a/scripts/hostclass/invidious_server b/scripts/hostclass/invidious_server
new file mode 100644
index 0000000..95333a5
--- /dev/null
+++ b/scripts/hostclass/invidious_server
@@ -0,0 +1,91 @@
+#!/bin/sh
+
+# Note: does not work. inv_sig_helper does not build on FreeBSD...
+
+# Generate using: https://github.com/iv-org/youtube-trusted-session-generator
+: ${invidious_po_token:='changeme'}
+: ${invidious_visitor_data:='changeme'}
+
+: ${invidious_username:='s-invidious'}
+: ${invidious_password:='changeme'}
+: ${invidious_hmac_key:='changemeeeeeeeeeeee'}
+: ${invidious_dbname:='invidious'}
+: ${invidious_dbhost:="$postgres_host"}
+: ${invidious_fqdn:="$fqdn"}
+: ${invidious_repo='https://github.com/iv-org/invidious'}
+: ${invidious_branch='master'}
+
+invidious_dn="uid=${invidious_username},${robots_basedn}"
+invidious_local_username=$nginx_user
+invidious_home=/usr/local/invidious
+invidious_port=8080
+invidious_repo_dir="${invidious_home}/invidious.git"
+invidious_https_cert="${nginx_conf_dir}/invidious.crt"
+invidious_https_key="${nginx_conf_dir}/invidious.key"
+invidious_signature_sock=/tmp/inv_sig_helper.sock
+
+# Install required packages.
+pkg install -y \
+ ca_root_nss \
+ git \
+ crystal \
+ shards \
+ sqlite3 \
+ nginx \
+ postgresql${postgresql_version}-client \
+ rust
+
+# Create invidious user account.
+ldap_add "$invidious_dn" <<EOF
+objectClass: account
+objectClass: simpleSecurityObject
+uid: ${invidious_username}
+userPassword: {SSHA-512}
+EOF
+
+# Set LDAP password for invidious user.
+ldap_passwd "$invidious_dn" "$invidious_password"
+
+# Create postgres user and database.
+postgres_create_role "$invidious_dbhost" "$invidious_username"
+postgres_create_database "$invidious_dbhost" "$invidious_dbname" "$invidious_username"
+
+# Clone git repo.
+install_directory -o "$invidious_local_username" -g "$invidious_local_username" -m 0775 "$invidious_home"
+[ -d "${invidious_repo_dir}" ] || su -m "$invidious_local_username" -c "git clone ${invidious_repo} ${invidious_repo_dir}"
+
+# Update git repo.
+su -m "$invidious_local_username" -c "git -C ${invidious_repo_dir} pull --ff-only"
+su -m "$invidious_local_username" -c "git -C ${invidious_repo_dir} switch ${invidious_branch}"
+
+# Build invidious.
+( cd "$invidious_repo_dir"
+ su -m "$invidious_local_username" -c "HOME=${invidious_home} shards install --production"
+ su -m "$invidious_local_username" -c "HOME=${invidious_home} crystal build src/invidious.cr --release"
+)
+
+# Copy invidious configuration.
+install_template -o "$invidious_local_username" -g "$invidious_local_username" -m 0600 "${invidious_repo_dir}/config/config.yml"
+
+# Copy invidious rc script.
+install_file -m 0555 /usr/local/etc/rc.d/invidious
+
+# Copy TLS certificate for nginx.
+install_certificate invidious "$invidious_https_cert"
+install_certificate_key invidious "$invidious_https_key"
+
+# Generate nginx configuration.
+install_template -m 0644 \
+ /usr/local/etc/nginx/nginx.conf \
+ /usr/local/etc/nginx/vhosts.conf
+
+# Start daemons.
+sysrc -v \
+ invidious_enable=YES \
+ nginx_enable=YES
+service invidious restart
+service nginx restart
+
+# Copy invidous auto-update script.
+install_file -m 0555 /usr/local/libexec/invidious-update
+install_template -m 0644 /etc/cron.d/invidious
diff --git a/scripts/hostclass/laptop b/scripts/hostclass/laptop
index 26f9fe6..dba2c5f 100644
--- a/scripts/hostclass/laptop
+++ b/scripts/hostclass/laptop
@@ -1,5 +1,9 @@
#!/bin/sh
+# Enable thinkpad hardware features.
+load_kernel_module acpi_ibm
+set_loader_conf acpi_ibm_load=YES
+
# Set USB power savings
usbconfig | awk -F: '{ print $1 }' | xargs -rtn1 -I% usbconfig -d % power_save ||:
install_file /etc/rc.local
@@ -14,6 +18,19 @@ load_kernel_module if_urndis
set_loader_conf if_urndis_load=YES
sysrc -v ifconfig_ue0='DHCP'
+# Install laptop packages.
+pkg install -y networkmgr
+
+# Misc power saving stuff.
+set_loader_conf \
+ vfs.zfs.txg.timeout=10 \
+
+if [ "$graphics_type" = intel ]; then
+ set_loader_conf \
+ compat.linuxkpi.i915_disable_power_well=1 \
+ compat.linuxkpi.i915_enable_dc=2
+fi
+
case ${wireless_type:-} in
iwm*)
set_loader_conf \
@@ -28,6 +45,9 @@ case ${wireless_type:-} in
;;
esac
+# Enable power saving for sound card.
+set_sysctl hw.snd.latency=7
+
# Configure wireless card.
sysrc -v \
create_args_wlan0='country US regdomain FCC' \
diff --git a/scripts/hostclass/nfs_server b/scripts/hostclass/nfs_server
new file mode 100644
index 0000000..ce47cfe
--- /dev/null
+++ b/scripts/hostclass/nfs_server
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# Jails serving NFS need 'allow.nfsd' option.
+
+: ${nfsuserd_cache_size:='256'}
+: ${nfsuserd_num_servers:='4'}
+: ${nfsuserd_cache_timeout:='1'}
+: ${nfsd_srvmaxio:='1048576'}
+
+nfs_root=/share
+nfs_dataset="${state_dataset}/nfs"
+
+# Create ZFS dataset for NFS share.
+create_dataset -o "mountpoint=${nfs_root}" "${nfs_dataset}"
+
+# Create nfs service principal and keytab.
+add_principal -nokey -x "containerdn=${services_basedn}" "nfs/${fqdn}"
+ktadd -k "${keytab_dir}/host.keytab" "nfs/${fqdn}"
+
+if [ "$BOXCONF_VIRTUALIZATION_TYPE" != jail ]; then
+ set_sysctl \
+ vfs.nfsd.issue_delegations=1 \
+ vfs.nfsd.enable_locallocks=0
+fi
+
+sysrc -v \
+ nfs_server_managegids=YES \
+ nfsuserd_enable=YES \
+ nfsuserd_flags="-usermax ${nfsuserd_cache_size} -usertimeout ${nfsuserd_cache_timeout} ${nfsuserd_num_servers}" \
+ gssd_enable=YES \
+ nfs_server_enable=YES \
+ nfs_server_flags='-t' \
+ nfs_server_maxio="$nfsd_srvmaxio" \
+ nfsv4_server_only=YES \
+ mountd_enable=YES \
+ mountd_flags='-R -S'
+
+# Our krb5.conf assumes MIT Kerberos, but the gssd in base uses the base
+# Heimdal kerberos, which doesnt support %{euid} expansion. So we must
+# override the keytab path with an environment variable.
+sysrc -v gssd_env="KRB5_KTNAME=${keytab_dir}/host.keytab"
+
+install_template -m 0644 /etc/exports
+
+for service in gssd nfsuserd mountd nfsd; do
+ service "$service" restart
+done
diff --git a/scripts/hostclass/pkg_repository b/scripts/hostclass/pkg_repository
index 6070794..7226b77 100644
--- a/scripts/hostclass/pkg_repository
+++ b/scripts/hostclass/pkg_repository
@@ -9,6 +9,8 @@
: ${poudriere_ccache_size:='50.0G'}
: ${poudriere_default_versions:='imagemagick=7-nox11'}
+poudriere_https_cert="${nginx_conf_dir}/poudriere.crt"
+poudriere_https_key="${nginx_conf_dir}/poudriere.key"
poudriere_data_dir=/usr/local/poudriere
poudriere_conf_dir=/usr/local/etc/poudriere.d
poudriere_patch_dir="${poudriere_conf_dir}/patches"
@@ -42,10 +44,15 @@ install_directory -m 0755 /usr/ports/distfiles
install_directory -m 0755 -o nobody -g nobody "${poudriere_data_dir}/ccache"
install_template -m 0644 -o nobody -g nobody "${poudriere_data_dir}/ccache/ccache.conf"
+# Copy TLS certificate for nginx.
+install_certificate nginx "$poudriere_https_cert"
+install_certificate_key nginx "$poudriere_https_key"
+
# Configure and enable nginx to serve the packages.
install_template -m 0644 \
/usr/local/etc/nginx/nginx.conf \
/usr/local/etc/nginx/vhosts.conf
+
sysrc -v nginx_enable=YES
service nginx restart
@@ -59,7 +66,8 @@ poudriere ports -v -u -p latest
install_directory -m 0755 "$poudriere_patch_dir"
rm -f "${poudriere_patch_dir}/"*.patch
install_file -m 0644 \
- "${poudriere_patch_dir}/postgresql16-gssapi.patch"
+ "${poudriere_patch_dir}/postgresql16-gssapi.patch" \
+ "${poudriere_patch_dir}/chromium-gssapi.patch"
for patch in "${poudriere_patch_dir}/"*.patch; do
[ -f "$patch" ] || continue
diff --git a/scripts/hostclass/postgresql_server b/scripts/hostclass/postgresql_server
index fb0ddcd..10bafc8 100644
--- a/scripts/hostclass/postgresql_server
+++ b/scripts/hostclass/postgresql_server
@@ -8,7 +8,10 @@
: ${postgres_maintenance_work_mem:="$(( memsize / 20 ))"}
: ${postgres_temp_buffers:="$((32 * 1024 * 1024))"}
: ${postgres_effective_cache_size:="$(( memsize * 3 / 4 ))"}
+: ${postgres_ldap_username:='s-postgresql'}
+: ${postgres_ldap_password:='changeme'}
+postgres_dn="uid=${postgres_ldap_username},${robots_basedn}"
postgres_user=postgres
postgres_home=/var/db/postgres
postgres_data_dir="${postgres_home}/data${postgresql_version}"
@@ -16,10 +19,6 @@ postgres_tls_cert="${postgres_home}/postgres.crt"
postgres_tls_key="${postgres_home}/postgres.key"
postgres_keytab="${keytab_dir}/postgres.keytab"
-psql(){
- command psql --quiet --no-align --echo-all --tuples-only --no-password --username=postgres --dbname=postgres "$@"
-}
-
pkg install -y postgresql${postgresql_version}-server
# Create ZFS dataset for postgresql data.
@@ -46,8 +45,16 @@ postgres_uid=$(id -u "$postgres_user")
install_directory -o "$postgres_user" -m 0700 "/var/krb5/user/${postgres_uid}"
ln -snfv "$postgres_keytab" "/var/krb5/user/${postgres_uid}/keytab"
-# Create postgresql PAM service.
-install_template -m 0644 /etc/pam.d/postgresql
+# Create PostgreSQL LDAP user account.
+ldap_add "$postgres_dn" <<EOF
+objectClass: account
+objectClass: simpleSecurityObject
+uid: ${postgres_ldap_username}
+userPassword: {SSHA-512}
+EOF
+
+# Set LDAP password for PostgreSQL user.
+ldap_passwd "$postgres_dn" "$postgres_ldap_password"
# Copy TLS certificate for postgres.
install_certificate -m 0644 -o root -g "$postgres_user" postgres "$postgres_tls_cert"
@@ -63,10 +70,11 @@ install_file -m 0600 -o "$postgres_user" -g "$postgres_user" \
# The postgresql rc script seems to hold onto open descriptors, which causes
# the parent boxconf SSH process to never close.
echo 'Restarting postgresql.'
-service postgresql restart > /dev/null 2>&1 < /dev/null
+service postgresql restart > /dev/null 2>&1 < /dev/null || die 'failed to start postgresql'
# Create boxconf admin user.
-psql -c "DO
+psql --quiet --no-align --echo-all --tuples-only --no-password --username=postgres --dbname=postgres -c \
+"DO
\$$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${boxconf_username}') THEN
@@ -74,4 +82,3 @@ BEGIN
END IF;
END
\$$"
-
diff --git a/scripts/hostclass/radius_server b/scripts/hostclass/radius_server
new file mode 100644
index 0000000..bde1be2
--- /dev/null
+++ b/scripts/hostclass/radius_server
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# radius_clients=client1
+# radius_client1_address='192.168.1.0/24'
+# radius_client1_secret='s3cret'
+
+: ${radius_clients=''}
+
+freeradius_user=freeradius
+freeradius_conf_dir=/usr/local/etc/raddb
+freeradius_tls_cert="${freeradius_conf_dir}/freeradius.crt"
+freeradius_tls_key="${freeradius_conf_dir}/freeradius.key"
+freeradius_cache_dir=/var/cache/radiusd
+freeradius_tlscache_dir="${freeradius_cache_dir}/tlscache"
+
+# Install packages.
+pkg install -y freeradius3
+
+freeradius_version=$(pkg info freeradius3 | awk '$1 == "Version" { print $3 }')
+
+# Generate configuration.
+install_directory -m 0755 "${freeradius_conf_dir}/certs"
+install_template -o "$freeradius_user" -g "$freeradius_user" -m 0640 \
+ "${freeradius_conf_dir}/radiusd.conf" \
+ "${freeradius_conf_dir}/mods-available/eap"
+rm -f "${freeradius_conf_dir}/sites-enabled/inner-tunnel"
+
+# Copy TLS certificate for freeradius.
+install_certificate -g "$freeradius_user" freeradius "$freeradius_tls_cert"
+install_certificate_key -g "$freeradius_user" freeradius "$freeradius_tls_key"
+
+# Generate clients.conf.
+install -Cv -o "$freeradius_user" -g "$freeradius_user" -m 0660 /dev/null "${freeradius_conf_dir}/clients.conf"
+for client_name in $radius_clients; do
+ eval "client_address=\$radius_${client_name}_address"
+ eval "client_secret=\$radius_${client_name}_secret"
+ cat <<EOF >> "${freeradius_conf_dir}/clients.conf"
+client ${client_name} {
+ ipaddr = ${client_address}
+ secret = ${client_secret}
+}
+
+EOF
+done
+
+# Create cache directories.
+install_directory -o "$freeradius_user" -g "$freeradius_user" -m 700 \
+ "$freeradius_cache_dir" \
+ "$freeradius_tlscache_dir"
+
+# Clean up tlscache with cron job.
+install_template -m 0644 /etc/cron.d/freeradius
+
+# Enable and start daemons.
+sysrc -v radiusd_enable=YES
+service radiusd restart
diff --git a/scripts/hostclass/smtp_server/10-rspamd b/scripts/hostclass/smtp_server/10-rspamd
index 1794e04..7b1aae9 100644
--- a/scripts/hostclass/smtp_server/10-rspamd
+++ b/scripts/hostclass/smtp_server/10-rspamd
@@ -77,8 +77,8 @@ install_template -m 0640 -g "$rspamd_user" \
printf '%s\n' ${rspamd_domain_whitelist} | tee "${rspamd_conf_dir}/local.d/maps.d/domain-whitelist.map"
# Copy DKIM keys.
-for domain in $postfix_virtual_domains; do
- install_file -m 0640 -g "$rspamd_user" "${rspamd_data_dir}/dkim/${domain}.key"
+for _domain in $postfix_virtual_domains; do
+ install_file -m 0640 -g "$rspamd_user" "${rspamd_data_dir}/dkim/${_domain}.key"
done
# Add rspamd user to redis group, so it can write to the redis unix socket.
diff --git a/scripts/hostclass/unifi_controller b/scripts/hostclass/unifi_controller
new file mode 100644
index 0000000..32df063
--- /dev/null
+++ b/scripts/hostclass/unifi_controller
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+unifi_user=unifi
+unifi_home=/usr/local/share/java/unifi
+unifi_https_cert="${unifi_home}/data/unifi.crt"
+unifi_https_key="${unifi_home}/data/unifi.key"
+unifi_keystore="${unifi_home}/data/keystore"
+
+# Install required packages.
+pkg install -y unifi8
+
+# Create ZFS dataset for unifi data.
+create_dataset -o "mountpoint=${unifi_home}/data" "${state_dataset}/unifi"
+
+# Set ownership on unifi data dir.
+install_directory -o "$unifi_user" -g "$unifi_user" -m 0700 "${unifi_home}/data"
+
+# Copy TLS certificate for unifi.
+install_certificate -g "$unifi_user" unifi "$unifi_https_cert"
+install_certificate_key -m 0640 -g "$unifi_user" unifi "$unifi_https_key"
+
+# Enable unifi.
+sysrc -v unifi_enable=YES
+
+# Stop the unifi service.
+service unifi status && service unifi stop
+
+# Add HTTPS certificate to unifi keystore.
+[ -f "${unifi_home}/data/keystore" ] || install -Cv -o "$unifi_user" -g "$unifi_user" -m 0600 /dev/null "${unifi_home}/data/keystore"
+su -m "$unifi_user" -c "java -jar ${unifi_home}/lib/ace.jar import_key_cert ${unifi_https_key} ${unifi_https_cert} ${site_cacert_path}"
+
+# Disable analytics.
+install_directory -m 0640 -o "$unifi_user" -g "$unifi_user" \
+ "${unifi_home}/data/sites" \
+ "${unifi_home}/data/sites/default"
+grep -xFq 'config.system_cfg.1=system.analytics.anonymous=disabled' "${unifi_home}/data/sites/default/config.properties" \
+ || echo 'config.system_cfg.1=system.analytics.anonymous=disabled' | tee -a "${unifi_home}/data/sites/default/config.properties"
+
+# Start unifi.
+service unifi start
diff --git a/scripts/hostname/nfs1 b/scripts/hostname/nfs1
new file mode 100644
index 0000000..98d5bcc
--- /dev/null
+++ b/scripts/hostname/nfs1
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+homedir_priv_quota=250G
+homedir_pub_quota=10G
+
+create_dataset "${nfs_dataset}/user"
+create_dataset "${nfs_dataset}/group"
+
+for user in ${nfs_homedirs:-}; do
+ create_dataset "${nfs_dataset}/user/${user}"
+ create_dataset "${nfs_dataset}/user/${user}/priv"
+ create_dataset "${nfs_dataset}/user/${user}/pub"
+
+ zfs set "refquota=${homedir_priv_quota}" "${nfs_dataset}/user/${user}/priv"
+ zfs set "refquota=${homedir_pub_quota}" "${nfs_dataset}/user/${user}/pub"
+
+ chown "${user}:${user}" \
+ "${nfs_root}/user/${user}/priv" \
+ "${nfs_root}/user/${user}/pub"
+
+ chmod 700 "${nfs_root}/user/${user}/priv"
+ chmod 755 "${nfs_root}/user/${user}/pub"
+done
+
+ ldap_add "automountKey=*,automountMapName=auto_home,${automount_basedn}" <<EOF
+objectClass: automount
+automountKey: *
+automountInformation: -nfsv4,gssname=host,sec=krb5p ${fqdn}:/user/&/priv
+EOF
diff --git a/scripts/os/freebsd/10-cpu b/scripts/os/freebsd/10-cpu
index adc27d4..ea2afcf 100644
--- a/scripts/os/freebsd/10-cpu
+++ b/scripts/os/freebsd/10-cpu
@@ -19,6 +19,8 @@ sysrc -v \
performance_cx_lowest="$cx_lowest" \
economy_cx_lowest="$cx_lowest"
+set_loader_conf machdep.hwpstate_pkg_ctrl=0
+
# Set energy/performance preference for Intel P-states.
# 0 = most performance, 100 = most power savings
if sysctl -n dev.hwpstate_intel.0.epp >/dev/null 2>&1; then
diff --git a/scripts/os/freebsd/10-sysctls b/scripts/os/freebsd/10-sysctls
index 865544a..b07a46c 100644
--- a/scripts/os/freebsd/10-sysctls
+++ b/scripts/os/freebsd/10-sysctls
@@ -70,6 +70,8 @@ if [ "$BOXCONF_VIRTUALIZATION_TYPE" != jail ]; then
security.bsd.see_other_gids="$see_other_uids" \
security.bsd.see_other_uids="$see_other_uids" \
security.bsd.unprivileged_read_msgbuf=0 \
+ vfs.nfsd.enable_locallocks=0 \
+ vfs.nfsd.issue_delegations=1 \
vfs.zfs.min_auto_ashift=12
# FreeBSD automatically scales kern.maxfilesperproc with the amount of memory.
diff --git a/scripts/os/freebsd/20-zfs b/scripts/os/freebsd/20-zfs
index aa37c0a..1cdc465 100644
--- a/scripts/os/freebsd/20-zfs
+++ b/scripts/os/freebsd/20-zfs
@@ -3,7 +3,7 @@
# Every host should have a "state" dataset, which is a ZFS dataset which
# persists across OS rebuilds.
[ -n "${state_dataset:-}" ] || die 'state_dataset not defined!'
-create_dataset "$state_dataset"
+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
diff --git a/scripts/os/freebsd/50-idm b/scripts/os/freebsd/50-idm
index d9c2541..0a9e882 100644
--- a/scripts/os/freebsd/50-idm
+++ b/scripts/os/freebsd/50-idm
@@ -20,7 +20,8 @@ pkg install -y \
# Configure PAM/NSS integration.
install_file -m 0644 \
/etc/nsswitch.conf \
- /etc/pam.d/sshd
+ /etc/pam.d/sshd \
+ /etc/pam.d/sudo
install_template -m 0644 \
/etc/krb5.conf \
@@ -114,7 +115,11 @@ install_file -m 0555 \
/usr/local/libexec/idm-ssh-authorized-keys
# Create user for running SSH AuthorizedKeysCommand.
-add_user -u "$ssh_authzkeys_uid" -g "$host_keytab_groupname" "$ssh_authzkeys_username"
+add_user \
+ -u "$ssh_authzkeys_uid" \
+ -g "$host_keytab_groupname" \
+ -d /nonexistent \
+ "$ssh_authzkeys_username"
# Enable and start nslcd/nscd.
sysrc -v \
diff --git a/scripts/os/freebsd/51-autofs b/scripts/os/freebsd/51-autofs
new file mode 100644
index 0000000..4fe3c52
--- /dev/null
+++ b/scripts/os/freebsd/51-autofs
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# NFS mounts are not supported within jails.
+if [ "$BOXCONF_VIRTUALIZATION_TYPE" = jail ] || \
+ [ "$BOXCONF_HOSTCLASS" = nfs_server ] || \
+ [ "${enable_idm:-}" = false ] || \
+ [ "${enable_autofs:-}" = false ]; then
+ return 0
+fi
+
+: ${nfsuserd_cache_size:='256'}
+: ${nfsuserd_num_servers:='4'}
+: ${nfsuserd_cache_timeout:='1'}
+
+sysrc -v \
+ nfsuserd_enable=YES \
+ nfsuserd_flags="-usermax ${nfsuserd_cache_size} -usertimeout ${nfsuserd_cache_timeout} ${nfsuserd_num_servers}" \
+ gssd_enable=YES \
+ gssd_flags='-h -s /tmp' \
+ gssd_env="KRB5_KTNAME=${keytab_dir}/host.keytab"
+ nfs_client_enable=YES \
+ nfscbd_enable=NO \
+ nfscbd_flags="-p ${nfscbd_port} -P host" \
+ autofs_enable=YES
+
+install_file -m 0644 /etc/auto_master
+install_file -m 0555 /usr/local/libexec/idm-autofs-map
+ln -snfv /usr/local/libexec/idm-autofs-map /etc/autofs/include
+
+# No nfscbd: causes kernel panics on FreeBSD 14.1
+for service in gssd nfsclient nfsuserd automount automountd autounmountd; do
+ service "$service" status || service "$service" start
+done
diff --git a/vars/common b/vars/common
index 92a0c96..d072ea8 100644
--- a/vars/common
+++ b/vars/common
@@ -58,7 +58,7 @@ tcp_buffer_size=2097152 # suitable for 1 GigE
nginx_nofile=2048
nginx_worker_connections=768
-if (( nproc > 4 )); then
+if [ "$nproc" -gt 4 ]; then
nginx_worker_processes=4
else
nginx_worker_processes=$nproc
diff --git a/vars/hostclass/cups_server b/vars/hostclass/cups_server
new file mode 100644
index 0000000..9c2915a
--- /dev/null
+++ b/vars/hostclass/cups_server
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+allowed_tcp_ports="ssh http https ipp"
diff --git a/vars/hostclass/desktop b/vars/hostclass/desktop
new file mode 100644
index 0000000..fe6f4bc
--- /dev/null
+++ b/vars/hostclass/desktop
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+desktop_common_packages="
+bind-tools
+chromium
+eclipse
+firefox
+git
+gnupg
+krb5
+libreoffice
+libva-intel-media-driver
+password-store
+py${python_version}-pip
+signal-desktop
+stow
+terminus-font
+terminus-ttf
+tmux
+tree
+wireguard-tools
+xorg"
+
+desktop_kde_packages='
+dino
+gajim
+juk
+k3b
+kde5
+kid3-qt6
+kmix
+konversation
+sddm'
+
+desktop_i3_packages='
+compton
+dunst
+dmenu
+i3
+i3lock
+i3status
+profanity
+xfontsel
+xidle
+xterm'
diff --git a/vars/hostclass/invidious_server b/vars/hostclass/invidious_server
new file mode 100644
index 0000000..5ae7588
--- /dev/null
+++ b/vars/hostclass/invidious_server
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+allowed_tcp_ports="ssh http https"
diff --git a/vars/hostclass/laptop b/vars/hostclass/laptop
new file mode 120000
index 0000000..8714ca2
--- /dev/null
+++ b/vars/hostclass/laptop
@@ -0,0 +1 @@
+desktop \ No newline at end of file
diff --git a/vars/hostclass/nfs_server b/vars/hostclass/nfs_server
new file mode 100644
index 0000000..2957aec
--- /dev/null
+++ b/vars/hostclass/nfs_server
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+allowed_tcp_ports='ssh nfsd'
diff --git a/vars/hostclass/pkg_repository b/vars/hostclass/pkg_repository
index 4752685..e60a0c4 100644
--- a/vars/hostclass/pkg_repository
+++ b/vars/hostclass/pkg_repository
@@ -1,4 +1,4 @@
#!/bin/sh
-allowed_tcp_ports='ssh http'
+allowed_tcp_ports='ssh http https'
nginx_redirect=false
diff --git a/vars/hostclass/radius_server b/vars/hostclass/radius_server
new file mode 100644
index 0000000..1354ecd
--- /dev/null
+++ b/vars/hostclass/radius_server
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+allowed_udp_ports="radius"
diff --git a/vars/hostclass/roadwarrior_laptop/desktop b/vars/hostclass/roadwarrior_laptop/desktop
new file mode 120000
index 0000000..2c7c348
--- /dev/null
+++ b/vars/hostclass/roadwarrior_laptop/desktop
@@ -0,0 +1 @@
+../desktop \ No newline at end of file
diff --git a/vars/hostclass/roadwarrior_laptop b/vars/hostclass/roadwarrior_laptop/vars
index 45bade8..712d724 100644
--- a/vars/hostclass/roadwarrior_laptop
+++ b/vars/hostclass/roadwarrior_laptop/vars
@@ -1,4 +1,6 @@
#!/bin/sh
+
resolvers=$bootstrap_resolvers
pf_skip_interfaces=wg
see_other_uids=1
+enable_idm=false
diff --git a/vars/hostclass/unifi_controller b/vars/hostclass/unifi_controller
new file mode 100644
index 0000000..d937b0d
--- /dev/null
+++ b/vars/hostclass/unifi_controller
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+allowed_tcp_ports='ssh 6789 8080 8443 8843 8880'
+allowed_udp_ports='3478 10001'
+
+redirect_tcp_ports='
+https 8443
+http 8880'
diff --git a/vars/hostname/invidious1 b/vars/hostname/invidious1
new file mode 100644
index 0000000..f06a891
--- /dev/null
+++ b/vars/hostname/invidious1
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+cnames=invidious
+invidious_fqdn="invidious.${domain}"
diff --git a/vars/hostname/nfs1 b/vars/hostname/nfs1
new file mode 100644
index 0000000..3ea50e6
--- /dev/null
+++ b/vars/hostname/nfs1
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cnames=nfs
diff --git a/vars/hostname/radius1 b/vars/hostname/radius1
new file mode 100644
index 0000000..5d5380e
--- /dev/null
+++ b/vars/hostname/radius1
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cnames='radius'
diff --git a/vars/hostname/unifi1 b/vars/hostname/unifi1
new file mode 100644
index 0000000..7c418d9
--- /dev/null
+++ b/vars/hostname/unifi1
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cnames=unifi
diff --git a/scripts/hostname/znc1 b/vars/hostname/znc1
index dc11b11..dc11b11 100644
--- a/scripts/hostname/znc1
+++ b/vars/hostname/znc1