Turn Ubuntu into a Web Developing Workstation
Updated March 27, 2016.
I was going through some old notes and found directions I wrote for myself when the site was still using WordPress. And sharing is caring, right?
If you want to create a website, an offline version contained entirely on your local computer will be one of your primary development tools. No domain or web hosting is necessary and you don’t even need an internet connection. Then after you get everything registered and online, you can still write content and experiment with changes locally without disrupting the live site.
Even in the easy Linux distros, this can be confusing and problematic so here’s a guide to local Drupal and WordPress installs on top of a LAMP server in Debian 8 and Ubuntu (14.04 and 16.04) using Apache 2.4. There are 5 major steps to set yourself up with Clean and Permalink URLs, no lingering permissions issues and zero time needed scouring forums for configuration file fixes (which has become a rite of passage of sorts).
A web content management system in Linux usually uses a LAMP server (Linux, Apache, MySQL and PHP). Other variations replace Apache with nginx, PHP with Perl, and MySQL for MariaDB or PostregSQL. The LAMP equavalent in Windows is WAMP and OS X would use MAMP.
Regardless of your choice, this server stack runs the CMS backend and you’re literally installing full-powered web and SQL servers onto your computer so you must take care to not allow Apache internet access. By default, it listens for incoming connections on TCP port 80 from all interfaces so we’ll disable that. If you want, you can also switch on the default AppArmor profiles for Apache and MySQL. For that you’ll want the package apparmor-profiles from the repositories.
Drupal and WordPress are two of many web development frameworks frequently found in Linux repositories. Usually the repo packages install into /usr/share/ and symlink to /var/www/ but that gains you nothing except unnecessary complexity. Drupal and WordPress update themselves, themes, plugins and modules from within the platform’s own interface, not through the distro’s repos. To start with the most recent version you’ll need to download from the CMS’s official site anyway, so you should start there and not your distribution’s repositories.
Step 1 – LAMP Stack
There are three main ways to do this: First is using Tasksel, second is installing each component separately and third is the command below. Methods one and two are, again, unnecessary and the command given is the easiest way to do it while not requiring extra packages. First open a root terminal which you’ll need throughout this page.
sudo -i apt-get install lamp-server^
The ^ symbol is not a typo. During installation, you will assign an admin password for MySQL’s root account. This has nothing to do with the system’s root account or filesystem permissions so it’s alright to build local sites with MySQL’s root account.
Step 2 – Configure Apache
As mentioned, installing a default Apache opens TCP port 80 to the public. That means it’s accepting incoming connections from the internet. It’s always there, listening…judging. That must be stopped.
sed -i 's/Listen 80/Listen 127.0.0.1:80/g' > /etc/apache2/ports.conf
sed is a text stream editor which makes editing single lines of configuration files very easy. The above command simply changes “Listen 80” to “Listen 127.0.0.1:80” in the file /etc/apache2/ports.conf.
Remove Error for Fully Qualified Domain Name
Apache tries to detect its domain name on startup but can’t because it doesn’t have one. Apache reports this error in the terminal and how it defaults to 127.0.1.1 for the ServerName. We’ll make a config file so it knows what to do and doesn’t spam the logs. We’ll continue using boss commands.
echo "ServerName localhost" | tee /etc/apache2/conf-available/fqdn.conf && a2enconf fqdn
To use Drupal’s Clean URLs or WordPress’s Permalinks, enable Apache’s URL rewrite module.
Then edit the config file to allow symlink following in the site directory.
sed -i 's/AllowOverride None/AllowOverride All/g' > /etc/apache2/apache2.conf
Default Apache Site Directory
Apache 2.4 looks for site directories in /var/www/html/. The easiest thing to do is leave this default domicile alone so you’d have /var/www/html/site1, /var/www/html/site2, etc. If you do want to relocate your site directory to someplace else like external media, go back into apache2.conf or …*****/sites-available/default above and change the lines “DocumentRoot /var/www/html” and “Directory /var/www/html” to your new directory path.
When you’re finished making all your changes to Apache, restart it.
service apache2 restart
Then run netstat to see what services are listening.
You should see something like this:
That screenshot was taken on a default Ubuntu VM so it has Cups and Dnsmasq still enabled. But notice how Apache is listening locally—that’s what we want. See MySQL on localhost too? Now on to that.
Step 3 – Configure MySQL
- In CMS terminology, a database basically means your website.
- MySQL’s username and password and the sitename (the database name) you use below will be used again in the first few steps of installing Drupal or WordPress. Don’t loose them.
It’s never a bad idea to run the MySQL hardening script. Answer yes for each prompt.***
The command below will ask you for the MySQL root password you picked when you first installed the LAMP stack in Step 1. The sitename can be whatever you want it to be (domain, company name, etc.).
mysqladmin -uroot -p create sitename
We don’t need network access for MySQL with a local site so we’ll disable it.
sed -i 's/bind-address = 127.0.0.1/#bind-address = 127.0.0.1/g' > /etc/mysql/my.cnf
***Then add as the very next line after #bind-address:
Restart MySQL and if you run netstat again, you won’t see it present.
service mysql restart
Step 4 – Install the CMS
First make the folder your site will live in.
This command downloads WordPress with wget, extracts the wordpress folder from the tarball to /tmp and then copies the wordpress folder’s contents to /var/www/html/sitename.
wget https://wordpress.org/latest.tar.gz && tar -xvzf latest.tar.gz -C /tmp && cp -r /tmp/wordpress/* /var/www/html/sitename
Drupal’s download files are named by release. There’s no one reliable URL to wget like with WordPress so you’ll need to download the tarball from Drupal’s website. Once you have it, you can use a wildcard in place of the version number in the file name. So:
tar -xvzf /home/yourusername/Downloads/drupal*.tar.gz -C /tmp && cp -r /tmp/drupal*/* /var/www/html/sitename
Drupal also needs the package php5-gd installed.
apt-get install php5-gd
This last part is the magic which makes everything come together. To install plugins, modules and themes or to update either CMS, Apache’s user account needs full access to the site directory. To do this, give Apache ownership of that directory—don’t change its permissions (do chown, not chmod) because that applies to all users on the system. Then restart Apache and exit the root terminal.
chown -R www-data /var/www/html/sitename && service apache2 restart exit
Step 5 – CMS Welcome Page
Now go to localhost/sitename in a web browser and fill in the forms as you go. The database name, username and password you enter here are what you used earlier when you first set up MySQL; this was the second important point in Step 3. Leave both the database host (which should be localhost) and the table prefix as default.
For Drupal, you will be greeted with this:
Once you get the CMS set up, you should bookmark the admin dashboard for easy access. In Drupal, you want the url: http://localhost/sitename/?q=node and for WordPress, it’ll be: http://localhost/sitename/wp-login.php.
- If you want to modify a theme, create a child theme first and work only in that. The child theme directory needs to be owned by www-data (Apache). More on child themes at the WordPress Codex.
Upload the Site Online
This is what worked for me with WordPress on a hosting server using Apache 2.2 and CPanel. Your mileage may vary.
Step 1: When ready to upload, first create the MySQL database on the hosting server. Don’t use a MySQL root account for this and do use a strong password. If you have the access, make sure you run the mysql_secure_installation script to harden the MySQL server process.
If you’re using WordPress, you should also use the iThemes/Better WordPress Security plugin to harden your site. Install it into a fresh WP and go through its settings before uploading anything. The plugin has a few options that, if you choose to enable, should be switched on before any of your content is on the host server.
Step 2: Compress the entire directory for your local site into a tar.gz and upload the tarball to the host server. Extract it into public_html on the host.
Step 3: Export all WordPress settings from the local install, then import the .xml file into WP on the host server. Edit wp-config.php and set DB_NAME, DB_USER and DB_PASSWORD to those for the MySQL database on the host.
Step 4: Install the WP plugin Search and Replace. Check All and replace all instances of localhost/sitename with your website’s top-level domain. Example: Replace localhost/thesimplecomputer with thesimplecomputer.info. There should be no need to do anything with PhpMyAdmin locally or on the hosting server. After you get the site working, can remove the Search and Replace plugin.
Step 5: When everything is working correctly, back it all up. Set CPanel or Plesk or whatever to show hidden files, create a tarball of the public_html folder and export all the site settings in WP to an .xml file. Don’t store these online and after you’ve downloaded the tarballed backup folder, delete it from the hosting server!
! This is Important !
Drupal and WordPress don’t give you encrypted connections to login pages by default. This means that when your site is online and you access the administration pages through a browser, you’re logging in over HTTP, not HTTPS, so your username and password are sent in plaintext. It is very important that you change this. Setting up HTTPS access to only the login pages is complicated and links for how to do this are given further below.
A better solution would be to use Let’s Encrypt to create a free SSL certificate and install that on your hosting provider. What you get in return is, rather than telling WordPress or Drupal to force encryption for only a few pages, you’re instead telling the web server to force your entire site over an encrypted connection. Instructions for this are also in a link below.
MySQL Crash Course
Basic commands for working with MySQL through the terminal which you’ll probably find useful at some point.
Log in with password prompt.
mysql -u username -p
Show all databases (all websites).
Remove a database.
drop schema databasename;