= FreeBSD System Setup = <> = Introduction = This page explains how to setup a FreeBSD system capable of acting as a DrawMGT server. FreeBSD differs from Linux systems in that the basic installation includes very few users tools or applications by default. This means that you need to install all application support tools that DrawMGT requires, like Apache, MySQL and PHP. This page describes the setup of the version 9.0. The procedure can be slightly different for other versions. FreeBSD is well documented. See the [[http://www.freebsd.org/doc/en/books/handbook|FreeBSD Handbook]] Installing FreeBSD applications, called ''ports'' is simple and is explained [[http://www.freebsd.org/doc/en/books/handbook/ports.html|here]]. The basic steps to prepare a FreeBSD server are: 1. Install the base operating system 1. Setup disk mirroring 1. Install support software 1. Install other support tools 1. Install and test DrawMGT These steps are described below. == Tips and Tricks == === FreeBSD User Ports === If there is network problems accessing the pre-configured master databases, try an http server accessable from the internet browser, e.g. {{{ cd /usr/ports/devel/git make MASTER_SITE_OVERRIDE=http://ftp7.freebsd.org/sites/ftp.freebsd.org/pub/FreeBSD/distfiles/ install }}} = Base Operating System Installation = To be completed = Post Installation Tasks = 1. NTP Setup * Configure NTP servers, enable and start NTP daemon {{{ vi /etc/ntp.conf # zg-3.softxs.ch:/etc/ntp.conf server 0.ch.pool.ntp.org server 1.ch.pool.ntp.org server 2.ch.pool.ntp.org server 3.ch.pool.ntp.org :x vi /etc/rc.conf # Add: ntpd_enable="YES" :x /etc/rc.d/ntpd start }}} * Check NTP is running and has connected to servers: {{{ ntpq -p }}} * Configure user ports {{{ To be completed }}} 1. Install manpages . {{{ To be completed }}} 1. Install vim . {{{ cd /usr/ports/editors/vim make install # Note: it installs python26 also }}} 1. Install bash . {{{ cd /usr/ports/shells/bash make install }}} 1. Install lsof . {{{ cd /usr/ports/sysutils/lsof make install }}} = Disk Mirroring Configuration = To be completed = Software Package Management = = Encrypted Filesystem Configuration = To be completed = Firewall Settings = IPFILTER is used as firewall. It is exactly set as described in [[http://www.freebsd.org/doc/en/books/handbook/firewalls-ipf.html|FreeBSD Handbook - Chapter 30.5 The IPFILTER (IPF) Firewall]]. Short summary of required steps: To activate IPF at boot time, the following statements need to be added to /etc/rc.conf: {{{ # IPFILTER TN 2010-02-23 ipfilter_enable="YES" # Start ipf firewall ipfilter_rules="/etc/ipf.rules" # loads rules definition text file ipmon_enable="YES" # Start IP monitor log ipmon_flags="-Ds" # D = start as daemon # s = log to syslog # v = log tcp window, ack, seq # n = map IP & port to names }}} Rulesets must be defined in /etc/rc.conf. An example ruleset ([[attachment:ipf.rules.orig]]) of a very secure inclusive type of firewall can be found in [[http://www.freebsd.org/doc/en/books/handbook/firewalls-ipf.html#AEN40317|FreeBSD Handbook - 30.5.13 Inclusive Ruleset Example]]. {{{ To be completed }}} = Main Applications to Install = Recommended installation sequence is as listed here. 1. MySQL Server/Client . {{{ cd /usr/ports/databases/mysql55-server make install # Note: it installs mysql55-client also }}} 1. Apache . {{{ cd /usr/ports/www/apache22 make install # Use default options plus MYSQL }}} 1. PHP5, PEAR and PECL_HTTP (use defaults if not otherwise noted) . {{{ cd /usr/ports/lang/php5 make install # Use default options plus APACHE cd /usr/ports/lang/php5-extensions make install # Use default options plus MBSTRING, MYSQL cd /usr/ports/devel/pear make install cd /usr/ports/databases/pear-DB make install cd /usr/ports/sysutils/pear-Log make install # Select options PEAR_DB, PEAR_Mail, PEAR_NET_SMTP cd /usr/ports/net/pear-XML_RPC make install cd /usr/ports/mail/pear-Mail_Mime make install cd /usr/ports/www/pecl-http make install }}} 1. Perl packages {{{ cd /usr/ports/devel/p5-Config-General make install }}} = MySQL Configuration = * FreeBSD does not automatically include a default my.cnf for MySQL. Instead, a set of sample configuration files can be found under /usr/local/share/mysql. These configuration files include my-small.cnf, my-medium.cnf, my-large.cnf, my-innodb-heavy-4G, my-huge.cnf and my-innodb-heavy-4G.cnf. The appropriate file can be copied and used as a template for configuration: . {{{ cp /usr/local/share/mysql/my-innodb-heavy-4G.cnf /usr/local/etc/my.cnf vi /usr/local/etc/my.cnf diff /usr/local/share/mysql/my-innodb-heavy-4G.cnf /usr/local/etc/my.cnf 46a47,50 > # Change following line if you want to store your database elsewhere > datadir = /v01/local/var/db/mysql > > sql-mode="PIPES_AS_CONCAT" # allow || as string concat 115c119 < read_buffer_size = 2M --- > read_buffer_size = 8M 121c125 < read_rnd_buffer_size = 16M --- > read_rnd_buffer_size = 32M 160c164 < query_cache_size = 64M --- > query_cache_size = 128M 203a208 > expire_logs_days=14 313c318 < key_buffer_size = 32M --- > key_buffer_size = 384M 373c378 < innodb_data_file_path = ibdata1:10M:autoextend --- > innodb_data_file_path = ibdata1:2000M;ibdata2:10M:autoextend 377c382 < #innodb_data_home_dir = --- > innodb_data_home_dir = /v01/local/var/db/mysql 430c435 < #innodb_log_group_home_dir --- > innodb_log_group_home_dir = /v01/local/var/db/mysql 451a457,465 > # You can store each InnoDB table and its indexes in its own file. > # This feature is called "multiple tablespaces" because in effect > # each table has its own tablespace > innodb_file_per_table > > # Default locale settings > character_set_server=utf8 > collation_server=utf8_general_ci > cd /usr/local ./bin/mysql_install_db chown -R mysql:mysql /v01/local/var/db/mysql /usr/local/etc/rc.d/mysql-server start ./bin/mysql_secure_installation }}} * Use the following command in '''mysql''' to check actual and available settings . {{{ mysql .... SHOW CHARACTER SET; -- list available character sets SHOW COLLATION LIKE 'utf8%'; -- list available UTF-8 collations -- show current database settings show variables like "character_set_%"; -- show current settings show variables like "collation_%"; -- List all databases with locale information (mysql 5.x) select SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME from information_schema.SCHEMATA; }}} * Use the following command in '''mysql''' to create database not as default settings . {{{ create database db character set utf8 collate utf8_hungarian_ci; }}} * Notes * Use the following command to set the correct character set in mysql: . {{{ set names utf8; }}} * mysql allows you enter national characters if the LANG variable is correctly set . {{{ export LANG=en_US.UTF-8 }}} * Note that character conversion will be made automatically if you copy data between databases of different characters sets * Check if mysql timezone table is filled up: . {{{ mysl> select * from mysql.time_zone_name }}} * If the select above gives no records, fill up the timezone table: . {{{ $ mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -uroot -psqladmin mysql }}} * Remember to run mysql_upgrade (with the optional --datadir= flag) the first time you start the MySQL server after an upgrade from an earlier version, i.e. if the database files were copied from an earlier version. = PHP Configuration = * Change '''php.ini''', take the recommended production version and change it . {{{ cd /usr/local/etc cp php.ini-production php.ini diff php.ini-production php.ini 384c384 < max_execution_time = 30 --- > max_execution_time = 240 405c405 < memory_limit = 128M --- > memory_limit = 512M 478c478 < display_errors = Off --- > display_errors = On 584c584 < ;error_log = php_errors.log --- > error_log = /var/log/php_errors.log 672c672 < post_max_size = 8M --- > post_max_size = 128M 705c705 < ;include_path = ".:/php/includes" --- > include_path = ".:/php/includes:/usr/local/share/pear" 800c800 < upload_max_filesize = 2M --- > upload_max_filesize = 128M 919c919 < ;date.timezone = --- > date.timezone = "Europe/Zurich" 1362c1362 < ;browscap = extra/browscap.ini --- > browscap = /usr/local/etc/browscap.ini 1542c1542 < session.use_trans_sid = 0 --- > session.use_trans_sid = 1 }}} * Install a browscap.ini file. Download php_browscap.ini from http://browsers.garykeith.com/downloads.asp, change the name to browscap.ini, and save it in the /usr/local/etc. * Setup session directory . {{{ mkdir -p /var/lib/php/session chmod 770 /var/lib/php/session chgrp www /var/lib/php/session }}} * The session timeout (timeout for automatic logout) is set also in php.ini. See [[SessionTimeout|Setting Session Timeout]]. = Apache Configuration = == Basic Configuration == * Enable and start HTTP daemon {{{ vi /etc/rc.conf # Add: apache22_enable="YES" :x }}} == Apache PHP module configuration == * Edit apache configuration file: . {{{ vi /usr/local/etc/apache22/httpd.conf }}} * You have to add index.php after index.html to the !DirectoryIndex directive, so it should look like this: . {{{ # DirectoryIndex: sets the file that Apache will serve if a directory # is requested. # DirectoryIndex index.html index.php }}} * Add the following lines at the end and save changes: . {{{ AddType application/x-httpd-php .php AddType application/x-httpd-php-source .phps }}} * All changes: . {{{ diff httpd.conf-ORIG httpd.conf 141c141 < ServerAdmin you@example.com --- > ServerAdmin support@softxs.ch 150c150 < #ServerName www.example.com:80 --- > ServerName zg-3.softxs.ch:80 157c157 < DocumentRoot "/usr/local/www/apache22/data" --- > DocumentRoot "/v01/local/www/html" 168,170c168,172 < AllowOverride None < Order deny,allow < Deny from all --- > Options FollowSymLinks > AllowOverride All > #AllowOverride None > #Order deny,allow > #Deny from all 183c185 < --- > 196c198 < Options Indexes FollowSymLinks --- > Options -Indexes FollowSymLinks 203c205,206 < AllowOverride None --- > # AHAHAH AllowOverride AuthConfig Limit > AllowOverride AuthConfig All 218c221 < DirectoryIndex index.html --- > DirectoryIndex index.html index.php 384a388,391 > # AHHAHAH 2009.02.23 > AddType application/x-httpd-php .php > AddType application/x-httpd-php-source .phps }}} * Start apache . {{{ /usr/local/etc/rc.d/apache22 start }}} * Check apache php modul * Create phpinfo . {{{ cd /v01/local/www/html cat > phpinfo.php ^D # CTRL-D = EOF }}} * Run phpinfo in the browser (use appropriate address instead of 192.168.1.100): . {{{ http://192.168.1.100/phpinfo.php }}} . You should see a detailed table about PHP and apache settings. * Check apache, php and mysql * Create [[test-db.php]] (native mysql connection) in /v01/local/www/html * Run test-db.php from the browser, you should get the message "connected" . {{{ http://192.168.1.100/test-db.php }}} * Create [[user.php]] (PEAR DB connection) in /usr/local/www/apache22/data * Run user.php from the browser . {{{ http://192.168.1.100/user.php }}} . You should get a similar table: . || Host || User || Password || || localhost || root || *E2DB48CF596333DCD736D6DDFDA77AFB1068A7DF || * Check apache logfile for any error: . {{{ view /var/log/httpd-error.log }}} == Virtual Host Configuration == = Additional Tools Required for DrawMGT = == PERL modules, wget, zip == . {{{ cd /usr/ports/www/p5-HTML-Parser make install cd /usr/ports/ftp/wget make install cd /usr/ports/archivers/zip make install }}} == htmldoc == . Unfortunately the '''htmldoc''' version (1.9.x or higher) which supports UTF-8 is a buggy version. We can use 1.8.27, but only in an ISO8859-1 environment. Check version in /usr/ports/textproc/htmldoc/distinfo before installing it, it must be 1.8.27. . {{{ cd /usr/ports/textproc/htmldoc make install }}} == pdflatex == . We need to install '''texlive''' package as root, which is not available (yet) as user port. . {{{ cd /tmp wget http://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz tar xf install-tl-unx.tar.gz cd install-tl-20130102 install-tl --gui=text O # options L # create symlinks in standard directories 3x R # return to main menu I # start installation to hard disk }}} . ''Thai'' language support is not build in the LaTeX babel package, we need to istall it manually if necessary (CAUTION: use gmake '''instead''' of '''make'''): . {{{ wget ftp://linux.thai.net/pub/thailinux/software/thailatex/thailatex-0.4.6.tar.gz tar xf thailatex-0.4.6.tar.gz cd thailatex-0.4.6 ./configure --with-texmfdir=/usr/local/texlive/2011/texmf gmake install cd sripts sh sync-babel sh sync-thailatex cd /usr/ports/print/fontforge make install wget ftp://linux.thai.net/pub/thailinux/software/thaifonts-scalable/thaifonts-scalable-0.4.17.tar.gz tar xf thaifonts-scalable-0.4.17.tar.gz cd thaifonts-scalable-0.4.17 ./configure --enable-latex --with-texmfdir=/usr/local/texlive/2011/texmf gmake install }}} = WebDAV Configuration = See [[WebDavConfiguration|here]]. = DocBook Configuration = See [[SetupDocBook|here]]. = Secure (chroot-ed) access setting for external users = == SSH login to allow SSH port forwarding == Create a minimal chroot environment for user who logs in the system with ssh. Only the shell will be enabled. Perform the whole procedure as '''root'''. * Create the user (e.g. ''limited'') with own group and '''sh''' as shell (as root) and change the ownership of his home directory (needed by chroot). . {{{ adduser cd /home/limited chown root:wheel . }}} * Copy the minimum environment to allow to run /bin/sh with /home/limited as root directory: . {{{ ldd /bin/sh # determine shared libraries to be copied libedit.so.6 => /lib/libedit.so.6 (0x28097000) libncurses.so.7 => /lib/libncurses.so.7 (0x280ac000) libc.so.7 => /lib/libc.so.7 (0x280eb000) mkdir lib cp /lib/libedit.so.6 /lib/libncurses.so.7 /lib/libc.so.7 lib # copy the ELF runner mkdir libexec cp /libexec/ld-elf.so.1 libexec }}} * Change sshd settings to switch in chroot-ed environment for this user ans restart sshd: . {{{ vim /etc/ssh/sshd_config # add the following lines Match User limited ChrootDirectory %h Match /etc/rc.d/sshd restart }}} == Allow SCP and SFTP only == Create a minimal chroot environment for user who should have the rights only to use scp and sftp limited to his home directory. A good and free SFTP and FTP client for Windows is [[http://winscp.net/eng/index.php|WinSCP]]. Perform the whole procedure below as '''root'''. * Install rssh from the ports system, if it is not installed yet: . {{{ cd /usr/ports/shells/rssh make install }}} * Create the user (e.g. ''limited'') with own group and '''rssh''' as shell (as root) and change the ownership of his home directory (needed by chroot). . {{{ adduser cd /home/limited chown root:wheel . }}} * Create and edit rssh config file . {{{ cp -n /usr/local/etc/rssh.conf.dist /usr/local/etc/rssh.conf # CAUTION only at first time setting vi /usr/local/etc/rssh.conf # uncoment the following lines to enable rcp and sftp allowscp allowsftp # add the following line for each user user=limited:022:00011:/home/limited }}} * Copy the minimum '''chroot''' environment to allow to run rssh, sftp with /home/limited as root directory: . {{{ cd /home/limited mkdir -p usr/bin usr/libexec usr/local/libexec usr/lib lib libexec bin dev etc cp /usr/bin/scp usr/bin/ cp /usr/libexec/sftp-server usr/libexec/ cp /usr/local/libexec/rssh_chroot_helper usr/local/libexec/ cp /bin/sh bin/ cp /libexec/ld-elf.so.1 libexec ldd /usr/bin/scp /bin/sh # determine shared libraries to be copied /usr/bin/scp: libssh.so.4 => /usr/lib/libssh.so.4 (0x28081000) libcrypt.so.4 => /lib/libcrypt.so.4 (0x280be000) libcrypto.so.5 => /lib/libcrypto.so.5 (0x280d7000) libz.so.4 => /lib/libz.so.4 (0x28230000) libc.so.7 => /lib/libc.so.7 (0x28242000) libgssapi.so.9 => /usr/lib/libgssapi.so.9 (0x28344000) libkrb5.so.9 => /usr/lib/libkrb5.so.9 (0x2834b000) libasn1.so.9 => /usr/lib/libasn1.so.9 (0x28385000) libcom_err.so.4 => /usr/lib/libcom_err.so.4 (0x283ae000) libmd.so.4 => /lib/libmd.so.4 (0x283b0000) libroken.so.9 => /usr/lib/libroken.so.9 (0x283bf000) /bin/sh: libedit.so.6 => /lib/libedit.so.6 (0x28097000) libncurses.so.7 => /lib/libncurses.so.7 (0x280ac000) libc.so.7 => /lib/libc.so.7 (0x280eb000) cp /usr/lib/libssh.so.4 /usr/lib/libgssapi.so.9 /usr/lib/libkrb5.so.9 /usr/lib/libasn1.so.9 /usr/lib/libcom_err.so.4 /usr/lib/libroken.so.9 usr/lib cp /lib/libcrypt.so.4 /lib/libcrypto.so.5 /lib/libz.so.4 /lib/libc.so.7 /lib/libmd.so.4 /lib/libedit.so.6 /lib/libncurses.so.7 lib }}} * Create a '''devfs''' filesystem inside the /dev directory in the chroot environment . {{{ vi /etc/fstab # add the following line none /home/limited/dev devfs rw 0 0 mount -t devfs devfs /home/limited/dev }}} * Copy both '''/etc/passwd''' and '''/etc/master.passwd''' to the chroot environment. It is a good idea to edit them and remove all existing accounts except the one(s) for the user(s) that will have access to the chroot. After edited the files, we have to use the pwd_mkdb tool to generate the password database inside the chroot environment: . {{{ cp /etc/passwd /etc/master.passwd etc/ pwd_mkdb -d /home/limited/etc /home/limited/etc/master.passwd }}} = Setting logrotate = * Edit /etc/newsyslog.conf and add similar lines: . {{{ # # -- HCMC2 # # logfilename [owner:group] mode count size when flags /home/hcmc2/www/html/test/var/hcmc2/zg.softxs.ch-test/log/drawmgt.log www:hcmc2 664 10 50000 * J /home/hcmc2/www/html/test/var/hcmc2/zg.softxs.ch-test/log/event.log hcmc2:hcmc2 664 10 50000 * J /home/hcmc2/www/html/prod/var/hcmc2/zg.softxs.ch-prod/log/drawmgt.log www:hcmc2 664 10 50000 * J /home/hcmc2/www/html/prod/var/hcmc2/zg.softxs.ch-prod/log/event.log hcmc2:hcmc2 664 10 50000 * J }}} = Monitoring the Server = 1. File system space 1. Backups 1. Mirroring ok * By hand {{{ gmirror status -s mirror/gm0 COMPLETE ad0 mirror/gm0 COMPLETE ad2 }}} * Via cron {{{ # lofn.softxs.ch:crontab # $Id$ # # -- Gmirror monitoring # 57 02 * * * /root/bin/mailcron -x -u"alan@softxs.ch" -s"lofn: Gmirror monitoring" /root/bin/checkGmirror.pl -v # # -- end -- }}} * Script: /root/bin/checkGmirror.pl {{{ #!/usr/bin/perl # # Check that gmirror disks are present and OK. # By default expects that two disks are present. # # Usage: checkGmirror.pl [-v] # # Typical output of 'gmirror status -s' # # mirror/gm0 COMPLETE ad0 # mirror/gm0 COMPLETE ad2 # # $component $status $device # use strict; my $V = ( $ARGV[ 0 ] eq '-v' ) ? 1 : 0; my $RC = 0; my $EXPECTED_DEVICE_COUNT = 2; my $CMD="/sbin/gmirror status -s"; open( CMD, "$CMD|" ) or die( "$0: Unable to run command: \'$CMD\'\n" ); my %components; my $line; while( defined( $line = ) ) { chomp ( $line ); my( $component, $status, $device ) = split( /\s+/, $line ); $components{ $device } = $status; $RC = 1 if ( $status eq 'DEGRADED' ); } close( CMD ); if ( scalar( keys( %components ) ) != $EXPECTED_DEVICE_COUNT ) { $RC = 1; $V = 1; } if ( $RC || $V ) { if ( $RC ) { print( "$0: ERROR: gmirror: status: BAD\n" ); } else { print( "$0: gmirror: status OK\n" ); } foreach my $device ( keys( %components ) ) { my $status = $components{ $device }; print( " device: $device, status: $status\n" ); } } exit $RC; # -- end -- }}}