======================================= freebsd apache mysql php letsencrypt ======================================= Example config to setup a web stack to host multiple domains. - apache - php - mysql - phpmyadmin - certbot - logrotate LAN: 192.168.99.100 dog WAN: 97.98.99.100 www.example.com You will want to write some scripts to automate the management of things such as creating and deleting customers as well as their sites. ======================================= dns server zone record ======================================= https://www.genunix.com/o1/freebsd_bind9.txt --------------------------------------- @ A 97.98.99.100 www A 97.98.99.100 ======================================= update the server ======================================= freebsd-version -kru freebsd-update fetch freebsd-update install shutdown -r now pkg update pkg upgrade ======================================= install apache ======================================= pkg install apache24 ======================================= /etc/rc.conf --------------------------------------- # apache apache24_enable="YES" ======================================= /usr/local/etc/apache24/httpd.conf --------------------------------------- LoadModule socache_shmcb_module libexec/apache24/mod_socache_shmcb.so LoadModule ssl_module libexec/apache24/mod_ssl.so LoadModule rewrite_module libexec/apache24/mod_rewrite.so CustomLog "/var/log/httpd-access.log" combined Include etc/apache24/extra/httpd-autoindex.conf Include etc/apache24/extra/httpd-default.conf Include etc/apache24/extra/httpd-ssl.conf Include etc/apache24/vhosts/*.conf ======================================= /usr/local/etc/apache24/extra/httpd-default.conf --------------------------------------- ServerTokens Prod ServerSignature Off ======================================= create self signed certificate --------------------------------------- openssl req -new -x509 -days 36500 -nodes -keyout /usr/local/etc/apache24/server.key -out /usr/local/etc/apache24/server.crt ======================================= /usr/local/etc/apache24/extra/httpd-ssl.conf --------------------------------------- Listen 443 SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4:!3DES SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4:!3DES SSLHonorCipherOrder on SSLProtocol all -SSLv3 SSLProxyProtocol all -SSLv3 SSLPassPhraseDialog builtin SSLSessionCache "shmcb:/var/run/ssl_scache(512000)" SSLSessionCacheTimeout 300 <VirtualHost _default_:443> DocumentRoot "/usr/local/www/apache24/data" ServerName 192.168.99.100 ServerAlias 97.98.99.100 ServerAdmin admin@example.com ErrorLog "/var/log/httpd-error.log" TransferLog "/var/log/httpd-access.log" SSLEngine on SSLCertificateFile "/usr/local/etc/apache24/server.crt" SSLCertificateKeyFile "/usr/local/etc/apache24/server.key" <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> <Directory "/usr/local/www/apache24/cgi-bin"> SSLOptions +StdEnvVars </Directory> BrowserMatch "MSIE [2-5]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 CustomLog "/var/log/httpd-ssl_request.log" \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" </VirtualHost> ======================================= /usr/local/etc/apache24/vhosts/000.conf --------------------------------------- # If the server ip address is hit then the FIRST named virtual host will respond therefore we need this to direct it away. <VirtualHost _default_:80> ServerName 192.168.99.100 ServerAlias 97.98.99.100 ErrorLog "/var/log/httpd-error.log" CustomLog "/var/log/httpd-access.log" combined RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA] </VirtualHost> --------------------------------------- mkdir /usr/local/etc/apache24/vhosts mkdir /usr/local/etc/apache24/auth touch /usr/local/etc/apache24/auth/passwd touch /usr/local/etc/apache24/auth/group apachectl configtest service apache24 start ======================================= Confirm it works --------------------------------------- http://192.168.99.100 https://192.168.99.100 http://97.98.99.100 https://97.98.99.100 ======================================= install php ======================================= pkg install mod_php84 php84 php84-bcmath php84-brotli php84-bsdconv php84-bz2 php84-calendar php84-ctype php84-curl php84-dba php84-dom php84-enchant php84-exif php84-ffi php84-fileinfo php84-filter php84-gd php84-geos php84-gettext php84-gmp php84-iconv php84-intl php84-ldap php84-lz4 php84-mbstring php84-mysqli php84-odbc php84-opcache php84-pcntl php84-pdo php84-pecl-imagick php84-pecl-pspell php84-phar php84-posix php84-readline php84-session php84-shmop php84-simplexml php84-soap php84-sockets php84-sodium php84-sqlite3 php84-sysvmsg php84-sysvsem php84-sysvshm php84-tidy php84-tokenizer php84-xml php84-xmlreader php84-xmlwriter php84-xsl php84-zip php84-zlib php84-zstd cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini ======================================= /usr/local/etc/php.ini --------------------------------------- expose_php = Off ======================================= /usr/local/etc/apache24/httpd.conf --------------------------------------- LoadModule php_module libexec/apache24/libphp.so DirectoryIndex index.php index.html ======================================= /usr/local/etc/apache24/Includes/php.conf --------------------------------------- <FilesMatch "\.php$"> SetHandler application/x-httpd-php </FilesMatch> <FilesMatch "\.phps$"> SetHandler application/x-httpd-php-source </FilesMatch> ======================================= /usr/local/www/apache24/data/phpinfo.php --------------------------------------- <?php phpinfo(); ?> --------------------------------------- apachectl configtest apachectl restart ======================================= Confirm it works --------------------------------------- https://192.168.99.100/phpinfo.php --------------------------------------- rm /usr/local/www/apache24/data/phpinfo.php zpool create -f -m /export -o autoexpand=off -O compression=lz4 -O checksum=sha512 -O atime=on tank ada1 zfs create tank/http ======================================= creating vhosts ======================================= zfs create tank/http/owner chown -R root:wheel /export/http/owner chmod 755 /export/http/owner ======================================= creating vhost sites --------------------------------------- zfs create tank/http/owner/www.example.com chmod 755 /export/http/owner/www.example.com mkdir "/export/http/owner/www.example.com/logs" mkdir "/export/http/owner/www.example.com/tmp" mkdir "/export/http/owner/www.example.com/htdocs" chown root:wheel "/export/http/owner/www.example.com" chown root:wheel "/export/http/owner/www.example.com/logs" ======================================= /export/http/owner/www.example.com/htdocs/index.php --------------------------------------- Hello World ======================================= /usr/local/etc/apache24/vhosts/owner.www.example.com.conf --------------------------------------- <VirtualHost *:80> DocumentRoot "/export/http/owner/www.example.com/htdocs" ServerName www.example.com ServerAlias example.com ServerAdmin admin@example.com <Directory "/export/http/owner/www.example.com/htdocs"> Options +FollowSymLinks -Indexes AllowOverride All Require all granted </Directory> ErrorLog /export/http/owner/www.example.com/logs/www.example.com-error.log CustomLog /export/http/owner/www.example.com/logs/www.example.com-access.log combined </VirtualHost> --------------------------------------- apachectl configtest apachectl restart ======================================= Confirm it works --------------------------------------- http://example.com http://www.example.com ======================================= install certbot letsencrypt ======================================= pkg search certbot pkg install py39-certbot-apache ======================================= Get certificates --------------------------------------- certbot --apache certonly ======================================= Renew certificates by hand --------------------------------------- certbot renew --dry-run ======================================= crontab -e --------------------------------------- @weekly /usr/local/bin/certbot renew ======================================= /usr/local/etc/apache24/vhosts/www.example.com.conf --------------------------------------- <VirtualHost *:80> ServerName www.example.com ServerAlias example.com Redirect / https://www.example.com/ </VirtualHost> <VirtualHost *:443> ServerName www.example.com ServerAdmin admin@example.com DocumentRoot "/export/http/owner/www.example.com/htdocs" <Directory "/export/http/owner/www.example.com/htdocs"> Options +FollowSymLinks -Indexes AllowOverride All Require all granted </Directory> SSLEngine on Include /usr/local/etc/letsencrypt/options-ssl-apache.conf SSLCertificateFile /usr/local/etc/letsencrypt/live/www.example.com/cert.pem SSLCertificateKeyFile /usr/local/etc/letsencrypt/live/www.example.com/privkey.pem SSLCertificateChainFile /usr/local/etc/letsencrypt/live/www.example.com/chain.pem <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> BrowserMatch ".*MSIE.*" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 ErrorLog /export/http/owner/www.example.com/logs/www.example.com-error.log CustomLog /export/http/owner/www.example.com/logs/www.example.com-access.log combined </VirtualHost> --------------------------------------- apachectl configtest apachectl restart ======================================= confirm it works --------------------------------------- http://example.com https://example.com http://www.example.com https://www.example.com ======================================= install mariadb (mysql) ======================================= pkg install mariadb114-server mariadb114-client ======================================= /etc/rc.conf --------------------------------------- # mariadb mysql_enable="YES" mysql_optfile="/usr/local/etc/mysql/my.cnf" mysql_dbdir="/export/mysql" ======================================= /usr/local/etc/mysql/conf.d/server.cnf --------------------------------------- [mysqld] datadir = /export/mysql sql_mode = ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION --------------------------------------- rm -rf /var/db/mysql zfs create tank/mysql chown mysql:mysql /export/mysql chmod 700 /export/mysql service mysql-server start mysql_secure_installation mysql -u root -p -e "show variables like '%datadir%';" Enter password: +---------------+----------------+ | Variable_name | Value | +---------------+----------------+ | datadir | /export/mysql/ | +---------------+----------------+ mysql -u root -p -e "show variables like '%sql_mode%';" Enter password: +---------------+-----------------------------------------------------------------------+ | Variable_name | Value | +---------------+-----------------------------------------------------------------------+ | sql_mode | ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | +---------------+-----------------------------------------------------------------------+ mysql -u root -p -e "CREATE USER 'owner'@'localhost' IDENTIFIED VIA mysql_native_password USING '<password>';GRANT USAGE ON *.* TO 'owner'@'localhost' REQUIRE NONE WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;GRANT ALL PRIVILEGES ON `owner\_%`.* TO 'owner'@'localhost';" ======================================= install phpmyadmin ======================================= pkg install phpMyAdmin5-php81 ======================================= /usr/local/etc/apache24/Includes/phpmyadmin.conf --------------------------------------- Alias /myphpmyadminalias "/usr/local/www/phpMyAdmin/" <Directory "/usr/local/www/phpMyAdmin/"> Options None AllowOverride Limit Require ip 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12 </Directory> --------------------------------------- apachectl configtest apachectl restart rm /usr/local/www/phpMyAdmin/config.inc.php ======================================= phpmyadmin setup --------------------------------------- https://192.168.99.100/myphpmyadminalias/setup/ ======================================= /usr/local/www/phpMyAdmin/config.inc.php --------------------------------------- <?php /** * Generated configuration file * Generated by: phpMyAdmin 5.2.0 setup script * Date: Sun, 12 Feb 2023 05:02:26 +0000 */ /* Servers configuration */ $i = 0; /* Server: localhost [1] */ $i++; $cfg['Servers'][$i]['verbose'] = ''; $cfg['Servers'][$i]['host'] = ''; $cfg['Servers'][$i]['port'] = ''; $cfg['Servers'][$i]['socket'] = '/var/run/mysql/mysql.sock'; $cfg['Servers'][$i]['auth_type'] = 'cookie'; $cfg['Servers'][$i]['user'] = ''; $cfg['Servers'][$i]['password'] = ''; /* End of servers configuration */ $cfg['blowfish_secret'] = '*<T2GaXw}:\\9n6&aqJ#)GP-ki^7X3b$F3'; $cfg['DefaultLang'] = 'en'; $cfg['ServerDefault'] = 1; $cfg['UploadDir'] = ''; $cfg['SaveDir'] = ''; ======================================= confirm it works --------------------------------------- https://192.168.99.100/myphpmyadminalias/ ======================================= install logrotate ======================================= pkg install logrotate ======================================= /usr/local/etc/logrotate.conf --------------------------------------- # see "man logrotate" for details # rotate log files weekly weekly # keep 4 weeks worth of backlogs rotate 4 # create new (empty) log files after rotating old ones create # uncomment this if you want your log files compressed #compress # RPM packages drop log rotation information into this directory include /usr/local/etc/logrotate.d #/var/log/lastlog { # monthly # rotate 1 #} # system-specific logs may be configured here ======================================= /usr/local/etc/logrotate.d/apache24 --------------------------------------- /var/log/httpd-*.log /export/http/*/*/logs/*.log { daily missingok rotate 36500 dateext notifempty create 644 root wheel sharedscripts postrotate /usr/local/sbin/apachectl graceful endscript } --------------------------------------- rm /usr/local/etc/logrotate.d/consolekit logrotate -d /usr/local/etc/logrotate.conf <--- dry run logrotate -f /usr/local/etc/logrotate.conf <--- force run ======================================= create vhost sftp users ======================================= pw useradd -n owner -u 3000 -g www -c "WWW User John Doe" -d /export/http/owner -s /usr/sbin/nologin -C /dev/null ======================================= /etc/rc.conf --------------------------------------- syslogd_flags="-s -l /export/http/owner/dev/log" --------------------------------------- mkdir /export/http/owner/dev chown owner:www /export/http/owner service syslogd restart ======================================= /etc/ssh/sshd_config --------------------------------------- Match Group www PubkeyAuthentication yes ChrootDirectory %h AllowTcpForwarding no X11Forwarding no ForceCommand internal-sftp -f AUTH -l INFO --------------------------------------- service sshd restart ======================================= setup some protection ======================================= https://www.genunix.com/o1/freebsd_ipfw.txt https://www.genunix.com/o1/freebsd_fail2ban.txt ======================================= done =======================================