Setting up a new WordPress site (Virtual host) on macOS
201121-22
A. Install and prepare our site’s WordPress Folder
Prerequisites
It is supposed that previously:
- We have downloaded the latest WordPress .tar file, and that we have untarred it into a folder of our local machine. In our case this is the /tmp1/wp/ folder
- We have created a site’s folder under the www Document Root folder (DocumentRoot). In our case the www root folder is ‘/usr/local/var/www’ and the full path-name of the site’s folder is ‘/usr/local/var/www/test1.com’ for the site: test1.com. Since now, this folder contains just one file, the index.html file, for testing purposes.
- We have enabled virtual hosts for the Apache server, and that we have already put the site’s basic script block inside the virtual hosts configuration httpd-vhosts.conf file, which is located inside the /usr/local/etc/httpd/extra folder. The script block for our test1.com site is actually:
#--------------------201120---------------------------------- <VirtualHost *:80> ServerAdmin youremail@gmail.com ServerName test1.com ServerAlias www.test1.com DocumentRoot /usr/local/var/www/test1.com/ #ErrorLog ${APACHE_LOG_DIR}/error.log #CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory /usr/local/var/www/test1.com/> AllowOverride All DirectoryIndex index.html </Directory> </VirtualHost> #-----------------------------------------------------------
- We have added our site in hosts file of our MAC (/etc/hosts).
- We are able to test our site via our browser:
Installation (copy) of WordPress files (folder structure) into site’s folder
The WordPress folder/files installation is pretty straightforward and quite simple. (NB: In this post of the present site you can find detailed instructions). We have just to copy the WordPress untarred files to our site’s folder. For instance, if we have untarred them into /tmp/wordpress/ folder we can use the cp command:
$ cp -a /tmp1/wordpress/. /usr/local/var/www/test1.com/
Here we are:
.htaccess
.htaccess is a configuration file that can be used with web sites running under the Apache Web Server. When a .htaccess file is placed in a directory, then the .htaccess file can be detected and executed by the Apache Web Server software. We have to configure Apache server in order to be able to detect and use the .htacess file.
.htaccess files can are useful when we want to alter the configuration of the Apache Web Server and enable/disable additional functionality and features of the Apache Web Server software. Such features include basic redirect functionality, such as through WordPress permalinks, or for instance, if a ‘404 file not found’ error occurs, or for more advanced functions such as content password protection or image hotlink prevention.
.htaccess files (known as hypertext access files or “distributed configuration files”) provide a way to make configuration changes on a per-directory basis. A file, containing one or more configuration directives, is placed in a particular web site document directory, and the directives apply to that directory and all subdirectories thereof.
Enabling .htaccess
By default, the use of all .htaccess files is disabled (denied). Below is an extract of the main (global) Apache configuration file /usr/local/etc/httpd/httpd.conf.
# # The following lines prevent .htaccess and .htpasswd files from being # viewed by Web clients. # <Files ".ht*"> Require all denied </Files>
WordPress and many WordPress plugins use .ht* (.htaccess) files extensively for in-directory tweaks to the web server’s behavior. So, we have to enable them, at least for our site.
The use of .htaccess can be enabled on per web site (virtual host) basis and per directory. To enable a web site (a virtual host) to by-pass the global prohibition we have to declare it (using the appropriate ‘directive’), inside our site’s (test1.com) script block into the httpd-vhosts.conf file, which is located inside the /usr/local/etc/httpd/extra folder.
<Directory /usr/local/var/www/test1.com/> AllowOverride All </Directory>
Adding an empty .htaccess file
Then, we have to add a dummy (an empty) .htaccess file inside the site’s web top folder /usr/local/var/www/test1.com/, so this will be available for WordPress later use. In our case we can create the file by typing:
$ touch /usr/local/var/www/test1.com/.htaccess
For using .htaccess with WordPress, see more at https://wordpress.org/support/article/htaccess/.
Also, if you, later on, encounter issues modifying the .htaccess file, this might be caused because Apache module mod_rewrite is not enabled. So, to enable it, you can see [here]
Folder and file permission settings
Here we are going to implement permission settings rules that are recommended for most users. These are:
All folders and sub-folders: 755
The suggested permissions for all the folders are 755. This translates to read, write, and execute permissions for the user and only read and execute permissions for groups and others.
All files: 644
The appropriate permission for all files in WordPress should be 644. This means that the users have read and write permissions and groups and others can only read the files. This will ensure that no one accessing the files can alter them, apart from the owner.
Permission Modes
The permission mode is computed by adding up the following values for the user, the filegroup, and for everyone else. The diagram shows how.
Read 4 – Allowed to read files
Write 2 – Allowed to write/modify files
eXecute 1 – Read/write/delete/modify/directory
user | group | world (all) |
7 | 5 | 5 |
r+w+x | r+x | r+x |
4+2+1 | 4+0+1 | 4+0+1 = 755 |
6 | 4 | 4 |
r+w | r | r |
4+2 | 4+0+0 | 4+0+0 = 744 |
➜ / ls -al usr/local/var/www/test1.com/ total 400 drwxr-xr-x 23 zp staff 736 Nov 23 17:43 . drwxr-xr-x 8 zp admin 256 Nov 20 14:49 .. -rw-r--r--@ 1 zp staff 6148 Nov 23 18:17 .DS_Store -rw-r--r--@ 1 zp admin 194 Nov 20 14:53 index.html -rw-r--r-- 1 zp staff 405 Feb 6 2020 index.php -rw-r--r-- 1 zp staff 19915 Feb 12 2020 license.txt -rw-r--r--@ 1 zp staff 7278 Jun 26 16:58 readme.html -rw-r--r-- 1 zp staff 7101 Jul 28 20:20 wp-activate.php drwxr-xr-x 97 zp staff 3104 Oct 30 22:41 wp-admin -rw-r--r-- 1 zp staff 351 Feb 6 2020 wp-blog-header.php -rw-r--r-- 1 zp staff 2332 Jul 23 03:52 wp-comments-post.php -rw-r--r-- 1 zp staff 2913 Feb 6 2020 wp-config-sample.php drwxr-xr-x 5 zp staff 160 Oct 30 22:41 wp-content -rw-r--r-- 1 zp staff 3940 Feb 6 2020 wp-cron.php drwxr-xr-x 220 zp staff 7040 Oct 30 22:41 wp-includes -rw-r--r-- 1 zp staff 2496 Feb 6 2020 wp-links-opml.php -rw-r--r-- 1 zp staff 3300 Feb 6 2020 wp-load.php -rw-r--r-- 1 zp staff 48761 Jul 7 06:59 wp-login.php -rw-r--r-- 1 zp staff 8509 Apr 14 2020 wp-mail.php -rw-r--r-- 1 zp staff 20181 Jul 6 13:50 wp-settings.php -rw-r--r-- 1 zp staff 31159 Jul 24 00:11 wp-signup.php -rw-r--r-- 1 zp staff 4755 Feb 6 2020 wp-trackback.php -rw-r--r-- 1 zp staff 3236 Jun 8 22:55 xmlrpc.php ➜
For Folders:
$ find /usr/local/var/www/test1.com/ -type d -exec chmod 755 {} \;
For Files:
$ find /usr/local/var/www/test1.com/ -type f -exec chmod 644 {} \;
➜ / find /usr/local/var/www/test1.com/ -type d -exec chmod 755 {} \; ➜ / find /usr/local/var/www/test1.com/ -type f -exec chmod 644 {} \; ➜ / ➜ / ls -al usr/local/var/www/test1.com/ total 400 drwxr-xr-x 23 zp staff 736 Nov 23 17:43 . drwxr-xr-x 8 zp admin 256 Nov 20 14:49 .. -rw-r--r--@ 1 zp staff 6148 Nov 23 18:17 .DS_Store -rw-r--r--@ 1 zp admin 194 Nov 20 14:53 index.html -rw-r--r-- 1 zp staff 405 Feb 6 2020 index.php -rw-r--r-- 1 zp staff 19915 Feb 12 2020 license.txt -rw-r--r--@ 1 zp staff 7278 Jun 26 16:58 readme.html -rw-r--r-- 1 zp staff 7101 Jul 28 20:20 wp-activate.php drwxr-xr-x 97 zp staff 3104 Oct 30 22:41 wp-admin -rw-r--r-- 1 zp staff 351 Feb 6 2020 wp-blog-header.php -rw-r--r-- 1 zp staff 2332 Jul 23 03:52 wp-comments-post.php -rw-r--r-- 1 zp staff 2913 Feb 6 2020 wp-config-sample.php drwxr-xr-x 5 zp staff 160 Oct 30 22:41 wp-content -rw-r--r-- 1 zp staff 3940 Feb 6 2020 wp-cron.php drwxr-xr-x 220 zp staff 7040 Oct 30 22:41 wp-includes -rw-r--r-- 1 zp staff 2496 Feb 6 2020 wp-links-opml.php -rw-r--r-- 1 zp staff 3300 Feb 6 2020 wp-load.php -rw-r--r-- 1 zp staff 48761 Jul 7 06:59 wp-login.php -rw-r--r-- 1 zp staff 8509 Apr 14 2020 wp-mail.php -rw-r--r-- 1 zp staff 20181 Jul 6 13:50 wp-settings.php -rw-r--r-- 1 zp staff 31159 Jul 24 00:11 wp-signup.php -rw-r--r-- 1 zp staff 4755 Feb 6 2020 wp-trackback.php -rw-r--r-- 1 zp staff 3236 Jun 8 22:55 xmlrpc.php ➜ /
B. Setting up the WordPress Configuration File
The major WordPress configuration file is called wp-config.php (a php language source file). The WordPress package (that one we have downloaded and put its copy into our site’s folder (/usr/local/var/www/test1.com/) comes with a sample file (wp-config-sample.php), which can be used for necessary modifications and then save the modified version to the real wp-config.php file.
We can use the VS Code editor to open the wp-config-sample.php file.
First, we have to make the adjustment to point to our site (database and use names, password, etc.)
Next, we set the method that WordPress should use to write to the filesystem. Since we’ve given the web server permission to write where it needs to, we can explicitly set the filesystem method to “direct”. Failure to set this with our current settings would result in WordPress prompting for FTP credentials when we perform some actions.
After that, we have to adjust some secret keys to provide some security for our installation. These are the ‘Authentication Unique Keys and Salts’.
WordPress uses cookies (or information stored in your browser) to verify the identity of logged in users and commenters. To better protect and ensure encryption of the login information stored in your WordPress cookies, WordPress includes secret authentication keys and salts in your wp-config.php file.
Updating your keys and salts on a regular basis is another way to harden WordPress. Again, while the existing keys are extremely difficult to break, changing them every so often adds another layer of complexity.
Updating your keys & salts will force all logged in users to log in again because changing them automatically invalidates the login of any user logged in to the site.
WordPress provides a secure generator for these values so that you do not have to try to come up with good values on your own. These are only used internally, so it won’t hurt usability to have complex, secure values here.
To grab secure values from the WordPress secret key generator, type:
$ curl -s https://api.wordpress.org/secret-key/1.1/salt/
You will get back unique values that look something like this:
➜ / ➜ / curl -s https://api.wordpress.org/secret-key/1.1/salt/ define('AUTH_KEY', '1o/}(5L$?nDr8lK=~*V<9G/:bo3Ll&.R9L23FtM~*+s$BnN~|>mO22o{pn<G%F3J'); define('SECURE_AUTH_KEY', 'xz-&s[YBH+e%W805p2T|z#d0e8yu$ qc.Ol!5ze8Y(T%w=Q(lT]?_NR/WQp:ov}<'); define('LOGGED_IN_KEY', '?g3pUQG`=W7^:24*n|3>q<pn#+{MK# !V|`1a68IX?~Wo+GmAvh,nhYOUYWi@ewx'); define('NONCE_KEY', 'f!&%.a5;W [l&r4hI-=9NgPK&k7`Fvb64]=V1z5l$5-db+i>t3?8.Z}|9^go}AIR'); define('AUTH_SALT', 'Y-k(+a<j7..T~EX`q9+m{X9PA:On@|zkn?(>vR+-<e&b B)E?!_Ui9D}j;Iv{Fp;'); define('SECURE_AUTH_SALT', 'C/X<VK|O:HTNl404bO!FJ^n|zOKKv7{%+woKBxQ^V((6QcD2p3$TRe-.Wcd;TNl;'); define('LOGGED_IN_SALT', ']x-NbFh yn2Oa? 1tk4;dVAX,h*)+?0,*+7+|!4<L=7i^wBx-uU+hREOz+F/6`x'); define('NONCE_SALT', '8{Ya?#5lo,|g!C.z)&bnBq^!g]ShKb|sX~e DVVNj*Kp$~`/G7a,TBVnCGyk64S;'); ➜ /
This is how should be the whole wp-config.php file, for our site:
<?php /** * The base configuration for WordPress * * The wp-config.php creation script uses this file during the * installation. You don't have to use the web site, you can * copy this file to "wp-config.php" and fill in the values. * * This file contains the following configurations: * * * MySQL settings * * Secret keys * * Database table prefix * * ABSPATH * * @link https://wordpress.org/support/article/editing-wp-config-php/ * * @package WordPress */ // ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define( 'DB_NAME', 'macdbwptest1' ); /** MySQL database username */ define( 'DB_USER', 'macuser1' ); /** MySQL database password */ define( 'DB_PASSWORD', 'macdbpassw' ); /** MySQL hostname */ define( 'DB_HOST', 'localhost' ); /** Database Charset to use in creating database tables. */ define( 'DB_CHARSET', 'utf8mb4' ); /** The Database Collate type. Don't change this if in doubt. */ define( 'DB_COLLATE', 'utf8mb4_unicode_ci' ); /** WordPress should use to write directly to the filesystem (not via FTP) */ define('FS_METHOD', 'direct'); /**#@+ * Authentication Unique Keys and Salts. * * Change these to different unique phrases! * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service} * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again. * * @since 2.6.0 */ define('AUTH_KEY', '1o/}(5L$?nDr8lK=~*V<9G/:bo3Ll&.R9L23FtM~*+s$BnN~|>mO22o{pn<G%F3J'); define('SECURE_AUTH_KEY', 'xz-&s[YBH+e%W805p2T|z#d0e8yu$ qc.Ol!5ze8Y(T%w=Q(lT]?_NR/WQp:ov}<'); define('LOGGED_IN_KEY', '?g3pUQG`=W7^:24*n|3>q<pn#+{MK# !V|`1a68IX?~Wo+GmAvh,nhYOUYWi@ewx'); define('NONCE_KEY', 'f!&%.a5;W [l&r4hI-=9NgPK&k7`Fvb64]=V1z5l$5-db+i>t3?8.Z}|9^go}AIR'); define('AUTH_SALT', 'Y-k(+a<j7..T~EX`q9+m{X9PA:On@|zkn?(>vR+-<e&b B)E?!_Ui9D}j;Iv{Fp;'); define('SECURE_AUTH_SALT', 'C/X<VK|O:HTNl404bO!FJ^n|zOKKv7{%+woKBxQ^V((6QcD2p3$TRe-.Wcd;TNl;'); define('LOGGED_IN_SALT', ']x-NbFh yn2Oa? 1tk4;dVAX,h*)+?0,*+7+|!4<L=7i^wBx-uU+hREOz+F/6`x'); define('NONCE_SALT', '8{Ya?#5lo,|g!C.z)&bnBq^!g]ShKb|sX~e DVVNj*Kp$~`/G7a,TBVnCGyk64S;'); /**#@-*/ /** * WordPress Database Table prefix. * * You can have multiple installations in one database if you give each * a unique prefix. Only numbers, letters, and underscores please! */ $table_prefix = 'wp_'; /** * For developers: WordPress debugging mode. * * Change this to true to enable the display of notices during development. * It is strongly recommended that plugin and theme developers use WP_DEBUG * in their development environments. * * For information on other constants that can be used for debugging, * visit the documentation. * * @link https://wordpress.org/support/article/debugging-in-wordpress/ */ define( 'WP_DEBUG', false ); /* That's all, stop editing! Happy publishing. */ /** Absolute path to the WordPress directory. */ if ( ! defined( 'ABSPATH' ) ) { define( 'ABSPATH', __DIR__ . '/' ); } /** Sets up WordPress vars and included files. */ require_once ABSPATH . 'wp-settings.php';
C. Finalize, the virtual-host script block of our site
As we have said, the script block into the httpd-vhosts.conf file of our site, is located inside the /usr/local/etc/httpd/extra folder.
Previously we have allowed the .htaccess:
<Directory /usr/local/var/www/test1.com/> AllowOverride All </Directory>
Now we have to change the directive that will make the index.php, directory index file, instead of index.html:
<Directory /var/www/sv_wp1/> AllowOverride All DirectoryIndex index.php </Directory>
The final ‘version’ of our site’s script block is:
#--------------------201120---------------------------------- <VirtualHost *:80> ServerAdmin youremail@gmail.com ServerName test1.com ServerAlias www.test1.com DocumentRoot /usr/local/var/www/test1.com #ErrorLog ${Custom_Log}/error.log #CustomLog ${Custom_Log}/access.log combined <Directory /usr/local/var/www/test1.com> AllowOverride All DirectoryIndex index.php </Directory> </VirtualHost> #-----------------------------------------------------------
The whole virtual hosts file (active containers – script blocks):
#--------------------201121---------------------------------- <VirtualHost *:80> ServerAdmin youremail@gmail.com ServerName localhost #ServerAlias www.test1.com DocumentRoot /usr/local/var/www #ErrorLog ${Custom_Log}/error.log #CustomLog ${Custom_Log}/access.log combined <Directory /usr/local/var/www> #AllowOverride All DirectoryIndex index.html index.php </Directory> </VirtualHost> #----------------------------------------------------------- #--------------------201124---------------------------------- <VirtualHost *:80> ServerAdmin youremail@gmail.com ServerName test1.com ServerAlias www.test1.com DocumentRoot /usr/local/var/www/test1.com #ErrorLog ${Custom_Log}/error.log #CustomLog ${Custom_Log}/access.log combined <Directory /usr/local/var/www/test1.com> AllowOverride All DirectoryIndex index.php </Directory> </VirtualHost> #-----------------------------------------------------------
D. Completing the Installation Through the WordPress Web Interface
Now that the server configuration is complete, we can complete the installation through the web interface.
Restart Apache
➜ / brew services stop httpd Stopping `httpd`... (might take a while) ==> Successfully stopped `httpd` (label: homebrew.mxcl.httpd) ➜ / brew services start httpd ==> Successfully started `httpd` (label: homebrew.mxcl.httpd) ➜ /
In your web browser, navigate to your server’s domain name or public IP address:
Select the language you would like to use and press Continue to proceed to the main setup page of WordPress. Select a name for your WordPress site and choose a username (it is recommended not to choose something like “admin” for security purposes). A strong password is generated automatically. Save this password or select an alternative strong password. Then enter your email address and select whether you want to discourage search engines from indexing your site:
Site Title: <MyTestSite1>
Username: <user1>
Password: <apaasword>
Your Email: youremail@gmail.com
Finally, click on Install WordPress:
Then you can login to your new site:
That’s it!
Thank you for reading!