<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[O'Brien Cloud Engineering]]></title><description><![CDATA[Tailored web, cloud, and software solutions for SMBs]]></description><link>https://obrien.engineer/</link><image><url>https://obrien.engineer/favicon.png</url><title>O&apos;Brien Cloud Engineering</title><link>https://obrien.engineer/</link></image><generator>Ghost 5.75</generator><lastBuildDate>Fri, 27 Mar 2026 07:17:30 GMT</lastBuildDate><atom:link href="https://obrien.engineer/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Ghost and Mailgun For Tiny Newsletters - An Update]]></title><description><![CDATA[<p>While scoping work for a potential new client recently I discovered to my mild dismay that the plans offered by Mailgun have changed recently and the Flex plan I wrote about in our <a href="https://obrien.engineer/ghost-and-mailgun-for-tiny-newsletters/" rel="noreferrer">original post</a> is <a href="https://help.mailgun.com/hc/en-us/articles/360048661093-Can-you-explain-pay-as-you-go-PAYG-billing?ref=obrien.engineer" rel="noreferrer">no longer available to new customers</a>. The Internet Archive seems to suggest that this</p>]]></description><link>https://obrien.engineer/mailgun-for-tiny-newsletters/</link><guid isPermaLink="false">6793ca0e4721600573bb225a</guid><category><![CDATA[Ghost CMS]]></category><dc:creator><![CDATA[JJ O'Brien]]></dc:creator><pubDate>Thu, 06 Feb 2025 19:16:30 GMT</pubDate><content:encoded><![CDATA[<p>While scoping work for a potential new client recently I discovered to my mild dismay that the plans offered by Mailgun have changed recently and the Flex plan I wrote about in our <a href="https://obrien.engineer/ghost-and-mailgun-for-tiny-newsletters/" rel="noreferrer">original post</a> is <a href="https://help.mailgun.com/hc/en-us/articles/360048661093-Can-you-explain-pay-as-you-go-PAYG-billing?ref=obrien.engineer" rel="noreferrer">no longer available to new customers</a>. The Internet Archive seems to suggest that this change was introduced some time in July 2024, but there was no communication about this to existing customers.</p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2025/01/image.png" class="kg-image" alt="Screenshot from Mailgun documentation that reads: Deprecated The Flex plan was a formerly offered Pay-As-You-Go (PAYG) billing model where each message accrued a charge. This article is retained as a reference for any accounts that may still be using this legacy plan." loading="lazy" width="713" height="178" srcset="https://obrien.engineer/content/images/size/w600/2025/01/image.png 600w, https://obrien.engineer/content/images/2025/01/image.png 713w"></figure><p>If you are already on Flex plan, like we are, you get to keep it at least for now. Mailgun may change their mind about that and &quot;sunset&quot; that plan in the future. So what are the new plans that they&apos;re making available and are they any good? </p><h2 id="two-new-plans">Two new plans</h2><p>The Foundation plan discussed in our previous post remains largely unchanged, but the Flex Plan has been replaced with two new plans: Free and Basic.</p><h3 id="free"><br>Free</h3><p>The Free plan comes with a sending limit of 100 emails per day. Technically this would allow you to send anywhere between 2800 and 3100 emails a month if you limit yourself to batches of 100 emails, but this is not really how email newsletters work. In practice this is a suitable plan only if you still have under 100 subscribers. </p><p>The limit is also firm - you can&apos;t simply pay for more emails (aka overages). To be able to send unlimited emails you must have a monthly plan. </p><p>More details about the free plan can be found <a href="https://help.mailgun.com/hc/en-us/articles/203068914-What-does-the-Free-plan-offer?ref=obrien.engineer" rel="noreferrer">here</a>.</p><h3 id="basic">Basic</h3><p>The Basic plan is now the cheapest unlimited option, but it starts at &#x20AC;15 a month. </p><p>It comes with 10,000 emails a month included in the price and has no daily sending limit. If you&apos;re sending more than that you can either pay for the extra emails, or upgrade to the Foundation plan which remains largely unchanged.</p><h3 id="overages">Overages</h3><p>Hidden in the new price structure is also a change to how much overages cost, ie. how much Mailgun will charge you for additional 1,000 emails. </p><p>In the now deprecated Flex Plan and previous pricing for Foundation plan a 1,000 emails extra in a month would have cost you $1. </p><p>Under the new pricing you can get a 1,000 emails for $1.80 under Basic, $1.30 under Foundation, and $1.10 under Scale. Fundamentally the more expensive your monthly plan, the cheaper the overages; the more you send the less you pay per email. </p><p>You should compare the plans they offer <a href="https://www.mailgun.com/pricing/?ref=obrien.engineer" rel="noreferrer">on their website</a> in more detail.</p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2025/02/image.png" class="kg-image" alt="Screenshot of the Mailgun&apos;s Pricing Page" loading="lazy" width="1230" height="694" srcset="https://obrien.engineer/content/images/size/w600/2025/02/image.png 600w, https://obrien.engineer/content/images/size/w1000/2025/02/image.png 1000w, https://obrien.engineer/content/images/2025/02/image.png 1230w" sizes="(min-width: 720px) 720px"></figure><h2 id="conclusion">Conclusion</h2><p>The two new plans don&apos;t come near the advantages you would have gotten with the Flex plan. If you have more than 100 subscribers and are sending fewer than 10,000 emails a month the options that are available are now less than desirable. They are more expensive and well, less flexible! </p><p>If you are already on Flex plan and have already close to sending 10,000 emails a day you now have an option to switch to the Basic monthly plan a little earlier. This will make the billing more predictable until you hit the 10k mark, but note <strong>I don&apos;t recommend doing so</strong>; the cost per email, overages included, is still lower on Flex plan than it is on Basic. </p><p>I&apos;m happy to report that the point at which you should switch from a Flex to a Foundation plan remains the same; it&apos;s after you start to routinely send more than 35k of emails a month. Foundation remains priced at $35 for 50k emails, which is the best price for people who send between 35k and 50k emails a month.</p><p>If you start on Basic plan and you&apos;re considering switching to Foundation you should do this just after you reach 21k emails a month. With the price of overages being $1.8 per 1k of emails on Basic Plan, 21k emails will come to about $34.8. You will have to pay $36.6 for 22k emails, which is more expensive than the Foundation plan&apos;s base cost offering 50k.</p><p>I have shopped around and have not found another reputable email delivery company that has a better starting plan. I note however with suspicion that Mailgun&apos;s new Basic plan mimics the base cost, quantity of email, and overage pricing of a pre-existing <a href="https://postmarkapp.com/pricing?ref=obrien.engineer" rel="noreferrer">Postmark&apos;s Basic plan</a> exactly. </p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2025/02/image-1.png" class="kg-image" alt="Screenshot of Postmark&apos;s Basic Plan pricing page." loading="lazy" width="343" height="531"></figure><p></p>]]></content:encoded></item><item><title><![CDATA[Ghost on Digital Ocean for tiny newsletters]]></title><description><![CDATA[<p>As mentioned in <a href="https://obrien.engineer/ghost-and-mailgun-for-tiny-newsletters/">Ghost and Mailgun for tiny newsletters</a> we have chosen to self-host Ghost CMS rather than choosing their fully hosted solution Ghost Pro. This decision was made for two reasons: autonomy and cost.</p><p><a href="https://ghost.org/pricing/?ref=obrien.engineer" rel="noreferrer">Ghost Pro</a> Starter plan is $9 per month, billed annually, or $11 per month billed</p>]]></description><link>https://obrien.engineer/ghost-on-do-for-tiny-newsletters/</link><guid isPermaLink="false">672369904721600573bb20e9</guid><category><![CDATA[Ghost CMS]]></category><dc:creator><![CDATA[JJ O'Brien]]></dc:creator><pubDate>Thu, 31 Oct 2024 16:00:05 GMT</pubDate><content:encoded><![CDATA[<p>As mentioned in <a href="https://obrien.engineer/ghost-and-mailgun-for-tiny-newsletters/">Ghost and Mailgun for tiny newsletters</a> we have chosen to self-host Ghost CMS rather than choosing their fully hosted solution Ghost Pro. This decision was made for two reasons: autonomy and cost.</p><p><a href="https://ghost.org/pricing/?ref=obrien.engineer" rel="noreferrer">Ghost Pro</a> Starter plan is $9 per month, billed annually, or $11 per month billed monthly, but to get the same functionality - custom themes, custom integrations, and 2 staff users - we would have had to choose their Creator plan... which is $25/mo if billed annually and $31/mo when billed monthly. This seemed too much for what is right now a small site with limited number of members and infrequently published newsletter. You may have found yourself in the same situation and looking for a less costly solution.</p><h2 id="digital-ocean">Digital Ocean</h2><p>Our hosting platform of choice is Digital Ocean because of their very predictable pricing, ease of use, and fantastic documentation. Digital Ocean offers Ghost CMS as a one-click app which streamlines the setup of Ghost installations. Even if you&apos;re not familiar with managing Linux servers it&apos;s very approachable.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://marketplace.digitalocean.com/apps/ghost?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Ghost | DigitalOcean Marketplace 1-Click App</div><div class="kg-bookmark-description">Ghost is a fully open source, adaptable platform for building and running a modern online publication. It powers blogs, magazines and journalists from Zappos to Sky News.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://marketplace.digitalocean.com/static/apple-touch-icon.png" alt><span class="kg-bookmark-author">DigitalOcean</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://marketplace-assets.digitalocean.com/logos/ghost-20-04.svg" alt></div></a></figure><p></p><p>Using the one-click app will create a Digital Ocean droplet (which is their nomenclature for a virtual private server, or VPS), deploy Ghost, and help you set it up once it&apos;s ready and your DNS records are enabled. You will have a choice of various Droplet configurations to choose from, but the cheapest one you will be able to select is the $12 Basic droplet with, which comes with a 50GB hard drive, 2GB of RAM and 1 Intel vCPU.</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">Digital Ocean pricing is exclusive of VAT. </div></div><p>This will work great for most people but this is not the cheapest droplet available on Digital Ocean overall. We have found that very small blogs and newsletters like ours don&apos;t need that much memory or disk space and you could save more money by choosing $6 Basic droplet. Unfortunately because the droplet disks can only be sized up - and can&apos;t be reduced in size after the droplet is deployed - if you start with the $12 droplet there&apos;s no going back.</p><p>Where the one-click-app saves you a lot of time and hassle, it locks you into using $12 droplet - or larger - for the foreseeable future.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">If you&apos;d like to try out DigitalOcean, <a href="https://m.do.co/c/3c350328189f?ref=obrien.engineer" rel="noreferrer">sign up here</a> and get $200 in credit for your first 60 days.</div></div><h2 id="pinching-pennies">Pinching Pennies</h2><p>As with many things in the technology space you can spend your time instead of money when starting out. By choosing the slightly harder path and installing Ghost on a Digital Ocean droplet manually rather than via one-click-app you can save yourself $6 a month, or $72 per annum.</p><p>This may seem intimidating if you&apos;re not familiar with the Linux command line, but every step of the way is thoroughly documented both by Digital Ocean and by Ghost. Below I offer some tips on how to get there.</p><h3 id="create-a-6-digital-ocean-droplet">Create a $6 Digital Ocean Droplet</h3><p>Follow the Digital Ocean documentation to set up your droplet:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.digitalocean.com/products/droplets/getting-started/recommended-droplet-setup/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Set up a Production-Ready Droplet | DigitalOcean Documentation</div><div class="kg-bookmark-description">Create a new Droplet with our recommended configuration for improved security, reliability, and monitoring.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.digitalocean.com/favicon.png" alt><span class="kg-bookmark-author">DigitalOcean Documentation</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.digitalocean.com/opengraph/opengraph-base-NOOPT_hu10d88a98f142b24c84f649282c796338_6896_filter_11753308817968588138.png" alt></div></a></figure><p></p><p>More straight-forward instructions are available but we recommend you use the this guide as it includes basic instructions on pre-configuring and securing your droplet as well.</p><p>Pay attention to the options that are available to you when creating the droplet. While some of these options can be changed after the droplet is created, most are immutable. </p><ul><li>select a region that is closest to you, or to your readers. The further away geographically it is, the slower the site will load</li><li>select an image that is supported by Ghost installation - these currently are Ubuntu 20.04 LTS and Ubuntu 22.04 LTS - while newer versions of Ubuntu are available, they are not fully tested and instructions may not work for you </li><li>in size section select a Basic droplet type, then Regular CPU with SSD disk type, then finally select $6/mo droplet</li><li>name your droplet the same as your domain name for easier identification</li><li>tag your droplet to ensure you can apply firewall protection to it</li></ul><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/10/image.png" class="kg-image" alt="Screenshot of the Digital Ocean Control Panel showing a section of the droplet creation page with the size and pricing options selected." loading="lazy" width="1177" height="708" srcset="https://obrien.engineer/content/images/size/w600/2024/10/image.png 600w, https://obrien.engineer/content/images/size/w1000/2024/10/image.png 1000w, https://obrien.engineer/content/images/2024/10/image.png 1177w" sizes="(min-width: 720px) 720px"></figure><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">&#x26A0;&#xFE0F;</div><div class="kg-callout-text">When customising the <b><strong style="white-space: pre-wrap;">Advanced Options Initalization Scripts</strong></b> ensure that the username you select is anything other than usernames root and ghost. Username root is reserved, and username ghost would conflict with the <a href="https://ghost.org/docs/install/ubuntu/?ref=obrien.engineer" rel="noreferrer">Ghost setup requirements</a> which we&apos;ll discuss later. </div></div><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/10/image-2.png" class="kg-image" alt="Screenshot of the Digital Ocean Control Panel showing a section of the droplet creation page showing how the advanced options initialisation script looks like" loading="lazy" width="1171" height="742" srcset="https://obrien.engineer/content/images/size/w600/2024/10/image-2.png 600w, https://obrien.engineer/content/images/size/w1000/2024/10/image-2.png 1000w, https://obrien.engineer/content/images/2024/10/image-2.png 1171w" sizes="(min-width: 720px) 720px"></figure><h3 id="set-up-your-dns">Set up your DNS</h3><p>Same as if you were using a one-click-app for Ghost you now need to set up your Domain Name Service (DNS) record. Domain name registrars usually provide a way for you to manage your DNS records that vary wildly, so you will need to consult their documentation for this. </p><p>You need to create a new A record and point it to the IP address of the droplet you have just created. The droplet IP address will be visible in your Digital Ocean control panel.</p><p>We use Digital Ocean for managing our DNS though and recommend it as well. You can learn more about that in their documentation.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.digitalocean.com/products/networking/dns/how-to/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">DNS How-Tos | DigitalOcean Documentation</div><div class="kg-bookmark-description">How to accomplish specific tasks in detail, like creation/deletion, configuration, and management.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.digitalocean.com/favicon.png" alt><span class="kg-bookmark-author">DigitalOcean Documentation</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.digitalocean.com/opengraph/opengraph-base-NOOPT_hu10d88a98f142b24c84f649282c796338_6896_filter_13399187742419726410.png" alt></div></a></figure><p></p><h3 id="resize-your-droplet">Resize your droplet</h3><p>While running the Ghost installation on a $6 droplet is perfectly fine, Node.js which Ghost is written with requires increased memory for the installation and update process. For this we recommend to <strong>temporarily</strong> resize your droplet to the $12 one, <u>making sure that the disk size remains the same</u>. This will allow you to resize the droplet back down to the smaller $6 size when the installation is completed. </p><p>Follow these instructions to resize the droplet, and ensure you select the <strong>&quot;CPU and RAM only&quot;</strong> option.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.digitalocean.com/products/droplets/how-to/resize/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to Resize Droplets | DigitalOcean Documentation</div><div class="kg-bookmark-description">Resize a Droplet to change the amount of CPU and RAM a Droplet has, optionally add additional disk space, or change to a different type of Droplet plan or CPU.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.digitalocean.com/favicon.png" alt><span class="kg-bookmark-author">DigitalOcean Documentation</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.digitalocean.com/opengraph/opengraph-base-NOOPT_hu10d88a98f142b24c84f649282c796338_6896_filter_10383194552133664514.png" alt></div></a></figure><p></p><h3 id="install-ghost">Install Ghost</h3><p>Use SSH to access your droplet and install ghost following these instructions. I recommend you read through the entire instructions first before you get started.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://ghost.org/docs/install/ubuntu/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to install &amp; setup Ghost on Ubuntu 20.04 or 22.04</div><div class="kg-bookmark-description">A full production install guide for how to install the Ghost professional publishing platform on a production server running Ubuntu 20.04 or 22.04.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://ghost.org/favicon.ico" alt><span class="kg-bookmark-author">Ghost - The Professional Publishing Platform</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://ghost.org/images/meta/ghost-docs.png" alt></div></a></figure><p></p><p>If you have used the Advanced Options Initialization Script when setting up your droplet you can skip the &quot;Create a new user&quot; section. Instead when logging into your server log in as the same user you added in the script:</p><pre><code># Login via SSH
ssh notghost@droplet_ip</code></pre><p>Follow with all the steps as in the instructions, replacing &quot;user&quot; in the scripts with the actual username you have selected. </p><p>Once you run the installation process, it will ask you some questions. I recommend you let Ghost set things up for you automatically by choosing the default options, but ensure that blog URL is the same domain name as the record you have set up in the DNS step before. </p><p>Now it&apos;s time for a cup of tea or coffee! The installation process can take a while. </p><p>Once the installation is completed navigate to your Ghost site and create your owner account by appending your domain name with <code>/ghost</code></p><h3 id="resize-your-droplet-again">Resize your droplet again </h3><p>You may get excited at this point and want to go straight to configuring and building your Ghost publication... but wait! </p><p>Your droplet is still at $12/mo following the installation. </p><p>Navigate back to Digital Ocean control panel and shrink the droplet back to $6/mo size. </p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.digitalocean.com/products/droplets/how-to/resize/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to Resize Droplets | DigitalOcean Documentation</div><div class="kg-bookmark-description">Resize a Droplet to change the amount of CPU and RAM a Droplet has, optionally add additional disk space, or change to a different type of Droplet plan or CPU.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.digitalocean.com/favicon.png" alt><span class="kg-bookmark-author">DigitalOcean Documentation</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.digitalocean.com/opengraph/opengraph-base-NOOPT_hu10d88a98f142b24c84f649282c796338_6896_filter_10383194552133664514.png" alt></div></a></figure><p></p><p>Now your Ghost installation is ready for you to get started. You can customise it further by going through the documentation below: </p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://ghost.org/resources/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Ghost Resources &#x2014; Stories &amp; Ideas About Indie Publishing</div><div class="kg-bookmark-description">A library of resources to help you share content, grow your audience, and build an independent subscription business in the creator economy!</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://ghost.org/resources/content/images/size/w256h256/2021/10/ghost-orb-pink-transparent-01-1.png" alt><span class="kg-bookmark-author">Ghost Resources</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://ghost.org/resources/content/images/size/w1200/2021/10/ghost-resources-2.png" alt></div></a></figure><p></p><h2 id="monitoring">Monitoring</h2><p>Running Ghost on the smallest possible droplet will mean your memory utilisation will be upwards from 80% of the 1GB allocated, even when it&apos;s idle or not particularly busy. This means your site will be at more risk of running out of memory and either becoming too slow to respond to requests, or unavailable entirely. </p><p>To mitigate that risk we do recommend to use a monitoring service that will periodically automatically check if the site is up and responding, and let you know if it&apos;s not. We like Uptime Robot which is free for basic functionality. </p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://uptimerobot.com/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">UptimeRobot: Free Website Monitoring Service</div><div class="kg-bookmark-description">Start monitoring in 30 seconds. Use advanced SSL, keyword and cron monitoring. Get notified by email, SMS, Slack and more. Get 50 monitors for FREE!</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://uptimerobot.com/favicon.ico" alt><span class="kg-bookmark-author">GoDaddy logo</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://uptimerobot.com/assets/images/ogimage.png" alt></div></a></figure><p></p><p>Should your website become too popular for the $6 droplet you can always scale up! </p><h2 id="how-does-it-stack-up">How does it stack up?</h2><p><br>This minimal setup is very plainly cheaper than what you would have to pay for Ghost Pro and it will work well for small sites. </p><h3 id="monthly-billing">Monthly Billing</h3>
<!--kg-card-begin: html-->
<figure class="kg-card kg-width-regular embed">
  <table><thead>
    <tr>
      <th>Ghost Pro Starter</th>
      <th>Ghost Pro Creator</th>
      <th>Ghost on Digital Ocean</th>
    </tr></thead>
  <tbody>
    <tr>
      <td>$11</td>
      <td>$31</td>
      <td>$6 + VAT</td>
    </tr>
  </tbody>
  </table>

</figure>

<!--kg-card-end: html-->
<h3 id="annual-billing">Annual Billing </h3>
<!--kg-card-begin: html-->
<figure class="kg-card kg-width-regular embed">
  <table><thead>
    <tr>
      <th>Ghost Pro Starter</th>
      <th>Ghost Pro Creator</th>
      <th>Ghost on Digital Ocean</th>
    </tr></thead>
  <tbody>
    <tr>
      <td>$108</td>
      <td>$300</td>
      <td>$72 + VAT</td>
    </tr>
  </tbody>
  </table>

</figure>

<!--kg-card-end: html-->
<div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">Note that the prices above don&apos;t include Mailgun integration. <br>For Mailgun integration pricing recommendations see <br><a href="https://obrien.engineer/ghost-and-mailgun-for-tiny-newsletters/" rel="noreferrer">Ghost and Mailgun for tiny newsletters</a></div></div><h3 id="other-considerations">Other Considerations</h3><p>A more detailed breakdown of costs, features, and bundled options on self-hosted vs Ghost Pro can be found below:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://ghost.org/docs/hosting/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Hosting a Ghost publication - Fully-managed PaaS &amp; self-hosted</div><div class="kg-bookmark-description">The most efficient way to deploy an instance of Ghost is on our official fully-managed PaaS. Or you can self-host using our recommended stack!</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://ghost.org/favicon.ico" alt><span class="kg-bookmark-author">Ghost - The Professional Publishing Platform</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://ghost.org/images/meta/ghost-docs.png" alt></div></a></figure><p></p><p>Note however that the pricing for Self-Hosting in that document makes some assumptions that may not apply to you - and are designed to sway you towards choosing Ghost Pro. It&apos;s perfectly fine if you prefer that! </p><p>You should note that: </p><ul><li>the features available to you on Ghost Pro <a href="https://ghost.org/pricing/?ref=obrien.engineer" rel="noreferrer">depend on the tier</a> but on self hosted they are available to you straight away</li><li>by following the steps above you reduce base hosting cost to $6/mo + VAT</li><li>using CDN only becomes advantageous for very busy sites, Fastly do offer a free tier, and they are not the only provider on the market</li><li>email newsletter sending even with Mailgun has lower-tiered pricing available, and custom integrations with other providers are also out there</li><li>fully automated backups can be enabled on Digital Ocean for just 20% extra</li><li>the built-in Pintura image editor is nifty, but hardly required</li></ul><p>As you grow you can always increase the Droplet size or invest in additional services such as CDN or advanced integrations mentioned above. </p><p>The obvious disadvantage here is that hosting your own Ghost publication requires not only more time to set up, but also will require regular maintenance, and occasional troubleshooting. While it doesn&apos;t take a lot of time, it does require ongoing commitment. </p><p>Some documentation on this subject can be found below:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.digitalocean.com/community/tutorials/how-to-keep-ubuntu-22-04-servers-updated?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to Keep Ubuntu 22.04 Servers Updated | DigitalOcean</div><div class="kg-bookmark-description">DigitalOcean makes it possible for you to run as many droplets as you need for a project with one click. However, it&#x2019;s more straightforward to deploy a serve&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.digitalocean.com/_next/static/media/apple-touch-icon.d7edaa01.png" alt><span class="kg-bookmark-author">DigitalOcean</span><span class="kg-bookmark-publisher">Alex Garnett</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://www.digitalocean.com/_next/static/media/intro-to-cloud.d49bc5f7.jpeg" alt></div></a></figure><p></p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://ghost.org/docs/update/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Ghost Docs</div><div class="kg-bookmark-description">Everything you need to know about working with the Ghost professional publishing platform.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://ghost.org/favicon.ico" alt><span class="kg-bookmark-author">Ghost - The Professional Publishing Platform</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://ghost.org/images/meta/ghost-docs.png" alt></div></a></figure><p></p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://obrien.engineer/how-to-automate-lets-encrypt-wildcard-certificates/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to: Automate Let&#x2019;s Encrypt Wildcard Certificates</div><div class="kg-bookmark-description">Learn how to automate your systems for issuing and renewing Let&#x2019;s Encrypt wildcard certificates</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://obrien.engineer/favicon.ico" alt><span class="kg-bookmark-author">O&apos;Brien Cloud Engineering</span><span class="kg-bookmark-publisher">Tom O&#x2019;Brien</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://obrien.engineer/content/images/2024/04/markus-spiske-cvBBO4PzWPg-unsplash.jpg" alt></div></a></figure><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x26A0;&#xFE0F;</div><div class="kg-callout-text">It&apos;s also worth noting that all content you publish on Ghost Pro will be subject to their <a href="https://ghost.org/terms/?ref=obrien.engineer" rel="noreferrer">Terms of Service</a></div></div><p>That&apos;s it! I hope this will help any small blog owners out there!</p><hr><p>Do you still want to self-host... but not go through these steps? We get you! <br>Get in touch with us using the button below and we&apos;ll be happy to help you out.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div><hr>]]></content:encoded></item><item><title><![CDATA[How to:  Prepare video for YouTube with FFmpeg]]></title><description><![CDATA[When preparing media for Youtube, it's best to stick with their recommended settings. This command below resizes, adjusts frame rate (optional), and encodes your video to a new MP4 with specific settings for quality and compatibility.]]></description><link>https://obrien.engineer/how-to-prepare-video-for-youtube-ffmpeg/</link><guid isPermaLink="false">65dda6eecd79b99eb48b2af5</guid><category><![CDATA[FFmpeg Series]]></category><category><![CDATA[How To...?]]></category><dc:creator><![CDATA[Tom O'Brien]]></dc:creator><pubDate>Mon, 06 May 2024 10:00:12 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">If you need help installing FFmpeg on your system, <a href="https://obrien.engineer/how-to-install-ffmpeg" rel="noreferrer">check out this earlier post</a> which will walk you through the process.</div></div><p>Let&apos;s take a look at <a href="https://support.google.com/youtube/answer/4603579?hl=en&amp;ref=obrien.engineer" rel="noreferrer">Youtube&apos;s recommended settings</a> for uploading media to their platform. From here we can apply these settings with FFmpeg.</p><pre><code class="language-shell">ffmpeg \                # Calling the binary
-i input.mp4 \          # Input video file
-r 30000/1001 \         # Set the frame rate - optional
-vf scale=&quot;1920:1080&quot; \ # Resize video - optional
-codec:v libx264 \      # X264 Video Codec
-crf 21 \               # Video Quality
-bf 2 \                 # Maximum 2 B-frames as per guideline
-flags +cgop \          # Closed GOP as per guideline
-pix_fmt yuv420p \      # Chroma subsampling 4:2:0 as per guideline
-c:a aac \              # Fraunhofer FDK AAC codec library
-b:a 128k \             # Audio Bitrate
-ac 2 \                 # Audio channels
-r:a 44100 \            # Audio samplerate
-map 0:v:0 \            # First file : video : first track
-map 0:a:0 \            # First file : audio : first track 
-movflags faststart \   # Put MOOV atom at the front of the file
output.mp4</code></pre><h2 id="command-breakdown-converting-video-with-specific-settings">Command Breakdown: Converting video with specific settings</h2><p>This FFmpeg command takes an MP4 video (<code>input.mp4</code>) and converts it to another MP4 file (<code>output.mp4</code>) with some specific settings:</p><p><strong>Input and Output:</strong></p><ul><li><code>-i input.mp4</code>: This tells FFmpeg to use the file named &quot;input.mp4&quot; as the source video.</li><li><code>output.mp4</code>: This specifies the name of the output file, which will also be in MP4 format.</li></ul><p><strong>Video Processing (Optional):</strong></p><ul><li><code>-r 30000/1001</code>: This option is used to set the frame rate of the output video to 30 frames per second (fps). This is optional, and if omitted, the original frame rate will be kept.</li><li><code>-vf scale=&quot;1920:1080&quot;</code>: This option resizes the video to a resolution of 1920x1080 pixels. This is also optional, and the video will remain its original size if not specified.</li></ul><p><strong>Video Encoding:</strong></p><ul><li><code>-codec:v libx264</code>: This specifies the video codec used for encoding. Here, <code>libx264</code> is used, which is a popular choice for high-quality H.264 video encoding.</li><li><code>-crf 21</code>: This sets the Constant Rate Factor (CRF) for video quality. Lower values result in higher quality (larger file size), and higher values result in lower quality (smaller file size). 21 is a commonly used value for good quality videos.</li><li><code>-bf 2</code>: This sets the maximum number of B-frames to 2. B-frames are used for better compression, but using too many can affect compatibility with some players. Following encoding guidelines, this is set to 2.</li><li><code>-flags +cgop</code>: This enables Closed GOP (Group of Pictures) encoding. Following guidelines, this is enabled for better compatibility with some players.</li><li><code>-pix_fmt yuv420p</code>: This sets the pixel format to YUV 4:2:0, which is a common color space used for video compression. Following guidelines, this format is chosen.</li></ul><p><strong>Audio Encoding:</strong></p><ul><li><code>-c:a aac</code>: This specifies the audio codec used for encoding. Here, <code>aac</code> is used, which is a popular and efficient audio codec.</li><li><code>-b:a 128k</code>: This sets the audio bitrate to 128 kilobits per second (kbps). This is a common choice for good quality audio.</li><li><code>-ac 2</code>: This sets the number of audio channels to 2 (stereo).</li><li><code>-r:a 44100</code>: This sets the audio sample rate to 44.1 kHz, which is a standard audio sample rate.</li></ul><p><strong>Mapping Streams (Optional):</strong></p><ul><li><code>-map 0:v:0</code>: This tells FFmpeg to copy the first video stream (stream 0) from the input file (indicated by the &quot;0&quot;) to the output file.</li><li><code>-map 0:a:0</code>: Similar to the previous option, this copies the first audio stream (stream 0) from the input file to the output file.</li></ul><p><strong>Output Optimization:</strong></p><ul><li><code>-movflags faststart</code>: This places the MOOV atom (which contains essential information about the video) at the beginning of the file. This can improve seeking performance in some players.</li></ul><hr><p>Need some help with online video delivery, storage and processing? Get in touch with us using the button below and we&apos;ll be happy to help you out.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div>]]></content:encoded></item><item><title><![CDATA[How to: Understand FFmpeg flags]]></title><description><![CDATA[FFmpeg's flags can be confusing if you aren't familiar with them, and sometimes even if you are familiar! Let's take a look at some of them and see what they mean.]]></description><link>https://obrien.engineer/how-to-understand-ffmpeg-flags/</link><guid isPermaLink="false">65dda1b7cd79b99eb48b2ab8</guid><category><![CDATA[FFmpeg Series]]></category><category><![CDATA[How To...?]]></category><dc:creator><![CDATA[Tom O'Brien]]></dc:creator><pubDate>Mon, 29 Apr 2024 10:00:04 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">Flags, also known as options or switches, are <b><strong style="white-space: pre-wrap;">command-line parameters used to modify the behavior of a command or program</strong></b>. Flags are typically preceded by a hyphen (-) or a double hyphen (--), and they provide additional instructions or specify options when executing a command.</div></div><p>FFmpeg is a powerful tool for processing audio and video files, but its commands can appear complex at first glance. Let&apos;s break down the process of understanding an FFmpeg command into simpler steps:</p><h3 id="identify-the-basic-function">Identify the basic function</h3><p>Most FFmpeg commands start with an action verb, like <code>ffmpeg -i input.mp4 output.avi</code>. Here, <code>ffmpeg</code> is the program name, <code>-i</code> specifies the input file (<code>input.mp4</code>), and <code>output.avi</code> is the output filename.</p><h3 id="break-down-the-options">Break down the options</h3><p>The <code>-i</code> option is followed by various flags and parameters that control FFmpeg&apos;s behavior. These can be categorized into:</p><ul><li><strong>Input options:</strong> These specify properties of the input file, like <code>-i input.mp4</code> which tells FFmpeg to use &quot;input.mp4&quot; as the source.</li><li><strong>Output options:</strong> These control the output file&apos;s format, quality, and other aspects. For example, <code>.avi</code> in the command specifies the output format as AVI.</li><li><strong>Codec options:</strong> Codecs are used for encoding and decoding audio/video data. FFmpeg can use different codecs depending on your needs.</li></ul><h3 id="understand-common-options">Understand common options</h3><p>Some frequently used options include:</p><ul><li><code>-c:v codec</code>: This specifies the video codec to use for encoding/decoding (e.g., <code>-c:v libx264</code> for H.264 video).</li><li><code>-c:a codec</code>: Similar to <code>-c:v</code> but for audio codecs (e.g., <code>-c:a libmp3lame</code> for MP3 audio).</li><li><code>-b:v bitrate</code>: Sets the video bitrate, which affects video quality and file size (e.g., <code>-b:v 5M</code> for 5 Mbps bitrate).</li><li><code>-ar samplerate</code>: Sets the audio sample rate, which affects audio quality (e.g., <code>-ar 44100</code> for 44.1 kHz sample rate).</li></ul><hr><p>Need some help with online video delivery, storage and processing? Get in touch with us using the button below and we&apos;ll be happy to help you out.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div>]]></content:encoded></item><item><title><![CDATA[How to: Extract Audio from Video with FFmpeg]]></title><description><![CDATA[Extracting audio from a video is a fairly simple process with FFmpeg. There are several ways to do this, and you may find that one method suits over another. Let's take a look.]]></description><link>https://obrien.engineer/how-to-extract-audio-from-video-ffmpeg/</link><guid isPermaLink="false">65dc819ccd79b99eb48b2a22</guid><category><![CDATA[FFmpeg Series]]></category><category><![CDATA[How To...?]]></category><dc:creator><![CDATA[Tom O'Brien]]></dc:creator><pubDate>Sat, 27 Apr 2024 10:53:50 GMT</pubDate><media:content url="https://obrien.engineer/content/images/2024/04/kelly-sikkema-X-etICbUKec-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">If you need help installing FFmpeg on your system, <a href="https://obrien.engineer/how-to-install-ffmpeg" rel="noreferrer">check out this earlier post</a> which will walk you through the process.</div></div><img src="https://obrien.engineer/content/images/2024/04/kelly-sikkema-X-etICbUKec-unsplash.jpg" alt="How to: Extract Audio from Video with FFmpeg"><p>A couple of things to note for the examples below:</p><ul><li><strong>your_video_file.mp4</strong> refers to the file name of your video, so change this appropriately.</li><li>Each method will create a file called <strong>audio.mp3</strong>. You can change this file name to whatever you like.</li></ul><h3 id="without-encoding">Without encoding</h3><p>This method will simply extract the audio in its original state from the video file.</p><pre><code class="language-shell">ffmpeg -i your_video_file.mp4 -vn audio.mp3</code></pre><h3 id="with-encoding">With encoding</h3><p>This next method will allow you to re-encode the audio from the video file with a different codec to the original one. Below you&apos;ll find conversions with libmp3lame, AAC and Opus codecs.</p><pre><code class="language-shell">ffmpeg -i your_video_file.mp4 -vn -acodec libmp3lame audio.mp3
ffmpeg -i your_video_file.mp4 -vn -acodec aac audio.mp3
ffmpeg -i your_video_file.mp4 -vn -acodec opus audio.mp3</code></pre><hr><p>Need some help with online video delivery, storage and processing? Get in touch with us using the button below and we&apos;ll be happy to help you out.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div>]]></content:encoded></item><item><title><![CDATA[How to: Encode video with the H.264 codec with FFmpeg]]></title><description><![CDATA[Perhaps you have an old AVI video file that won't play on some modern applications, or would like to ensure your media can be played on the web. The H.264 codec is widely supported across all major browsers, and on both Apple and Android devices. Let's take a look.]]></description><link>https://obrien.engineer/how-to-encode-video-with-h-264-ffmpeg/</link><guid isPermaLink="false">65dd9bb2cd79b99eb48b2a75</guid><category><![CDATA[FFmpeg Series]]></category><category><![CDATA[How To...?]]></category><dc:creator><![CDATA[Tom O'Brien]]></dc:creator><pubDate>Sat, 27 Apr 2024 10:53:29 GMT</pubDate><media:content url="https://obrien.engineer/content/images/2024/04/gr-stocks-q8P8YoR6erg-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">If you need help installing FFmpeg on your system, <a href="https://obrien.engineer/how-to-install-ffmpeg" rel="noreferrer">check out this earlier post</a> which will walk you through the process.</div></div><img src="https://obrien.engineer/content/images/2024/04/gr-stocks-q8P8YoR6erg-unsplash.jpg" alt="How to: Encode video with the H.264 codec with FFmpeg"><p>A couple of things to note for the examples below:</p><ul><li><strong>your_video_file.mp4</strong> refers to the file name of your video, so change this appropriately.</li><li>Each method will create a file called <strong>output_video.mp4</strong>. You can change this file name to whatever you like.</li></ul><h3 id="encode-video-with-h264">Encode video with H.264</h3><p>This command will create a new video file from your existing media using the H.264 codec.</p><pre><code class="language-shell">ffmpeg -i your_video_file.mp4 -c:v libx264 output_video.mp4</code></pre><h3 id="encode-video-with-compression">Encode video with compression</h3><p>This command will give you good compression without any noticeable loss in picture quality.</p><pre><code class="language-shell">ffmpeg -i your_video_file.mp4 -c:v libx264 -crf 27 output_video.mp4</code></pre><h3 id="encode-video-with-high-quality">Encode video with high quality</h3><p>This command will sacrifice compression in order to produce the best picture quality.</p><pre><code class="language-shell">ffmpeg -i your_video_file.mp4 -c:v libx264 -crf 18 -preset veryslow output_video.mp4</code></pre><hr><p>Need some help with online video delivery, storage and processing? Get in touch with us using the button below and we&apos;ll be happy to help you out.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div>]]></content:encoded></item><item><title><![CDATA[How to: Install FFmpeg]]></title><description><![CDATA[Getting FFmpeg installed and configured on your system can be tricky if you haven't done it before. Here's how to do just that, with guides below for MacOS, Ubuntu / Debian, and Windows systems.]]></description><link>https://obrien.engineer/how-to-install-ffmpeg/</link><guid isPermaLink="false">65cb9b9ecd79b99eb48b292f</guid><category><![CDATA[FFmpeg Series]]></category><category><![CDATA[How To...?]]></category><dc:creator><![CDATA[Tom O'Brien]]></dc:creator><pubDate>Mon, 18 Mar 2024 10:00:17 GMT</pubDate><media:content url="https://obrien.engineer/content/images/2024/04/gabriel-heinzer-xbEVM6oJ1Fs-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<h3 id="install-ffmpeg-on-macos">Install FFmpeg on MacOS</h3><img src="https://obrien.engineer/content/images/2024/04/gabriel-heinzer-xbEVM6oJ1Fs-unsplash.jpg" alt="How to: Install FFmpeg"><p>We&apos;ll start by opening a terminal (&#x2318; + T) and installing <a href="https://brew.sh/?ref=obrien.engineer" rel="noreferrer">Homebrew</a>. </p><pre><code class="language-bash">/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;</code></pre><p>Now we can install FFmpeg</p><pre><code class="language-bash">brew install ffmpeg</code></pre><p>If you want to install FFmpeg with additional options, such as Chromaprint, use the following:</p><pre><code class="language-bash">brew uninstall --force --ignore-dependencies ffmpeg
brew install chromaprint amiaopensource/amiaos/decklinksdk
brew tap homebrew-ffmpeg/ffmpeg
brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-chromaprint</code></pre><p>You can verify the install was successful by checking its version</p><pre><code class="language-bash">ffmpeg -version</code></pre><h3 id="install-ffmpeg-on-ubuntu-debian">Install FFmpeg on Ubuntu / Debian</h3><p>We&apos;ll start by opening a terminal (CTRL + SHIFT + T), updating our APT repositories and installing FFmpeg stable</p><pre><code class="language-bash">sudo apt update
sudo apt install ffmpeg</code></pre><p>You can verify the install was successful by checking its version</p><pre><code class="language-bash">ffmpeg -version</code></pre><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">If you&apos;d like to build FFmpeg from source, this <a href="https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu?ref=obrien.engineer" rel="noreferrer">guide from the the people behind FFmpeg</a> will set you right. If not, stick with the stable version. </div></div><h3 id="install-ffmpeg-on-windows">Install FFmpeg on Windows</h3><p>We&apos;ll start by downloading FFmpeg. Go to the <a href="https://ffmpeg.org/download.html?ref=obrien.engineer" rel="noreferrer">download page</a> and click on the Windows logo in the middle:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://obrien.engineer/content/images/2024/02/ffmpeg-download-page.png" class="kg-image" alt="How to: Install FFmpeg" loading="lazy" width="794" height="231" srcset="https://obrien.engineer/content/images/size/w600/2024/02/ffmpeg-download-page.png 600w, https://obrien.engineer/content/images/2024/02/ffmpeg-download-page.png 794w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">FFmpeg download page</span></figcaption></figure><p>On the <a href="https://www.gyan.dev/ffmpeg/builds/?ref=obrien.engineer" rel="noreferrer">gyan.dev builds page</a>, click on <a href="https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z?ref=obrien.engineer"><code>ffmpeg-git-full.7z</code></a> and download it.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://obrien.engineer/content/images/2024/02/ffmpeg-git-master-builds.png" class="kg-image" alt="How to: Install FFmpeg" loading="lazy" width="1064" height="378" srcset="https://obrien.engineer/content/images/size/w600/2024/02/ffmpeg-git-master-builds.png 600w, https://obrien.engineer/content/images/size/w1000/2024/02/ffmpeg-git-master-builds.png 1000w, https://obrien.engineer/content/images/2024/02/ffmpeg-git-master-builds.png 1064w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">gyan.dev builds page</span></figcaption></figure><p>Once it has been downloaded, unzip the file with <a href="https://www.7-zip.org/download.html?ref=obrien.engineer" rel="noreferrer">7zip</a></p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/open-archive-with-7zip.png" class="kg-image" alt="How to: Install FFmpeg" loading="lazy" width="1119" height="632" srcset="https://obrien.engineer/content/images/size/w600/2024/02/open-archive-with-7zip.png 600w, https://obrien.engineer/content/images/size/w1000/2024/02/open-archive-with-7zip.png 1000w, https://obrien.engineer/content/images/2024/02/open-archive-with-7zip.png 1119w" sizes="(min-width: 720px) 720px"></figure><p>Rename the extracted folder to <code>ffmpeg</code></p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/rename-ffmpeg-folder.png" class="kg-image" alt="How to: Install FFmpeg" loading="lazy" width="818" height="768" srcset="https://obrien.engineer/content/images/size/w600/2024/02/rename-ffmpeg-folder.png 600w, https://obrien.engineer/content/images/2024/02/rename-ffmpeg-folder.png 818w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/rename-ffmpeg-folder-2.png" class="kg-image" alt="How to: Install FFmpeg" loading="lazy" width="516" height="162"></figure><p>Move the <code>ffmpeg</code> folder to the root of your <code>C:\</code> drive</p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/03/ffmpeg-c-drive.png" class="kg-image" alt="How to: Install FFmpeg" loading="lazy" width="818" height="492" srcset="https://obrien.engineer/content/images/size/w600/2024/03/ffmpeg-c-drive.png 600w, https://obrien.engineer/content/images/2024/03/ffmpeg-c-drive.png 818w" sizes="(min-width: 720px) 720px"></figure><p>Run <code>cmd</code> as an administrator</p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/open-cmd-admin.png" class="kg-image" alt="How to: Install FFmpeg" loading="lazy" width="403" height="576"></figure><p>Set the environment path variable for FFmpeg by running the following command:</p><pre><code class="language-cmd">setx /m PATH &quot;C:\ffmpeg\bin;%PATH%&quot;</code></pre><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/image.png" class="kg-image" alt="How to: Install FFmpeg" loading="lazy" width="512" height="115"></figure><p>Now, <strong>reboot your system</strong> and verify that the install was successful by checking its version</p><pre><code class="language-cmd">ffmpeg -version</code></pre><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/ffmpeg-version.png" class="kg-image" alt="How to: Install FFmpeg" loading="lazy" width="975" height="509" srcset="https://obrien.engineer/content/images/size/w600/2024/02/ffmpeg-version.png 600w, https://obrien.engineer/content/images/2024/02/ffmpeg-version.png 975w" sizes="(min-width: 720px) 720px"></figure><h3 id="using-ffmpeg-via-docker">Using FFmpeg via Docker</h3><p>If you&apos;re familiar with <a href="https://hub.docker.com/?ref=obrien.engineer" rel="noreferrer">Docker</a> and would like to use FFmpeg for cloud-based deployments, you should try <a href="https://hub.docker.com/r/mwader/static-ffmpeg/?ref=obrien.engineer" rel="noreferrer">this excellent image</a>, which I&apos;ve personally used in a production environment for <a href="https://downsampl.com/?ref=obrien.engineer" rel="noreferrer">Downsampl</a>, and works like a charm. Github source repository for the image is <a href="https://github.com/wader/static-ffmpeg?ref=obrien.engineer" rel="noreferrer">here</a>.</p><hr><p>Need some help with online video delivery, storage and processing? Get in touch with us using the button below and we&apos;ll be happy to help you out.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div>]]></content:encoded></item><item><title><![CDATA[Ghost and Mailgun for tiny newsletters]]></title><description><![CDATA[<div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">&#x26A0;&#xFE0F;</div><div class="kg-callout-text">The Flex plan mentioned in this article has now been retired. <br><a href="https://obrien.engineer/mailgun-for-tiny-newsletters/" rel="noreferrer">Read out update here.</a></div></div><p>This website is powered by <a href="https://ghost.org/?ref=obrien.engineer" rel="noreferrer">Ghost CMS</a>, a free and open source (FOSS) publishing platform. While there are many reasons why we chose this platform one important one is the ability to send</p>]]></description><link>https://obrien.engineer/ghost-and-mailgun-for-tiny-newsletters/</link><guid isPermaLink="false">65c4fdaacd79b99eb48b27c2</guid><category><![CDATA[Ghost CMS]]></category><dc:creator><![CDATA[JJ O'Brien]]></dc:creator><pubDate>Mon, 11 Mar 2024 10:00:14 GMT</pubDate><media:content url="https://obrien.engineer/content/images/2024/02/25l.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">&#x26A0;&#xFE0F;</div><div class="kg-callout-text">The Flex plan mentioned in this article has now been retired. <br><a href="https://obrien.engineer/mailgun-for-tiny-newsletters/" rel="noreferrer">Read out update here.</a></div></div><img src="https://obrien.engineer/content/images/2024/02/25l.jpg" alt="Ghost and Mailgun for tiny newsletters"><p>This website is powered by <a href="https://ghost.org/?ref=obrien.engineer" rel="noreferrer">Ghost CMS</a>, a free and open source (FOSS) publishing platform. While there are many reasons why we chose this platform one important one is the ability to send newsletters to people who subscribe and not having to worry much about crafting separate web and email views.</p><p>You can choose to go with Ghost Pro which is a fully hosted solution that has email integration already configured and included in the pricing. We have chosen to self-host Ghost which also means we set up all themes and integrations ourselves. If you&apos;re in the same boat you may have wondered how to minimise the expense of sending out bulk email.</p><p>Ghost integrates with Mailgun out-of-the-box for sending email newsletters. Without it you can still allow users to subscribe, but won&apos;t be able to send posts as a newsletter. Furthermore Ghost doesn&apos;t offer any additional options for this feature. If you&apos;re in love with Postmark or Sendgrid and you would rather use them it&apos;s tough luck for you. It&apos;s not that you can&apos;t - you can always write a custom integration if you&apos;re so inclined - but this becomes technically tricky.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://ghost.org/docs/faq/mailgun-newsletters/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Why do I have to set up Mailgun for newsletters?</div><div class="kg-bookmark-description">Sending bulk email to many recipients using SMTP is not supported. In order to send newsletters from Ghost you&#x2019;ll need to setup Bulk Mail with Mailgun.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://ghost.org/favicon.ico" alt="Ghost and Mailgun for tiny newsletters"><span class="kg-bookmark-author">Ghost - The Professional Publishing Platform</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://ghost.org/images/meta/ghost-docs.png" alt="Ghost and Mailgun for tiny newsletters"></div></a></figure><h2 id="mailgun-plans-and-pricing">Mailgun plans and pricing</h2><p>Mailgun is fairly intuitive when it comes to setup but the pricing can look pretty grim if you&apos;re independent blogger or publisher who&apos;s just starting up. The Free tier only allows you to send emails to &quot;five authorized users&quot;. To clarify, this means specific pre-defined email addresses. This makes it only suitable for testing purposes and pretty much nothing else.</p><p>The next tier up according to their <a href="https://www.mailgun.com/pricing/?ref=obrien.engineer" rel="noreferrer">Pricing page</a> is Foundation which allows you to send 50 000 emails for $35 a month - and that is quite a jump in both price and the quantity. If you don&apos;t intend to send <em>that many</em> you may be reluctant to sign up.</p><p>What Mailgun doesn&apos;t openly advertise is that there is also a hidden Flex plan which bills as follows:</p><ul><li>free for first 1000 emails a month</li><li>$1 per every next 1000 emails</li></ul><p>This is documented in more detail <a href="https://help.mailgun.com/hc/en-us/articles/203068914-What-Are-the-Differences-Between-the-Free-and-Flex-Plans?ref=obrien.engineer" rel="noreferrer">here</a> and <a href="https://help.mailgun.com/hc/en-us/articles/360048661093-How-does-PAYG-billing-work?ref=obrien.engineer" rel="noreferrer">here</a>, but it&apos;s not clearly stated anywhere in the user interface, and you won&apos;t find this information easily unless you already know what you&apos;re looking for. It&apos;s also tricky to switch to that plan that it&apos;s decidedly a cancellation type <a href="https://www.emailtooltester.com/en/blog/dark-patterns-canceling-subscription-report/?ref=obrien.engineer" rel="noreferrer">dark pattern</a>.</p><h2 id="switching-to-flex-plan">Switching to Flex plan</h2><p>When you open a Mailgun account you will be given an option to add your credit card at the beginning or to subscribe to a Free plan. Regardless what you choose you will have to give them a payment method and go <em>through</em> a Foundation plan to get to the Flex plan, so it is faster to give them your card to begin with.</p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/data-src-image-27842bcf-5954-4630-9ae6-c82d46777808.png" class="kg-image" alt="Ghost and Mailgun for tiny newsletters" loading="lazy" width="979" height="775" srcset="https://obrien.engineer/content/images/size/w600/2024/02/data-src-image-27842bcf-5954-4630-9ae6-c82d46777808.png 600w, https://obrien.engineer/content/images/2024/02/data-src-image-27842bcf-5954-4630-9ae6-c82d46777808.png 979w" sizes="(min-width: 720px) 720px"></figure><p>If you started with the Free plan however, navigate to your account -&gt; <a href="https://app.eu.mailgun.com/app/account/billing/plans?ref=obrien.engineer" rel="noreferrer">Plans and Billing</a> and select the Foundation plan. Enter your payment details and proceed with the upgrade.</p><p>Mailgun will then start your 30-day free trial of Foundation plan.</p><p>Whether you started with Foundation trial or switched to it from Free you won&apos;t be able to downgrade to Flex immediately yet must do so before the end of the free trial so that you&apos;re not charged $35 subscription fee.</p><p>On another day (I did this a few days after subscribing) navigate do your <a href="https://app.eu.mailgun.com/app/account/billing/plans?ref=obrien.engineer" rel="noreferrer">Plans and Billing</a> screen again. You will see your Foundation 50k Trial on top and a prominent Upgrade button. Ignore it completely and select the little settings cog next to it.</p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/Pasted-image-20240208153055.png" class="kg-image" alt="Ghost and Mailgun for tiny newsletters" loading="lazy" width="754" height="249" srcset="https://obrien.engineer/content/images/size/w600/2024/02/Pasted-image-20240208153055.png 600w, https://obrien.engineer/content/images/2024/02/Pasted-image-20240208153055.png 754w" sizes="(min-width: 720px) 720px"></figure><p>You will be presented with two options: <strong>Downgrade</strong> or <strong>Unsubscribe</strong>. Counter-intuitively downgrade button will just trap you on a pricing page with only options to upgrade. Instead of clicking downgrade select <strong>Unsubscribe</strong>. This will start the process of switching your plan to Flex.</p><p>This switch is also not immediate - it didn&apos;t start showing on the billing screen until the following day. When the switch is in effect you should see the following warning message on your billing page:</p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/Pasted-image-20240208153229.png" class="kg-image" alt="Ghost and Mailgun for tiny newsletters" loading="lazy" width="661" height="254" srcset="https://obrien.engineer/content/images/size/w600/2024/02/Pasted-image-20240208153229.png 600w, https://obrien.engineer/content/images/2024/02/Pasted-image-20240208153229.png 661w"></figure><p>That&apos;s it! You should now be on the pay-as-you-go Flex Plan.</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">Didn&apos;t work? Open a support ticket by going to account -&gt; Support -&gt; <a href="https://app.mailgun.com/support/create?ref=obrien.engineer" rel="noreferrer">Open a Ticket</a> (that button is on the very bottom of the page!)</div></div><h2 id="when-should-you-upgrade-from-flex-to-foundation-plan">When should you upgrade from Flex to Foundation plan?</h2><p>Flex plan is the sensible option until you start growing your audience. Most bloggers and small publishers will find it cheaper than Foundation plan for a long while. If you get very popular however, and publish regularly, then a time will come when it will be cheaper to switch to the Foundation plan.</p><p>How big an audience? How long a while? That moment is precisely when you start sending more than <strong>36 thousand emails a month</strong>, which will cost you $35 - at that point switching to Foundation plan is the way to go as for the same price your limit will go up to 50k, with the same cost of overages as the Flex plan. </p><p>Hopefully by that stage you will have so many paying subscribers or conversions that this won&apos;t really matter!</p><hr><p>Can&apos;t possibly go through this yourself? Too much of a hassle? We get you!<br>Get in touch with us using the button below and we&apos;ll be happy to help you out.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div><hr>]]></content:encoded></item><item><title><![CDATA[How to: FFmpeg Series]]></title><description><![CDATA[Have you ever stumbled upon a video file in a format your device just refuses to play? Or perhaps you dream of editing clips, converting audio, or streaming live content, but the command line seems daunting? Fear not, for this blog series will guide you through the sometimes complex world of FFmpeg.]]></description><link>https://obrien.engineer/how-to-ffmpeg-series/</link><guid isPermaLink="false">65cb8aa4cd79b99eb48b2911</guid><category><![CDATA[FFmpeg Series]]></category><category><![CDATA[How To...?]]></category><dc:creator><![CDATA[Tom O'Brien]]></dc:creator><pubDate>Mon, 04 Mar 2024 10:00:56 GMT</pubDate><content:encoded><![CDATA[<h3 id="what-is-ffmpeg">What is FFmpeg?</h3><p>Imagine a Swiss Army knife for multimedia. That&apos;s essentially what FFmpeg is. It&apos;s a free and open-source collection of tools that can handle virtually any audio, video, and image format you throw at it. From basic conversions to advanced editing and streaming, FFmpeg handles more media formats than you can shake a stick at.</p><p>This series aims to unlock the potential of FFmpeg for users of all levels. Whether you&apos;re a complete beginner or a seasoned techie, here&apos;s what you can gain:</p><h3 id="what-will-this-series-cover">What will this series cover?</h3><p>We&apos;ll explore the following topics to get you up and running:</p><ul><li>Installation: Downloading and setting up FFmpeg on different operating systems (Windows, Mac, Linux).</li><li>Basic Commands: Mastering the essential commands for conversions, basic edits, and playback.</li><li>Advanced Techniques: Delving into filters, scripting, and automation for power users.</li><li>Real-world Applications: Putting your newfound skills to practice with practical use cases like streaming, editing, and format conversions.</li></ul><p>By the end of this series, you&apos;ll be wielding FFmpeg with confidence, transforming your multimedia experience from frustration to freedom. Stay tuned for the next post, where we&apos;ll guide you through the installation process and get you started with your first FFmpeg commands.</p><hr><p>Need some help with online video delivery, storage and processing? Get in touch with us using the button below and we&apos;ll be happy to help you out.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div>]]></content:encoded></item><item><title><![CDATA[How to: Automate Let's Encrypt Wildcard Certificates]]></title><description><![CDATA[Learn how to automate your systems for issuing and renewing Let's Encrypt wildcard certificates]]></description><link>https://obrien.engineer/how-to-automate-lets-encrypt-wildcard-certificates/</link><guid isPermaLink="false">65c4fc0ccd79b99eb48b27a9</guid><category><![CDATA[How To...?]]></category><category><![CDATA[Engineering]]></category><category><![CDATA[Automation]]></category><dc:creator><![CDATA[Tom O'Brien]]></dc:creator><pubDate>Mon, 04 Mar 2024 10:00:22 GMT</pubDate><media:content url="https://obrien.engineer/content/images/2024/04/markus-spiske-cvBBO4PzWPg-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://obrien.engineer/content/images/2024/04/markus-spiske-cvBBO4PzWPg-unsplash.jpg" alt="How to: Automate Let&apos;s Encrypt Wildcard Certificates"><p>Maintaining SSL certificates has always been a tricky prospect. The process used to involve <a href="https://assets.gcore.pro/blog/why-the-web-moved-to-lets-encrypt/1596007961.png?ref=obrien.engineer">paying a few hundred dollars</a> to a Certificate Authority, who would then issue an SSL certificate for you to install on your servers. Very little automation existed.</p><p>When Let&#x2019;s Encrypt launched <a href="https://letsencrypt.org/2015/12/03/entering-public-beta?ref=obrien.engineer">nearly 10 years ago</a>, it was a godsend for SysAdmins and DevOps folk. Automated certificate creation? Automated renewals? Wildcard certificates? For free?! Yes, please, and thank you.</p><p>Let&#x2019;s Encrypt uses <a href="https://letsencrypt.org/docs/challenge-types/?ref=obrien.engineer#http-01-challenge">HTTP-01 ACME</a> for validating and re-validating a server&#x2019;s SSL certificate. This is great for hosted websites as port 80 is open for web traffic anyway. This is not-so-great if you&#x2019;re hosting web services behind a VPN or on a local network / intranet, or if you&#x2019;re running non-web services on your server such as email. This method also can&#x2019;t be used to issue wildcard certificates.</p><p>This is where <a href="https://letsencrypt.org/docs/challenge-types/?ref=obrien.engineer#dns-01-challenge">DNS-01 ACME</a> comes to the fore. It uses a DNS challenge to ensure that you have control over your domain, and can create TXT records in response.</p><p>Since we use DigitalOcean for the vast majority of our services, I&#x2019;ll be showing you how to use DNS challenges with DigitalOcean&#x2019;s API on an Ubuntu or other Debian-based Linux system. You&#x2019;ll need to ensure that you have <code>sudo</code> access to your system before beginning.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">If you&apos;d like to try out DigitalOcean, <a href="https://m.do.co/c/3c350328189f?ref=obrien.engineer" rel="noreferrer">sign up here</a> and get $200 in credit for your first 60 days.</div></div><h3 id="install-certbot-on-ubuntu-using-snaps">Install Certbot on Ubuntu using Snaps</h3><p>Install Snap</p><pre><code class="language-shell">sudo snap install core; sudo snap refresh core</code></pre><p>Install Let&#x2019;s Encrypt Certbot</p><pre><code class="language-shell">sudo snap install --classic certbot</code></pre><p>Symlink the Certbot snap</p><pre><code class="language-shell">sudo ln -s /snap/bin/certbot /usr/bin/certbot</code></pre><h3 id="install-dns-challenge-plugin">Install DNS challenge plugin</h3><p>Allow the Certbot snap access to root (to install DNS plugins)</p><pre><code class="language-shell">sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-digitalocean</code></pre><h3 id="install-certbot-on-ubuntu-or-other-debian-systems-without-snaps">Install Certbot on Ubuntu or other Debian systems without Snaps</h3><p>Install Let&#x2019;s Encrypt Certbot</p><pre><code class="language-shell">sudo apt update
sudo apt install certbot</code></pre><h3 id="install-dns-challenge-plugin-1">Install DNS challenge plugin</h3><p>Install certbot-dns-digitalocean python plugin</p><pre><code class="language-shell">sudo apt install python3-certbot-dns-digitalocean</code></pre><h3 id="create-an-api-key-in-digitalocean">Create an API key in DigitalOcean</h3><p>Log in to your DigitalOcean account and <a href="https://cloud.digitalocean.com/account/api/tokens/new?ref=obrien.engineer" rel="noreferrer">visit the API section</a> to create your new API key. Make sure to enable Write permissions so that new DNS TXT records can be created, and then click on &quot;Generate Token&quot;.</p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/02/Screenshot-from-2024-02-08-17-03-13.png" class="kg-image" alt="How to: Automate Let&apos;s Encrypt Wildcard Certificates" loading="lazy" width="796" height="631" srcset="https://obrien.engineer/content/images/size/w600/2024/02/Screenshot-from-2024-02-08-17-03-13.png 600w, https://obrien.engineer/content/images/2024/02/Screenshot-from-2024-02-08-17-03-13.png 796w" sizes="(min-width: 720px) 720px"></figure><p>Save the key in a file called <code>.digitalocean-dns-letencrypt.ini</code> in <code>/root</code> in the following format</p><pre><code class="language-shell"># DigitalOcean API credentials used by Certbot
dns_digitalocean_token = dop_v1_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</code></pre><p>Set read and write access to the file for the root user only</p><pre><code class="language-shell">sudo chmod 600 /root/.digitalocean-dns-letencrypt.ini</code></pre><h2 id="automation-with-cron">Automation with Cron</h2><p>Edit the root crontab</p><pre><code class="language-shell">sudo crontab -e</code></pre><p>Add the following lines</p><pre><code class="language-shell">0 4 * * 0 certbot certonly --dns-digitalocean --dns-digitalocean-credentials /root/.digitalocean-dns-letencrypt.ini --email certbot@example.com --agree-tos --non-interactive -d example.com -d *.example.com
5 4 * * 0 systemctl restart dovecot postfix apache2 spamassassin</code></pre><p>Certbot will now run every week on Sunday at 04:00, and associated services will be restarted 5 minutes later at 04:05. The second line restarts services that use the certificate. For example, if you&apos;re using Nginx instead of Apache, ensure that <code>systemctl restart</code> command reflects this. Make sure to set the email (--email) and domains (-d) appropriately.</p><p><strong>And there you have it!</strong> Your system will now check your certificates on a weekly basis and renew automatically if needed.</p><hr><p>Are you still renewing your certificates manually? Don&apos;t really want to go through this process? That&apos;s OK!<br>Get in touch with us using the button below and we&apos;ll be happy to help you out.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div><hr><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[How to: Configure Ghost CMS for extra long author bio]]></title><description><![CDATA[<p><a href="https://ghost.org/?ref=obrien.engineer" rel="noreferrer">Ghost Content Management System</a> (CMS) is a popular free and open source (FOSS) publishing platform. In fact this website is using Ghost! </p><p>While it&apos;s excellent in many ways, Ghost also comes with some built-in limitations. You can modify and customise it by creating new or modifying existing themes,</p>]]></description><link>https://obrien.engineer/how-to-configure-ghost-cms-for-extra-long-author-bio/</link><guid isPermaLink="false">65acdcc875fa7ded186fb9e4</guid><category><![CDATA[Ghost CMS]]></category><category><![CDATA[How To...?]]></category><dc:creator><![CDATA[JJ O'Brien]]></dc:creator><pubDate>Mon, 26 Feb 2024 10:00:00 GMT</pubDate><content:encoded><![CDATA[<p><a href="https://ghost.org/?ref=obrien.engineer" rel="noreferrer">Ghost Content Management System</a> (CMS) is a popular free and open source (FOSS) publishing platform. In fact this website is using Ghost! </p><p>While it&apos;s excellent in many ways, Ghost also comes with some built-in limitations. You can modify and customise it by creating new or modifying existing themes, but this can often be cumbersome especially if you don&apos;t have strong technical skills. </p><p>One such limitation is the length of the author bio. Ghost limits the author bio field to only 200 characters - and this is often too short if you wish to provide more details! Ghost users and admins have long requested for this limit to be extended. This has however not been yet implemented and may never be.  </p><p>As a workaround you can create your own author bio as a page, even with a separate custom channel page to mimic the original author page. </p><p>This works best if you don&apos;t have many authors, and it also falls back to original behaviour for all authors who don&apos;t have a custom page. </p><h2 id="about-routes-and-slugs">About Routes and Slugs</h2><p>To understand what&apos;s about to happen here you need to understand that the URL schema for Ghost can be customised for your publication. It is defined in a routes.yaml file. By default it looks like this:</p><pre><code>routes:

