This is an old revision of the document!
selfhostedwp
This tutorial is for users of Debian GNU/Linux using the LAMP stack, who are self-hosting two or more websites, have already set up TLS, directory authentication, etc., and are ready to build a self-hosted WordPress (WP) site for one of those virtual hosts. We need to begin by doing some ground work for the content management system WP gives us, by setting up an sftp server so we can add plug-ins, etc.
sudo apt install proftpd ftp ftp-ssl <sudo apt install ftpd-ssl> (not sure if this is needed any longer) cd /etc/proftpd sudo openssl req -new -x509 -days 7305 -nodes -out ftpd-rsa.pem -keyout ftpd-rsa-key.pem sudo nano /etc/proftpd/proftpd.conf <IfModule mod_tls.c> TLSEngine on TLSLog /var/log/proftpd-tls.log TLSProtocol TLSv1 # Are clients required to use FTP over TLS when talking to this server? TLSRequired off TLSRSACertificateFile /etc/proftpd/ftpd-rsa.pem TLSRSACertificateKeyFile /etc/proftpd/ftpd-rsa-key.pem # Authenticate clients that want to use FTP over TLS? TLSVerifyClient off </IfModule>
You can technically put this snippet anywhere, but its proper location is under “#Include /etc/proftpd/tls.conf” in the configuration, a space designated for small TLS configurations. Now, restart the service:
sudo systemctl restart proftpd.service
I do not change the TLSRequired setting above, because my apache configuration already redirects it, and having two can cause an HSTS error. Depending on your configuration, you might toggle that parameter above to “on.” Okay, now to mysql-server set up and making index.php default.
sudo apt install mysql-server php7.0 phpmyadmin apache2-utils php libapache2-mod-php php-mcrypt php-mysql sudo mysql_secure_installation sudo nano /etc/apache2/mods-enabled/dir.conf <IfModule mod_dir.c> DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm </IfModule> sudo systemctl restart mysqld.service
Secure phpmyadmin with user phpmyadmin and .htaccess file .phpmyadmin for security.
sudo htpasswd -c /etc/apache2/.phpmyadmin phpmyadmin sudo nano /usr/share/phpmyadmin/.htaccess AuthType Basic AuthName "Restricted Files" AuthUserFile /etc/apache2/.phpmyadmin Require valid-user sudo systemctl restart apache2.service
Now, the MySQL - more here than neeeded in case of trouble:
sudo mysql -u root -p mysql> CREATE DATABASE database1name DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; mysql> GRANT ALL ON database1name.* TO 'databaseuser'@'localhost' IDENTIFIED BY 'passwdhere'; mysql> CREATE DATABASE database2name DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; mysql> GRANT ALL ON database2name.* TO 'databaseuser'@'localhost' IDENTIFIED BY 'passwdhere'; mysql> FLUSH PRIVILEGES; mysql> EXIT;
Install PHP, configure .htaccess to allow overrides, enable apache modules:
sudo apt update sudo apt-get install php-curl php-gd php-mbstring php-mcrypt php-xml php-xmlrpc sudo nano /etc/apache2/apache2.conf <Directory /var/www/html/> AllowOverride All </Directory> sudo systemctl restart apache2 sudo a2enmod rewrite sudo apache2ctl configtest
If you have not set the fully qualified domain name, you may get an error - that can safely be ignored unless you desire it.
cd ~/Downloads mkdir wpdownload cd wpdownload curl -O https://wordpress.org/latest.tar.gz tar xzvf latest.tar.gz touch ~/Downloads/wordpress/.htaccess sudo chmod 660 ~/Downloads/wordpress/.htaccess cp ~/Downloads/wpdownload/wordpress/wp-sample-config.php ~/Downloads/wpdownload/wordpress/wp-config.php mkdir ~/Downloads/wpdownload/wordpress/wp-content/upgrade sudo cp -ar ~/Downloads/wpdownload/wordpress/. /var/www/site1.com/public_html/ sudo cp -ar ~/Downloads/wpdownload/wordpress/. /var/www/site2.com/public_html/ sudo chown -R username:www-data /var/www/site1.com/public_html sudo chown -R username:www-data /var/www/site2.com/public_html sudo find /var/www/site1.com/public_html -type d -exec chmod g+s {} \; sudo find /var/www/site2.com/public_html -type d -exec chmod g+s {} \; sudo chmod g+w /var/www/site1.com/public_html/wp-content sudo chmod g+w /var/www/site2.com/public_html/wp-content sudo chmod -R g+w /var/www/site1.com/public_html/wp-content/themes sudo chmod -R g+w /var/www/site2.com/public_html/wp-content/themes sudo chmod -R g+w /var/www/site1.com/public_html/wp-content/plugins sudo chmod -R g+w /var/www/site2.com/public_html/wp-content/plugins
Grab secure values from Word Press for wp-config.php:
curl -s https://api.wordpress.org/secret-key/1.1/salt/ sudo nano /var/www/site1.com/public_html/ <swap the defined values from first curl> curl -s https://api.wordpress.org/secret-key/1.1/salt/ sudo nano /var/www/site2.com/public_html/ <swap the defined values from second curl>
Enter user name and password for database in wp-config.php:
sudo nano /var/www/site1.com/public_html/wp-config.php . . . define('DB_NAME', 'database1name'); /** MySQL database username */ define('DB_USER', 'databaseuser'); /** MySQL database password */ define('DB_PASSWORD', 'passwdhere'); . . . define('FS_METHOD', 'direct'); sudo nano /var/www/site2.com/public_html/wp-config.php . . . define('DB_NAME', 'database2name'); /** MySQL database username */ define('DB_USER', 'databaseuser'); /** MySQL database password */ define('DB_PASSWORD', 'passwdhere'); . . . define('FS_METHOD', 'direct'); sudo systemctl restart apache2
Plug-ins and other WP services can mess with the .htaccess file often, so use this default configuration below when that happens; more templates can be found here: WP Codex
sudo nano /var/www/site1.com/public_html/.htaccess # BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> # END WordPress
Visit wordpress site and configure by opening a web browser of your choice and entering site1.com and site2.com in separate tabs. Follow the instructions it provides, especially if you do not have a publicly writeable wp-config.php file (which is a good thing).
localhost
Add Joomla, symlinks, directory permissions for low hanging fruit on WP,
Addenda on web roots outside of /var/www/