<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>@Summitt Dweller’s Personal Blog - DigitalOcean</title>
    <link>https://blog.summittdweller.com/tags/digitalocean/</link>
    <description>All entries in DigitalOcean on Personal Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    
    <lastBuildDate>Mon, 12 Jun 2023 19:30:18 +0000</lastBuildDate>
    <atom:link href="https://blog.summittdweller.com/tags/digitalocean/" rel="self" type="application/rss+xml" />
    
      
      <item>
        <title>Upgrading Matomo PHP</title>
        <link>https://blog.summittdweller.com/posts/2023/06/upgrading-matomo-php/</link>
        <pubDate>Mon, 12 Jun 2023 19:30:18 +0000</pubDate>
        <author>Mark McFate</author>
        <guid>https://blog.summittdweller.com/posts/2023/06/upgrading-matomo-php/</guid>
        <description>&lt;p&gt;This afternoon I&amp;rsquo;m adding &lt;code&gt;https://digital.grinnell.edu&lt;/code&gt; (site ID is 17) to my own Matomo instance and I&amp;rsquo;m prompted to upgrade PHP on that Matomo droplet (DigitalOcean).  I did so quite easily following &lt;a href=&#34;https://www.digitalocean.com/community/questions/upgrade-php-from-7-2-to-7-4-on-centos-8-and-apache&#34;&gt;Upgrade PHP from 7.2 to 7.4 on CentOS 8 and Apache&lt;/a&gt;.  I&amp;rsquo;ve also updated my Drupal version, and some modules, in &lt;a href=&#34;https://digital.grinnell.edu&#34;&gt;https://digital.grinnell.edu&lt;/a&gt; along with adding the &lt;code&gt;matomo&lt;/code&gt; module, but that module is now reporting:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    The validation of &amp;quot;http://analytics.summittservices.com/matomo.php&amp;quot; failed with error &amp;quot;Error opening socket ssl://analytics.summittservices.com:443&amp;quot; (HTTP code 0).
    The validation of &amp;quot;https://analytics.summittservices.com/matomo.php&amp;quot; failed with error &amp;quot;Error opening socket ssl://analytics.summittservices.com:443&amp;quot; (HTTP code 0).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hmmm&amp;hellip;wonder what&amp;rsquo;s up with that?&lt;/p&gt;
&lt;p&gt;So, I tried this&amp;hellip;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Last login: Mon Jun 12 19:21:45 2023 from 162.243.190.66
[root@centos-s-1vcpu-1gb-nyc1-01 ~]# sudo certbot renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/summittservices.com-0001.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Renewing an existing certificate for summittservices.com and analytics.summittservices.com
Reloading nginx server after certificate renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/summittservices.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Renewing an existing certificate for summittservices.com and www.summittservices.com
Reloading nginx server after certificate renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all renewals succeeded: 
  /etc/letsencrypt/live/summittservices.com-0001/fullchain.pem (success)
  /etc/letsencrypt/live/summittservices.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;hellip;and&amp;hellip; NO more validation errors!  Yay!&lt;/p&gt;
</description>
      </item>
      
    
      
      <item>
        <title>Wrap EVERYTHING in NPM!</title>
        <link>https://blog.summittdweller.com/posts/2023/05/wrap-everything-in-npm/</link>
        <pubDate>Fri, 19 May 2023 22:27:00 +0000</pubDate>
        <author>Mark McFate</author>
        <guid>https://blog.summittdweller.com/posts/2023/05/wrap-everything-in-npm/</guid>
        <description>&lt;p&gt;So, &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; seem to be all the rage these days, and perhaps for good reason.  I recently fell in love with &lt;a href=&#34;https://www.11ty.dev&#34;&gt;Eleventy/11ty&lt;/a&gt; over &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt; because it&amp;rsquo;s Javascript, not Go, and it&amp;rsquo;s elegantly simple with tons of flexibility.  I recently tried to add &lt;em&gt;Pagefind&lt;/em&gt; search to a Hugo static web site (see &lt;a href=&#34;https://static.grinnell.edu/dlad-blog/posts/143-significant-rootstalk-retooling/&#34;&gt;https://static.grinnell.edu/dlad-blog/posts/143-significant-rootstalk-retooling/&lt;/a&gt;).  If &lt;em&gt;Rootstalk&lt;/em&gt;, an Azure Static Web App was framed in &lt;code&gt;node.js&lt;/code&gt;, as both &lt;em&gt;Eleventy&lt;/em&gt; and &lt;em&gt;Pagefind&lt;/em&gt; are, there would be no problem.  The Azure scripts used to deploy those frameworks are far more customizable than Hugo, and there&amp;rsquo;s documentation to prove it.&lt;/p&gt;