collections:
  /:
    permalink: /{slug}/
    template: index

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/</code></pre><p>Routes file broadly describes what URL will any page have, relative to the domain name. In the default behaviour above all posts and pages will have URL such as:</p><p><code>https://example.com/post-slug</code></p><p>and importantly, the author&apos;s page will have the URL such as:</p><p><code>https://example.com/author/author-slug</code></p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://ghost.org/docs/themes/routing/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Ghost Themes - Dynamic URLs &amp; Routing</div><div class="kg-bookmark-description">Build dedicated URL structures using Ghost&#x2019;s dynamic routing system, for custom homepages, podcasts, categories and more.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://ghost.org/favicon.ico" alt><span class="kg-bookmark-author">Ghost - The Professional Publishing Platform</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://ghost.org/images/meta/ghost-docs.png" alt></div></a></figure><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">In publishing and print a <b><strong style="white-space: pre-wrap;">slug</strong></b> is the headline of a news item. For digital publshing this tends to be the title of the page cleaned up to be useable in a URL. In Ghost slugs are used for posts, pages, and authors. </div></div><p>Routes are designed to be modified to your needs whether you self-host Ghost or use a hosted service through Ghost.org. This allows for powerful customisations when it comes to organising and theming your publication. Furthermore while a slug for a post or a page will be auto-generated from a title, you can also modify it yourself when you publish or edit a page. </p><p>As a quirk of how Ghost evaluates routes and resolves conflicts, if a page exists with the same slug as an author bio the page will win out. We will leverage this fact to replace the standard bio with a custom page instead. </p><h2 id="replacing-authors-bio-page">Replacing author&apos;s bio page</h2><p>To prepare first download the current routes.yaml file from your Ghost publication. To do so log in as a publication admin <code>/ghost/</code> URL:</p><p><code>https://example.com/ghost/</code></p><p>Navigate to Settings -&gt; Advanced -&gt; Labs and click Open. <br>Then, select the Beta Features tab. You will then find the option to download - and later upload - the routes file. </p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/01/image.png" class="kg-image" alt="Screenshot from the Ghost Admin page showing open Labs panel" loading="lazy" width="680" height="530" srcset="https://obrien.engineer/content/images/size/w600/2024/01/image.png 600w, https://obrien.engineer/content/images/2024/01/image.png 680w"></figure><p>Click on &quot;Download current routes&quot; link and save the file. Now create a backup copy of the file so that you can go back to the original state if you need to. </p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">You can always go back to the Ghost default either by copying the code above, or by getting an original from <a href="https://ghost.org/docs/themes/routing/?ref=obrien.engineer" rel="noreferrer">Ghost Routes Documentation</a> page</div></div><h3 id="update-the-taxonomy-route-for-authors">Update the taxonomy route for authors </h3><p>We will be replacing the author page with a regular page. The page and post slugs can be changed at the publishing stage, but they can&apos;t contain slashes. As such we will first make sure that the route for authors goes straight to author slug, same as a page. In your routes.yaml file replace the default author taxonomy:</p><p><code>author: /author/{slug}/</code> </p><p>with the following</p><p><code>author: /{slug}/</code></p><p>Upload the modified routes.yaml file in the Labs section of your Ghost Settings. </p><p>Now navigate to an author&apos;s page to validate that the URL is in the correct format:</p><p><code>https://example.com/author-slug</code></p><h3 id="verify-author-slug">Verify author slug</h3><p>By default the author slug for Ghost staff is their first name, but it&apos;s always worth checking. In Ghost Settings page navigate to the Staff section. Hover over the user to see the profile link - it will be &quot;View Profile&quot; if you&apos;re editing your own profile, or &quot;Edit&quot; for other members. </p><p>In the profile section the slug will show on the bottom of the left hand-side column. You can change the slug here if you so wish. Take note of the author slug - you will need this for the next step. <br></p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/01/image-3.png" class="kg-image" alt="Screenshot of the author&apos;s profile showing the slug field" loading="lazy" width="534" height="675"></figure><h3 id="create-a-new-page-with-a-matching-slug">Create a new page with a matching slug</h3><p>Now navigate to Ghost admin page and click on &quot;Pages&quot;. Create a new page with author&apos;s name as title. Ghost will automatically generate a post slug for this page, but it&apos;s not likely to match the author slug. Open the side panel and rewrite the page slug to match the author slug and publish.</p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/01/image-4.png" class="kg-image" alt="Screenshot showing the page editor with page settings panel opened and highlighted slug field" loading="lazy" width="1536" height="277" srcset="https://obrien.engineer/content/images/size/w600/2024/01/image-4.png 600w, https://obrien.engineer/content/images/size/w1000/2024/01/image-4.png 1000w, https://obrien.engineer/content/images/2024/01/image-4.png 1536w" sizes="(min-width: 720px) 720px"></figure><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">Both author slug and post slug can be modified later if needed.</div></div><p>Now navigate to the author&apos;s bio page again and confirm that it has been replaced by your custom page.</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">If you don&apos;t create a page with the same slug as the author, Ghost will fall back to the normal author page. This means you don&apos;t need to worry about having broken pages, and also don&apos;t need to create a custom page for all your authors if you don&apos;t want to.</div></div><h2 id="going-a-step-further">Going a step further</h2><p>The author&apos;s page has now been fully replaced by a regular page, but what if you still want to be able to see all of the author&apos;s posts like with a default author&apos;s page? </p><p>Ghost only loads information on a page depending on a context, so while not entirely impossible it is difficult to show posts by an author in a context of a page. </p><p>However it is entirely possible, using the channel controller, to create a new route that will display author&apos;s posts as if it was the standard author&apos;s bio page. The only problem here is that this needs to be added to routes.yaml file for each author slug and this will not dynamically update. </p><p>The format for this is as follows:</p><pre><code class="language-yaml">routes:

  /author-slug/posts:
    template: author
    data: author.author-slug
    controller: channel
    filter: primary_author:author-slug</code></pre><p>Note here that because the slug is not dynamic here the <code>author-slug</code> needs to be replaced with an actual slug for each staff member. </p><pre><code>routes:
  /tom/posts/:
    template: author
    data: author.tom
    controller: channel
    filter: primary_author:tom
  /jj/posts/:
    template: author
    data: author.jj
    controller: channel
    filter: primary_author:jj

