<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thomas Blevins</title>
    <description>The latest articles on DEV Community by Thomas Blevins (@tb-development).</description>
    <link>https://dev.to/tb-development</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1098578%2F3fb9d530-6ec4-424c-9480-3f936c31514b.jpeg</url>
      <title>DEV Community: Thomas Blevins</title>
      <link>https://dev.to/tb-development</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tb-development"/>
    <language>en</language>
    <item>
      <title>Configuring and Enabling fail2ban to mitigate Wordpress authentication theft with Debian 12</title>
      <dc:creator>Thomas Blevins</dc:creator>
      <pubDate>Sat, 08 Nov 2025 21:29:36 +0000</pubDate>
      <link>https://dev.to/tb-development/configuring-and-enabling-fail2ban-to-mitigate-wordpress-authentication-theft-with-debian-12-f52</link>
      <guid>https://dev.to/tb-development/configuring-and-enabling-fail2ban-to-mitigate-wordpress-authentication-theft-with-debian-12-f52</guid>
      <description>&lt;p&gt;We've recently run into a problem with our Wordpress site occasionally getting bombarded with login requests. To safeguard against this, we have implemented fail2ban on our Linux Machine to rate limit these requests.&lt;/p&gt;

&lt;h1&gt;
  
  
  Nginx Considerations
&lt;/h1&gt;

&lt;p&gt;I am using fail2ban against Nginx access logs, and I've seen multiple times a recommendation to utilize Nginx's built-in rate-limiting &lt;code&gt;limit-req&lt;/code&gt; (&lt;a href="https://blog.nginx.org/blog/rate-limiting-nginx" rel="noopener noreferrer"&gt;Rate Limiting with Nginx&lt;/a&gt;), and their &lt;code&gt;zone&lt;/code&gt; idea seems to be what I'm doing when looking for specific requests.&lt;/p&gt;

&lt;p&gt;I'm instead implementing fail2ban on its own, and just reading the access logs.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is fail2ban?
&lt;/h1&gt;

&lt;p&gt;Fail2ban reactively scans &lt;code&gt;log files&lt;/code&gt; for requests matching a &lt;code&gt;filter&lt;/code&gt; (known as a fail) that (over a &lt;code&gt;findtime&lt;/code&gt; duration) break the &lt;code&gt;maxretry&lt;/code&gt; limit.  If this happens, it locks them in &lt;code&gt;jail&lt;/code&gt; for a &lt;code&gt;bantime&lt;/code&gt;, stopping further requests.&lt;/p&gt;

&lt;h1&gt;
  
  
  Installing fail2ban
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;fail2ban
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure the package is installed correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fail2ban-client &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Configuring fail2ban
&lt;/h1&gt;

&lt;p&gt;Copy the default files into files that you can safely customize, without risk of overwriting them with a package update.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
&lt;span class="nb"&gt;cp&lt;/span&gt; /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Configuring the Filter
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;/etc/fail2ban/filter.d/wordpress-login.conf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;[&lt;span class="n"&gt;Definition&lt;/span&gt;]

&lt;span class="c"&gt;# Match any access log line that starts with an IP address and attempts to access the wp-login via POST
# If we do want to limit xml access
#           ^&amp;lt;HOST&amp;gt; .*"(POST) /xmlrpc\.php.*"
# If we do want to limit access
#           ^&amp;lt;HOST&amp;gt; .*"(GET|POST) /wp-admin/.*"
&lt;/span&gt;&lt;span class="n"&gt;failregex&lt;/span&gt; = ^&amp;lt;&lt;span class="n"&gt;HOST&lt;/span&gt;&amp;gt; .*&lt;span class="s2"&gt;"(POST) /wp-login\.php.*"&lt;/span&gt;