&lt;p&gt;So, how might I approach combining Hugo with Pagefind in the cloud?  Well, &lt;a href=&#34;https://web.archive.org/web/20220818082611/https://www.blogtrack.io/blog/powerful-blog-setup-with-hugo-and-npm/&#34;&gt;A Powerful Blog Setup with Hugo and NPM&lt;/a&gt;* by Tom Hombergs looked like a promising place to start.  The process that Tom advocates leverages a neat little package called &lt;a href=&#34;https://www.npmjs.com/package/hugo-bin&#34;&gt;hugo-bin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;*&lt;em&gt;The links provided above and below are to a Wayback Machine capture of the original post.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;that-was-too-easy&#34;&gt;That Was Too Easy!&lt;/h1&gt;
&lt;p&gt;Wrapping my Hugo site in an NPM package was so easy that I forgot to document it&amp;hellip; and maybe I really didn&amp;rsquo;t need too.  Time to catch up, so here&amp;rsquo;s a brief sysnopsis of what I did&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;following-toms-excellent-advice&#34;&gt;Following Tom&amp;rsquo;s Excellent Advice&lt;/h2&gt;
&lt;p&gt;I started by studying &lt;a href=&#34;https://web.archive.org/web/20220818082611/https://www.blogtrack.io/blog/powerful-blog-setup-with-hugo-and-npm/&#34;&gt;A Powerful Blog Setup with Hugo and NPM&lt;/a&gt; and quickly found that I could easily follow it almost verbatim.  Since I already had &lt;code&gt;npm&lt;/code&gt; and &lt;code&gt;Hugo&lt;/code&gt; installed I skipped ahead to the section titled &amp;ldquo;Setting Up a Hugo Project&amp;rdquo; and then to the &lt;code&gt;npx&lt;/code&gt; and &lt;code&gt;git&lt;/code&gt; commands there.  My experience, mostly in commands, looked like this on my Mac Mini workstation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd ~/GitHub/
# Named the new project npm-rootstalk so it would not confilct with any of my existing `rootstalk...` directories
mkdir npm-rootstalk      
cd npm-rootstalk
npx hugo new site . --force
# Copied the contents of my old project into the new one and then removed whatever I no longer needed
cp -fr ~/GitHub/rootstalk/. .  
# Installed Pagefind...
npm install pagefind
git init
# I created a new empty repo in GitHub called npm-rootstalk, then...
git remote add origin https://github.com/Digital-Grinnell/npm-rootstalk 
git add . 
git commit -m &amp;quot;Initial commit of new npm-wrapped Hugo project&amp;quot;
git push
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Having secured a new repo I moved to running Hugo locally, then polishing my &lt;code&gt;package.json&lt;/code&gt; scripts as Tom did.  I now have a &lt;code&gt;package.json&lt;/code&gt; that reads like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;npm-rootstalk&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;1.0.0&amp;quot;,
  &amp;quot;description&amp;quot;: &amp;quot;Rootstalk website built with Hugo and the Lightbi theme inside an NPM package.  May 2023.&amp;quot;,
  &amp;quot;main&amp;quot;: &amp;quot;index.js&amp;quot;,
  &amp;quot;scripts&amp;quot;: {
    &amp;quot;test&amp;quot;: &amp;quot;echo \&amp;quot;Error: no test specified\&amp;quot; &amp;amp;&amp;amp; exit 1&amp;quot;,
    &amp;quot;build&amp;quot;: &amp;quot;npm run hugo:build &amp;amp;&amp;amp; npx pagefind --source public&amp;quot;,
    &amp;quot;do:build&amp;quot;: &amp;quot;hugo -d public &amp;amp;&amp;amp; npx pagefind --source public&amp;quot;,
    &amp;quot;azure:build&amp;quot;: &amp;quot;hugo -d public --baseURL=\&amp;quot;https://yellow-wave-0e513e510.3.azurestaticapps.net/\&amp;quot; &amp;amp;&amp;amp; npx pagefind --source public&amp;quot;,
    &amp;quot;clean&amp;quot;: &amp;quot;npm run hugo:clean&amp;quot;,
    &amp;quot;serve&amp;quot;: &amp;quot;npm run hugo:build &amp;amp;&amp;amp; npx pagefind --source public --bundle-dir ../static/_pagefind &amp;amp;&amp;amp; npm run hugo:serve&amp;quot;,
    &amp;quot;hugo:build&amp;quot;: &amp;quot;hugo -d public&amp;quot;,
    &amp;quot;hugo:serve&amp;quot;: &amp;quot;hugo server&amp;quot;,
    &amp;quot;hugo:clean&amp;quot;: &amp;quot;rm -rf build resources public&amp;quot;
  },
  &amp;quot;author&amp;quot;: &amp;quot;Mark A. McFate&amp;quot;,
  &amp;quot;license&amp;quot;: &amp;quot;ISC&amp;quot;,
  &amp;quot;dependencies&amp;quot;: {
    &amp;quot;hugo-bin&amp;quot;: &amp;quot;^0.102.0&amp;quot;,
    &amp;quot;pagefind&amp;quot;: &amp;quot;^0.12.0&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;it-works&#34;&gt;It Works!&lt;/h1&gt;
&lt;p&gt;Now I just use &lt;code&gt;npm run serve&lt;/code&gt; to build the Hugo site, index it with Pagefind, and serve it locally at &lt;a href=&#34;http://localhost:1313&#34;&gt;http://localhost:1313&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;a-staging-site-in-azure&#34;&gt;A Staging Site in Azure&lt;/h1&gt;
&lt;p&gt;I can simply push changes to the &lt;code&gt;main&lt;/code&gt; branch of the &lt;code&gt;npm-rootstalk&lt;/code&gt; repo to trigger an Azure (aka GitHub Actions) rebuild, indexing and deployment of the site to &lt;a href=&#34;https://yellow-wave-0e513e510.3.azurestaticapps.net/&#34;&gt;this address&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;a-new-production-branch&#34;&gt;A New Production Branch&lt;/h1&gt;
&lt;p&gt;Pushing to production is just as simple, I just have to push changes to the new &lt;code&gt;production&lt;/code&gt; branch of the code and my app spec at DigitalOcean (see below) takes care of building, indexing, and deploying to &lt;a href=&#34;https://rootstalk.grinnell.edu&#34;&gt;https://rootstalk.grinnell.edu&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That DO app spec reads like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alerts:
- rule: DEPLOYMENT_FAILED
- rule: DOMAIN_FAILED
domains:
- domain: rootstalk.grinnell.edu
  type: PRIMARY
- domain: prairiejournal.grinnell.edu
  type: ALIAS
envs:
- key: TZ
  scope: RUN_AND_BUILD_TIME
  value: America/Chicago
- key: HUGO_MATOMO_ID
  scope: RUN_AND_BUILD_TIME
  value: &amp;quot;15&amp;quot;
ingress:
  rules:
  - component:
      name: npm-rootstalk
    match:
      path:
        prefix: /
name: npm-rootstalk
region: nyc
static_sites:
- build_command: npm run build
  environment_slug: node-js
  github:
    branch: production
    deploy_on_push: true
    repo: Digital-Grinnell/npm-rootstalk
  name: npm-rootstalk
  source_dir: /
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;p&gt;It&amp;rsquo;s heavenly!  And that&amp;rsquo;s all for now.&lt;/p&gt;
</description>
      </item>
      
    
      
      <item>
        <title>A Pagefind Problem?</title>
        <link>https://blog.summittdweller.com/posts/2023/05/a-pagefind-problem/</link>
        <pubDate>Wed, 10 May 2023 14:33:09 +0000</pubDate>
        <author>Mark McFate</author>
        <guid>https://blog.summittdweller.com/posts/2023/05/a-pagefind-problem/</guid>
        <description>&lt;h1 id=&#34;not-just-a-hugo-issue&#34;&gt;Not Just a Hugo Issue&lt;/h1&gt;
&lt;p&gt;Take note of the question mark at the end of the title, otherwise it could be somewhat misleading.  This is not really a problem with Hugo, but one with cloud deployment of Hugo static apps, particularly as an Azure Static Web App.&lt;/p&gt;
&lt;h1 id=&#34;the-nutshell&#34;&gt;The Nutshell&lt;/h1&gt;
&lt;p&gt;As you may know from &lt;a href=&#34;https://static.grinnell.edu/dlad-blog/posts/143-significant-rootstalk-retooling/&#34;&gt;post 143&lt;/a&gt;, I have successfully installed and configured &lt;a href=&#34;https://pagefind.app/&#34;&gt;Pagefind&lt;/a&gt; in &lt;a href=&#34;https://rootstalk.grinnell.edu&#34;&gt;Rootstalk&lt;/a&gt;, but thus far it only works locally.  When I try to deploy Pagefind to the cloud, specifically as an Azure Static Web App, I can&amp;rsquo;t make it work because there&amp;rsquo;s no apparent way to invoke the necessary &lt;code&gt;npx pagefind...&lt;/code&gt; command AFTER Hugo compiles the site, but BEFORE the site gets deployed.  Azure leverages GitHub Actions to build Hugo sites, but that process also involves some custom/proprietary Azure scripts.  Therein lies the problem.&lt;/p&gt;
&lt;p&gt;The Azure script auto-detects the presence of a Hugo project, or any one of many other platforms.  That makes the process super-easy to use, but nearly impossible to &amp;ldquo;customize&amp;rdquo;.  Azure does provide some configuration variables to influence the script behavior, most notably there&amp;rsquo;s an &lt;code&gt;app_build_command&lt;/code&gt; variable that looks promising, but it only works for &lt;code&gt;node&lt;/code&gt; builds, and not for Hugo.&lt;/p&gt;
&lt;h1 id=&#34;three-possible-solutions&#34;&gt;Three Possible Solutions&lt;/h1&gt;
&lt;p&gt;I can reasonably see three possible solutions to this dilema.  In order of simplicity they are:&lt;/p&gt;
&lt;h2 id=&#34;1-skip-azure-and-deploy-only-to-digitalocean&#34;&gt;1. Skip Azure and Deploy Only to DigitalOcean&lt;/h2&gt;
&lt;p&gt;Ultimately, Rootstalk&amp;rsquo;s production instance is a DigitalOcean (DO) static web app, Azure is only used for &amp;ldquo;staging&amp;rdquo; of a locally viable Rootstalk instance.  DO doesn&amp;rsquo;t use GitHub Actions, a drawback in my book, so its build script, called an &amp;ldquo;App Spec&amp;rdquo; in DO, is a little more &amp;ldquo;open&amp;rdquo;.  The critical portion of the App Spec I use to deploy Rootstalk in DO reads like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;static_sites:
- build_command: hugo -d public
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s it, just a simple &lt;code&gt;hugo -d public&lt;/code&gt; command.  So, in theory I should be able to just change that to read:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;static_sites:
- build_command: hugo -d public &amp;amp;&amp;amp; npm_config_yes=true npx pagefind --source &amp;quot;public&amp;quot; --bundle-dir ../static/_pagefind
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&amp;rsquo;s basically just a &amp;ldquo;compound&amp;rdquo; command to run &lt;code&gt;npx&lt;/code&gt; immediately after &lt;code&gt;hugo&lt;/code&gt; is done compiling.&lt;/p&gt;
&lt;p&gt;The problem with this very simple solution, assuming it even works, is that it&amp;rsquo;s somewhat unique to Rootstalk which is already deployed to DigitalOcean.  Other Hugo projects, and I have many like &lt;a href=&#34;https://static.grinnell.edu/dlad-blog&#34;&gt;this blog&lt;/a&gt;, that need Azure or another cloud provider other than DO, would not benefit from this fix.&lt;/p&gt;
&lt;h3 id=&#34;update-12-may-2023-same-problem-exists-in-digitalocean&#34;&gt;Update 12-May-2023: Same Problem Exists in DigitalOcean&lt;/h3&gt;
&lt;p&gt;Well, I tried.  I attempted to push my Pagefind additions to Rootstalk forward directly into production on DigitalOcean.  Unfortunately, that failed in similar fashion to what I saw in Azure.  It all works locally, but DigitalOcean, like Azure, has no way of &amp;ldquo;detecting&amp;rdquo; that my Hugo project has an NPM component, and therefore takes no steps to build NPM or Pagefind into my solution.&lt;/p&gt;
&lt;p&gt;So, I&amp;rsquo;m moving on to option #2 below.  Wish me luck.&lt;/p&gt;
&lt;h2 id=&#34;2-wrap-hugo-in-npm&#34;&gt;2. Wrap Hugo in &lt;code&gt;npm&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;So, &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; seem to be all the rage these days, and perhaps for good reason.  I recently fell in love with &lt;a href=&#34;https://www.11ty.dev&#34;&gt;Eleventy/11ty&lt;/a&gt; because it&amp;rsquo;s Javascript, not Go, and it&amp;rsquo;s elegantly simple with tons of flexibility.  If my Azure Static Web App was framed in &lt;code&gt;node.js&lt;/code&gt;, as both &lt;em&gt;Eleventy&lt;/em&gt; and &lt;em&gt;Pagefind&lt;/em&gt; are, there would be no problem.  The Azure scripts used to deploy those frameworks are far more customizable than Hugo, and there&amp;rsquo;s documentation to prove it.&lt;/p&gt;
&lt;p&gt;So, how might I approach something like this?  Well, &lt;a href=&#34;https://www.blogtrack.io/blog/powerful-blog-setup-with-hugo-and-npm/&#34;&gt;A Powerful Blog Setup with Hugo and NPM&lt;/a&gt; by Tom Hombergs looks like a promising place to start.  The process that Tom advocates leverages a neat little package called &lt;a href=&#34;https://www.npmjs.com/package/hugo-bin&#34;&gt;hugo-bin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If strategy #1 fails I&amp;rsquo;ll certainly give this #2 a try.  Even if #1 works, I might give this strategy a spin if/when I re-tool &lt;a href=&#34;https://static.grinnell.edu/dlad-blog&#34;&gt;this blog&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;update-29-may-2023-npm-is-great&#34;&gt;Update 29-May-2023: NPM is GREAT!&lt;/h2&gt;
&lt;p&gt;Since my first option (above) failed very quickly, I moved on to this option and I honestly think I might transition every static site that I have to be wrapped inside NPM, it works wonderfully and is a really attractive solution for so many ills!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to document my experience with NPM wrapped around Hugo and will post that document here soon, probably as &lt;a href=&#34;https://blog.summittdweller.com/wrap-everything-in-npm/&#34;&gt;Wrap EVERYTHING in NPM!&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;3-transition-from-hugo-to-eleventy&#34;&gt;3. Transition from Hugo to Eleventy&lt;/h2&gt;
&lt;p&gt;Reasonable?  Yes.  A lot of work?  That&amp;rsquo;s relative.  The right thing to do?  Probably.&lt;/p&gt;
&lt;p&gt;So, it&amp;rsquo;s already been done, see &lt;a href=&#34;https://blog.summittdweller.com/this-blog-in-eleventy-ghost/&#34;&gt;This Blog in Eleventy + Ghost&lt;/a&gt; and &lt;a href=&#34;https://blog.summittdweller.com/glad-i-found-pagefind/&#34;&gt;Searching for a Search Solution&lt;/a&gt;.  That&amp;rsquo;s all I&amp;rsquo;m going to say about this option, a definite maybe.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;That&amp;rsquo;s all folks&amp;hellip; for now.&lt;/p&gt;
</description>
      </item>
      
    
      
      <item>
        <title>Wrapping Hugo in NPM</title>
        <link>https://blog.summittdweller.com/microposts/2023/05/wrapping-hugo-in-npm/</link>
        <pubDate>Tue, 09 May 2023 23:13:09 +0000</pubDate>
        <author>Mark McFate</author>
        <guid>https://blog.summittdweller.com/microposts/2023/05/wrapping-hugo-in-npm/</guid>
        <description>&lt;p&gt;I ran into a big road block with implementation of Pagefind in &lt;em&gt;Rootstalk&lt;/em&gt; today&amp;hellip; everything works fine in development, but I can&amp;rsquo;t easily deploy to &lt;em&gt;Azure&lt;/em&gt; because there&amp;rsquo;s no way to &amp;ldquo;inject&amp;rdquo; Pagefind into an Azure Static Web App build before the &amp;ldquo;public&amp;rdquo; content gets deployed.  I can generate the Pagefind parts after deployment, but that does me no good.&lt;/p&gt;
&lt;p&gt;Tomorrow I need to have a look at my &lt;em&gt;Rootstalk&lt;/em&gt; DigitalOcean deployment to see if what I already have might work there (DO uses a build script that I can add an &lt;code&gt;npx...&lt;/code&gt; command to).  If that fails I need to look back at &lt;a href=&#34;https://www.blogtrack.io/blog/powerful-blog-setup-with-hugo-and-npm/&#34;&gt;https://www.blogtrack.io/blog/powerful-blog-setup-with-hugo-and-npm/&lt;/a&gt; to see if there&amp;rsquo;s a solution there for me.&lt;/p&gt;
&lt;p&gt;-/-/-/&lt;/p&gt;
&lt;p&gt;location: Toledo, IA&lt;/p&gt;
</description>
      </item>
      
    
      
      <item>
        <title>Searching for a Search Solution</title>
        <link>https://blog.summittdweller.com/posts/2023/04/glad-i-found-pagefind/</link>
        <pubDate>Thu, 20 Apr 2023 17:02:00 +0000</pubDate>
        <author>Mark McFate</author>
        <guid>https://blog.summittdweller.com/posts/2023/04/glad-i-found-pagefind/</guid>
        <description>&lt;p&gt;A few months ago I sat in on a &lt;a href=&#34;https://cfe.dev/sessions/static-search-with-pagefind/&#34;&gt;CFE.dev webinar&lt;/a&gt; and I was really impressed with what I saw.  I made a note to come back and look closer at &lt;a href=&#34;https://pagefind.app/&#34;&gt;Pagefind&lt;/a&gt;, and my new blog &amp;ndash; this blog that you&amp;rsquo;re presumably reading right now &amp;ndash; really needed a search feature, so the &amp;ldquo;Search&amp;rdquo; box on this page (I hope it&amp;rsquo;s there) is the outcome.&lt;/p&gt;
&lt;h2 id=&#34;glad-i-found-pagefind&#34;&gt;Glad I Found Pagefind&lt;/h2&gt;
&lt;p&gt;So, I started looking closely at search options and considered things like &lt;a href=&#34;https://lunrjs.com/&#34;&gt;Lunr&lt;/a&gt;, which I&amp;rsquo;ve used before, and &lt;a href=&#34;https://solr.apache.org/&#34;&gt;Solr&lt;/a&gt;, which I both love and hate (because of its JAVA roots).  Pagefind was, of course, also on that short list and it quickly solidified its position at the top of the list when I found &lt;a href=&#34;https://mikefallows.com/posts/adding-search-to-eleventy-site/&#34;&gt;Adding search to an Eleventy site&lt;/a&gt; by &lt;a href=&#34;https://mikefallows.com/about/&#34;&gt;Mike&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mike doesn&amp;rsquo;t explain the setup in detail, but this comment really resonated with me so I decided to follow the same path:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Weirdly, I&amp;rsquo;ve found that I seem to read the posts on this site more than I write them. I say read, but I just mean referring to the stuff I&amp;rsquo;ve written because it has left my head.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Mike does provide a link to the reference he used, namely &lt;a href=&#34;https://rknight.me/using-pagefind-with-eleventy-for-search/&#34;&gt;Using PageFind with Eleventy for Search&lt;/a&gt; by &lt;a href=&#34;https://rknight.me/&#34;&gt;Robb Knight&lt;/a&gt;.  I found Robb&amp;rsquo;s guidance and experience to be VERY helpful.  Thank you, Robb!&lt;/p&gt;
&lt;h2 id=&#34;implementing-robbs-approach&#34;&gt;Implementing Robb&amp;rsquo;s Approach&lt;/h2&gt;
&lt;p&gt;I won&amp;rsquo;t bother duplicating what Robb explains quite well, but this wasn&amp;rsquo;t a 10-minute solution for me, probably because I&amp;rsquo;m really still learning &lt;em&gt;Javascript&lt;/em&gt; and &lt;em&gt;Eleventy&lt;/em&gt;, and also because I&amp;rsquo;m using a &lt;em&gt;Ghost&lt;/em&gt; back-end with packages managed via &lt;em&gt;Yarn&lt;/em&gt; rather than &lt;em&gt;npm&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So, in the few sections that follow I&amp;rsquo;ll try to briefly described what&amp;rsquo;s different about my approach versus Robb&amp;rsquo;s, along with what didn&amp;rsquo;t, and what ultimately did work.&lt;/p&gt;
&lt;h2 id=&#34;yarn-not-npm&#34;&gt;&lt;code&gt;yarn&lt;/code&gt;, Not &lt;code&gt;npm&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The first significant difference I encountered was the requirement that this blog project uses &lt;code&gt;yarn&lt;/code&gt;, not &lt;code&gt;npm&lt;/code&gt; for package management.  Eventually I found that I just needed to replace Robb&amp;rsquo;s &lt;code&gt;npm install pagefind&lt;/code&gt; command with a &lt;code&gt;yarn add pagefind&lt;/code&gt; equivalent.  I don&amp;rsquo;t really understand the details of that difference, but it worked.&lt;/p&gt;
&lt;h2 id=&#34;eleventyafter-never-fires&#34;&gt;eleventy.after Never Fires?&lt;/h2&gt;
&lt;p&gt;The biggest hurdle for me was trying to get this bit of Robb&amp;rsquo;s code to work.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const { execSync } = require(&#39;child_process&#39;)

module.exports = function(eleventyConfig) {
  eleventyConfig.on(&#39;eleventy.after&#39;, () =&amp;gt; {
    execSync(`npx pagefind --source _site --glob \&amp;quot;**/*.html\&amp;quot;`, { encoding: &#39;utf-8&#39; })
  })
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my case the &lt;code&gt;--source&lt;/code&gt; parameter needed to be &lt;code&gt;dist&lt;/code&gt; since this blog is generated into a directory by that name, and my configuration object is simply &lt;code&gt;config&lt;/code&gt; rather than &lt;code&gt;eleventyConfig&lt;/code&gt;.  I made those simple changes and added my snippet to the &lt;code&gt;.eleventy.js&lt;/code&gt; file, but found that it never triggered.  I even replaced the &lt;code&gt;execSync&lt;/code&gt; function call with a simple &lt;code&gt;console.log&lt;/code&gt; statement and still got nothing.  And still to this day, I have no idea why that didn&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;That snippet of code is supposed to be responsible for indexing all of the &lt;code&gt;.html&lt;/code&gt; files after &lt;em&gt;Eleventy&lt;/em&gt; has generated them.  Well, I found out that everything else was working properly, but the &lt;code&gt;_pagefind&lt;/code&gt; bundle generated by that indexing operation was just &amp;ldquo;missing&amp;rdquo;, since the index never was created.  That made me wonder what would happen if I &amp;ldquo;forced&amp;rdquo; the system to index my content in a different manner&amp;hellip;and that wonder ultimately worked.&lt;/p&gt;
&lt;h2 id=&#34;using-npx-pagefind-to-index-content&#34;&gt;Using &lt;code&gt;npx pagefind...&lt;/code&gt; to Index Content&lt;/h2&gt;
&lt;p&gt;Having studied some of the &lt;a href=&#34;https://pagefind.app/docs/&#34;&gt;Pagefind documentation&lt;/a&gt; I wondered what adding some post-processing to my build workflow might do, something like &lt;code&gt;npx pagefind --source dist&lt;/code&gt;?  That ultimately worked, but not in that original form.&lt;/p&gt;
&lt;p&gt;I found that when I ran &lt;code&gt;yarn start&lt;/code&gt; to locally rebuild the site, there was no generated &lt;code&gt;./dist/_pagefind&lt;/code&gt; bundle present, so I got no &amp;ldquo;Search&amp;rdquo; user interface elements, but there was an empty &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; where that belonged.  So, with my localhost instance still running I opened a new terminal and ran &lt;code&gt;npx pagefind --source dist&lt;/code&gt; in the project directory. Voila! The &lt;code&gt;./dist/_pagefind&lt;/code&gt; bundle magically appeared and the &amp;ldquo;Search&amp;rdquo; control was instantly visible in my localhost window!  It was working, and it was beautiful.&lt;/p&gt;
&lt;h2 id=&#34;added-a-pagefind-script-didnt-work&#34;&gt;Added a &lt;code&gt;pagefind&lt;/code&gt; Script&amp;hellip; Didn&amp;rsquo;t Work&lt;/h2&gt;
&lt;p&gt;Ok, with the above breakthrough in-hand I made this addition to the &lt;code&gt;scripts:&lt;/code&gt; key in my &lt;code&gt;package.json&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  &amp;quot;pagefind&amp;quot;: &amp;quot;npx pagefind --source dist&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then I added the following to the end of my &lt;code&gt;steps:&lt;/code&gt; key in &lt;code&gt;.github/workflows/build-and-deploy.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  - run: yarn pagefind
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This worked to some extent, but wasn&amp;rsquo;t reliable and absolutely didn&amp;rsquo;t work when deployed to my &lt;em&gt;DigitalOcean&lt;/em&gt; app.  The inner-workings of &lt;code&gt;yarn&lt;/code&gt; and build caching in these environments is still a DEEP mystery to me!&lt;/p&gt;
&lt;h2 id=&#34;extending-my-encrypt-script&#34;&gt;Extending My &lt;code&gt;encrypt&lt;/code&gt; Script&lt;/h2&gt;
&lt;p&gt;What does work, both locally and on &lt;em&gt;DigitalOcean&lt;/em&gt;, is essentially an &amp;ldquo;extension&amp;rdquo; of my old &lt;code&gt;encrypt&lt;/code&gt; script.  My old build workflow included these two elements of &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;build-and-deploy.yml&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &amp;quot;encrypt&amp;quot;: &amp;quot;staticrypt ./dist/rebuild.html &#39;***hidden***&#39; --short -o ./dist/rebuild.html -f ./src/auth/login.html -t &#39;Summitt Dweller Blog - Rebuild&#39; -i &#39;Please enter the passphrase.&amp;lt;br/&amp;gt;Hint: gh0st&#39; --label-error &#39;Sorry, Ella says no. Try again.&#39;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;hellip;and&amp;hellip;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  - run: yarn encrypt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I took note of the relative path spec for &lt;code&gt;./dist/rebuild.html&lt;/code&gt; in the &lt;code&gt;encrypt&lt;/code&gt; command, reasoned that I should run &lt;code&gt;pagefind&lt;/code&gt; in a similar fashion &amp;ndash; but just before encryption &amp;ndash; and came up with this change in &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &amp;quot;encrypt&amp;quot;: &amp;quot;npx pagefind --source ./dist &amp;amp;&amp;amp; staticrypt ./dist/rebuild.html &#39;***hidden***&#39; --short -o ./dist/rebuild.html -f ./src/auth/login.html -t &#39;Summitt Dweller Blog - Rebuild&#39; -i &#39;Please enter the passphrase.&amp;lt;br/&amp;gt;Hint: gh0st&#39; --label-error &#39;Sorry, Ella says no. Try again.&#39;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;It works!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When I&amp;rsquo;m running locally my &lt;code&gt;build-and-deploy.yml&lt;/code&gt; doesn&amp;rsquo;t apply so in that case I typically will do this IF I want my search index (and encryption) updated:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn start
yarn encrypt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When I rebuild in production on &lt;em&gt;DigitalOcean&lt;/em&gt; my &lt;code&gt;build-and-deploy.yml&lt;/code&gt; configuration IS run so including &lt;code&gt;npx pagefind...&lt;/code&gt; as part of the &lt;code&gt;yarn encrypt&lt;/code&gt; step does the trick.&lt;/p&gt;
&lt;h2 id=&#34;time-to-test&#34;&gt;Time to Test&amp;hellip;&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m going to save this post now and rebuild this blog on &lt;em&gt;DigitalOcean&lt;/em&gt;, where with any luck, a search for a term like &amp;ldquo;DEEP&amp;rdquo; should return this post, and maybe one or two others.  Drum roll please&amp;hellip;  &lt;strong&gt;Huzzah!&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;man-do-i-feel-stupid&#34;&gt;Man, Do I Feel Stupid&lt;/h2&gt;
&lt;p&gt;Previously I mentioned that my additon of a &lt;code&gt;package.json&lt;/code&gt; script named &lt;code&gt;pagefind&lt;/code&gt; didn&amp;rsquo;t work, and that my &lt;em&gt;DigitalOcean&lt;/em&gt; builds kept trying to do &lt;code&gt;yarn encrypt&lt;/code&gt; after &lt;code&gt;yarn build&lt;/code&gt;.  Well, turns out that&amp;rsquo;s because &lt;code&gt;build-and-deploy.yml&lt;/code&gt;, where I had inserted the &lt;code&gt;yarn pagefind&lt;/code&gt; step IS NOT in control of building my &lt;em&gt;DigitalOcean&lt;/em&gt; app.  In fact, it&amp;rsquo;s a &lt;code&gt;.github&lt;/code&gt; workflow so I&amp;rsquo;m really not sure what role that file plays, if any?&lt;/p&gt;
&lt;p&gt;I went looking in my &lt;em&gt;DigitalOcean&lt;/em&gt; app configuration settings for &lt;code&gt;yarn encrypt&lt;/code&gt; and found it, in the app&amp;rsquo;s &amp;ldquo;App Settings&amp;rdquo; subsection titled &amp;ldquo;App Spec&amp;rdquo;.  When I view that &amp;ldquo;App Spec&amp;rdquo; I see this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alerts:
- rule: DEPLOYMENT_FAILED
- rule: DOMAIN_FAILED
domains:
- domain: blog.summittdweller.com
  type: PRIMARY
  zone: summittdweller.com
envs:
- key: TZ
  scope: RUN_AND_BUILD_TIME
  value: America/Chicago
name: blog-summittdweller-11ty-ghost
region: nyc
static_sites:
- build_command: |-
    yarn build
    yarn encrypt
  environment_slug: node-js
  github:
    branch: main
    deploy_on_push: true
    repo: SummittDweller/blog-eleventy-ghost
  name: blog-eleventy-ghost
  output_dir: dist
  routes:
  - path: /
  source_dir: /
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the two &lt;code&gt;build_command:&lt;/code&gt; elements.  Let&amp;rsquo;s change those two steps to three, like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- build_command: |-
    yarn build
    yarn pagefind
    yarn encrypt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that I captured the &amp;ldquo;App Spec&amp;rdquo; in a file named &lt;code&gt;blog-summittdweller-11ty-ghost.yaml&lt;/code&gt; and I&amp;rsquo;ve saved that file in the project directory (where I hope it will do no harm).  &lt;strong&gt;Attention: After making the aforementioned addition I almost forgot to upload this file back to &lt;em&gt;DigitalOcean&lt;/em&gt; to replace our existing App Spec!&lt;/strong&gt;  Don&amp;rsquo;t be stupid like me!&lt;/p&gt;
&lt;p&gt;Next, I needed a corresponding change in &lt;code&gt;package.json&lt;/code&gt;, specifically these two lines (like I had them before, duh):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  &amp;quot;pagefind&amp;quot;: &amp;quot;npx pagefind --source ./dist&amp;quot;,
  &amp;quot;encrypt&amp;quot;: &amp;quot;staticrypt ./dist/rebuild.html &#39;***hidden***&#39; --short -o ./dist/rebuild.html -f ./src/auth/login.html -t &#39;Summitt Dweller Blog - Rebuild&#39; -i &#39;Please enter the passphrase.&amp;lt;br/&amp;gt;Hint: gh0st&#39; --label-error &#39;Sorry, Ella says no. Try again.&#39;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;push-to-rebuild&#34;&gt;Push to Rebuild&lt;/h2&gt;
&lt;p&gt;Ok, having modified &lt;strong&gt;and UPLOADED&lt;/strong&gt;&lt;code&gt;blog-summittdweller-11ty-ghost.yaml&lt;/code&gt;, and having modified &lt;code&gt;package.json&lt;/code&gt;, it came time to commit and push all my changes to see what happens.  Another drum roll, please&amp;hellip;&lt;/p&gt;
</description>
      </item>
      
    
      
      <item>
        <title>Engaging `s3cmd` to Download and Resize Images from DO Spaces</title>
        <link>https://blog.summittdweller.com/posts/2023/04/engaging-s3cmd-to-download-and-resize-images-from-do-spaces/</link>
        <pubDate>Sun, 16 Apr 2023 14:57:16 +0000</pubDate>
        <author>Mark McFate</author>
        <guid>https://blog.summittdweller.com/posts/2023/04/engaging-s3cmd-to-download-and-resize-images-from-do-spaces/</guid>
        <description>&lt;p&gt;Earlier in this blog there&amp;rsquo;s a &lt;code&gt;micropost&lt;/code&gt; that lays out the problem at hand.  In a nutshell, most of the photos I saved in &lt;em&gt;DigitalOcean Spaces&lt;/em&gt; are too big to be effective in this blog.  They suck up lots of time and bandwidth every time this blog gets rebuilt, and then they are rendered at a fraction of their original size. This is exceptionall wasteful and unnecessary.&lt;/p&gt;
&lt;p&gt;So, my task this morning is to install, configure, and engage the &lt;a href=&#34;https://s3tools.org/s3cmd&#34;&gt;s3cmd&lt;/a&gt; tools to help get this done.  There&amp;rsquo;s &lt;em&gt;DigitalOcean&lt;/em&gt;-specific guidance provided in &lt;a href=&#34;https://docs.digitalocean.com/products/spaces/reference/s3cmd/&#34;&gt;Setting Up s3cmd 2.x with DigitalOcean Spaces&lt;/a&gt; so that&amp;rsquo;s where I will begin.  Here goes&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;installing-s3cmd&#34;&gt;Installing &lt;code&gt;s3cmd&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This looks to be very simple and straightforward, &lt;code&gt;brew install s3cmd&lt;/code&gt; should do the trick. In a substantially abridged form, that looked like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;╭─mark@Marks-Mac-Mini ~/GitHub/blog-eleventy-ghost ‹main›
╰─$ brew install s3cmd
Running `brew update --auto-update`...
==&amp;gt; Auto-updated Homebrew!
==&amp;gt; Updated Homebrew from 4.0.10 (931327df1) to 4.0.13 (ac0663ae5).
Updated 4 taps (dart-lang/dart, sass/sass, homebrew/core and homebrew/cask).
...
You have 55 outdated formulae and 1 outdated cask installed.
...
==&amp;gt; Installing s3cmd
==&amp;gt; Pouring s3cmd--2.3.0.ventura.bottle.1.tar.gz
🍺  /usr/local/Cellar/s3cmd/2.3.0: 837 files, 11.4MB
==&amp;gt; Running `brew cleanup s3cmd`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That took about 10 minutes, but should be worth it.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;Next, to begin configuration I need to fetch the access key:value pair for &lt;code&gt;images-summittdweller&lt;/code&gt; that I created 4 years ago. I have the credentials necessary to view that information at &lt;a href=&#34;https://cloud.digitalocean.com/account/api/spaces&#34;&gt;https://cloud.digitalocean.com/account/api/spaces&lt;/a&gt; so that&amp;rsquo;s what I&amp;rsquo;ve done.&lt;/p&gt;
&lt;p&gt;Whoa, that didn&amp;rsquo;t work! I tried to use old access keys but apparently they are in the wrong format?  So, I created a new key named &lt;code&gt;key-for-s3cmd&lt;/code&gt; and applied that (see below) and it works.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;╭─mark@Marks-Mac-Mini ~/GitHub/blog-eleventy-ghost ‹main›
╰─$ s3cmd --configure

Enter new values or accept defaults in brackets with Enter.
Refer to user manual for detailed description of all options.

Access key and Secret key are your identifiers for Amazon S3. Leave them empty for using the env variables.
Access Key [images-summittdweller]: ***This is a secret***
Secret Key [4YPWYNXZZXFDIR6CRPHG]: ***An even bigger secret***
Default Region [US]:

Use &amp;quot;s3.amazonaws.com&amp;quot; for S3 Endpoint and not modify it to the target Amazon S3.
S3 Endpoint [nyc3.digitaloceanspaces.com]:

Use &amp;quot;%(bucket)s.s3.amazonaws.com&amp;quot; to the target Amazon S3. &amp;quot;%(bucket)s&amp;quot; and &amp;quot;%(location)s&amp;quot; vars can be used
if the target S3 system supports dns based buckets.
DNS-style bucket+hostname:port template for accessing a bucket [%(bucket)s.nyc3.digitaloceanspaces.com]:

Encryption password is used to protect your files from reading
by unauthorized persons while in transfer to S3
Encryption password [SummittDweller]:
Path to GPG program [/usr/local/bin/gpg]:

When using secure HTTPS protocol all communication with Amazon S3
servers is protected from 3rd party eavesdropping. This method is
slower than plain HTTP, and can only be proxied with Python 2.7 or newer
Use HTTPS protocol [Yes]:

On some networks all internet access must go through a HTTP proxy.
Try setting it here if you can&#39;t connect to S3 directly
HTTP Proxy server name:

New settings:
  Access Key: ***This is a secret***
  Secret Key: ***An even bigger secret***
  Default Region: US
  S3 Endpoint: nyc3.digitaloceanspaces.com
  DNS-style bucket+hostname:port template for accessing a bucket: %(bucket)s.nyc3.digitaloceanspaces.com
  Encryption password: SummittDweller
  Path to GPG program: /usr/local/bin/gpg
  Use HTTPS protocol: True
  HTTP Proxy server name:
  HTTP Proxy server port: 0

Test access with supplied credentials? [Y/n] Y
Please wait, attempting to list all buckets...
Success. Your access key and secret key worked fine :-)

Now verifying that encryption works...
Success. Encryption and decryption worked fine :-)

Save settings? [y/N] y
Configuration saved to &#39;/Users/mark/.s3cfg&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;using-s3cwd&#34;&gt;Using &lt;code&gt;s3cwd&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &amp;ldquo;More Information&amp;rdquo; section at the end of the document I used above says that&amp;hellip; &amp;ldquo;You can use our &lt;a href=&#34;https://docs.digitalocean.com/products/spaces/reference/s3cmd-usage/&#34;&gt;quick reference on s3cmd usage&lt;/a&gt; to get started.&amp;rdquo;  Ok, let&amp;rsquo;s have a look&amp;hellip; very nice!  I&amp;rsquo;m moving immediately to the &lt;a href=&#34;https://docs.digitalocean.com/products/spaces/reference/s3cmd-usage/#save-files-to-your-local-computer&#34;&gt;Save files to your local computer&lt;/a&gt; bits.&lt;/p&gt;
&lt;h3 id=&#34;fetching-files-of-the-august-2020-derecho&#34;&gt;Fetching Files of the August 2020 Derecho&lt;/h3&gt;
&lt;p&gt;The photos I saved of damage from our August 2020 Derecho, in a &lt;code&gt;images-summittdweller/2020-Aug-10-Derecho&lt;/code&gt; bucket, are rather depressing and certainly don&amp;rsquo;t need to be super high-res for the web, so let&amp;rsquo;s retrieve those and practice this workflow there first.&lt;/p&gt;
&lt;p&gt;The quick reference linked above says to use a command of the form &lt;code&gt;s3cmd get s3://spacename/path/ --recursive&lt;/code&gt; to get all files from a particular folder.  In my case, that&amp;rsquo;s&amp;hellip;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;╭─mark@Marks-Mac-Mini ~/Downloads/2020-derecho-photos
╰─$ s3cmd get s3://images-summittdweller/2020-Aug-10-Derecho/ --recursive

WARNING: Empty object name on S3 found, ignoring.
download: &#39;s3://images-summittdweller/2020-Aug-10-Derecho/Derecho - 1.png&#39; -&amp;gt; &#39;./Derecho - 1.png&#39;  [1 of 82]
 23486944 of 23486944   100% in    1s    21.04 MB/s  done
download: &#39;s3://images-summittdweller/2020-Aug-10-Derecho/Derecho - 10.png&#39; -&amp;gt; &#39;./Derecho - 10.png&#39;  [2 of 82]
 20861132 of 20861132   100% in    0s    23.45 MB/s  done
...
download: &#39;s3://images-summittdweller/2020-Aug-10-Derecho/Photo-2020-08-20-19-51.jpeg&#39; -&amp;gt; &#39;./Photo-2020-08-20-19-51.jpeg&#39;  [81 of 82]
 6277783 of 6277783   100% in    0s    16.86 MB/s  done
ERROR: Creation of file &#39;./for-the-web/&#39; failed (Reason: Is a directory)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, 81 images downloaded.  That was sooooooooo much better than the 1000-or-so clicks it would have taken to do that manually!  The only gottcha&amp;hellip; that last error message about not downloading the &lt;code&gt;for-the-web&lt;/code&gt; directory, which is currently empty anyway.  Before I go farther, I&amp;rsquo;m going to open that &lt;em&gt;DigitalOcean Spaces&lt;/em&gt; bucket and change the errant directory name to &lt;code&gt;web-ready&lt;/code&gt;; that&amp;rsquo;s where my &amp;ldquo;thumbnail&amp;rdquo; copies of all these images will be uploaded shortly.&lt;/p&gt;
&lt;h2 id=&#34;next-step-resize-those-images&#34;&gt;Next Step, Resize Those Images&lt;/h2&gt;
&lt;p&gt;I found some concise and timely advice in the first web post I Googled: &lt;a href=&#34;https://www.idownloadblog.com/2013/10/19/how-to-resize-multiple-images-mac/&#34;&gt;How to quickly resize multiple images at once on Mac&lt;/a&gt;. It uses exactly the tool I had in mind, the Mac-native &lt;code&gt;Preview&lt;/code&gt; app.&lt;/p&gt;
&lt;p&gt;Before begining that process I wanted to see just how much space my 81 images occupy, like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;╭─mark@Marks-Mac-Mini ~/Downloads/2020-derecho-photos
╰─$ du -sh
2.7G	.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2.7G isn&amp;rsquo;t all that much, but it&amp;rsquo;s still much bigger than it needs to be.  I&amp;rsquo;m firing up &lt;code&gt;Preview&lt;/code&gt; now to see if I can reduce all images proportionally to a maximum width of 800 pixels.  Be back in a couple of minutes&amp;hellip;&lt;/p&gt;
&lt;p&gt;Drum roll please&amp;hellip;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;╭─mark@Marks-Mac-Mini ~/Downloads/2020-derecho-photos
╰─$ du -sh
163M	.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not bad at all.  Only took a couple of minutes and it reduced the total image size from 2.7G down to 163M. Not too shabby.&lt;/p&gt;
&lt;h2 id=&#34;uploads-complete-next&#34;&gt;Uploads Complete&amp;hellip; Next?&lt;/h2&gt;
&lt;p&gt;In order to upload the resized images back to &lt;em&gt;DigitalOcean Spaces&lt;/em&gt;, I simply used the nice graphical interface available to me at &lt;a href=&#34;https://cloud.digitalocean.com/spaces/images-summittdweller?path=2020-Aug-10-Derecho%2Fweb-ready&#34;&gt;https://cloud.digitalocean.com/spaces/images-summittdweller?path=2020-Aug-10-Derecho%2Fweb-ready&lt;/a&gt; and the &lt;code&gt;Upload&lt;/code&gt; option there.  It worked nicely, but for whatever reason two of the images failed to upload: &lt;code&gt;Derecho - 38.png&lt;/code&gt; and &lt;code&gt;Derecho - 39.png&lt;/code&gt;.  After a little review, and retries, I could not figure out why these wouldn&amp;rsquo;t upload but that&amp;rsquo;s OK because they are both largely redundant with &lt;code&gt;Derecho - 40.png&lt;/code&gt;, so we&amp;rsquo;ll just stick with that one.&lt;/p&gt;
&lt;p&gt;So, in the original folder image &lt;code&gt;Derecho - 1.png&lt;/code&gt; has an endpoint of &lt;code&gt;https://images.summittdweller.com/2020-Aug-10-Derecho/Derecho%20-%201.png&lt;/code&gt;.  Makes sense.  In my new &lt;code&gt;web-ready&lt;/code&gt; directory the reduced-size copy of the same image naturally has an endpoint of &lt;code&gt;https://images.summittdweller.com/2020-Aug-10-Derecho/web-ready/Derecho%20-%201.png&lt;/code&gt;.  Fortunately, that&amp;rsquo;s a &amp;ldquo;match&amp;rdquo; except for the addition of the &lt;code&gt;web-ready&lt;/code&gt; subdirectory in the path.  Exactly what I hoped would happen.&lt;/p&gt;
&lt;p&gt;This means the next step is to&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;alter-content-to-include-the-web-ready-path&#34;&gt;Alter Content to Include the &lt;code&gt;web-ready&lt;/code&gt; Path&lt;/h2&gt;
&lt;p&gt;I used the admin search (magnifying glass) feature of the &lt;em&gt;Ghost&lt;/em&gt; instance behind &lt;a href=&#34;__GHOST_URL__/ghost/#/dashboard&#34;&gt;this blog&lt;/a&gt; to find all references to &lt;code&gt;https://images.summittdweller.com/2020-Aug-10-Derecho&lt;/code&gt; and it found: NOTHING.  Yikes.  Turns out all of the references were in one post, and it was draft.  So I edited the draft &amp;ldquo;manually&amp;rdquo; and published it.  Now let&amp;rsquo;s try that search again&amp;hellip; NOPE.  So, the text inside those &lt;code&gt;figure&lt;/code&gt; tags evidently isn&amp;rsquo;t discoverable.  ☹️  Just as well since I think a different approach is needed.&lt;/p&gt;
&lt;h2 id=&#34;not-web-ready-originals&#34;&gt;Not &lt;code&gt;web-ready&lt;/code&gt;, &lt;code&gt;originals&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Since editing the content (posts) to pick up the new &lt;code&gt;web-ready&lt;/code&gt; directory is a royal pain, what I&amp;rsquo;m going to do now is create a new &lt;code&gt;originals&lt;/code&gt; sub-directory in each bucket, download all the images, resize them locally as I did above, but replace the existing high-resolution images with the smaller copies AFTER I make a backup the original images in a new &lt;code&gt;originals&lt;/code&gt; directory.  That way I don&amp;rsquo;t have to edit any of my posts in order to get the smaller web-ready images, but I won&amp;rsquo;t lose the originals either.  &lt;strong&gt;Beautimous&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&#34;belay-that-order&#34;&gt;Belay That Order!&lt;/h2&gt;
&lt;p&gt;While I&amp;rsquo;m confident this approach (above) will work, it may not be necessary.  I looked, for example, in &lt;code&gt;images-summittdweller/Norway-Photos-2019/Bergen - Hordaland, June 19, 2019&lt;/code&gt; expecting to find some large images, but there were none over 800px in width.  In fact, I believe they are all under 640px wide, so nothing to do there, and that&amp;rsquo;s a good thing.&lt;/p&gt;
&lt;h2 id=&#34;thats-all-folks&#34;&gt;That&amp;rsquo;s All Folks&lt;/h2&gt;
&lt;p&gt;A detailed search of &lt;code&gt;images-summittdweller&lt;/code&gt; didn&amp;rsquo;t turn up any more enromous images that might get pushed to the web, so&amp;hellip; &amp;ldquo;That&amp;rsquo;s All Folks&amp;rdquo;, for now at least.&lt;/p&gt;
</description>
      </item>
      
    
      
      <item>
        <title>Proper Python</title>
        <link>https://blog.summittdweller.com/posts/2022/09/proper-python/</link>
        <pubDate>Sat, 24 Sep 2022 14:26:44 -0500</pubDate>
        <author>Mark McFate</author>
        <guid>https://blog.summittdweller.com/posts/2022/09/proper-python/</guid>
        <description>&lt;p&gt;What follows is the &lt;code&gt;README.md&lt;/code&gt; file from my &lt;em&gt;GitHub&lt;/em&gt; repo where &lt;a href=&#34;https://blog.summittdweller.com&#34;&gt;https://blog.summittdweller.com&lt;/a&gt; is built.  It outlines how to &amp;ldquo;properly&amp;rdquo; add Python to a project such that we can create an easily reproducible &amp;ldquo;virtual environment&amp;rdquo; without storing the necessary Python libraries in &lt;em&gt;GitHub&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;From the &lt;code&gt;README.md&lt;/code&gt;&amp;hellip;&lt;/p&gt;
&lt;!-- hugo: layouts/shortcodes/original.html --&gt;
&lt;div class=&#34;original&#34;&gt;
# blogs-SummittDweller
&lt;p&gt;The Python portions of this repo were gleaned from &lt;a href=&#34;https://github.com/SummittDweller/hikes&#34;&gt;https://github.com/SummittDweller/hikes&lt;/a&gt;.
This is the repo for my &lt;a href=&#34;https://blog.SummittDweller.com/&#34;&gt;https://blog.SummittDweller.com/&lt;/a&gt; static website.&lt;/p&gt;
&lt;h2 id=&#34;latest-python-improvements&#34;&gt;Latest Python Improvements&lt;/h2&gt;
&lt;p&gt;Using guidance at &lt;a href=&#34;https://predictivehacks.com/how-to-work-with-vs-code-and-virtual-environments-in-python/&#34;&gt;https://predictivehacks.com/how-to-work-with-vs-code-and-virtual-environments-in-python/&lt;/a&gt; I successfully created a new &lt;code&gt;.venv&lt;/code&gt; virtual environment.  The commands I used to do this were&amp;hellip;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;╭─mark@Marks-Mac-Mini ~/GitHub/blogs-SummittDweller ‹main*›
╰─$ python3 -m venv .venv

╭─mark@Marks-Mac-Mini ~/GitHub/blogs-SummittDweller ‹main*›
╰─$ source .venv/bin/activate

(.venv) ╭─mark@Marks-Mac-Mini ~/GitHub/blogs-SummittDweller ‹main› 
╰─$ pip3 freeze &amp;gt; python-requirements.txt

(.venv) ╭─mark@Marks-Mac-Mini ~/GitHub/blogs-SummittDweller ‹main*›
╰─$ pip3 install -r python-requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then I used &lt;code&gt;COMMAND-SHIFT-P&lt;/code&gt; to select and &lt;code&gt;Python: Select interpreter&lt;/code&gt; to choose the new &lt;code&gt;.venv&lt;/code&gt; Python.  After that&amp;hellip;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(.venv) ╭─mark@Marks-Mac-Mini ~/GitHub/blogs-SummitDweller ‹main*›
╰─$ python3 consolidate.py --start 20220806 --end 20220825

(.venv) ╭─mark@Marks-Mac-Mini ~/GitHub/blogs-SummitDweller ‹main*›
╰─$ hugo server
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;rebuilding-a-local-environment&#34;&gt;Rebuilding a Local Environment&lt;/h2&gt;
&lt;p&gt;Based on guideance from &lt;a href=&#34;https://stackoverflow.com/questions/6590688/is-it-bad-to-have-my-virtualenv-directory-inside-my-git-repository&#34;&gt;https://stackoverflow.com/questions/6590688/is-it-bad-to-have-my-virtualenv-directory-inside-my-git-repository&lt;/a&gt; I&amp;rsquo;ve reconstructed this project such that Python artifacts do NOT propogate into Github.&lt;/p&gt;
&lt;p&gt;The project should automatically &amp;ldquo;rebuild&amp;rdquo; as necessary when opened in VSCode, but if the Python virtual environment needs to be recreated use&amp;hellip;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;source .venv/bin/activate &amp;amp;&amp;amp; pip3 install -r python-requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;deployment-via-digitalocean&#34;&gt;Deployment via DigitalOcean&lt;/h2&gt;
&lt;p&gt;In order to deploy this &lt;code&gt;starter&lt;/code&gt; static app on &lt;em&gt;DigitalOcean&lt;/em&gt; I had to PERMANENTLY move all of my Python components (&lt;code&gt;.py&lt;/code&gt; scripts and &lt;code&gt;requirements.txt&lt;/code&gt;) to a &lt;code&gt;.python&lt;/code&gt; directory to hide it from view during app creation.  Before moving these elements &lt;em&gt;DigitalOcean&lt;/em&gt; would consistently try to deploy my app as Python, and that&amp;rsquo;s not right.&lt;/p&gt;
&lt;p&gt;See &lt;em&gt;DigitalOcean&lt;/em&gt; ticket [#06849069] &lt;code&gt;Hugo static site with Python components builds fail&lt;/code&gt; for details.&lt;/p&gt;
&lt;p&gt;The response I received from &lt;em&gt;DigitalOcean&lt;/em&gt;&amp;hellip;&lt;/p&gt;
&lt;!-- hugo: layouts/shortcodes/original.html --&gt;
&lt;div class=&#34;original&#34;&gt;&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;Thanks for contacting DigitalOcean.&lt;/p&gt;
&lt;p&gt;We appreciate you reaching out to us about your Hugo static site. From what you mentioned it does sound like your app is getting detected as a python webservice rather then a static site due to the requirements.txt file you had in the root of your repo.&lt;/p&gt;
&lt;p&gt;Unfortunately this is currently what App platform uses to detect applications as python apps. Either having a requirements.txt file or a setup.py file will cause that detection. Our engineers are looking into options to specify the build pack used rather then relying upon the auto detection, which would address this issue in your case, but don&amp;rsquo;t have a timeline yet for implementing it.&lt;/p&gt;
&lt;p&gt;In the mean time the work around that you have specified here should work fine for this. It should cause the app to be detected as a static site rather then python. Hopefully it isn&amp;rsquo;t impacting anything else in your app&amp;rsquo;s build process.&lt;/p&gt;
&lt;p&gt;If you have any questions, please let us know.&lt;/p&gt;
&lt;p&gt;Regards,
Nate
Senior Cloud Support Engineer
Check out our community for great tutorials, articles and FAQs!
digitalocean.com/community&lt;/p&gt;
&lt;p&gt;ref:_00Df218t5m._5004P21l4JM:ref&lt;/p&gt;
&lt;/div&gt;
&lt;!-- /hugo: layouts/shortcodes/original.html --&gt;
&lt;h3 id=&#34;remedy&#34;&gt;Remedy&lt;/h3&gt;
&lt;p&gt;Based on the response above I&amp;rsquo;m making final changes to eliminate the &lt;code&gt;.python&lt;/code&gt; folder, renaming &lt;code&gt;.python/requirements.txt&lt;/code&gt; as &lt;code&gt;python-requirements.txt&lt;/code&gt;, and pulling all other contents of &lt;code&gt;.python&lt;/code&gt; into the root of the project.&lt;/p&gt;
&lt;/div&gt;
&lt;!-- /hugo: layouts/shortcodes/original.html --&gt;
</description>
      </item>
      
    
  </channel>
</rss>
