/
portsbuild.sh
executable file
·9832 lines (7994 loc) · 341 KB
/
portsbuild.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/sh
# ******************************************************************************
# >>> PortsBuild
#
# Alternative to DirectAdmin's CustomBuild for FreeBSD systems using ports and packages.
# Scripted by mmx aka -sg aka sarog aka Saro.
# Based on the work of CustomBuild 2.x, written by JBMC and Martynas Bendorius (smtalk).
#
# https://github.com/portsbuild/portsbuild
#
# ******************************************************************************
#
# Requirements:
# - DirectAdmin license
# - FreeBSD 12/13.1+ (amd64 only)
# - chmod 700 portsbuild.sh
# - ./portsbuild.sh
# - Patience.
#
# New Installations:
# - Modify: options.conf
# - Setup : ./portsbuild.sh setup <USER_ID> <LICENSE_ID> <SERVER_FQDN> <ETH_DEV> <IP_ADDRESS> <IP_NETMASK>
#
# Existing users:
# - Update : ./portsbuild.sh update
# - Upgrade: ./portsbuild.sh upgrade <package|port|service>
# - Rewrite: ./portsbuild.sh rewrite <configuration>
# - Verify : ./portsbuild.sh verify
#
# ** Found a bug? Please submit an issue: https://github.com/portsbuild/portsbuild/issues
#
################################################################################
## Fun fact #1: root's shell is actually /bin/tcsh
PB_VER="0.2.0"
PB_BUILD_DATE=20221212
IFS="$(printf '\n\t')"
LANG=C
if [ "$(/usr/bin/id -u)" != "0" ]; then
printf "*** Error: Must run this script as the root user.\n"
exit 1
fi
readonly OS=$(uname)
readonly OS_VER=$(uname -r | cut -d- -f1) # 12.1, 13.0, 13.1, etc.
readonly OS_B64=$(uname -m | grep -c 64) # 0, 1
readonly OS_MAJ=$(uname -r | cut -d. -f1) # 11, 12, 13, 14
readonly OS_HOST=$(hostname)
if [ "${OS}" = "FreeBSD" ]; then
if [ "${OS_B64}" -eq 1 ]; then
if [ "${OS_MAJ}" -lt 11 ]; then
printf "Warning: Unsupported FreeBSD operating system detected.\n"
printf "PortsBuild has been tested to work with FreeBSD versions 11/12/13+ amd64 (x64) only.\n"
printf "You can press CTRL+C within 5 seconds to quit the PortsBuild script now,\n"
printf "or proceed at your own risk.\n"
sleep 5
fi
else
printf "Error: i386 (x86) systems are not supported.\n"
printf "PortsBuild requires the 64-bit version (amd64) of FreeBSD.\n"
exit 1
fi
else
printf "PortsBuild is for FreeBSD systems only.\n"
exit 1
fi
################################################################################
## PortsBuild Paths & Files
################################################################################
PB_PATH=/usr/local/portsbuild
if [ ! -e "${PB_PATH}" ] || [ "$(pwd)" != "${PB_PATH}" ]; then
PB_PATH=$(pwd)
else
PB_PATH=/usr/local/portsbuild
fi
readonly PB_PATH
readonly PB_DEBUG="NO"
readonly PB_CONF="${PB_PATH}/options.conf"
readonly PB_CONFIG="${PB_PATH}/configure"
readonly PB_CUSTOM="${PB_PATH}/custom"
readonly PB_PATCHES="${PB_PATH}/patches"
readonly PB_SETUP=/root/portsbuild.txt
## PortsBuild Remote File Repository
readonly PB_GITHUB="https://github.com/portsbuild/portsbuild"
readonly PB_GITRAW="https://raw.githubusercontent.com/portsbuild/portsbuild/master"
readonly PB_MIRROR="https://s3.amazonaws.com/portsbuild/files"
################################################################################
### File: constants.conf
################################################################################
## System Accounts
readonly DA_ADMIN_USER='admin'
readonly DA_SQLDB_USER='da_admin'
readonly APACHE_USER='apache' ## www
readonly APACHE_GROUP='apache' ## www
readonly NGINX_USER='nginx' ## www
readonly NGINX_GROUP='nginx' ## www
readonly WEBAPPS_USER='webapps'
readonly WEBAPPS_GROUP='webapps'
readonly EXIM_USER='mail' ## mailnull
readonly EXIM_GROUP='mail' ## mail
readonly DA_SRV_USER='diradmin'
readonly DA_SRV_GROUP='diradmin'
## System Binary/Application paths and variables
# readonly BIN=/bin
# readonly UB=/usr/bin
# readonly US=/usr/sbin
# readonly ULB=/usr/local/bin
# readonly ULS=/usr/local/sbin
# readonly ULE=/usr/local/etc
readonly LOGS=/var/log
readonly ENV=/usr/bin/env
readonly CHOWN=/usr/sbin/chown
readonly CHGRP=/usr/bin/chgrp
readonly CHMOD=/bin/chmod
readonly CP=/bin/cp
readonly COLUMN=/usr/bin/column
readonly FETCH=/usr/bin/fetch
readonly GREP=/usr/bin/grep
readonly KILLALL=/usr/bin/killall
readonly MAKE=/usr/bin/make
readonly MKDIR=/bin/mkdir
readonly PATCH=/usr/bin/patch
readonly PERL=/usr/local/bin/perl
readonly PKG=/usr/sbin/pkg
readonly PW=/usr/sbin/pw
readonly PORTSNAP=/usr/sbin/portsnap
readonly PORTMASTER=/usr/local/sbin/portmaster
readonly PRINTF=/usr/bin/printf
readonly RCD=/usr/local/etc/rc.d
readonly SERVICE=/usr/sbin/service
readonly STAT=/usr/bin/stat
readonly SYNTH=/usr/local/bin/synth
readonly SYSRC=/usr/sbin/sysrc
readonly SYSCTL=/sbin/sysctl
readonly TOUCH=/usr/bin/touch
readonly WGET=/usr/local/bin/wget
readonly WGET_CONNECT_OPTIONS='--connect-timeout=10 --read-timeout=10 --tries=3'
readonly TAR=/usr/bin/tar
## Runtime Discovery
readonly CPU_CORES="$("${SYSCTL}" -n hw.ncpu)"
readonly SERVER_DOMAIN=$(echo "${OS_HOST}" | cut -d. -f2,3,4,5,6)
readonly NEWSYSLOG_PATH=/usr/local/etc/newsyslog.conf.d
readonly NEWSYSLOG_FILE="${NEWSYSLOG_PATH}/directadmin.conf"
readonly SSHD_CONFIG=/etc/ssh/sshd_config
## DirectAdmin Paths & Files
readonly DA_PATH=/usr/local/directadmin
readonly DA_BIN="${DA_PATH}/directadmin"
readonly DA_SCRIPTS_PATH="${DA_PATH}/scripts"
readonly DA_CRON_FILE="${DA_SCRIPTS}/directadmin_cron"
readonly DA_CONF="${DA_PATH}/conf/directadmin.conf"
readonly DA_CONF_TEMPLATE="${DA_PATH}/data/templates/directadmin.conf"
readonly DA_MYSQL_CONF="${DA_PATH}/conf/mysql.conf"
readonly DA_MYSQL_CNF="${DA_PATH}/conf/my.cnf"
readonly DA_LICENSE="${DA_PATH}/conf/license.key"
readonly DA_SETUP_TXT="${DA_SCRIPTS_PATH}/setup.txt"
readonly DA_TASK_QUEUE="${DA_PATH}/data/task.queue.cb"
readonly DA_SERVICES="${DA_PATH}/data/admin/services.status"
readonly DA_SSL_KEY="${DA_PATH}/conf/cakey.pem"
readonly DA_SSL_CRT="${DA_PATH}/conf/cacert.pem"
readonly DA_SSL_CA="${DA_PATH}/conf/carootcert.pem"
## CustomBuild Paths & Files
readonly CB_PATH="${DA_PATH}/custombuild"
readonly CB_CONF="${CB_PATH}/options.conf"
## Apache 2.4
readonly APACHE_PATH=/usr/local/etc/apache24
readonly APACHE_LIBS="/usr/local/libexec/apache24"
readonly APACHE_EXTRAS="${APACHE_PATH}/extra"
readonly APACHE_CONF="${APACHE_PATH}/httpd.conf"
readonly APACHE_HOSTNAME_CONF="${APACHE_EXTRAS}/httpd-hostname.conf"
readonly APACHE_MIME_TYPES="${APACHE_PATH}/mime.types"
readonly APACHE_HTPASSWD=/usr/local/bin/htpasswd
readonly APACHE_HTTPD=/usr/local/sbin/httpd
readonly APACHE_SSL_KEY="${APACHE_PATH}/ssl/server.key"
readonly APACHE_SSL_CRT="${APACHE_PATH}/ssl/server.crt"
readonly APACHE_SSL_CA="${APACHE_PATH}/ssl/server.ca"
readonly APACHE_SUEXEC=/usr/local/sbin/suexec
readonly APXS=/usr/local/sbin/apxs
readonly PHP_HANDLERS_CONF="${APACHE_EXTRAS}/httpd-php-handlers.conf"
# readonly APACHE_PID=/var/run/httpd.pid
## Nginx
readonly NGINX_PATH=/usr/local/etc/nginx
readonly NGINX_CONF="${NGINX_PATH}/nginx.conf"
readonly NGINX_SSL_KEY="${NGINX_PATH}/ssl/server.key"
readonly NGINX_SSL_CRT="${NGINX_PATH}/ssl/server.crt"
readonly NGINX_SSL_CA="${NGINX_PATH}/ssl/server.ca"
# readonly NGINX_PID=/var/run/nginx.pid
## Needed?
# readonly NGINX_VHOSTS=${NGINX_PATH}/vhosts
# NGINX_VHOSTS_CONF=${NGINX_PATH}/directadmin-vhosts.conf
# NGINX_LOGS=${LOGS}/nginx/domains
# NGINX_IPS_CONF=${NGINX_PATH}/directadmin-ips.conf
readonly WWW_DIR=/usr/local/www ## Ports uses "${WWW_DIR}"
readonly WWW_TMP_DIR="${WWW_DIR}/tmp" ## Temporary files directory
readonly WEBMAIL_PATH="${WWW_DIR}/webmail"
readonly WEBMAIL_TMP_DIR="${WEBMAIL_PATH}/tmp"
## RoundCube
readonly ROUNDCUBE_PATH="${WWW_DIR}/roundcube"
readonly ROUNDCUBE_CONF="${ROUNDCUBE_PATH}/config/config.inc.php"
## PHP
readonly PHP_ETC=/usr/local/etc/php
readonly PHP_INI=/usr/local/etc/php.ini
readonly PHP_INI_WEBAPPS="${PHP_ETC}/50-webapps.ini"
# readonly PHP_INI_EXTENSIONS="${PHP_ETC}/extensions.ini"
readonly PHP_INI_OPCACHE="${PHP_ETC}/opcache.ini"
readonly PHP_INI_DIRECTADMIN="${PHP_ETC}/10-directadmin.ini"
readonly PHP_FPM_CONF="/usr/local/etc/php-fpm.conf"
readonly PHP_SOCKETS_PATH=/var/run/php/sockets
readonly PHP_RELEASE_SET="7.4 8.0 8.1 8.2"
readonly PHP_SHORTRELEASE_SET="$(echo "${PHP_RELEASE_SET}" | tr -d '.')"
readonly PHP_FPM_BIN=/usr/local/sbin/php-fpm
readonly SUPHP_CONF_FILE=/usr/local/etc/suphp.conf
readonly SUPHP_AP2_CONF="${APACHE_EXTRAS}/httpd-suphp.conf"
# readonly SUPHP_PATH=/usr/local/suphp
# readonly SUPHP_SO=/usr/lib/apache/mod_suphp.so
## Virtual Mail Directory
readonly VIRTUAL_PATH=/etc/virtual
## Exim
readonly EXIM_BIN=/usr/local/sbin/exim
readonly EXIM_PATH=/usr/local/etc/exim
readonly EXIM_CONF="${EXIM_PATH}/configure" ## required_files in rc.d/exim
readonly EXIM_BC_PATH="${EXIM_PATH}/bc"
readonly EXIM_ESF_PATH="${EXIM_PATH}/esf"
readonly EXIM_SSL_KEY="${EXIM_PATH}/ssl/exim.key"
readonly EXIM_SSL_CRT="${EXIM_PATH}/ssl/exim.crt"
readonly EXIM_SSL_CA="${EXIM_PATH}/ssl/exim.ca"
## Dovecot
readonly DOVECOT_BIN=/usr/local/sbin/dovecot
readonly DOVECOT_PATH=/usr/local/etc/dovecot
readonly DOVECOT_CONF="${DOVECOT_PATH}/dovecot.conf"
readonly DOVECOT_SSL_KEY="${DOVECOT_PATH}/ssl/dovecot.key"
readonly DOVECOT_SSL_CRT="${DOVECOT_PATH}/ssl/dovecot.crt"
readonly DOVECOT_SSL_CA="${DOVECOT_PATH}/ssl/dovecot.ca"
## phpMyAdmin
readonly PMA_PATH="${WWW_DIR}/phpMyAdmin"
readonly PMA_CONFIG="${PMA_PATH}/config.inc.php"
## MySQL/MariaDB
# readonly MYSQL_RELEASE_SET="5.6 5.7 8.0"
# readonly MARIADB_RELEASE_SET="10.3 10.4 10.5 10.6"
## 2022-12-12: recent ersions of MariaDB don't like 'my.cnf' here
readonly MYSQL_CNF=/usr/local/etc/my.cnf
readonly MYSQL=/usr/local/bin/mysql
readonly MYSQLADMIN=/usr/local/bin/mysqladmin
readonly MYSQLCHECK=/usr/local/bin/mysqlcheck
readonly MYSQLD=/usr/local/libexec/mysqld
readonly MYSQLD_SAFE=/usr/local/bin/mysqld_safe
readonly MYSQLDUMP=/usr/local/bin/mysqldump
readonly MYSQLIMPORT=/usr/local/bin/mysqlimport
readonly MYSQLSECURE=/usr/local/bin/mysql_secure_installation
readonly MYSQLSHOW=/usr/local/bin/mysqlshow
readonly MYSQLUPGRADE=/usr/local/bin/mysql_upgrade
## ClamAV
readonly CLAMDSCAN=/usr/local/bin/clamdscan
readonly CLAMD_CONF=/usr/local/etc/clamd.conf
readonly FRESHCLAM_CONF=/usr/local/etc/freshclam.conf
## ModSecurity
readonly MODSECURITY_PATH=/usr/local/etc/modsecurity
readonly MODSECURITY_CONF="${MODSECURITY_PATH}/modsecurity.conf"
## ProFTPD
readonly PROFTPD_CONF=/usr/local/etc/proftpd.conf
readonly PROFTPD_ETC=/usr/local/etc/proftpd
readonly PROFTPD_DHPARAMS="${PROFTPD_ETC}/dhparams.pem"
readonly PROFTPD_CLAMAV_CONF=/usr/local/etc/proftpd.clamav.conf
readonly PROFTPD_PASSWD=/usr/local/etc/proftpd.passwd
# readonly PROFTPD_PASSWD=/usr/local/etc/proftpd.db
## PureFTPD
readonly PUREFTPD_UPLOADSCAN_BIN=/usr/local/bin/pureftpd_uploadscan.sh
################################################################################
### File: defaults.conf (default values)
################################################################################
DA_ADMIN_EMAIL="${DA_ADMIN_USER}@${SERVER_DOMAIN}"
## todo: 2022-12-10: retrieve commit hash via dig
# COMMIT=$(dnstxt "freebsd-version.directadmin.com" | sed 's|.*commit=\([0-9a-f]*\).*|\1|')
# FILE="directadmin_${COMMIT}_freebsd_amd64.tar.gz"
# FILE="directadmin_${COMMIT}_linux_amd64.tar.gz"
# wget "https://download.directadmin.com/${FILE}"
case "${OS_MAJ}" in
# 9|10) DA_SERVICES_PKG="services_freebsd91_64.tar.gz" ;;
11) DA_SERVICES_PKG="services_freebsd110_64.tar.gz" ;;
12) DA_SERVICES_PKG="services_freebsd120_64.tar.gz" ;;
13) ;;
14) ;;
esac
## Environmental variables
: "${MIN_PASS_LENGTH:=12}" ## Min Random Password Length
: "${MAX_PASS_LENGTH:=16}" ## Max Random Password Length
: "${NEWSYSLOG_DAYS:=10}" ## Number of days to keep logs before rotating
: "${DA_LAN:=0}" ## DA LAN Mode (2022-12-12: no longer needed?)
: "${DA_INSECURE:=0}" ## DA Insecure Mode
: "${LAN_IP=""}" ## Server's LAN IP
: "${PHP_VERSION:="8.2"}" ## PHP #1 Version
: "${PHP_MODE:="php-fpm"}" ## PHP #1 Mode
: "${EXIM_RECIPIENTS_MAX:=150}" ## Exim Max Recipients
: "${SQL_DATA_PATH:=/var/db/mysql}" ## SQL DB files path (DA default: /home/mysql)
: "${MYSQL_HOST:=localhost}" ## SQL default hostname
: "${DEFAULT_MY_CNF:="my-huge.cnf"}" ## Default my.cnf file to use
## 2022-12-12: to review:
#: "${DA_CHANNEL:=}" # Download channel: alpha, beta, current, stable
#: "${DA_COMMIT:=}" # Exact DA build to install, will use latest from update channel if empty
#: "${DA_OS_SLUG:=}" # Build targeting specific platform: linux_amd64, debian10_amd64, rhel8_amd64, ...
#: "${DA_EMAIL:=}" # Default email address
#: "${DA_HOSTNAME:=}" # Hostname to use for installation
#: "${DA_ETH_DEV:=}" # Network device
#: "${DA_NS1:=}" # pre-defined ns1
#: "${DA_NS2:=}" # pre-defined ns2
## Custom SSL Certificates
CUSTOM_SSL_KEY='/usr/local/etc/ssl/server.key'
CUSTOM_SSL_CRT='/usr/local/etc/ssl/server.crt'
CUSTOM_SSL_CA='/usr/local/etc/ssl/server.ca'
# ROUNDCUBE_CONFIG_CUSTOM="${ROUNDCUBE_CONF}"
## Already defined in roundcube_install()
# ROUNDCUBE_PLUGINS="${PB_CUSTOM}/roundcube/plugins"
# ROUNDCUBE_SKINS="${PB_CUSTOM}/roundcube/skins"
# ROUNDCUBE_PROGRAM="${PB_CUSTOM}/roundcube/program"
# ROUNDCUBE_HTACCESS="${PB_CUSTOM}/roundcube/.htaccess"
################################################################################
### Alternatives Discovery
################################################################################
## OPT_WITH_OPENSSL_PORT=$(sysrc -e -f /etc/make.conf WITH_OPENSSL_PORT)
WITH_OPENSSL_PORT="$(${SYSRC} -q -e -f /etc/make.conf WITH_OPENSSL_PORT)"
## Use either BASE or PORT OpenSSL libraries.
## The latter only if make.conf contains WITH_OPENSSL_PORT=YES
if [ -x /usr/local/bin/openssl ] && [ "${WITH_OPENSSL_PORT}" ]; then
OPENSSL=/usr/local/bin/openssl
# GLOBAL_MAKE_VARIABLES="${GLOBAL_MAKE_VARIABLES} WITH_OPENSSL_PORT=YES"
elif [ -x /usr/bin/openssl ]; then
OPENSSL=/usr/bin/openssl
# GLOBAL_MAKE_VARIABLES="${GLOBAL_MAKE_VARIABLES} WITH_OPENSSL_BASE=YES"
else
printf "*** Error: OpenSSL binary not found. Does /usr/bin/openssl exist?\n"
exit 0
fi
readonly OPENSSL
## Check for this file and append to OpenSSL calls using -config:
# OPENSSL_EXTRA="-config ${PB_CUSTOM}/ssl/openssl_req.conf"
# -config ${PB_CUSTOM}/ssl/openssl_req.conf
OPENSSL_EXTRA=""
################################################################################
## See if IPV6 is enabled in DirectAdmin:
if [ -e "${DA_BIN}" ]; then
IPV6=$(${DA_BIN} c | grep -m1 '^ipv6=' | cut -d= -f2)
else
IPV6=0
fi
readonly IPV6
################################################################################
## PortsBuild Compatibility Switches
################################################################################
readonly COMPAT_APACHE24_SYMLINKS="NO"
readonly COMPAT_DOVECOT_SYMLINKS="YES"
readonly COMPAT_EXIM_SYMLINKS="YES"
readonly COMPAT_NAMED_SYMLINKS="YES"
readonly COMPAT_PHP_SYMLINKS="YES"
readonly COMPAT_SQL_SYMLINKS="YES"
################################################################################
################################################################################
### File: ports.conf
################################################################################
## FreeBSD Ports path
readonly PORTS_BASE=/usr/ports
# readonly PORTS_VAR_DB=/var/db/ports
# readonly PKG_VAR_DB=/var/db/pkgs
## Ports: Dependencies
readonly PORT_PORTMASTER='ports-mgmt/portmaster'
readonly PORT_SYNTH='ports-mgmt/synth'
readonly PORT_PERL='lang/perl5.34'
readonly PORT_AUTOCONF='devel/autoconf'
readonly PORT_AUTOMAKE='devel/automake'
readonly PORT_BISON='devel/bison'
readonly PORT_CA_ROOT_NSS='security/ca_root_nss'
readonly PORT_CURL='ftp/curl'
readonly PORT_LIBTOOL='devel/libtool'
readonly PORT_LIBXML2='textproc/libxml2'
readonly PORT_LIBXSLT='textproc/libxslt'
readonly PORT_LIBARCHIVE='archivers/libarchive'
readonly PORT_FREETYPE2='print/freetype2'
readonly PORT_CYRUSSASL2='security/cyrus-sasl2'
readonly PORT_PYTHON='lang/python'
readonly PORT_CCACHE='devel/ccache'
readonly PORT_CMAKE='devel/cmake'
readonly PORT_GMAKE='devel/gmake'
readonly PORT_WGET='ftp/wget'
readonly PORT_FLEX='textproc/flex'
readonly PORT_GD='graphics/gd'
readonly PORT_SASL2='security/cyrus-sasl2'
readonly PORT_MAILX='mail/mailx'
readonly PORT_BIND='dns/bind918'
readonly PORT_GCC6='lang/gcc6-aux'
readonly PORT_NCURSES='devel/ncurses'
## Compats
readonly PORT_COMPATS="misc/compat4x misc/compat5x misc/compat6x misc/compat7x misc/compat8x"
readonly PORT_DEPS="${PORT_GMAKE} ${PORT_PERL} ${PORT_WGET} ${PORT_BISON} \
${PORT_FLEX} ${PORT_GD} ${PORT_SASL2} ${PORT_CMAKE} ${PORT_PYTHON} \
${PORT_AUTOCONF} ${PORT_LIBTOOL} ${PORT_LIBARCHIVE} ${PORT_MAILX} ${PORT_CA_ROOT_NSS} \
${PORT_COMPATS}"
readonly PORT_DEPS_100="${PORT_DEPS} ${PORT_BIND} misc/compat9x"
readonly PORT_DEPS_110="${PORT_DEPS_100} misc/compat10x"
readonly PORT_DEPS_120="${PORT_DEPS_110} misc/compat11x"
readonly PORT_DEPS_130="${PORT_DEPS_120} misc/compat12x"
readonly PORT_DEPS_140="${PORT_DEPS_130} misc/compat13x"
readonly PORT_LINUX_BASE_C7='emulators/linux_base-c7'
## Ports: Web Servers
readonly PORT_APACHE24='www/apache24'
readonly PORT_NGINX='www/nginx'
readonly PORT_NGHTTP2='www/nghttp2'
readonly PORT_FASTCGI='www/mod_fastcgi'
readonly PORT_FCGID='www/mod_fcgid'
## Ports: PHP
readonly PORT_SUPHP='www/suphp'
readonly PORT_PHPMYADMIN='databases/phpmyadmin'
readonly PORT_IONCUBE='devel/ioncube'
readonly PORT_SUHOSIN='security/suhosin'
readonly PORT_HTSCANNER='devel/pecl-htscanner'
readonly PORT_MOD_SECURITY='www/mod_security'
## Ports: Mail & Related Services
readonly PORT_EXIM='mail/exim'
readonly PORT_SPAMASSASSIN='mail/spamassassin'
readonly PORT_SPAMASSASSIN_UTILITIES='mail/sa-utils'
readonly PORT_DOVECOT2='mail/dovecot2'
readonly PORT_PIGEONHOLE='mail/dovecot2-pigeonhole'
readonly PORT_CLAMAV='security/clamav'
readonly PORT_ROUNDCUBE='mail/roundcube'
readonly PORT_LIBSPF2='mail/libspf2'
readonly PORT_LIBDKIM='mail/libdkim'
readonly PORT_MAILMAN='mail/mailman'
readonly PORT_RSPAMD='mail/rspamd'
## Ports: FTPd
readonly PORT_PUREFTPD='ftp/pure-ftpd'
readonly PORT_PROFTPD='ftp/proftpd'
readonly PORT_PROFTPD_CLAMAV='security/proftpd-mod_clamav'
## Ports: Database Servers
### MariaDB
readonly PORT_MARIADB103='databases/mariadb103-server'
readonly PORT_MARIADB104='databases/mariadb104-server'
readonly PORT_MARIADB105='databases/mariadb105-server'
readonly PORT_MARIADB106='databases/mariadb106-server'
readonly PORT_MARIADB103_CLIENT='databases/mariadb103-client'
readonly PORT_MARIADB104_CLIENT='databases/mariadb104-client'
readonly PORT_MARIADB105_CLIENT='databases/mariadb105-client'
readonly PORT_MARIADB106_CLIENT='databases/mariadb106-client'
### MySQL
readonly PORT_MYSQL56='databases/mysql56-server'
readonly PORT_MYSQL57='databases/mysql57-server'
readonly PORT_MYSQL80='databases/mysql80-server'
readonly PORT_MYSQL56_CLIENT='databases/mysql56-client'
readonly PORT_MYSQL57_CLIENT='databases/mysql57-client'
readonly PORT_MYSQL80_CLIENT='databases/mysql80-client'
## Ports: Web Stats
readonly PORT_AWSTATS='www/awstats'
readonly PORT_WEBALIZER='www/webalizer'
# readonly PORT_PCRE='devel/pcre'
# to remove: readonly PORT_LETSENCRYPT='security/letsencrypt.sh'
################################################################################
### File: make.conf
################################################################################
### Global (default) make options
## These variables are included every time 'make' is called.
## Default is to source /etc/make.conf
: "${GLOBAL_MAKE_VARS=""}" # e.g. WITH_OPENSSL_PORT=YES BATCH=YES WITH_CCACHE_BUILD=YES
## These options are included every time a Port is built via 'make'.
: "${GLOBAL_MAKE_SET=""}"
: "${GLOBAL_MAKE_UNSET=""}" # EXAMPLES X11 HTMLDOCS CUPS TESTS DOCS NLS
APACHE24_MAKE_SET="SUEXEC" # MPM_EVENT
APACHE24_MAKE_UNSET="" # MPM_PREFORK
# APACHE24_EXTRA_PATCHES=""
NGINX_MAKE_SET=""
NGINX_MAKE_UNSET=""
## Prefixes for multi-PHP installations:
# readonly PHP74_PREFIX='/usr/local/php74'
# readonly PHP80_PREFIX='/usr/local/php80'
# readonly PHP81_PREFIX='/usr/local/php81'
# readonly PHP82_PREFIX='/usr/local/php82'
DEFAULT_PHP_MAKE_SET=""
DEFAULT_PHP_MAKE_UNSET=""
DEFAULT_PHP_EXT_MAKE_SET="BCMATH BZ2 CALENDAR CTYPE CURL DOM EXIF FILEINFO FILTER FTP \
GD GETTEXT HASH ICONV IMAP JSON MBSTRING MCRYPT MYSQL MYSQLI OPCACHE OPENSSL PDF \
PDO PDO_MYSQL PDO_SQLITE PHAR POSIX PSPELL READLINE RECODE SESSION SIMPLEXML SOAP \
SOCKETS SQLITE3 TOKENIZER WDDX XML XMLREADER XMLRPC XMLWRITER XSL ZIP ZLIB"
DEFAULT_PHP_EXT_MAKE_UNSET=""
PHP74_MAKE_SET="${DEFAULT_PHP_MAKE_SET}"
PHP74_MAKE_UNSET="${DEFAULT_PHP_MAKE_UNSET}"
PHP74_EXT_MAKE_SET="${DEFAULT_PHP_EXT_MAKE_SET}"
PHP74_EXT_MAKE_UNSET="${DEFAULT_PHP_EXT_MAKE_UNSET}"
## todo: 2022-12-12: verify options:
PHP80_MAKE_SET="${DEFAULT_PHP_MAKE_SET}"
PHP80_MAKE_UNSET="${DEFAULT_PHP_MAKE_UNSET}"
PHP80_EXT_MAKE_SET="${DEFAULT_PHP_EXT_MAKE_SET}"
PHP80_EXT_MAKE_UNSET="${DEFAULT_PHP_EXT_MAKE_UNSET}"
PHP81_MAKE_SET="${DEFAULT_PHP_MAKE_SET}"
PHP81_MAKE_UNSET="${DEFAULT_PHP_MAKE_UNSET}"
PHP81_EXT_MAKE_SET="${DEFAULT_PHP_EXT_MAKE_SET}"
PHP81_EXT_MAKE_UNSET="${DEFAULT_PHP_EXT_MAKE_UNSET}"
PHP82_MAKE_SET="${DEFAULT_PHP_MAKE_SET}"
PHP82_MAKE_UNSET="${DEFAULT_PHP_MAKE_UNSET}"
PHP82_EXT_MAKE_SET="${DEFAULT_PHP_EXT_MAKE_SET}"
PHP82_EXT_MAKE_UNSET="${DEFAULT_PHP_EXT_MAKE_UNSET}"
## todo: 2022-12-12: verify options:
PHP74_MOD_MAKE_SET=""
PHP74_MOD_MAKE_UNSET=""
PHP80_MOD_MAKE_SET=""
PHP80_MOD_MAKE_UNSET=""
PHP81_MOD_MAKE_SET=""
PHP81_MOD_MAKE_UNSET=""
PHP82_MOD_MAKE_SET=""
PHP82_MOD_MAKE_UNSET=""
ROUNDCUBE_MAKE_SET="" # SSL
ROUNDCUBE_MAKE_UNSET=""
PMA_MAKE_SET=""
PMA_MAKE_UNSET=""
EXIM_MAKE_SET="SPF SA_EXIM SRS" # DMARC DCC MILTER
EXIM_MAKE_UNSET=""
SPAMASSASSIN_MAKE_SET="DKIM SPF_QUERY" # DCC PYZOR RAZOR RELAY_COUNTRY
SPAMASSASSIN_MAKE_UNSET=""
SPAMASSASSIN_UTILITIES_MAKE_SET="SACOMPILE"
SPAMASSASSIN_UTILITIES_MAKE_UNSET=""
## todo: 2022-12-12: verify options:
RSPAMD_MAKE_SET=""
RSPAMD_MAKE_UNSET=""
DOVECOT2_MAKE_SET="" #
DOVECOT2_MAKE_UNSET=""
PIGEONHOLE_MAKE_SET="" # MANAGESIEVE
PIGEONHOLE_MAKE_UNSET=""
CLAMAV_MAKE_SET="" # MILTER
CLAMAV_MAKE_UNSET=""
PROFTPD_MAKE_SET=""
PROFTPD_MAKE_UNSET=""
PUREFTPD_MAKE_SET="UPLOADSCRIPT LARGEFILE" # PERUSERLIMITS THROTTLING
PUREFTPD_MAKE_UNSET=""
# MARIADB103_MAKE_SET=""
# MARIADB103_MAKE_UNSET=""
# MARIADB104_MAKE_SET=""
# MARIADB104_MAKE_UNSET=""
# MARIADB105_MAKE_SET=""
# MARIADB105_MAKE_UNSET=""
# MARIADB106_MAKE_SET=""
# MARIADB106_MAKE_UNSET=""
# MYSQL56_MAKE_SET=""
# MYSQL56_MAKE_UNSET=""
# MYSQL57_MAKE_SET=""
# MYSQL57_MAKE_UNSET=""
# MYSQL80_MAKE_SET=""
# MYSQL80_MAKE_UNSET=""
################################################################################
### Custom Configurations
################################################################################
## SSL Certificate Generation Parameters
SSL_REQ_CONF="${PB_CONFIG}/ssl/openssl_req.conf"
if [ -e "${PB_CUSTOM}/ssl/openssl_req.conf" ]; then
SSL_REQ_CONF="${PB_CUSTOM}/ssl/openssl_req.conf"
fi
## Mod Security for Apache
MODSECURITY_APACHE_INCLUDE="${PB_CONFIG}/ap2/conf/extra/httpd-modsecurity.conf"
if [ -e "${PB_CUSTOM}/ap2/conf/extra/httpd-modsecurity.conf" ]; then
MODSECURITY_APACHE_INCLUDE="${PB_CUSTOM}/ap2/conf/extra/httpd-modsecurity.conf"
fi
## Mod Security for Nginx
MODSECURITY_NGINX_INCLUDE="${PB_CONFIG}/nginx/conf/nginx-modsecurity.conf"
if [ -e "${PB_CUSTOM}/nginx/conf/nginx-modsecurity.conf" ]; then
MODSECURITY_NGINX_INCLUDE="${PB_CUSTOM}/nginx/conf/nginx-modsecurity.conf"
fi
## Mod Security for Apache+Nginx Reverse Proxy
MODSECURITY_NGINX_REVERSE_INCLUDE="${PB_CONFIG}/nginx_reverse/conf/nginx-modsecurity.conf"
if [ -e "${PB_CUSTOM}/nginx_reverse/conf/nginx-modsecurity.conf" ]; then
MODSECURITY_NGINX_REVERSE_INCLUDE="${PB_CUSTOM}/nginx_reverse/conf/nginx-modsecurity.conf"
fi
MODSECURITY_CUSTOM_RULES="${PB_CUSTOM}/modsecurity/conf"
################################################################################
## Verify: From CB2:
if [ "${OPT_WEBSERVER}" = "apache" ] || [ "${OPT_WEBSERVER}" = "nginx_apache" ]; then
## CB2: Do we have httpd-phpmodules.conf line?
NEWCONFIGS=1
if [ -e "${APACHE_CONF}" ]; then
if [ "$(grep -m1 -c -e "${APACHE_EXTRAS}/httpd-phpmodules.conf" "${APACHE_CONF}")" = "0" ]; then
NEWCONFIGS=0
fi
fi
fi
readonly NEWCONFIGS
################################################################################
## Get DirectAdmin Option Values (from CB2)
## Retrieves values from directadmin/conf/options.conf
getDA_Opt() {
local OPTION_NAME="$1"
local OPTION_DEFAULT="$2"
## Make sure directadmin.conf exists and contains values.
if [ ! -s "${DA_CONF}" ]; then
printf "%s\n" "${OPTION_DEFAULT}"
return
fi
## Check for value in ./directadmin c
if ! "${DA_BIN}" c | grep -m1 -q -e "^${OPTION_NAME}="; then
printf "%s\n" "${OPTION_DEFAULT}"
return
fi
## Retrieve DirectAdmin's default value:
${DA_BIN} c | grep -m1 "^${OPTION_NAME}=" | cut -d= -f2
}
################################################################################
## Emulate ${!variable} (from CB2)
################################################################################
eval_var() {
local var="$1"
if [ -z "${var}" ]; then
printf "\n"
else
eval newval="\$${var}"
echo "${newval}"
fi
}
################################################################################
## Get Option (from CB2)
## Used to retrieve CB options.conf
################################################################################
getOpt() {
local OPTION_NAME="$1"
local OPTION_DEFAULT="$2"
local GET_OPTION
## CB2: Added "grep -v" to workaround many lines with empty options
GET_OPTION="$(grep -v "^${OPTION_NAME}=$" "${CB_CONF}" | grep -m1 "^${OPTION_NAME}=" | cut -d= -f2)"
if [ -z "${GET_OPTION}" ]; then
echo "${OPTION_NAME}=${OPTION_DEFAULT}" >> "${CB_CONF}"
fi
echo "${GET_OPTION}"
}
################################################################################
## Set Option (from CB2)
## Used to manipulate CB options.conf
################################################################################
setOpt() {
local OPTION_NAME="$1"
local OPTION_VALUE="$2"
local OPTION_DEFAULT="$3"
local OPT_VALUE
OPT_VALUE="$(grep -m1 "^${OPTION_NAME}=" "${CB_CONF}" | cut -d= -f2)"
${PERL} -pi -e "s#${OPTION_NAME}=${OPT_VALUE}#${OPTION_NAME}=${OPTION_VALUE}#" "${CB_CONF}"
}
################################################################################
## Set Value ($1) to ($2) in file ($3) (from CB2)
################################################################################
setVal() {
local OPTION_NAME="$1"
local OPTION_VALUE="$2"
local OPTION_FILE="$3"
local FILE_DESC
if [ "${OPTION_FILE}" = "${DA_CONF}" ] && [ ! -e "${DA_CONF}" ]; then
return
fi
if [ "${OPTION_FILE}" = "${DA_CONF}" ]; then
FILE_DESC='directadmin.conf'
elif [ "${OPTION_FILE}" = "${DA_CONF_TEMPLATE}" ]; then
FILE_DESC='directadmin.conf (template)'
else
FILE_DESC="${OPTIONS_FILE}"
fi
printf "Setting %s to %s in %s\n" "${OPTION_NAME}" "${OPTION_VALUE}" "${FILE_DESC}"
## Check if file exists.
if [ ! -e "${OPTION_FILE}" ]; then
printf "setVal(): File not found: %s\n" "${OPTION_FILE}"
return
fi
## Can't put [brackets] around the statement else grep flips out.
if ! grep -m1 -q "${OPTION_NAME}=" "${OPTION_FILE}"; then
## It's not there, so add it.
echo "${OPTION_NAME}=${OPTION_VALUE}" >> "${OPTION_FILE}"
return
else
FIND_OPTION="$(grep "${1}=" "${OPTION_FILE}")"
NEW_OPT_VALUE="${OPTION_NAME}=${OPTION_VALUE}"
## The value is already in the file $3, so use Perl regex to replace it.
${PERL} -pi -e "s|${FIND_OPTION}|${NEW_OPT_VALUE}|" "${OPTION_FILE}"
# ${PERL} -pi -e "s/`grep ${1}= ${3}`/${1}=${2}/" ${3}
fi
}
################################################################################
## Get Value ($1) from file ($2)
## Returns 0 if option is undefined (doesn't exist or is blank).
################################################################################
getVal() {
local OPTION_NAME="$1"
local OPTION_FILE="$2"
local GET_VALUE
## Check if file exists:
if [ ! -e "${OPTION_FILE}" ]; then
return
fi
GET_VALUE="$(grep -v "^${OPTION_NAME}=$" "${OPTION_FILE}" | grep -m1 "^${OPTION_NAME}=" | cut -d= -f2 | tr -d '"')"
if [ -z "${GET_VALUE}" ]; then
echo "0"
# GET_VALUE=0
else
echo "${GET_VALUE}"
fi
return
}
################################################################################
## Used to set values ON/OFF in the services.status (from CB2)
## Usage: set_service name ON|OFF|delete
################################################################################
set_service() {
local SERVICE_NAME="$1"
local SERVICE_STATUS="$2"
local SERVICE_COUNT
if [ ! -e "${DA_SERVICES}" ]; then
return
fi
SERVICE_COUNT="$(grep -m1 -c "^$SERVICE_NAME=" ${DA_SERVICES})"
if [ "${SERVICE_STATUS}" = "delete" ]; then
if [ "${SERVICE_COUNT}" -eq 0 ]; then
return
else
${PERL} -pi -e "s/^${SERVICE_NAME}=.*\n//" "${DA_SERVICES}"
fi
return
fi
if [ "${SERVICE_STATUS}" = "ON" ] || [ "${SERVICE_STATUS}" = "OFF" ]; then
if [ "${SERVICE_COUNT}" -eq 0 ]; then
echo "${SERVICE_NAME}=${SERVICE_STATUS}" >> "${DA_SERVICES}"
else
${PERL} -pi -e "s/^${SERVICE_NAME}=.*/${SERVICE_NAME}=${SERVICE_STATUS}/" "${DA_SERVICES}"
fi
return
fi
printf "set_service(): %s: unknown option: %s\n" "${SERVICE_NAME}" "${SERVICE_STATUS}"
return
}
################################################################################
## Get File from PB Mirror
## $1 = source and $2 = target
## Usage: getFile configure/proftpd/proftpd.conf ${PROFTPD_CONF}
################################################################################
getFile() {
local SOURCE_FILE="$1" ## $1 = source (input, from PB mirror)
local TARGET_FILE="$2" ## $2 = target (output)
local IFS=' '
printf "*** Notice: Downloading %s to %s\n" "${SOURCE_FILE}" "${TARGET_FILE}"
${WGET} ${WGET_CONNECT_OPTIONS} -O ${TARGET_FILE} "${PB_MIRROR}/${SOURCE_FILE}"
return
}
################################################################################
## Convert string to lowercase
################################################################################
lc() {
local char="$*"
local out
out="$(echo "$char" | tr "[:upper:]" "[:lower:]")"
local retval=$?
echo "$out"
unset out
unset char
return $retval
}
################################################################################
## Convert string to uppercase
################################################################################
uc() {
local char="$*"
local out
out="$(echo "$char" | tr "[:lower:]" "[:upper:]")"
local retval=$?
echo "$out"
unset out char
return $retval
}
################################################################################
## Ask User a Question
## Usage: ask_user "Question"
################################################################################
ask_user() {
## not done: $2 = expected answer: "yn", "custom", etc. (optional)
## not done: $3 = execute command (optional)
local ASK_QUESTION="${1:="Do you want to continue?"}"
local RESPONSE=""
while true; do
read -p "${ASK_QUESTION} (y/n): " -r RESPONSE
case $RESPONSE in
[Yy]* ) return 1; break ;;
[Nn]* ) return 0; break ;;
* ) printf "Please answer with Yes or No.\n" ;;
esac
done
}
################################################################################
## Update /usr/ports via portsnap
################################################################################
ports_update() {
if [ ! -d "${PORTS_BASE}" ]; then
printf "Setting up %s for the first time.\n" ${PORTS_BASE}
${PORTSNAP} fetch extract
fi
printf "Updating /usr/ports\n"
${PORTSNAP} fetch update
return
}
################################################################################
## pkg shortcuts
################################################################################
pkgi() { ${PKG} -d install -f -y "$@"; }
pkgu() { ${PKG} upgrade -f -y "$@"; }
pkgd() { ${PKG} delete -f "$@"; }
pkgq() { ${PKG} query "$@"; }
pkg_clean() { ${PKG} clean -y; }
pkg_update() { ${PKG} update; }
pkg_update_force() { ${PKG} update -f; }
################################################################################
## Setup latest pkg repo
################################################################################
pkg_repo_setup() {
local PKG_REPO_DIR=/usr/local/etc/pkg/repos
if [ "${OPT_LATEST_PKG_REPO}" = "YES" ]; then
if [ ! -e "${PKG_REPO_DIR}/FreeBSD.conf" ]; then
${MKDIR} -p "${PKG_REPO_DIR}"
${TOUCH} "${PKG_REPO_DIR}/FreeBSD.conf"
printf "FreeBSD: {\n url: \"pkg+http://pkg.FreeBSD.org/\${ABI}/latest\"\n}" > "${PKG_REPO_DIR}/FreeBSD.conf"
fi
fi
return
}
################################################################################
## synth shortcuts
################################################################################
synth_prepare() { ${SYNTH} prepare-system; }
synth_upgrade() { ${SYNTH} upgrade-system; }
synth_status() { ${SYNTH} status; }
################################################################################
## portmaster shortcuts
################################################################################
## Clean stale ports (deprecate soon)
clean_stale_ports() { printf "Cleaning stale ports\n"; ${PORTMASTER} -s; }
## Reinstall all ports "in place" (deprecate soon)