collections:
  /:
    permalink: /{slug}/
    template: index

taxonomies:
  tag: /tag/{slug}/
  author: /{slug}/
</code></pre><p>To make it easy to navigate you can then add a posts button to the author&apos;s bio page: </p><figure class="kg-card kg-image-card"><img src="https://obrien.engineer/content/images/2024/01/image-6.png" class="kg-image" alt="Screenshot from page editing screen showing a button titled &quot;Read JJ&apos;s Articles&quot; with URL &quot;/jj/posts/&quot;" loading="lazy" width="1536" height="277" srcset="https://obrien.engineer/content/images/size/w600/2024/01/image-6.png 600w, https://obrien.engineer/content/images/size/w1000/2024/01/image-6.png 1000w, https://obrien.engineer/content/images/2024/01/image-6.png 1536w" sizes="(min-width: 720px) 720px"></figure><p>That&apos;s it! Now you have a custom author&apos;s page on your ghost publication without losing a taxonomy-like page... and you can make it as long as you wish! </p><p>See this in action for yourself by clicking on the author link in this post or by <a href="https://obrien.engineer/jj/" rel="noreferrer">clicking here</a>.</p><hr><p>Does this seem too bothersome and complicated to do yourself? No problem! <br>Get in touch with us using the button below and we&apos;ll be happy to help you out. </p><div class="kg-card kg-button-card kg-align-center"><a href="https://obrien.engineer/contact" class="kg-btn kg-btn-accent">Get in touch</a></div><hr><h2 id="further-reading">Further reading </h2><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://forum.ghost.org/t/bio-length-for-users/1084?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Bio Length For users</div><div class="kg-bookmark-description">Hello, First time posting. Wondering how we can go about changing the bio length on a self hosted instance? 200 characters is awful short. I seem to remember finding something way back about just changing the value in /current/core/server/data/schema/schema.js, but this doesn&#x2019;t seem to be affecting any change. thanks!</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://global.discourse-cdn.com/business4/uploads/ghost2/optimized/2X/f/f381b3b952df5ad42fe691a8b14aa7f0c96c461a_2_180x180.png" alt><span class="kg-bookmark-author">Ghost Forum</span><span class="kg-bookmark-publisher">DouglasWelcome</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://global.discourse-cdn.com/business4/uploads/ghost2/original/2X/8/8d4e1be1543b3ed506f105953a0d062b84797e42.png" alt></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://forum.ghost.org/t/change-character-length-of-author-bios/11527?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Change character length of author bios</div><div class="kg-bookmark-description">Hi, We need to have longer bios than the 200 char limit, we did used to change this within the ghost.min js file but this doesn&#x2019;t work anymore in the latest version (3.3.0), has this been moved? where do we now change it?</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://global.discourse-cdn.com/business4/uploads/ghost2/optimized/2X/f/f381b3b952df5ad42fe691a8b14aa7f0c96c461a_2_180x180.png" alt><span class="kg-bookmark-author">Ghost Forum</span><span class="kg-bookmark-publisher">Emma_Rayfield</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://global.discourse-cdn.com/business4/uploads/ghost2/original/2X/8/8d4e1be1543b3ed506f105953a0d062b84797e42.png" alt></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://ghost.org/tutorials/change-taxonomy-url/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Change the URL for tags and authors</div><div class="kg-bookmark-description">Transform tags into topics, authors into contributors, or any into any other terms by updating your site&#x2019;s taxonomy.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://ghost.org/favicon.ico" alt><span class="kg-bookmark-author">Tutorials</span><span class="kg-bookmark-publisher">Team Ghost</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://ghost.org/tutorials/content/images/size/w1200/2022/05/change-the-url--1-.jpg" alt></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://ghost.org/docs/themes/routing/?ref=obrien.engineer"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Ghost Themes - Dynamic URLs &amp; Routing</div><div class="kg-bookmark-description">Build dedicated URL structures using Ghost&#x2019;s dynamic routing system, for custom homepages, podcasts, categories and more.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://ghost.org/favicon.ico" alt><span class="kg-bookmark-author">Ghost - The Professional Publishing Platform</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://ghost.org/images/meta/ghost-docs.png" alt></div></a></figure>]]></content:encoded></item></channel></rss>