{"id":10235,"date":"2023-05-12T15:04:19","date_gmt":"2023-05-12T22:04:19","guid":{"rendered":"https:\/\/codedcommerce.com\/?p=10235"},"modified":"2024-12-06T13:08:42","modified_gmt":"2024-12-06T21:08:42","slug":"local-wordpress-development-via-homebrew","status":"publish","type":"post","link":"https:\/\/codedcommerce.com\/local-wordpress-development-via-homebrew\/","title":{"rendered":"Local WordPress development via Homebrew"},"content":{"rendered":"\n<div class=\"wp-block-group has-white-color has-tertiary-background-color has-text-color has-background has-link-color wp-elements-27bc8b34f4ee87e6026e2b7a561139a4 has-global-padding is-layout-constrained wp-container-core-group-is-layout-0910e091 wp-block-group-is-layout-constrained\" style=\"border-radius:4px;padding-top:var(--wp--preset--spacing--40);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40);padding-left:var(--wp--preset--spacing--40)\">\n<p class=\"wp-block-paragraph\"><strong>August 2024 update:<\/strong> Switched the below from Apache and MariaDB to Nginx and MySQL to match <a href=\"https:\/\/spinupwp.com\/?referral=3Q5ewR1rP4\" data-type=\"link\" data-id=\"https:\/\/spinupwp.com\/?referral=3Q5ewR1rP4\" target=\"_blank\" rel=\"noreferrer noopener\">SpinupWP<\/a> setup.<\/p>\n<\/div>\n\n\n\n<p class=\"has-drop-cap wp-block-paragraph\">Here&#8217;s a follow-up to my March 2022 <a href=\"https:\/\/codedcommerce.com\/tips-on-using-localwp-for-wordpress-sandboxing\/\">article on LocalWP power usage<\/a>. LocalWP has gotten too slow and eats-up loads of precious storage space. Some sites won&#8217;t shut down. The ones that do shut down take time to save backups each time. Starting up sites takes much longer than it used to. It&#8217;s become a pain!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve used lots of different local hosting environments over the years. I describe some of those in the above article and also in my 2020 <a href=\"https:\/\/codedcommerce.com\/local-wordpress-development-multi-environment-sandboxes-with-fully-trusted-ssl\/\">local development update article<\/a> as well.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Enter <a rel=\"noreferrer noopener\" href=\"https:\/\/brew.sh\" target=\"_blank\">Homebrew package manager for macOS<\/a>. Homebrew, or your package manager of choice for your operating system, can be used to install and maintain a high efficiency local hosting environment.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Here&#8217;s technical details describing how to set this up:<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Install web services<\/h3>\n\n\n\n<pre class=\"wp-block-code language-shell\"><code>brew install nginx php@8.3 wp-cli mysql phpmyadmin;\nbrew services start nginx;\nbrew services start php;\nbrew services start mysql;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Setup and secure the database service<\/h3>\n\n\n\n<pre class=\"wp-block-code language-shell\"><code>mysql_secure_installation;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Make some PHP adjustments<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Disable the attempted sending of email through PHP:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nano \/opt\/homebrew\/etc\/php\/8.3\/php.ini;\nEdit line: sendmail_path = \/dev\/null<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Tune your PHP-FPM for bigger WordPress sites:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nano \/opt\/homebrew\/etc\/php\/8.3\/php-fpm.d\/www.conf;\nEdit line: pm = ondemand\nEdit line: pm.max_children = 50\nEdit line: php_admin_value&#91;memory_limit] = 512M<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Setup the web service<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a self-signed SSL certificate:<\/p>\n\n\n\n<pre class=\"wp-block-code language-shell\"><code>openssl req -x509 -newkey rsa:4096 \\\n  -sha256 -days 3650 -nodes \\\n  -keyout \/opt\/homebrew\/etc\/nginx\/selfsigned.key \\\n  -out \/opt\/homebrew\/etc\/nginx\/selfsigned.crt \\\n  -subj \"\/CN=localhost\";<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Fix permissions issue by setting your default user and group:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chown -R USERNAME \/opt\/homebrew\/var\/run\/nginx;\nsudo chgrp -R staff \/opt\/homebrew\/var\/run\/nginx;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create the PhpMyAdmin site for database administration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir \/opt\/homebrew\/etc\/nginx\/servers;\nnano \/opt\/homebrew\/etc\/nginx\/servers\/phpmyadmin.conf;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Paste in the following for the file contents:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n\n        listen 443 ssl;\n        listen &#91;::]:443 ssl;\n        server_name phpmyadmin.local;\n\n        ssl_certificate \/opt\/homebrew\/etc\/nginx\/selfsigned.crt;\n        ssl_certificate_key \/opt\/homebrew\/etc\/nginx\/selfsigned.key;\n\n        location \/ {\n                root \/opt\/homebrew\/share\/phpmyadmin;\n                index index.html index.php;\n                try_files $uri $uri\/ \/index.php?$args;\n        }\n\n        location ~ \\.php$ {\n                root \/opt\/homebrew\/share\/phpmyadmin;\n                fastcgi_pass 127.0.0.1:9000;\n                fastcgi_index index.php;\n                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n                include fastcgi_params;\n        }\n\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Add the site domain name into your computer&#8217;s <code>\/etc\/hosts<\/code> file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/hosts;\nAdd line: 127.0.0.1 phpmyadmin.local<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Restart all services<\/h3>\n\n\n\n<pre class=\"wp-block-code language-shell\"><code>brew services restart --all;\nbrew services list;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Change links to the desired version<\/h3>\n\n\n\n<pre class=\"wp-block-code language-shell\"><code>brew unlink php@8.2\nbrew link php@8.3 --force --overwrite<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Navigate to <a href=\"https:\/\/phpmyadmin.local\">https:\/\/phpmyadmin.local<\/a> with your browser for database administration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setup a sandbox site<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For each sandbox site <code>\/opt\/homebrew\/etc\/nginx\/servers\/sandbox.conf<\/code> where <code>sandbox<\/code> represents the site name;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Add the site to your computer&#8217;s <code>\/etc\/hosts<\/code> file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/hosts;\nAdd line: 127.0.0.1 sandbox.local<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n\n        listen 443 ssl;\n        listen &#91;::]:443 ssl;\n        server_name sandbox.local;\n\n        ssl_certificate \/opt\/homebrew\/etc\/nginx\/selfsigned.crt;\n        ssl_certificate_key \/opt\/homebrew\/etc\/nginx\/selfsigned.key;\n\n        location \/ {\n                root \/opt\/homebrew\/var\/www\/sandbox;\n                index index.html index.php;\n                try_files $uri $uri\/ \/index.php?$args;\n        }\n\n        location ~ \\.php$ {\n                root \/opt\/homebrew\/var\/www\/sandbox;\n                fastcgi_pass 127.0.0.1:9000;\n                fastcgi_index index.php;\n                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n                include fastcgi_params;\n        }\n\n        location ~ ^\/wp-content\/uploads\/&#91;^\\\/]*\/.*$ {\n                log_not_found off;\n                try_files $uri $uri\/ @production;\n        }\n\n        location @production {\n                rewrite ^\/wp-content\/uploads\/(.*)$ https:\/\/production-url.com\/wp-content\/uploads\/$1;\n        }\n\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Restart the web server:<\/p>\n\n\n\n<pre class=\"wp-block-code language-shell\"><code>brew services restart nginx;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Install and configure WordPress<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/wordpress.org\/latest.zip\">Download WordPress<\/a> and unzip it into <code><em>\/opt\/homebrew\/var\/www\/<\/em>sandbox\/<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Edit <em><code>\/opt\/homebrew\/var\/www\/sandbox\/wp-config.php<\/code><\/em> with the following changes:<\/p>\n\n\n\n<pre class=\"wp-block-code language-php\"><code>define( 'DB_NAME', 'sandbox' );\ndefine( 'DB_USER', 'root' );\ndefine( 'DB_PASSWORD', 'password-that-you-set' );\ndefine( 'DB_HOST', 'localhost' );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Import your site&#8217;s database:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mysql -u root -p dbname &lt; import.sql<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Navigate to your website <a href=\"https:\/\/sandbox.local\">https:\/\/sandbox.local<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Setup Cron<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>crontab -e<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Type the lowercase letter <code>i<\/code> to begin Insert mode, then paste the below:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PATH=\/opt\/homebrew\/bin\/:\/usr\/local\/bin:\/usr\/bin:\/bin\n* * * * * \/opt\/homebrew\/bin\/wp --path=\/opt\/homebrew\/var\/www\/sandbox cron event run --due-now &gt;\/dev\/null 2&gt;&amp;1<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then type <code>:wq<\/code> and press Enter to save your changes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Mail trapping<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">I recommend using the <a href=\"https:\/\/wordpress.org\/plugins\/wp-mail-logging\/\" data-type=\"link\" data-id=\"https:\/\/wordpress.org\/plugins\/wp-mail-logging\/\" target=\"_blank\" rel=\"noreferrer noopener\">WP Mail Logging plugin<\/a> to be able to view blocked emails. Always disable any SMTP or email service plugins so that the dev environments can&#8217;t email out accidentally.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>August 2024 update: Switched the below from Apache and MariaDB to Nginx and MySQL to match SpinupWP setup. Here&#8217;s a follow-up to my March 2022 article on LocalWP power usage. LocalWP has gotten too slow and eats-up loads of precious storage space. Some sites won&#8217;t shut down. The ones that do shut down take time [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4543,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[52047,635718626],"tags":[],"class_list":["post-10235","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","category-wordpress-guides"],"jetpack_featured_media_url":"https:\/\/codedcommerce.com\/wp-content\/uploads\/2020\/06\/christopher-gower-m_HRfLhgABo-unsplash-scaled.jpg","_links":{"self":[{"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/posts\/10235","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/comments?post=10235"}],"version-history":[{"count":0,"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/posts\/10235\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/media\/4543"}],"wp:attachment":[{"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/media?parent=10235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/categories?post=10235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codedcommerce.com\/wp-json\/wp\/v2\/tags?post=10235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}