Recently, I had to setup a small development server for a team of 4-5 developers. The server needed to be accessible from the Internet and thus, needed to be secured. The server would use only free software. The server needed to provide the following development services: MySQL, Apache HTTP/HTTPS, PHP, Subversion, and SSH. For security, we will enable HTTPS/SSL on Apache and require that subversion be accessed through HTTPS.
The following are notes that I took when setting up such a server. They are not 100% comprehensive; hopefully the parts I missed are very obvious or set to acceptable defaults. I’ve indicated the specific versions of the software that I downloaded; it should be okay if you get newer versions.
Download OpenSUSE 11.3
There are many flavors of Linux out there. I just chose OpenSUSE because I am most familiar with the commercial SUSE Linux product at work. If you decide to use a different flavor such as Ubuntu or Red Hat, the Linux commands in this blog may need to be adjusted. In particular, the OpenSUSE installation program, YaST, is probably not available on other flavors.
Download the OpenSUSE distribution as an ISO image file (ex: “openSUSE-11.3-DVD-x86_64.iso”). I chose 64bit because my machine is 64bit capable. Most modern desktops and servers will support 64bit and it is recommended that you go with 64bit so your server can use more memory than 4GB.
If you are not using VMware, burn the OpenSUSE ISO image file to a DVD. Stick that DVD into your dedicated server machine and boot it up to install OpenSUSE.
Install VMware Player 3.1.3
Note: If you have a dedicated server or desktop to run OpenSUSE, you can skip this section.
Because I don’t have a dedicated machine for the Linux server, I will be using VMware Player to host it on my Windows 7 64bit machine. There are two free flavors of VMware virtual software, VMware Player and VMware Server. VMware Server is optimized for input/output (good for servers), will install as a Windows service, and thus appears to be the best choice for a Linux server. Unfortunately, from what I could find on the net, VMware Server will be end-of-life’d as of this year. So I decided to go with VMware Player.
- Download and install the VMware Player. You will need to create a free account with VMware to do the download.
- Run the VMware Player and click on “Create a New Virtual Machine”.
- Select “Installer disc image file (iso)” and browse to the OpenSUSE ISO image file you downloaded above. Click Next.
- Input a default username and password. Note that the password will also be used as the root user password. Click Next.
- Name your virtual machine and keep the default location or change it. Click Next.
- Take the default of 20GB or increase it. Leave the “Store virtual disk as a single file” selected. Click Next. (Note: It is very difficult to increase the size of this virtual disk later!)
- Click on “Customize Hardware”. I recommend increasing Memory to at least 1GB. Because the server will be accessible externally, I set the Network Adapter to be “Bridged: Connected directly to the physical network”. Leave the “Replicate physical network connection state” unchecked. Click Ok.
- Double-check the settings. Click Finish.
- VMWare will create the virtual machine, start it, and boot from the OpenSUSE ISO image.
Install OpenSUSE 11.3
There isn’t much to say about this. The OpenSUSE installation was totally hands-free. (Kudos to the OpenSUSE development team!) The installer will reboot into OpenSUSE when the installation is complete. You should see a nice green login screen.
Use YaST to Install Apache and PHP
YaST makes finding and installing software very easy. Even better, YaST will take care of software package dependencies and will configure installed packages to work with each other. However, you do give up some control in order to use YaST. At first, I was uneasy because I didn’t know where YaST installed everything. As I got more familiar with YaST, I started liking how it embedded binaries into the OS (/usr/bin or /usr/sbin) and consolidated configuration files (/etc). And I didn’t have to edit as many configuration files as when I had installed without YaST.
- Log into OpenSUSE as the root user.
- Click on the green OpenSUSE icon on the bottom-left, input “yast” into the Search box, and click on the found YaST program to run it.
- The “Software” category is pre-selected. On the right, click on “Software Management”.
- Click on the Search tab.
- Search for “apache”. Check “apache2” (Apache HTTP/S Server), “apache2-mod_php5” (Apache PHP5 Module), and “subversion-server” (Apache Subversion Module) in the search results. YaST will automatically check the must-have dependencies.
- Search for “php” and you will noticed that YaST has pre-selected “php5” and other items as a dependency of “apache2-mod_php5”. In addition, check “php5-mcrypt” (required for apps like PhpMyAdmin), “php5-mysql” (PHP MySQL library), and “php5-pear” (very useful for installing PHP extensions).
- OpenSUSE pre-installs MySQL, Subversion, and SSH. To double-check, you can search for “mysql”, “subversion”, and “ssh” to see that the related “mysql-community-server”, “subversion”, and “openssh” packages are already installed (green check with black background) along with their dependencies.
- Click on the Accept button and then the Continue button to start the installation.
- You may prompted to insert the OpenSUSE DVD.
- If you are using a dedicated machine and still have the OpenSUSE DVD in the DVD drive, you shouldn’t get this prompt. Otherwise, just insert the OpenSUSE DVD.
- If you are using VMware, you will need to re-mount the OpenSUSE ISO image by clicking on the active CD icon at the botom of the VMware window, selecting Settings, selecting “Use ISO image file”, browsing to the OpenSUSE ISO image file, and clicking on OK.
- Click on the Retry button to have YaST retry the DVD access.
- The Software Management dialog will close once everything is installed.
- Exit the YaST program.
Here is a quick reference for the programs installed on OpenSUSE that we are interested in:
- Service: rcmysql start/restart/stop/status (alternatively, “service mysql start/…”);
- Binary: /usr/bin/mysql, /usr/bin/mysqld, /usr/bin/mysql_safe, …
- Config: /etc/my.cnf, /etc/mysqlaccess.conf
- Logs: /var/log/mysql
- Apache HTTP/S Server
- Service: rcapache2 start/startssl/restart/stop/status (alternatively, “service apache2 start/…”)
- Binary: /usr/sbin/httpd2-prefork
- Config: /etc/apache2/httpd.conf, /etc/sysconfig/apache2
- Logs: /var/log/apache
- Document Root: /srv/www/htdocs
- Binary: /usr/bin/php
- Config: /etc/php5/apache, /etc/php5/cli
- Apache Config: /etc/apache2/conf.d/php5.conf
- Binary: /usr/bin/svn
- Apache Config: /etc/apache2/conf.d/subversion.conf
- Note: /usr/bin/svnserve is a small, standalone Subversion server. There is no need to run svnserve as subversion access will be provided through Apache.
- Service: rcsshd start/restart/stop (alternatively, “service sshd start/…”)
- Binary: /usr/bin/ssh, usr/sbin/sshd
- Config: /etc/ssh_config, /etc/sshd_config
Test the Installation (HTTP and PHP)
Let’s run some test to ensure that everything is installed correctly. Log in as root, run Terminal, and input the following commands:
- Test MySQL:
mysql -u root -p
mysql> show databases;
mysql> use mysql;
mysql> show tables;
- Test Apache:
- Create index.html and phpinfo.php:
echo "<html><body><h3>Hello</h3></body></html>" > /srv/www/htdocs/index.html
cat > /srv/www/htdocs/phpinfo.php << EOL
> <?php phpinfo(); ?>
- Browse to http://localhost/ to test HTTP and http://host/phpinfo.php to test PHP.
Configure Subversion on Apache
- Install apache modules to enable subversion (svn) by running these commands as the root user:
The last command “a2enmod -l” will list the configured apache modules to run and you should see “dav” and “dav_svn” listed. Later on, after you restart Apache, you can run “httpd2 -M” to see the actual modules loaded by Apache.
- Edit “/etc/apache2/conf.d/subversion.conf” and add the following right after “<IfModule mod_dav_svn.c>” and before “</IfModule>”:
# Limit write permission to list of valid users.
<LimitExcept GET PROPFIND OPTIONS REPORT>
# Require SSL connection for password protection.
AuthName "Authorization Realm"
# path to password file
(Note: Use SVNParentPath instead of SVNPath if you want to have multiple repositories under “/srv/svn/repos/” without having to modify the subversion.conf file for each.)
- Create the repository at “/srv/svn/repos” directory to match what is in subversion.conf:
mkdir -p /srv/svn/repos
svnadmin create /srv/svn/repos
chown -R wwwrun:www /srv/svn/repos
The reason to run the last “chown” command is so that the Apache user (“wwwrun”) can access the repository directory and its contents. Otherwise, you will get permission denied errors when running Subversion commands against the repository.
- Create a Subversion password file “/srv/svn/user_access/passwd” (to match what is in subversion.conf) and add the first user:
mkdir -p /srv/svn/user_access
htpasswd2 -mc /srv/svn/user_access/passwd <username>
Replace “<username>” with the username of your first Subversion user. You will be prompted to input a password for that user. To create additional users at any time, run this command:htpasswd2 -m /srv/svn/user_access/passwd <username2>
Note: The “htpasswd2” command for adding subsequent users does not include the “-c” flag. Be careful because the “-c” flag will re-create the password file and you will lose all pre-existing Subversion users!
- Restart Apache so that all the changes will take effect.
- Test Subversion by browsing to http://localhost/repos/.
- You can import an existing project directory into Subversion and then check it back out by running the following commands:
svn import ./project http://localhost/repos/project --username <username>
svn co http://localhost/repos/project ./project_test
You will need to specify your “<username>” in the first Subversion command. Once you do so, Subversion will remember the username and you will not need to include it in subsequent Subversion commands.
Configure SSL on Apache
To get SSL (aka HTTPS) working on the Apache HTTP/S Server, we will need to install a certificate for our server. Instead of paying for an official certificate from companies like VeriSign, I decided to generate a self-signed root CA (Certifcate Authority) certifcate and server certificate (signed by that root CA).
- Create the certificates using the provided OpenSUSE “mkcert.sh” script. Note that you must run the “mkcert.sh” script from its directory in order for everything to work properly.
./mkcert.sh make --no-print-directory /usr/bin/openssl /usr/sbin/ custom
The script will prompt you with a bunch of selections:
- Note: If you want to leave a field blank below, just input “.”. Unless otherwise stated, just take the default selection.
- For section “STEP 2: Generating X.509 certificate signing request for CA [ca.csr]”:
- Enter “US” (United States) for “Country Name”.
- Enter the full state name for “State or Province Name” (ex: “California”).
- Enter the full city name for “Locality Name” (ex: “Los Angeles”).
- Enter the full company name for “Organization Name” (ex: “Snake Oil Company”).
- Take the default “Certificate Authority” for “Organization Unit Name”.
- Enter the full company name with “CA” (for Certificate Authority) at the end for “Common Name” (ex: “Snake Oil Company CA”).
- Enter an email address (ex: “firstname.lastname@example.org”).
- For section “STEP 5: Generating X.509 certificate signing request for SERVER [server.csr]”:
- Except for “Common Name”, repeat the inputs from STEP 2 for “Country Name”, “Start or Province Name”, etc.,
- For “Common Name”, input the fully-qualified domain name for your server (ex: “www.snakeoil.com”).
- For section “STEP 7: Enrypting RSA private key of CA with a pass phrase for security [ca.key]”:
- Answer Y for yes and input a password.
- Note: We want a password because we will be distributing the root CA certificate so users can manually install it into the browser as a trusted root CA certificate (which is used to automatically trust websites signed by it).
- For section “STEP 8: Enrypting RSA private key of SERVER with a pass phrase for security [server.key]”:
- Answer N to avoid inputting a password.
- Note: If you input a password for the server key, you will need to input this password every time you start Apache. There is really no need for a password because we will not be distributing this key.
- You should get a success message. Ignore the text about where the certificates are stored. The certificates are actually stored in the following locations where Apache can make use of them:
/etc/apache2/ssl.key/ca.key (CA RSA Private Key 1024bit; encrypted with password)
/etc/apache2/ssl.crt/ca.crt (CA X.509 Certificate Signed by itself)
/etc/apache2/ssl.key/server.key (Server RSA Private key 1024bit, not encrypted with password)
/etc/apache2/ssl.crt/server.crt (Server X.509 Certifcate Signed by CA)
(These certificates are valid for one year.)
- Copy the root CA certificate (“ca.crt”) to the non-SSL document root so that users can download and add it as a trusted root CA certifcate to their browser.
cp /etc/apache2/ssl.crt/ca.crt /srv/www/htdocs/ca.crt
- We need to create a virtual host for the HTTPS port 443:
- Make a copy of “/etc/apache2/vhosts.d/vhost-ssl.template” in the same directory and name it something like “your_vhost-ssl.conf” (ex: “snakeoil-ssl.conf”). You can name the file to whatever you want; you just need to keep the “.conf” extension.
- Edit “/etc/apache2/vhosts.d/your_vhost-ssl.conf” to make the following changes.
- Uncomment the “ServerName” and “ServerAdmin” entries. Please replace the “www.snakeoil.com” and “email@example.com” entries below with your server’s hostname (this should match what you inputted as the “Common Name” in the server certificate) and email address.
- Uncomment “#SSLCertificateChainFile /etc/apache2/ssl.crt/ca.crt” by removing the “#” pound character. Add the following line: “SSLCACertificateFile /etc/apache2/ssl.crt/ca.crt”. Also, make sure “SSLCertificateFile” and “SSLCertificateKeyFile” are set. You should end up with the following:
The first line will add our self-signed root CA certifcate into the server certificate’s authorization chain. The second line will identify our self-signed root CA certificate as the server certificate’s root CA. The third and four line identifies the server certificate that Apache HTTPS should use.
- Because we are not re-using the “/srv/www/htdocs” directory as a parent for our vhost directory, we need to define the access options for the “/src/www/htdocs-ssl” directory. Add the following near the bottom of the “<VirtualHost>” definition before “</VirtualHost>”. Look for the existing “<Directory “/src/www/cgi-bin”> … </Directory>” section and add the following right after it:
Allow from all
- The apache “ssl” module should already be installed. Run the “a2enmod -l” command and check that “ssl” is listed.
- Create the vhost document root directory and add some test files to it:
mkdir -p /srv/www/htdocs-ssl
echo "<html><body><h3>Encrypted</h3></body></html>" > /srv/www/htdocs-ssl/index.html
cp /srv/www/htdocs/phpinfo.php /srv/www/htdocs-ssl/phpinfo.php
- Restart Apache to have the SSL changes take effect. Unfortunately, if you restart using “rcapache2 restart”, SSL won’t work!
- The problem is that to enable SSL, you need to run Apache with the SSL flag set. The way to do that is to stop Apache with “rcapache2 stop” and then start Apache with the special “rcapache2 startssl” command.
- To configure “rcapache2 start/restart” to run with the SSL flag (like with “rcapache2 startssl”), run the following command:
This will modify the “/etc/sysconfig/apache2” file to add “SSL” to the “APACHE_SERVER_FLAGS” variable to be:APACHE_SERVER_FLAGS="SSL"
After you make this change, just run “rcapache2 restart” like normal. (Alternatively, you can run YaST to set “SSL” in System –> /etc/sysconfig Editor –> Network –> WWW –> Apache2 –> APACHE_SERVER_FLAGS.)
- Test the Apache SSL support:
- Browse to “http://www.yourhostname.com/ca.crt” (replace “yourhostname” with your server’s hostname) to download the root CA certificate. On Firefox, select the “Trust this CA to identify web sites” option and click the OK button.
- Browse to “https://www.yourhostname.com/” to make sure HTML works under SSL.
- Browse to “https://www.yourhostname.com/phpinfo.php” to make sure PHP works under SSL.
- Browse to “https://www.yourhostname.com/repos/” to make sure Subversion works under SSL.
- If you run into trouble, here are some troubleshooting tools:
- To view the open ports, run “netstat -vatn”. You should see port 443 (the default HTTPS port) listed.
- To view the virtual host configuration, run “httpd2 -D SSL -S”.
- To test using an SSL client, run “openssl s_client -connect localhost:443”.
Now that we know subversion works under SSL, let’s secure Subversion so it will only work under HTTPS/SSL. This is very simple to do. Edit “/etc/apache2/conf.d/subversion.conf” and uncomment the “#SSLRequireSSL” option. In addition, comment out or delete the “<LimitExcept>” and “</LimitExcept>” lines (just the two lines, not the content between them) to force the Subversion user to provide the password for all actions including viewing the repository. The result should look like:
# Limit write permission to list of valid users.
#<LimitExcept GET PROPFIND OPTIONS REPORT>
# Require SSL connection for password protection.
AuthName "Authorization Realm"
# path to password file
Surprise! You don’t need to configure anything to get SSH working. You just need to start the SSH server with this command.
Configure MySQL, Apache, and SSH to Start On Bootup
To configure MySQL and Apache to start at bootup, log in as root, run Terminal, and input the following commands:
Alternatively, run YaST, go to System, and run “System Services (Runlevel)”. Select “apache2” and click on the Enable button. Do the same for “mysql” and “sshd”.
If Firefox on OpenSUSE can’t browse to certain sites, the issue might be caused by IPv6 being enabled by default. To disable IPv6:
- Browse to “about:config”.
- Input “IPv6” into the “filter” to search.
- Click on “network.dns.disableIPv6” once to enable; the Value should turn to “true”.
If the DNS resolution doesn’t seem work in every situation, you may need to manually configure the DNS servers. For example, you can “ping google.com” but you can’t run “telnet google.com 80” (or SSH and scp) without getting a “Could not resolve hostname” error. To set the DNS servers to use Google’s DNS servers:
- Run YaST –> Network Devices –> Network Settings –> Hostname/DNS tab.
- Input 126.96.36.199 into the “Name Server1” field and 188.8.131.52 into the “Name Server2” field.
- Click Ok to apply the changes.
To secure the MySQL database, you can run the provided “/usr/bin/mysql_secure_installation” script (I haven’t tried this yet). This script will perform tasks like setting the MySQL root password and disabling the remote root login.
Some info above derived from the following websites: