<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Adam Patterson</title>
	<atom:link href="https://adampatterson.ca/feed/" rel="self" type="application/rss+xml" />
	<link>https://adampatterson.ca</link>
	<description>Edmonton Developer</description>
	<lastBuildDate>Sat, 28 Jun 2025 17:47:38 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.1</generator>
<site xmlns="com-wordpress:feed-additions:1">123805354</site>	<item>
		<title>How to Change Git Branches on a Site Deployed with Forge</title>
		<link>https://adampatterson.ca/development/how-to-change-git-branches-on-a-site-deployed-with-forge/</link>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Sat, 28 Jun 2025 17:36:46 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Tools]]></category>
		<guid isPermaLink="false">https://adampatterson.ca/?p=2147</guid>

					<description><![CDATA[When Forge provisions a site, it uses a shallow clone of a single branch, which prevents switching to other branches later. This is helpful for performance but can be limiting when you need to test or deploy from a different branch on a staging or test server. Here’s how Forge typically clones a repo If...]]></description>
										<content:encoded><![CDATA[
<p></p>



<p>When Forge provisions a site, it uses a shallow clone of a single branch, which prevents switching to other branches later. This is helpful for performance but can be limiting when you need to test or deploy from a different branch on a staging or test server.</p>



<h2 class="wp-block-heading"><strong>Here’s how Forge typically clones a repo</strong></h2>



<pre class="wp-block-code"><code class=""><code>git clone --depth=50 --single-branch -b staging git@github.com:adampatterson/repo repo</code></code></pre>



<p>If you check the remote branches:</p>



<pre class="wp-block-code"><code class=""><code>git branch -r
# origin/staging</code></code></pre>



<p>This setup locks the repository to the <code>staging</code> branch, as seen in the <code>.git/config</code>:</p>



<pre class="wp-block-code"><code class=""><code>[remote "origin"]
    url = git@github.com:adampatterson/repo
    fetch = +refs/heads/staging:refs/remotes/origin/staging<span style="background-color: rgb(40, 44, 52); font-size: 0.875em;"></span></code></code></pre>



<h3 class="wp-block-heading">Switching to Another Branch</h3>



<p>To allow access to all branches, update the fetch configuration:</p>



<pre class="wp-block-code"><code class=""><code>git config remote.origin.fetch "refs/heads/*:refs/remotes/origin/*"
git fetch<span style="font-size: 0.875em;"></span></code></code></pre>



<p>Your <code>.git/config</code> should now look like:</p>



<pre class="wp-block-code"><code class=""><code>[remote "origin"]
    url = git@github.com:adampatterson/repo
    fetch = refs/heads/*:refs/remotes/origin/<span style="background-color: rgb(40, 44, 52); font-size: 0.875em;"></span></code></code></pre>



<p>Now you can view all remote branches:</p>



<pre class="wp-block-code"><code class=""><code>git branch -r
# origin/dev
# origin/main
# origin/staging<span style="background-color: rgb(40, 44, 52); font-size: 0.875em;"></span></code></code></pre>



<p>To switch to a different branch:</p>



<pre class="wp-block-code"><code class=""><code>git fetch origin
git switch main</code></code></pre>



<p>If you want to lock the repository to a new default branch (e.g., <code>main</code>), reset the fetch:</p>



<pre class="wp-block-code"><code class=""><code>git config remote.origin.fetch "refs/heads/main:refs/remotes/origin/main"</code></code></pre>



<p></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2147</post-id>	</item>
		<item>
		<title>Setting Up a Cloudflare Tunnel with Wildcard Support</title>
		<link>https://adampatterson.ca/development/setting-up-a-cloudflare-tunnel-with-wildcard-support/</link>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Thu, 24 Apr 2025 17:39:25 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Tools]]></category>
		<guid isPermaLink="false">https://adampatterson.ca/?p=1981</guid>

					<description><![CDATA[Using Cloudflare Tunnel is a great way to expose your local websites to the public securely without configuring a traditional VPN or public IP addresses. Here&#8217;s a step-by-step guide on how to set up a Cloudflare Tunnel and use a wildcard to access multiple local sites: Step 1: Create a Cloudflare Account If you don&#8217;t...]]></description>
										<content:encoded><![CDATA[
<p>Using Cloudflare Tunnel is a great way to expose your local websites to the public securely without configuring a traditional VPN or public IP addresses. Here&#8217;s a step-by-step guide on how to set up a Cloudflare Tunnel and use a wildcard to access multiple local sites:</p>



<h2 class="wp-block-heading">Step 1: Create a Cloudflare Account</h2>



<p>If you don&#8217;t already have a Cloudflare account, you&#8217;ll need to create one and add your domain. Point your domain&#8217;s DNS settings to Cloudflare by changing your nameservers at your domain registrar.</p>



<h2 class="wp-block-heading">Step 2: Install Cloudflared</h2>



<p><code>Cloudflared</code> is the daemon used to create a Cloudflare Tunnel. You&#8217;ll need to install it on your local machine or the server where your sites are hosted.</p>



<ul class="wp-block-list">
<li><strong>For macOS</strong>: Use Homebrew:</li>
</ul>



<pre class="wp-block-code"><code lang="bash" class="language-bash">brew install cloudflared</code></pre>



<h2 class="wp-block-heading">Step 3: Authenticate Cloudflared</h2>



<p>Run the following command to authenticate <code>cloudflared</code> with your Cloudflare account:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">cloudflared tunnel login</code></pre>



<p>This command opens a browser window where you can log in to your Cloudflare account and authorize the connection.</p>



<p>Choose the domain that you&#8217;d like to use with your tunnel.</p>



<h2 class="wp-block-heading">Step 4: Create a Tunnel</h2>



<p>Create a new tunnel and give it a name:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">cloudflared tunnel create tunnel-name</code></pre>



<p>Confirm that the tunnel has been successfully created by running:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">cloudflared tunnel list</code></pre>



<p>Your tunnel configuration is complete! If you want to get information on the tunnel you just created, you can run:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">cloudflared tunnel info tunnel</code></pre>



<h2 class="wp-block-heading">Step 5: Configure the Tunnel</h2>



<p>Create a <code>config.yml</code> file inside <code>.cloudflared</code> to define how traffic is routed:</p>



<pre class="wp-block-code"><code lang="yaml" class="language-yaml">tunnel: &lt;Tunnel-UUID&gt;
credentials-file: /path/to/.cloudflared/Tunnel-UUID.json

ingress:
  - hostname: "*.domain.com"
    service: http://127.0.0.1:80
  - hostname: "*.example.com"
    service: http://127.0.0.1:80
  - service: http_status:404</code></pre>



<p>In this example, <code>*.example.com</code> will route all requests to your local web server running on port 80. Make sure to replace <code>example.com</code> with your actual domain.</p>



<p><strong>Validate your configuration:</strong></p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">cloudflared tunnel ingress validate</code></pre>



<pre class="wp-block-code"><code lang="bash" class="language-bash">Validating rules from ~/.cloudflared/config.yml
OK</code></pre>



<p><strong>Test a specific domain:</strong></p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">cloudflared tunnel ingress rule https://foo.domain.com</code></pre>



<pre class="wp-block-code"><code lang="bash" class="language-bash">Using rules from ~/.cloudflared/config.yml
Matched rule #0
    hostname: *.domain.com
    service: http://127.0.0.1:80</code></pre>



<p><strong>Tail the connection logs:</strong></p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">cloudflared tail &lt;Tunnel-UUID&gt;</code></pre>



<h2 class="wp-block-heading">Step 6: Start the Tunnel</h2>



<p><strong>Run the tunnel:</strong></p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">cloudflared tunnel run TUNNEL_NAME</code></pre>



<p><strong>To run it at login:</strong></p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo cloudflared service install
sudo cloudflared service uninstall</code></pre>



<p>Cloudflare Tunnel will be installed as a launch agent and start whenever you log in, using your local user configuration found in <code>~/.cloudflared/</code>.</p>



<p>Except there&#8217;s an <a href="https://github.com/cloudflare/cloudflared/issues/327#issuecomment-1763670368">issue</a> with the plist file that&#8217;s created. </p>



<p>To resolve this, we&#8217;re going to update the file by editing <code>/Library/LaunchDaemons/com.cloudflare.cloudflared.plist</code></p>



<p><strong>Original</strong>:</p>



<pre class="wp-block-code"><code lang="xml" class="language-xml">&lt;array&gt;
    &lt;string&gt;/usr/local/bin/cloudflared&lt;/string&gt;
&lt;/array&gt;</code></pre>



<p><strong>Updated</strong>:</p>



<pre class="wp-block-code"><code lang="xml" class="language-xml">&lt;array&gt;
    &lt;string&gt;/usr/local/bin/cloudflared&lt;/string&gt;
    &lt;string&gt;tunnel&lt;/string&gt;
    &lt;string&gt;run&lt;/string&gt;
&lt;/array&gt;</code></pre>



<p><strong>Start and stop the daemon:</strong></p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo launchctl start com.cloudflare.cloudflared
sudo launchctl stop com.cloudflare.cloudflared</code></pre>



<p><strong>Manage the service:</strong></p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo launchctl bootout system /Library/LaunchDaemons/com.cloudflare.cloudflared.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/com.cloudflare.cloudflared.plist</code></pre>



<h2 class="wp-block-heading">Step 7: Update DNS</h2>



<p>Finally, you need to add DNS records in your Cloudflare dashboard to point your desired subdomains (or wildcard<br>subdomains) to the tunnel. For wildcard subdomains, create a CNAME record like this:</p>



<ul class="wp-block-list">
<li><strong>Type</strong>: CNAME</li>



<li><strong>Name</strong>: <code>*</code></li>



<li><strong>Target</strong>: <code>&lt;TUNNEL_ID&gt;.cfargotunnel.com</code></li>
</ul>



<p><strong>Resulting in client.domain.dev</strong></p>



<p>If Cloudflare has an Edge Certificate you can also setup wild card subdomains.</p>



<ul class="wp-block-list">
<li><strong>Type</strong>: CNAME</li>



<li><strong>Name</strong>: <code>*.name.</code></li>



<li><strong>Target</strong>: <code>&lt;TUNNEL_ID&gt;.cfargotunnel.com</code></li>
</ul>



<p><strong>Resulting in client.your-name.domain.dev</strong></p>



<h2 class="wp-block-heading">Required Local Changes</h2>



<pre class="wp-block-code"><code lang="nginx" class="language-nginx">server {
    listen 80;
    server_name project.test project.example.com;
}</code></pre>



<p>There&#8217;s no need to update your hosts file or Gasmask settings.</p>



<h3 class="wp-block-heading">Additional Configurations for WordPress and Laravel</h3>



<p>Your local sites will now have full SSL, can be accessed by your mobile devices, and if required shared with team mates.<br><br><strong>WordPress</strong><br>Update <code>wp-config.php</code>:</p>



<pre class="wp-block-code"><code lang="php" class="language-php">define('WP_HOME', 'https://project.example.com');
define('WP_SITEURL', 'https://project.example.com');</code></pre>



<p><strong>Laravel</strong><br>Update your <code>.env</code>:</p>



<pre class="wp-block-code"><code class="">APP_URL=https://project.domain.com
HORIZON_DOMAIN=https://project.domain.com</code></pre>



<p>Next, you may need to force HTTPS by editing your <code>AppServiceProvider</code> boot method.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">use Illuminate\Support\Facades\URL;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        if (config('app.env') === 'local') {
            URL::forceScheme('https');
        }
    }
}</code></pre>



<h2 class="wp-block-heading">Additional Tips</h2>



<ul class="wp-block-list">
<li>Consider adding basic authentication in Nginx to prevent unauthorized access.</li>



<li>If you&#8217;re using Vite or hot module reloading, <a href="https://adampatterson.ca/general/running-vite-with-cloudflared-tunnels/">further adjustments are needed</a>.</li>
</ul>



<h3 class="wp-block-heading">Setting Up Cloudflare Tunnel via Web Interface</h3>



<p>Cloudflare allows you to configure your tunnel through its web interface:</p>



<ol start="1" class="wp-block-list">
<li>Go to <strong>Zero Trust &gt; Networks &gt; Tunnels</strong> in your Cloudflare dashboard.</li>



<li>Click <strong>Create Tunnel</strong>, select <strong>Cloudflared</strong>, and name your tunnel.</li>



<li>Choose an installation method:
<ul class="wp-block-list">
<li>If Cloudflared is not installed, follow the installation steps.</li>



<li>If Cloudflared is already installed, proceed with configuration.</li>
</ul>
</li>



<li>Add a <strong>public hostname</strong>:
<ul class="wp-block-list">
<li>Subdomain: <code>*</code></li>



<li>Domain: Select your domain</li>



<li>Set the service type to <strong>HTTP</strong> and the URL to <code>http://127.0.0.1:80</code></li>
</ul>
</li>
</ol>



<p>This setup provides full SSL support, allows access from mobile devices, and enables easy sharing with teammates.</p>



<p>By following these steps, you can securely expose multiple local sites using a single Cloudflare Tunnel with wildcard support—perfect for development, testing, and internal applications without exposing them directly to the intern</p>



<p></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1981</post-id>	</item>
		<item>
		<title>Open folders in PhpStorm</title>
		<link>https://adampatterson.ca/development/open-folders-in-phpstorm/</link>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Sun, 26 Jan 2025 21:12:55 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<guid isPermaLink="false">https://adampatterson.ca/?p=2055</guid>

					<description><![CDATA[PhpStorm has a command-line interface that you can install using the Tool Box, but did you know that you can also use the finder? Normally I&#8217;d just drag a folder into the app icon in the dock, and I guess that&#8217;s fine. But it&#8217;s also sometimes awkward on a dual monitor setup or when you&#8217;re...]]></description>
										<content:encoded><![CDATA[
<p>PhpStorm has a <a href="https://www.jetbrains.com/help/phpstorm/working-with-the-ide-features-from-command-line.html">command-line interface</a> that you can install using the <strong>Tool Box</strong>, but did you know that you can also use the finder?</p>



<p>Normally I&#8217;d just drag a folder into the app icon in the dock, and I guess that&#8217;s fine.</p>



<p>But it&#8217;s also sometimes awkward on a dual monitor setup or when you&#8217;re using the trackpad.<br><br>To get started, open Automator.app and choose &#8220;<strong>New Document</strong>&#8220;.</p>



<p>Then choose <strong>Quick action</strong>, now search for for and add the  <strong>Run Shell Script</strong> action by double clicking or dragging it.</p>



<p>In the <strong>Run Shell Script</strong> action Set <strong>Pass input</strong> to <strong>as arguments</strong>.</p>



<p>Now we can add the following for PhpStorm</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">for f in "$@"; do
  open -a 'PhpStorm' "$@"
done</code></pre>



<p>And this one&#8217;s for you if you&#8217;re a Visual Studio Code user.</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">for f in "$@"; do
  open -a 'Visual Studio Code' "$@"
done</code></pre>



<p>Save as the automation accordingly &#8220;<strong>Open in PhpStorm</strong>&#8220;.</p>



<p>Now, if you right click on any files or folders, you should see the Quick Action <strong>Open in PhpStorm.</strong></p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img fetchpriority="high" decoding="async" width="413" height="420" src="https://adampatterson.ca/wp-content/uploads/2025/01/image.png" alt="" class="wp-image-2057" srcset="https://adampatterson.ca/wp-content/uploads/2025/01/image.png 413w, https://adampatterson.ca/wp-content/uploads/2025/01/image-295x300.png 295w, https://adampatterson.ca/wp-content/uploads/2025/01/image-50x50.png 50w" sizes="(max-width: 413px) 100vw, 413px" /></figure></div>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2055</post-id>	</item>
		<item>
		<title>A better way to work with Composer locally</title>
		<link>https://adampatterson.ca/development/a-better-way-to-work-with-composer-locally/</link>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Tue, 31 Dec 2024 03:16:18 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<guid isPermaLink="false">https://adampatterson.ca/?p=2030</guid>

					<description><![CDATA[Working on a Composer package locally can be challenging. You don&#8217;t want to commit changes to Git just to test something, and constantly updating Composer to see changes isn&#8217;t ideal either. Previously, I often used symlinks for local development, and I still occasionally do. However, I&#8217;ve found an easier method for my core projects: using...]]></description>
										<content:encoded><![CDATA[
<p>Working on a Composer package locally can be challenging. You don&#8217;t want to commit changes to Git just to test something, and constantly updating Composer to see changes isn&#8217;t ideal either.</p>



<p><a href="https://adampatterson.ca/development/using-private-composer-packages-with-laravel/">Previously, I often used symlinks for local development</a>, and I still occasionally do. </p>



<p>However, I&#8217;ve found an easier method for my core projects: using the <a href="https://github.com/wikimedia/composer-merge-plugin">Wikimedia Composer Merge Plugin</a>. This approach simplifies working on projects without making significant changes to <code>composer.json</code> in situations where you don&#8217;t want to modify the file publicly.</p>



<p>The Wikimedia Composer Merge Plugin allows us to merge multiple <code>composer.json</code> files at runtime, offering flexibility for managing dependencies in complex projects.</p>



<h3 class="wp-block-heading">Getting Started</h3>



<p>Let&#8217;s pretend we&#8217;re developing a WordPress site and using Composer to install and manage themes. Our project includes the Axe and Handle themes from GitHub, and we also need to make updates to these themes locally before publishing.</p>



<p>Here’s an example of our <code>composer.json</code> setup:</p>



<pre class="wp-block-code"><code lang="json" class="language-json">{
  "require": {
    "adampatterson/axe": "dev-main",
    "adampatterson/handle": "dev-main"
  },
  "repositories": [
    {
      "type": "vcs",
      "url": "git@github.com:adampatterson/Axe.git"
    },
    {
      "type": "vcs",
      "url": "git@github.com:adampatterson/Handle.git"
    }
  ]
}</code></pre>



<h4 class="wp-block-heading">Folder Structure</h4>



<pre class="wp-block-code"><code class="">/sites/
    /wordpress.test/
        composer.json
        composer.local.json
    /axe/
        composer.json
    /handle/
        composer.json</code></pre>



<h3 class="wp-block-heading">Install the Merge Plugin</h3>



<p>First, install the <a href="https://github.com/wikimedia/composer-merge-plugin">Wikimedia Composer Merge Plugin</a> in your project:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">composer require wikimedia/composer-merge-plugin</code></pre>



<p>Next, configure the plugin in your <code>composer.json</code> file to include a local configuration:</p>



<pre class="wp-block-code"><code class="">{
  "require": {
    "wikimedia/composer-merge-plugin": "^2.1"
  },
  "extra": {
    "merge-plugin": {
      "include": [
        "composer.local.json"
      ],
      "replace": true
    }
  }
}</code></pre>



<h3 class="wp-block-heading">Define Local Packages</h3>



<p>Create a <code>composer.local.json</code> file to define your local packages. This file should also be added to <code>.gitignore</code> to prevent it from being committed.</p>



<pre class="wp-block-code"><code lang="json" class="language-json">{
  "repositories": [
    {
      "type": "path",
      "url": "/Users/adam/Sites/wordpress/Axe"
    },
    {
      "type": "path",
      "url": "/Users/adam/Sites/wordpress/Handle"
    }
  ]
}</code></pre>



<p>Now, when you run <code>composer install</code> or <code>composer update</code>, your themes will be symlinked automatically.</p>



<h3 class="wp-block-heading">Working with Published Packages</h3>



<p>If you want to install only the published packages, you can run:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">composer install --no-plugins</code></pre>



<p>However, keep in mind that WordPress themes and plugins managed with composer require <code>composer/installers</code>, which will be ignored when using <code>--no-plugins</code>. To work around this, temporarily rename your <code>composer.local.json</code> file before running the command.</p>



<h2 class="wp-block-heading">Could you use this with Laravel?</h2>



<p>Absolutely! </p>



<p>If you create a new Laravel project then yes, you can modify your <code>composer.json</code> file as mentioned above except that we&#8217;re going to need to include <code>laravel/framework</code> in <code>composer.local.json</code>.</p>



<pre class="wp-block-code"><code lang="json" class="language-json">{
    "require": {
        "laravel/framework": "*"
    },
    "repositories": [
        {
            "type": "path",
            "url": "/Users/adam/Sites/forks/framework"
        }
    ]
}</code></pre>



<p>If you&#8217;re working on <code>laravel/laravel</code> then I&#8217;d say no, since we don&#8217;t want to add the Wikimedia Composer Merge Plugin to the public repo.</p>



<p>Using the Wikimedia Composer Merge Plugin streamlines local development and testing for Composer projects, especially when working with themes or plugins in WordPress. It’s a flexible, efficient solution that avoids cluttering your Git history with unnecessary commits.\</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2030</post-id>	</item>
		<item>
		<title>How to fix Nginx client_body_temp Permission denied on macOS</title>
		<link>https://adampatterson.ca/development/how-to-fix-nginx-client_body_temp-permission-denied-on-macos/</link>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Fri, 06 Oct 2023 01:07:42 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Trouble Shooting]]></category>
		<guid isPermaLink="false">https://www.adampatterson.ca/?p=1825</guid>

					<description><![CDATA[I was working on a project that required file uploads like PDF/JPG. And it wouldn&#8217;t be a fun time unless something went wrong.In my case, I could upload a PDF but a JPG would thrown an error. My project is using Laravel Filament and the SpatieMediaLibraryFileUpload. Looking in the Chrome Network tab I could see...]]></description>
										<content:encoded><![CDATA[
<p>I was working on a project that required file uploads like PDF/JPG. And it wouldn&#8217;t be a fun time unless something went wrong.<br>In my case, I could upload a PDF but a JPG would thrown an error. My project is using <a href="https://filamentphp.com/" target="_blank" rel="noreferrer noopener nofollow">Laravel Filament</a> and the <code>SpatieMediaLibraryFileUpload</code>. Looking in the Chrome Network tab I could see a 500 error and the response shows a 500 error, but from Nginx and not Laravel.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="278" src="http://adampatterson.ca/wp-content/uploads/2023/08/image-1024x278.png" alt="" class="wp-image-1827" srcset="https://adampatterson.ca/wp-content/uploads/2023/08/image-1024x278.png 1024w, https://adampatterson.ca/wp-content/uploads/2023/08/image-300x81.png 300w, https://adampatterson.ca/wp-content/uploads/2023/08/image-768x209.png 768w, https://adampatterson.ca/wp-content/uploads/2023/08/image-625x170.png 625w, https://adampatterson.ca/wp-content/uploads/2023/08/image.png 1068w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>On an ARM macOS I ran  <code>tail -f /opt/homebrew/var/log/nginx/error.log</code> and could see the following error.</p>



<pre class="wp-block-code"><code class="">2023/08/11 09:53:43 [crit] 29890#0: *9 open() "/opt/homebrew/var/run/nginx/client_body_temp/0000000002" failed (13: Permission denied), client: 127.0.0.1, server: local.test, request: "POST /livewire/upload-file?expires=1691769523&amp;signature=61f7f20ef5a9047cec174fc9fa5dbb2b729b0f91394f75b23d41c0f358318463 HTTP/1.1", host: "local.test", referrer: "http://local.test/admin/inspections/5/submit"</code></pre>



<p>🤨 WTF!</p>



<figure class="wp-block-image size-full"><img decoding="async" width="554" height="194" src="http://adampatterson.ca/wp-content/uploads/2023/08/image-1.png" alt="" class="wp-image-1828" srcset="https://adampatterson.ca/wp-content/uploads/2023/08/image-1.png 554w, https://adampatterson.ca/wp-content/uploads/2023/08/image-1-300x105.png 300w" sizes="(max-width: 554px) 100vw, 554px" /></figure>



<p>I resolved the issue by by running <code>sudo chown -R $USER:_developer client_body_temp/</code></p>



<p>I am unclear why <code>nobody</code> was assigned to the folders, I also think that maybe my work laptop has the <code>_developer</code> group which I don&#8217;t think is standard.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="386" height="195" src="http://adampatterson.ca/wp-content/uploads/2023/08/image-3.png" alt="" class="wp-image-1832" srcset="https://adampatterson.ca/wp-content/uploads/2023/08/image-3.png 386w, https://adampatterson.ca/wp-content/uploads/2023/08/image-3-300x152.png 300w" sizes="auto, (max-width: 386px) 100vw, 386px" /></figure>



<p>You won&#8217;t need to restart Nginx but retry the file upload.  <br><br>Hopefully you found this helpful!</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1825</post-id>	</item>
		<item>
		<title>Fixing the &#8216;server busy or not enough resources&#8217; error in WordPress</title>
		<link>https://adampatterson.ca/general/fixing-the-server-busy-or-not-enough-resources-error-in-wordpress/</link>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Fri, 30 Dec 2022 19:26:38 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://www.adampatterson.ca/?p=1795</guid>

					<description><![CDATA[If you are using Nginx as your web server, one solution to this error is to update the client_max_body_size setting in your Nginx configuration. This setting specifies the maximum size of the request body, in bytes. By default, it is set to 1 megabyte (1024 kilobytes). If you are trying to upload an image that...]]></description>
										<content:encoded><![CDATA[
<p>If you are using Nginx as your web server, one solution to this error is to update the <code>client_max_body_size</code> setting in your Nginx configuration. This setting specifies the maximum size of the request body, in bytes. By default, it is set to 1 megabyte (1024 kilobytes). If you are trying to upload an image that is larger than this size, you may receive the &#8220;server cannot process image&#8221; error.</p>



<p>To fix this error, you can try increasing the <code>client_max_body_size</code> setting in your Nginx configuration. Here&#8217;s how:</p>



<p>1) Open your Nginx configuration file. This is typically located at <code>/etc/nginx/nginx.conf</code> on a Linux server.</p>



<p>2) Find the <code>http</code> block in the configuration file and add the following line:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">http {
    ...
    client_max_body_size [size];
}</code></pre>



<p>Replace <code>[size]</code> with the maximum size of the request body you want to allow, in bytes. For example, to set the maximum size to 10 megabytes, you would use <code>client_max_body_size 10m;</code>.</p>



<p>3) Save the configuration file, test and restart Nginx using the following command:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash"><code>sudo nginx -t</code>
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

<code>sudo systemctl restart nginx</code></code></pre>



<p>After increasing the <code>client_max_body_size</code> setting and restarting Nginx, you should be able to upload larger images to your WordPress website or blog without encountering the &#8220;server cannot process image&#8221; error.</p>



<p>However, if you are still experiencing this error after updating the <code>client_max_body_size</code> setting, there may be other factors at play. Here are a few additional things you can try:</p>



<ul class="wp-block-list">
<li>Update the <code>upload_max_filesize</code> setting in PHP. This setting specifies the maximum size of a file that can be uploaded to your server. If you are trying to upload an image that is larger than this size, you may receive the &#8220;server cannot process image&#8221; error. To fix this, you can increase the <code>upload_max_filesize</code> setting in your PHP configuration. This is typically located at <code>/etc/php/php.ini</code> or <code>/etc/php/8.2/fpm/php.ini</code> on a Linux server. Find the <code>upload_max_filesize</code> setting and increase it to a larger value, then save the file and restart your web server.</li>



<li>Reduce the size of the image you&#8217;re trying to upload. The suggested maximum size for images in WordPress is 2560 pixels. If your image is larger than this, you&#8217;ll need to resize it before uploading. You can use a free image editing tool like GIMP or Adobe Photoshop to resize your image.</li>



<li>Check your server&#8217;s resource usage. If the server is busy or has a high load, it may not have enough resources available to process your image. You can check your server&#8217;s resource usage by contacting your web host or using a tool like <strong>top</strong>. If the server&#8217;s resources are maxed out, you may need to upgrade to a more powerful hosting plan or consider moving to a different web host.</li>
</ul>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1795</post-id>	</item>
		<item>
		<title>How to execute multiple versions of PHP on macOS using the CLI</title>
		<link>https://adampatterson.ca/development/how-to-execute-multiple-versions-of-php-on-macos-using-the-cli/</link>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Fri, 19 Aug 2022 22:12:31 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Server]]></category>
		<guid isPermaLink="false">https://www.adampatterson.ca/?p=1776</guid>

					<description><![CDATA[Many sites still required php 7.4 even though it&#8217;s older and now considered deprecated. That being said, it&#8217;s still important to test with newer versions of PHP. Combined with PHP having a quicker release cycle PHP 8, 8.1, and 8.2 are on their way. I have to work with a couple of versions regularly in...]]></description>
										<content:encoded><![CDATA[
<p>Many sites still required php 7.4 even though it&#8217;s older and now considered deprecated.  That being said, it&#8217;s still important to test with newer versions of PHP. </p>



<p>Combined with PHP having a quicker release cycle PHP 8, 8.1, and 8.2 are on their way.</p>



<p>I have to work with a couple of versions regularly in the CLI, and the best way I found to do this was to create an alias.</p>



<p>Let&#8217;s assume that you installed your versions of PHP using brew, or already know where your version of PHP is.</p>



<p>Add the following to your bash profile.</p>



<pre class="wp-block-code"><code class="">alias php7='/usr/local/opt/php@7.4/bin/php'
alias php8='/usr/local/opt/php@8.0/bin/php'</code></pre>



<p>If you want you can install PHP 8.1 and 8.2 as well with <code>brew install php@8.X</code> and add another alias.</p>



<p>This will allow you to run <code>php8 composer</code>, you can do a quick test by creating an <code>index.php</code> file and adding <code>phpinfo()</code> to it.</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">php7 index.php | grep "PHP Version"
php8 index.php | grep "PHP Version"</code></pre>



<p>If you have an M1 mac, your system paths will be different. You can replace: </p>



<pre class="wp-block-code"><code class="">/usr/local/opt/</code></pre>



<p>with</p>



<pre class="wp-block-code"><code class="">/System/Volumes/Data/opt/homebrew/opt</code></pre>



<p>If you were to run <code>php -v</code> and see v7.4 then you can now run <code>php8 composer install</code> in most cases, this has worked perfectly, but if you need something a bit more permanent it&#8217;s still best to change your system environment.</p>



<p>Alternatively, if you want to change your version of PHP in the command line more permanently you can add this function to your <code>.bash_profile</code></p>



<pre title="" class="wp-block-code"><code lang="bash" class="language-bash">function phpv() {
    brew unlink php
    brew link --overwrite --force "php@$1"
    php -v
}</code></pre>



<p>And then run with <code>phpv 8.2</code></p>



<p>I can&#8217;t take credit for the above shell script, but I also can&#8217;t find the original post that I discovered it on.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1776</post-id>	</item>
		<item>
		<title>Super simple local wildcard SSL!</title>
		<link>https://adampatterson.ca/general/super-simple-local-wildcard-ssl/</link>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Wed, 27 Jan 2021 20:33:52 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://www.adampatterson.ca/?p=1697</guid>

					<description><![CDATA[Working locally most of the time a secure site won&#8217;t be necessary but from time to time you will require a secure connection. Such as working with oAuth providers, and making sure that you don&#8217;t serve any mixed assets. Previously I used OpenSSL locally on my Mac, and it was&#8230; OK, but it was sort...]]></description>
										<content:encoded><![CDATA[
<p>Working locally most of the time a secure site won&#8217;t be necessary but from time to time you will require a secure connection. Such as working with oAuth providers, and making sure that you don&#8217;t serve any mixed assets.</p>



<p>Previously I used <a href="http://adampatterson.ca/2018/local-greenbar-https-ssl-with-mamp/" target="_blank" rel="noreferrer noopener">OpenSSL locally on my Mac</a>, and it was&#8230; OK, but it was sort of complicated and involved a lot of copy and paste.</p>



<p>To get started let&#8217;s start off by installing <a href="https://blog.filippo.io/mkcert-valid-https-certificates-for-localhost/" target="_blank" rel="noreferrer noopener nofollow">mkCert</a> using <a href="https://brew.sh/" target="_blank" rel="noreferrer noopener nofollow">HomeBrew</a>.  Create a new folder in your Sites directory called SSL, and navigate your way there in the terminal.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">brew install mkcert
brew install nss # if you use Firefox

mkcert -install

mkcert site.local '*.site.local'</code></pre>



<p>That was it! Your certificate is is ready to go, but now what?</p>



<h3 class="wp-block-heading">Configure MAMP</h3>



<p>Open&nbsp;<code>/Applications/MAMP/conf/apache/httpd.conf</code>&nbsp;and search for&nbsp;<code># Virtual hosts</code>.</p>



<p>Add a line under&nbsp;<code>httpd-vhosts.conf</code>&nbsp;called&nbsp;<code>httpd-secure-vhosts.conf</code>.</p>



<p>Open&nbsp;<code>/Applications/MAMP/conf/apache/httpd-secure-vhosts.conf</code>&nbsp;and add the following, changing the names and paths to reflect your needs.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">NameVirtualHost *:443

&lt;VirtualHost *:443>
	ServerName site.local
    ServerAlias *.site.local
    ServerAlias dev.smi
    ServerAlias *.dev.smi

	DocumentRoot "/Users/{username}}/Sites/web_path/"

    &lt;IfModule xsendfile_module>
        XSendFilePath "/Users/{username}}/Sites/web_path/"
    &lt;/IfModule>

    SSLEngine on

    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

    ErrorLog "/Applications/MAMP/logs/apache_ssl_error.log"
    TransferLog "/Applications/MAMP/logs/apache_ssl_access.log"
    CustomLog "/Applications/MAMP/logs/apache_ssl_request.log" "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

    SSLCertificateFile "/Users/{username}}/Sites/ssl/site.local+1.pem"
    SSLCertificateKeyFile "/Users/{username}}/Sites/ssl/site.local+1-key.pem"

    SSLSessionTickets on

    &lt;FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
    &lt;/FilesMatch>

    &lt;Directory "/Applications/MAMP/Library/cgi-bin">
        SSLOptions +StdEnvVars
    &lt;/Directory>

    BrowserMatch ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

	&lt;Directory "/Users/{username}}/Sites/web_path/">
		Options Includes FollowSymLinks ExecCGI
		AllowOverride All
		Order allow,deny
        Allow from all

	&lt;/Directory>

&lt;/VirtualHost></code></pre>



<p>Open&nbsp;<code>/Applications/MAMP/conf/apache/httpd.conf</code>&nbsp;again and look for&nbsp;<code>Include /Applications/MAMP/conf/apache/extra/httpd-ssl.conf</code> and uncomment that line.</p>



<p>I personally remove the VirtualHost from this file and leave it the <code>httpd-secure-vhosts.conf </code>file that we previously created.</p>



<p>By creating a wild card certificate you can simply add every new local site under that subdomain if you so choose.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1697</post-id>	</item>
		<item>
		<title>Customize WordPress menu items based on Geographic Location</title>
		<link>https://adampatterson.ca/development/wordpress-custom-links-based-on-geo-location/</link>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Tue, 01 Sep 2020 00:20:31 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<guid isPermaLink="false">https://www.adampatterson.ca/?p=1672</guid>

					<description><![CDATA[The internet is a huge place, and not all of your visitors live in your region. At times it makes sense to adjust your site&#8217;s content based on their geography. In my free time I like to make stuff and post it on YouTube, and my &#8220;other&#8221; blog called Hey I&#8217;m A Maker. A lot...]]></description>
										<content:encoded><![CDATA[
<p>The internet is a huge place, and not all of your visitors live in your region. At times it makes sense to adjust your site&#8217;s content based on their geography.</p>



<p>In my free time I like to make stuff and post it on <a href="https://www.youtube.com/imamakerca" target="_blank" rel="noreferrer noopener nofollow">YouTube</a>, and my &#8220;other&#8221; blog called <a href="https://imamaker.ca/" target="_blank" rel="noreferrer noopener">Hey I&#8217;m A Maker</a>. A lot of content creators will use affiliate links in order to make some extra income from their content. There are plenty of services out there to help you do this.</p>



<p>At the moment I have an Amazon Affiliate store that I tossed a few interesting items into. The issue is that I live in Canada and many of my viewers also live in Canada.  The Amazon stores are not transferable between <strong>.com</strong> and <strong>.ca</strong>.</p>



<p>I began looking into ways of routing the link based on Geography. I discovered a few paid services for $10-20 a month which was far more than I wanted to spend.</p>



<p>After some exploring, I learned that <a href="https://www.cloudflare.com/" target="_blank" rel="noreferrer noopener nofollow">Cloudflare</a> is able to add Geolocation headers to their responses. If you are interested you can read more on how to set that up <a href="https://support.cloudflare.com/hc/en-us/articles/200168236-Configuring-Cloudflare-IP-Geolocation" target="_blank" rel="noreferrer noopener nofollow">here</a>. </p>



<h3 class="wp-block-heading">Modify your WordPress theme</h3>



<p>Once I had enabled the IP Geolocation feature I was able to see my region as <code>CA</code> using the following code as a test.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">echo $_SERVER["HTTP_CF_IPCOUNTRY"];</code></pre>



<p>The goal I want to achieve here is to modify a nav item based on our geographical location. In my case, Canadian visitors should see my Canadian affiliate store.</p>



<p>In the following code snippets, I will assume that your menu location is called <code>primary</code> and that the link you want to modify was added as a <strong>custom link</strong>.</p>



<p>To get this started I want to modify the WordPress menu items before the HTML has been created. To do this I will use the filter <code>wp_nav_menu_objects</code>.</p>



<p>Create a function called <code>update_shop_link</code> which will accept two parameters, <code>$items</code> and <code>$args</code>.</p>



<p>By now you should have something that looks like this located in your <code>functions.php</code>.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">add_filter( 'wp_nav_menu_objects', 'update_shop_link', 10, 2 );
function update_shop_link( $items, $args ) {
    // Code here
}</code></pre>



<p>Next up, we want to only modify a link that is in our <code>primary</code> menu and to make sure that <code>HTTP_CF_IPCOUNTRY</code> is set.  </p>



<p>Once those are true we can set a variable <code>$region</code>, and then loop through the $items looking for a link that is of the type custom, and whose title is equal to <code>Shop</code>.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">if ( $args-&gt;theme_location == 'primary' &amp;&amp; array_key_exists( 'HTTP_CF_IPCOUNTRY', $_SERVER ) ) {
    $region = $_SERVER["HTTP_CF_IPCOUNTRY"];

    foreach ( $items as $key =&gt; $item ) {
        if ( $region === 'CA' &amp;&amp; $item-&gt;type === 'custom' &amp;&amp; $item-&gt;title === 'Shop' ) {
            // Code here
        }
    }
}</code></pre>



<p>Now we have found out shop link you can modify the URL by overwriting it.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">$item-&gt;url = 'https://www.amazon.ca/shop/adampatterson';</code></pre>



<h3 class="wp-block-heading">Wrapping it up</h3>



<p>That&#8217;s all there is to it, now let&#8217;s roll it all together.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">add_filter( 'wp_nav_menu_objects', 'update_shop_link', 10, 2 );
function update_shop_link( $items, $args ) {
	if ( $args-&gt;theme_location == 'primary' &amp;&amp; array_key_exists( 'HTTP_CF_IPCOUNTRY', $_SERVER ) ) {
		$region = $_SERVER["HTTP_CF_IPCOUNTRY"];

		foreach ( $items as $key =&gt; $item ) {
			if ( $region === 'CA' &amp;&amp; $item-&gt;type === 'custom' &amp;&amp; $item-&gt;title === 'Shop' ) {
				$item-&gt;url = 'https://www.amazon.ca/shop/adampatterson';
			}
		}
	}

	return $items;
}</code></pre>



<p>This method was specific to WordPress, but as long as you are using a server-side language you can intercept the region and do whatever you like.</p>



<p>You could even create a page like domain.com/shop that would automatically redirect to your Amazon store. If you really wanted that URL could redirect to a tiny URL that would allow you to collect some basic analytics.</p>



<p>If you enjoyed this then I would love it if you subscribed to my <a href="https://www.youtube.com/imamakerca" target="_blank" rel="noreferrer noopener">YouTube channel</a> or had a look at my site <a href="https://imamaker.ca/" target="_blank" rel="noreferrer noopener">Hey I&#8217;m A Maker</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1672</post-id>	</item>
		<item>
		<title>How to add and Use WordPress Custom Image sizes</title>
		<link>https://adampatterson.ca/general/how-to-add-and-use-wordpress-custom-image-sizes/</link>
					<comments>https://adampatterson.ca/general/how-to-add-and-use-wordpress-custom-image-sizes/#respond</comments>
		
		<dc:creator><![CDATA[Adam Patterson]]></dc:creator>
		<pubDate>Fri, 10 Jul 2020 15:24:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://www.adampatterson.ca/?p=1264</guid>

					<description><![CDATA[Adding a custom image size to WordPress could not be easier. The following will create a size called Square that is 150 by 150 pixels, the parameter true will result in the cropping of an image. Now any time an new image is uploaded WordPress will generate a file something like image-150&#215;150.jpg. If you want...]]></description>
										<content:encoded><![CDATA[
<p>Adding a custom image size to WordPress could not be easier. The following will create a size called Square that is 150 by 150 pixels, the parameter true will result in the cropping of an image.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">add_image_size('square', 150, 150, true);</code></pre>



<p>Now any time an new image is uploaded WordPress will generate a file something like image-150&#215;150.jpg.</p>



<p>If you want to be able to insert these images in your posts then you will need to register the size with the Media moda.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">add_filter('image_size_names_choose', 'add_image_sizes_editor');

function add_image_sizes_editor($sizes)
{
    return array_merge($sizes, [
        'square'   => __('Square', 'axe'),
    ]);
}</code></pre>



<p>Now when you create a post and want to add an image your custom sizes will be available to you.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://adampatterson.ca/general/how-to-add-and-use-wordpress-custom-image-sizes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1264</post-id>	</item>
	</channel>
</rss>