&lt;span class="c"&gt;# If we do want to limit access, don't look for asset requests
# ignoreregex = ^&amp;lt;HOST&amp;gt; .*"(GET|POST) /wp-admin/(images|js|css)/.*"
&lt;/span&gt;&lt;span class="n"&gt;ignoreregex&lt;/span&gt; = 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Configuring the Jail
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;/etc/fail2ban/jail.local&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;[&lt;span class="n"&gt;wordpress&lt;/span&gt;-&lt;span class="n"&gt;login&lt;/span&gt;]
&lt;span class="n"&gt;enabled&lt;/span&gt; = &lt;span class="n"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;filter&lt;/span&gt; = &lt;span class="n"&gt;wordpress&lt;/span&gt;-&lt;span class="n"&gt;login&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt; = &lt;span class="n"&gt;http&lt;/span&gt;,&lt;span class="n"&gt;https&lt;/span&gt;
&lt;span class="n"&gt;logpath&lt;/span&gt; = /&lt;span class="n"&gt;var&lt;/span&gt;/&lt;span class="n"&gt;log&lt;/span&gt;/&lt;span class="n"&gt;nginx&lt;/span&gt;/*.&lt;span class="n"&gt;access&lt;/span&gt;.&lt;span class="n"&gt;log&lt;/span&gt;
&lt;span class="n"&gt;action&lt;/span&gt; = &lt;span class="n"&gt;iptables&lt;/span&gt;-&lt;span class="n"&gt;multiport&lt;/span&gt;[&lt;span class="n"&gt;name&lt;/span&gt;=&lt;span class="n"&gt;http&lt;/span&gt;, &lt;span class="n"&gt;port&lt;/span&gt;=&lt;span class="s2"&gt;"http,https"&lt;/span&gt;, &lt;span class="n"&gt;protocol&lt;/span&gt;=&lt;span class="n"&gt;tcp&lt;/span&gt;]
&lt;span class="n"&gt;maxretry&lt;/span&gt; = &lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;findtime&lt;/span&gt; = &lt;span class="m"&gt;60&lt;/span&gt;
&lt;span class="n"&gt;bantime&lt;/span&gt; = &lt;span class="m"&gt;3600&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;logpath&lt;/code&gt; is utilizing a wildcard to scan all site access logs.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;action&lt;/code&gt; is specifying that we will use the &lt;code&gt;iptables&lt;/code&gt; of the firewall to restrict the requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Testing fail2ban
&lt;/h1&gt;

&lt;p&gt;Before booting this up, you can test your individual log files (I believe wildcard is not supported) to see if your filter is reading the "failures" correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fail2ban-regex /var/log/nginx/my.access.log /etc/fail2ban/filter.d/wordpress-login.conf &lt;span class="nt"&gt;--print-all-matched&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Though, keep in mind you'll have to have logs that will match this filter regex to see anything here.&lt;/p&gt;

&lt;h1&gt;
  
  
  Starting and Stopping fail2ban
&lt;/h1&gt;

&lt;p&gt;To Start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;fail2ban
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start fail2ban
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To Stop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl disable fail2ban
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl stop fail2ban
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Monitoring fail2ban jails
&lt;/h1&gt;

&lt;p&gt;To see how a specific jail is faring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fail2ban-client status wordpress-login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you'll see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Status for the jail: wordpress-login
|- Filter
|  |- Currently failed: 156
|  |- Total failed:     101134
|  `- File list:        /var/log/nginx/my.access.log ...
`- Actions
   |- Currently banned: 0
   |- Total banned:     1145
   `- Banned IP list:   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Extra
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Also check out the default &lt;code&gt;sshd&lt;/code&gt; jail, all you have to do is enable it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.cloudflare.com/waf/rate-limiting-rules/best-practices/" rel="noopener noreferrer"&gt;Cloudfare - Rate Limiting Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bornoe.org/blog/2023/09/basic-fail2ban-commands/" rel="noopener noreferrer"&gt;Basic fail2ban Commands&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>fail2ban</category>
      <category>wordpress</category>
      <category>linux</category>
      <category>nginx</category>
    </item>
    <item>
      <title>Creating thumbnails for multi-page Pdfs in Carrierwave 2.2.3 and Rails 7</title>
      <dc:creator>Thomas Blevins</dc:creator>
      <pubDate>Fri, 09 Jun 2023 19:16:14 +0000</pubDate>
      <link>https://dev.to/tb-development/creating-thumbnails-for-multi-page-pdfs-in-carrierwave-223-and-rails-7-1ifb</link>
      <guid>https://dev.to/tb-development/creating-thumbnails-for-multi-page-pdfs-in-carrierwave-223-and-rails-7-1ifb</guid>
      <description>&lt;p&gt;Prerequisites:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have set up Carrierwave to upload files&lt;/li&gt;
&lt;li&gt;Know what &lt;code&gt;version :thumb&lt;/code&gt; does&lt;/li&gt;
&lt;li&gt;Have &lt;code&gt;imagemagick&lt;/code&gt; and &lt;code&gt;ghostscript&lt;/code&gt; installed on the host machine.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Please review this Carrierwave Uploader as the final solution.  The documentation should be worthy enough to explain what's going on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VersionUploader&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;CarrierWave&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Uploader&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;CarrierWave&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MiniMagick&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;CarrierWave&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RMagick&lt;/span&gt;
  &lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="ss"&gt;:fog&lt;/span&gt;

  &lt;span class="c1"&gt;# @doc Specifies the position on remote hosting to save the file&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"shared/system/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;id_partition&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt;

  &lt;span class="c1"&gt;# @doc Returns the model class name, camel_case and pluralized.&lt;/span&gt;
  &lt;span class="c1"&gt;# @example &lt;/span&gt;
  &lt;span class="c1"&gt;#   irb(main):038:0&amp;gt; MyModel.first.file.file.klass&lt;/span&gt;
  &lt;span class="c1"&gt;#   =&amp;gt; "my_models"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;klass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;underscore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluralize&lt;/span&gt;

  &lt;span class="c1"&gt;# @doc Specifies the uploader's association name that is mounted on the model.  In the model `MyModel.rb`, we mount an uploader called VersionUploader, and we call that mount `file`.  This is considered the `attachment`&lt;/span&gt;
  &lt;span class="c1"&gt;# @example&lt;/span&gt;
  &lt;span class="c1"&gt;#   irb(main):039:0&amp;gt; MyModel.first.file.file.attachment&lt;/span&gt;
  &lt;span class="c1"&gt;#   =&amp;gt; "files"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mounted_as&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluralize&lt;/span&gt;

  &lt;span class="c1"&gt;# @doc Creates a section of the final path partitioned by the id's of the model&lt;/span&gt;
  &lt;span class="c1"&gt;# @note&lt;/span&gt;
  &lt;span class="c1"&gt;#   These appear to be the id of the model, with a weird operation done to them.&lt;/span&gt;
  &lt;span class="c1"&gt;#   I sourced this code from the paperclip compatibility source code of Carrierwave's github as in my situation, I was converting from Paperclip to Carrierwave&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;id_partition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%09d"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/.{3}/&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# @doc Specifies the style of file for storage directory purposes&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:original&lt;/span&gt;

  &lt;span class="c1"&gt;# @doc Returns the first page of a file&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="ss"&gt;:thumb&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="ss"&gt;:to_array&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="ss"&gt;:front&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="ss"&gt;convert: &lt;/span&gt;&lt;span class="s2"&gt;"jpg"&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;full_filename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jpg"&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:thumb&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="c1"&gt;# @doc Utilizes minimagick to split the uploading file from it's temporary path into an array&lt;/span&gt;
  &lt;span class="c1"&gt;# @note This code was sourced from https://github.com/janko/image_processing/wiki/Splitting-a-PDF-into-multiple-images, though I've made a few edits&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_array&lt;/span&gt;
    &lt;span class="no"&gt;MiniMagick&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;page_number&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="no"&gt;ImageProcessing&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MiniMagick&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"jpg"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colorspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"RGB"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;page: &lt;/span&gt;&lt;span class="n"&gt;page_number&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
    &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# @doc Used in conjunction with `to_array` to return the first page of the array of pages&lt;/span&gt;
  &lt;span class="c1"&gt;# @note This utilizes the module CarrierWave::RMagick in some way...&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;front&lt;/span&gt;
    &lt;span class="n"&gt;manipulate!&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zero?&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hopefully I've made this journey easier than mine was, thanks!&lt;/p&gt;

</description>
      <category>carrierwave</category>
      <category>ruby</category>
      <category>rails</category>
      <category>imageprocessing</category>
    </item>
  </channel>
</rss>
